找到程序入口 WinMain,WinMain里面除去一些七七八八的只剩两行
OgreBites::SampleBrowser brows (nograb, startUpSampleIdx);
brows.go();
看看类关系
class SampleBrowser : public SampleContext, public TrayListener
class SampleContext : public ApplicationContext, public InputListener
通过昨天的学习,知道 ApplicationContext 继承自 FrameListener。
InputListener 响应设备输入事件,TrayListener响应UI事件。
粗略看看 SampleBrowser, SampleContext 发现重载了很多事件响应。
这其中发现重载了一个比较奇怪的函数 createWindow
virtual NativeWindowPair createWindow(const Ogre::String& name, uint32_t w, uint32_t h, Ogre::NameValuePairList miscParams)
{
#if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID
#endif
NativeWindowPair res = ApplicationContext::createWindow(name, w, h, miscParams);
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE_IOS
#endif
return res;
}
这个函数对不同的平台做了一些不同的设置,调用了父类的 ApplicationContext::createWindow。
既然可以重载createWindow
virtual NativeWindowPair
createWindow(const Ogre::String& name, uint32_t w = 0, uint32_t h = 0,
Ogre::NameValuePairList miscParams = Ogre::NameValuePairList());
struct NativeWindowPair
{
Ogre::RenderWindow* render;
NativeWindowType* native;
};
createWindow 返回的是一个pair,包含 RenderWindow, NativeWindowType。
调试一下,看看 createWinow 都做了什么。
最终会进入到 ApplicationContextSDL::createWindow
NativeWindowPair ApplicationContextSDL::createWindow(const Ogre::String& name, Ogre::uint32 w, Ogre::uint32 h, Ogre::NameValuePairList miscParams)
{
NativeWindowPair ret = {NULL, NULL};
if(!SDL_WasInit(SDL_INIT_VIDEO)) {
SDL_InitSubSystem(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER);
}
int flags = p.useFullScreen ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_RESIZABLE;
int d = Ogre::StringConverter::parseInt(miscParams["monitorIndex"], 1) - 1;
ret.native =
SDL_CreateWindow(p.name.c_str(), SDL_WINDOWPOS_UNDEFINED_DISPLAY(d),
SDL_WINDOWPOS_UNDEFINED_DISPLAY(d), p.width, p.height, flags);
#if OGRE_PLATFORM != OGRE_PLATFORM_EMSCRIPTEN
SDL_SysWMinfo wmInfo;
SDL_VERSION(&wmInfo.version);
SDL_GetWindowWMInfo(ret.native, &wmInfo);
#endif
ret.render = mRoot->createRenderWindow(p);
mWindows.push_back(ret);
return ret;
}
通过SDL2创建了一个窗口,然后创建了一个RenderWindow,RenderWindow 包含了一个SwapChain。(D3D11)
Root是ogre的入口,Application 属于 Component,那么,它并非核心部分,只要能获取其他的窗口句柄,它就应该可以Attach到任意一个窗口上。
现在归纳一下,SampleBrowser 继承自 FrameListener, InputListener, TrayListener。它就拥有了UI,输入的功能。创建了系统窗口,创建了渲染窗口,接下来就是创建UI了。
按照之前的获得的信息,创建UI应该在重载的 setup 函数里, 直接去瞄一眼。
直接在 SampleBrowser::setup里来一个断点调试。F10。
ApplicationContext::setup();
发现当运行 ApplicationContext::setup() 时, UI 已经在运行了。已知ogre还没有运行到 Frame事件,不会发生更新事件。那么,UI与ogre不是同一个流程。UI的渲染也不是用的ogre渲染系统?
带着这个疑问,一步一步的调试,发现SampleBrowser重载了 loadResources在里面加载一些资源, 加载资源的时候,会通过 TrayManager::Update 调用到 RenderWindow::Updata,实现刷新画面。
通过这个现象,猜测可以在任何时候去更新应用的画面。如果UI与Frame同一帧都调用了RenderWindow::Update,怎么防止呢?暂时留着疑问。
回到 setup,继续
Sample* startupSample = loadSamples();
从配置文件加载例子
Ogre::MaterialPtr thumbMat = Ogre::MaterialManager::getSingleton().create("SdkTrays/SampleThumbnail", "Essential");
thumbMat->setLightingEnabled(false);
thumbMat->setDepthCheckEnabled(false);
thumbMat->getTechnique(0)->getPass(0)->createTextureUnitState();
创建缩略图材质
setupWidgets();
加载UI
if (startupSample && mFirstRun){
runSample(startupSample);
}
运行初始场景
然后,就是点击UI,选择运行场景了。