版权声明:未经同意,不能用于商业用途,版权归本博主所有 https://blog.csdn.net/qq_16123279/article/details/82464831
osg嵌入到MFC后,就没有控制台了,为了方便看OSG的各种信息,所以要把输入日志打印到文本。
源码路径:
头文件:OpenSceneGraph-3.7.0\include\osg\Notify
源文件:OpenSceneGraph-3.7.0\src\osg\Notify.cpp
日志通知等级
enum NotifySeverity {
ALWAYS=0,
FATAL=1,
WARN=2,
NOTICE=3,
INFO=4,
DEBUG_INFO=5,
DEBUG_FP=6
};
先别激动,来看看什什么等级的日志能notify
#define OSG_NOTIFY(level) if (osg::isNotifyEnabled(level)) osg::notify(level)
#define OSG_ALWAYS OSG_NOTIFY(osg::ALWAYS)
#define OSG_FATAL OSG_NOTIFY(osg::FATAL)
#define OSG_WARN OSG_NOTIFY(osg::WARN)
#define OSG_NOTICE OSG_NOTIFY(osg::NOTICE)
#define OSG_INFO OSG_NOTIFY(osg::INFO)
#define OSG_DEBUG OSG_NOTIFY(osg::DEBUG_INFO)
#define OSG_DEBUG_FP OSG_NOTIFY(osg::DEBUG_FP)
if (osg::isNotifyEnabled(level)) osg::notify(level),如果osg::isNotifyEnabled(level))返回真就通知,来看看里面都写了什么逻辑:
#ifndef OSG_NOTIFY_DISABLED
bool osg::isNotifyEnabled( osg::NotifySeverity severity )
{
//入参要小于你设置的等级才会被通知,就是说你设置成ALWAYS,
//永远不会触发notify(),你想全部消息都通告的话就设置成DEBUG_FP
return severity<=getNotifySingleton()._notifyLevel;
}
#endif
上面说的好好注意下,我被坑过,以为把等级设置成ALWAYS是全部消息都打印,其实上什么消息都不被打印!!!!!
默认的通知等级跟通知输出设置
struct NotifySingleton
{
NotifySingleton()
{
// _notifyLevel
// =============
_notifyLevel = osg::NOTICE; // Default value
std::string OSGNOTIFYLEVEL;
if(getEnvVar("OSG_NOTIFY_LEVEL", OSGNOTIFYLEVEL) || getEnvVar("OSGNOTIFYLEVEL", OSGNOTIFYLEVEL))
{
std::string stringOSGNOTIFYLEVEL(OSGNOTIFYLEVEL);
// Convert to upper case
for(std::string::iterator i=stringOSGNOTIFYLEVEL.begin();
i!=stringOSGNOTIFYLEVEL.end();
++i)
{
*i=toupper(*i);
}
if(stringOSGNOTIFYLEVEL.find("ALWAYS")!=std::string::npos) _notifyLevel=osg::ALWAYS;
else if(stringOSGNOTIFYLEVEL.find("FATAL")!=std::string::npos) _notifyLevel=osg::FATAL;
else if(stringOSGNOTIFYLEVEL.find("WARN")!=std::string::npos) _notifyLevel=osg::WARN;
else if(stringOSGNOTIFYLEVEL.find("NOTICE")!=std::string::npos) _notifyLevel=osg::NOTICE;
else if(stringOSGNOTIFYLEVEL.find("DEBUG_INFO")!=std::string::npos) _notifyLevel=osg::DEBUG_INFO;
else if(stringOSGNOTIFYLEVEL.find("DEBUG_FP")!=std::string::npos) _notifyLevel=osg::DEBUG_FP;
else if(stringOSGNOTIFYLEVEL.find("DEBUG")!=std::string::npos) _notifyLevel=osg::DEBUG_INFO;
else if(stringOSGNOTIFYLEVEL.find("INFO")!=std::string::npos) _notifyLevel=osg::INFO;
else std::cout << "Warning: invalid OSG_NOTIFY_LEVEL set ("<<stringOSGNOTIFYLEVEL<<")"<<std::endl;
}
// Setup standard notify handler
osg::NotifyStreamBuffer *buffer = dynamic_cast<osg::NotifyStreamBuffer *>(_notifyStream.rdbuf());
if (buffer && !buffer->getNotifyHandler())
buffer->setNotifyHandler(new StandardNotifyHandler);
}
osg::NotifySeverity _notifyLevel;
osg::NullStream _nullStream;
osg::NotifyStream _notifyStream;
};
可以看出来,默认等级是osg::NOTICE,然后会到系统的环境变量名为:OSG_NOTIFY_LEVEL去读用户设置的通告等级,环境变量设置的格式为:
[变量名:值]->[OSG_NOTIFY_LEVEL :NOTICE ]
用户能干预的设置
再看头文件有4个导出的函数为:
extern OSG_EXPORT void setNotifyLevel(NotifySeverity severity);
/** get the notify level. */
extern OSG_EXPORT NotifySeverity getNotifyLevel();
/** initialize notify level. */
extern OSG_EXPORT bool initNotifyLevel();
#ifdef OSG_NOTIFY_DISABLED
inline bool isNotifyEnabled(NotifySeverity) { return false; }
#else
/** is notification enabled, given the current setNotifyLevel() setting? */
extern OSG_EXPORT bool isNotifyEnabled(NotifySeverity severity);
#endif
extern OSG_EXPORT void setNotifyHandler(NotifyHandler *handler);
/** Get currrent notification handler. */
extern OSG_EXPORT NotifyHandler *getNotifyHandler();
这些函数就是用户能调用的,看函数名不难理解其用意,其中我们需要关心的就是
setNotifyLevel 和 setNotifyHandler,一个是设置通知的等级,一个是设置如何处理通告。通告的等级不难理解,如何处理通知看函数的传入参数为NotifyHandler *handler,所以我们需要继承这个类重写里面的方法来实现。
class OSG_EXPORT NotifyHandler : public osg::Referenced
{
public:
virtual void notify(osg::NotifySeverity severity, const char *message) = 0;
};
写好后在调用的地方set一下就ok了。
实战例子
//重定向osg日志输出
class RoadbedNotifyHandler :public osg::NotifyHandler
{
public:
virtual void notify(osg::NotifySeverity severity, const char *message)
{
if (severity <= osg::WARN)
app_print_info(message_type::MT_INFO,message);
else
{
std::string logFileName= string_tools::CString_to_string(file_tools::get_app_path_with_xg());
logFileName += "3D_Error.log";
FILE* fp=nullptr;
fopen_s(&fp, logFileName.c_str(), "w");
if (!fp)
{
app_print_info(message_type::MT_ERROR, _T("3D日志创建失败!"));
return;
}
else
{
fprintf_s(fp, message);
fputchar('\n');
fclose(fp);
}
}
}
};
/*调用*/
//设置成INFO就行了,DEBUG_FP每一帧都有N条消息吃不消
osg::setNotifyLevel(osg::NotifySeverity::INFO);
osg::setNotifyHandler(new RoadbedNotifyHandler);