详述:OgreRenderer::bootstrapSystem()

没有用过cegui0.7.7以前的版本,所以不是很清楚它之前的版本是怎么初始化的,这里只是说一下bootstrapSystem的这种方式。

cegui作为一个ui框架,它的底层是直接采用低级图形渲染API实现的(d3d或opengl),它的大致思路是这样的。1.通过配置的方式加载样式和资源。2.在渲染的时候调用底层渲染API。3.针对自己定义的控件实现了一套事件机制,用这套机制相应事件。图形界面相关的永远都是怎么显示怎么交互之类的问题。

在cegui0.7.7版本配合ogre的时候,初始化很简单,只需要调用CEGUI::OgreRenderer::bootstrapSystem();方法就行了。挺好用的也不要参数,但是不好理解,尤其是它是怎么获取ogre相关的对象来渲染自己的,都没有体现出来,为此简单的看了一下这个方法相关的代码。

 

bootstrapSystem:

 

OgreRenderer& OgreRenderer::bootstrapSystem()
{
    if (System::getSingletonPtr())
        CEGUI_THROW(InvalidRequestException("OgreRenderer::bootstrapSystem: "
            "CEGUI::System object is already initialised."));

    OgreRenderer& renderer = create();
    OgreResourceProvider& rp = createOgreResourceProvider();
    OgreImageCodec& ic = createOgreImageCodec();
    System::create(renderer, &rp, static_cast<XMLParser*>(0), &ic);

    return renderer;
}

 

 这个方法有两个比较重要地方,创建了一个OgreRenderer对象和一个System对象。其中OgreRenderer对象用来渲染所有界面上的元素。System是cegui的根与ogre的root类型,说到这里必须说一下的是,ogre的代码写的真心烂,什么都放在头文件里,我还以为这个是行业规范呢,看了cegui才找到了回归标准的感觉。

 

 

1.OgreRenderer:

 

OgreRenderer::OgreRenderer() :
    d_pimpl(new OgreRenderer_impl())
{
    checkOgreInitialised();

    // get auto created window
    Ogre::RenderWindow* rwnd = d_pimpl->d_ogreRoot->getAutoCreatedWindow();
    if (!rwnd)
        CEGUI_THROW(RendererException(
            "Ogre was not initialised to automatically create a window, you "
            "should therefore be explicitly specifying a Ogre::RenderTarget in "
            "the OgreRenderer::create function."));

    constructor_impl(*rwnd);
}

OgreRenderer_impl() :d_displayDPI(96, 96),d_maxTextureSize(2048),
        d_ogreRoot(Ogre::Root::getSingletonPtr()),d_previousVP(0),
      d_activeBlendMode(BM_INVALID),d_makeFrameControlCalls(true)
        {}

1. 这里需要关注的第一个是d_pimpl对象,它是一个结构体,里面是一些常用对象,其中一个成员是ogreRoot。这个地方默认对其进行初始化d_pimpl(new OgreRenderer_impl(),从下面的OgreRenderer_impl构造可以看出,默认对ogreRoot进行获取了。Ogre::Root::getSingletonPtr() 这表示在对OgreRenderer初始化前必须先new出root。

2. getAutoCreatedWindow 是获取RenderWindow而不是重新new,所以在此之前也必须new出RenderWindow。

3.最后看看constructor_impl这个方法,构造的实现名字取的真不俗,其实主要是对d_pimpl结构体的填充。

 

constructor_impl :

 

void OgreRenderer::constructor_impl(Ogre::RenderTarget& target)
{
    d_pimpl->d_renderSystem = d_pimpl->d_ogreRoot->getRenderSystem();

    d_pimpl->d_displaySize.d_width  = target.getWidth();
    d_pimpl->d_displaySize.d_height = target.getHeight();

    // create default target & rendering root (surface) that uses it
    d_pimpl->d_defaultTarget =
        new OgreWindowTarget(*this, *d_pimpl->d_renderSystem, target);
    d_pimpl->d_defaultRoot =
        new RenderingRoot(*d_pimpl->d_defaultTarget);

    // hook into the rendering process
    d_pimpl->d_ogreRoot->addFrameListener(&S_frameListener);
}

 能从ogreRoot获取的坚决不自己new,反正OgreRenderer的初始化就这么些东西了。渲染对象的根也是在这个时候添加的,我们自己new出来的组件都是挂接在这个根上的。渲染对象的关系虽然是个tree但是是以list的形势存储的,父在前子在后,所以查询当前鼠标选中的组件的时候,都是从后面向前面查找的,因为子比父的优先级高。如果要实现点击后子和其父都要进行响应,做法应该是子响应后继续向前找下一个选中的渲染对象。

 

 

2.System :

System 的构造看起来比OgreRenderer的更复杂,但它只是履行了它作为这个cegui的入口的责任,大量的创建和初始化。System 的构造看起来比较长,里面主要涉及两个内容:

1.Config_xmlHandler:这个对象里面封装着各种xml配置,在System 构造里会加载这些配置。

2.createSingletons和addStandardWindowFactories的调用。

createSingletons:

 

void System::createSingletons()
{
    // cause creation of other singleton objects
    new ImagesetManager();
    new FontManager();
    new WindowFactoryManager();
    new WindowManager();
    new SchemeManager();
    new MouseCursor();
    new GlobalEventSet();
    new AnimationManager();
    new WidgetLookManager();
    new WindowRendererManager();
    new RenderEffectManager();
}

 

addStandardWindowFactories:

 

void System::addStandardWindowFactories()
{
    // Add factories for types all base elements
    WindowFactoryManager::addFactory< TplWindowFactory<GUISheet> >();
    WindowFactoryManager::addFactory< TplWindowFactory<DragContainer> >();
    WindowFactoryManager::addFactory< TplWindowFactory<ScrolledContainer> >();
    WindowFactoryManager::addFactory< TplWindowFactory<ClippedContainer> >();
    WindowFactoryManager::addFactory< TplWindowFactory<Checkbox> >();
    WindowFactoryManager::addFactory< TplWindowFactory<PushButton> >();
    WindowFactoryManager::addFactory< TplWindowFactory<RadioButton> >();
    WindowFactoryManager::addFactory< TplWindowFactory<Combobox> >();
    WindowFactoryManager::addFactory< TplWindowFactory<ComboDropList> >();
    WindowFactoryManager::addFactory< TplWindowFactory<Editbox> >();
    WindowFactoryManager::addFactory< TplWindowFactory<FrameWindow> >();
    WindowFactoryManager::addFactory< TplWindowFactory<ItemEntry> >();
    WindowFactoryManager::addFactory< TplWindowFactory<Listbox> >();
    WindowFactoryManager::addFactory< TplWindowFactory<ListHeader> >();
    WindowFactoryManager::addFactory< TplWindowFactory<ListHeaderSegment> >();
    WindowFactoryManager::addFactory< TplWindowFactory<Menubar> >();
    WindowFactoryManager::addFactory< TplWindowFactory<PopupMenu> >();
    WindowFactoryManager::addFactory< TplWindowFactory<MenuItem> >();
    WindowFactoryManager::addFactory< TplWindowFactory<MultiColumnList> >();
    WindowFactoryManager::addFactory< TplWindowFactory<MultiLineEditbox> >();
    WindowFactoryManager::addFactory< TplWindowFactory<ProgressBar> >();
    WindowFactoryManager::addFactory< TplWindowFactory<ScrollablePane> >();
    WindowFactoryManager::addFactory< TplWindowFactory<Scrollbar> >();
    WindowFactoryManager::addFactory< TplWindowFactory<Slider> >();
    WindowFactoryManager::addFactory< TplWindowFactory<Spinner> >();
    WindowFactoryManager::addFactory< TplWindowFactory<TabButton> >();
    WindowFactoryManager::addFactory< TplWindowFactory<TabControl> >();
    WindowFactoryManager::addFactory< TplWindowFactory<Thumb> >();
    WindowFactoryManager::addFactory< TplWindowFactory<Titlebar> >();
    WindowFactoryManager::addFactory< TplWindowFactory<Tooltip> >();
    WindowFactoryManager::addFactory< TplWindowFactory<ItemListbox> >();
    WindowFactoryManager::addFactory< TplWindowFactory<GroupBox> >();
    WindowFactoryManager::addFactory< TplWindowFactory<Tree> >();
    WindowFactoryManager::addFactory< TplWindowFactory<HorizontalLayoutContainer> >();
    WindowFactoryManager::addFactory< TplWindowFactory<VerticalLayoutContainer> >();
    WindowFactoryManager::addFactory< TplWindowFactory<GridLayoutContainer> >();
}

 System 作为cegui的入口,初始化的时候为我们new出了所需要使用的所有对象,这些对象都是以单例的形势存在的,这也是为什么初始化的时候没有赋值给某个引用。当然了,这里的单例模式没有java里面实现的严格,严格意义上讲,为保证单例必须使构造私有化。

 

总结:一般一个开源的框架,为了使用者的方便,会对初始化部分进行统一的内部处理,以简化使用者的使用。这样的结果是我们很难理解它到底做了些什么,所以在使用前有必要点进去看一下。整个cegui的初始化过程,强调了两个东西

OgreRenderer :它集中的处理了界面的渲染,使用者不需要自己关注界面元素是如何渲染的,你只需要为界面上的组件设置相应的样式,然后把样式涉及到的资源加载到资源管理器中即可。

System :它管理了cegui里面的所有管理对象包括OgreRenderer ,在构造的时候会对xml配置进行加载,获取初始化的参数。

此文,尽管不涉及细节,但是对cegui整体的了解还是有所帮助的。

 

你可能感兴趣的:(bootstrap)