• CEGUI窗口的渲染顺序 四


    定义和实现:CEGUIBase 里的:CEGUIWindow.h和CEGUIWindow.cpp。

    cegui使用一个vector来存放所有的窗口,另外,再用一个vector存放渲染的顺序。

       //! definition of type used for the list of attached child windows.
        typedef std::vector<Window*> ChildList;    
    //! The list of child Window objects attached to this.    
    ChildList d_children;    
    //! Child window objects arranged in rendering order.   
     ChildList d_drawList;

     

    再有新的窗口添加时有两个重载的函数addChildWindow:

    //添加一个名为name窗口作为this的子窗口。如果窗口存在,则先分离再添加。

    void Window::addChildWindow(const String& name{
        addChildWindow(WindowManager::getSingleton().getWindow(name));
    }

    //----------------------------------------------------------------------------//

    //添加wnd窗口作为this的子窗口。如果窗口存在,则先分离再添
    void Window::addChildWindow(Window* window){
        // don't add null window or ourself as a child
        if (!window || window == this)  //检查不能添加自己为自己的孩子
            return;

        addChild_impl(window);//执行添加
        WindowEventArgs args(window); //激发事件
        onChildAdded(args);
        window->onZChange_impl();//通知窗口的Z值改变,窗口的Z值影响窗口的描述顺序
    }

    //添加指定窗口到合适的位置

    void Window::addChild_impl(Window* wnd)

    {
       //如果先前有父窗口则断开与先前父窗口的联系。
        if (wnd->getParent())         

             wnd->getParent()->removeChildWindow(wnd);

    //添加窗口到描绘列表   

    addWindowToDrawList(*wnd);

        //添加子窗口到列表

        d_children.push_back(wnd);

        // set the parent window
        wnd->setParent(this);

      //强制更新子窗口区域,因为父窗口已变

        WindowEventArgs args(this);
        wnd->onParentSized(args);
    }

     

     /*Add the given window to the drawing list at an appropriate position for
            it's settings and the required direction.  Basically, when \a at_back
            is false, the window will appear in front of all other windows with the
            same 'always on top' setting.  When \a at_back is true, the window will
            appear behind all other windows wih the same 'always on top' setting.*/

    添加指定的窗口到绘制的列表的合适的位置。如果at_back为false,并且设置“always on top”,这个窗口会显示有所有的窗口前面。如果at_back为true,则这窗口会设置在所有"'always on top"的窗口的后面。

    void Window::addWindowToDrawList(Window& wnd, bool at_back)
    {
        // add behind other windows in same group
        if (at_back)
        {
             // calculate position where window should be added for drawing
            ChildList::iterator pos = d_drawList.begin();
            if (wnd.isAlwaysOnTop())
            {
                // find first topmost window
                while ((pos != d_drawList.end()) && (!(*pos)->isAlwaysOnTop()))
                    ++pos;
            }
            // add window to draw list
            d_drawList.insert(pos, &wnd);
        }
        // add in front of other windows in group
        else
        {
            // calculate position where window should be added for drawing
            ChildList::reverse_iterator position = d_drawList.rbegin();
            if (!wnd.isAlwaysOnTop())
            {
                // find last non-topmost window
                while ((position != d_drawList.rend()) && ((*position)->isAlwaysOnTop()))
                    ++position;
            }
            // add window to draw list
            d_drawList.insert(position.base(), &wnd);
        }
    }

     /*!
        \brief
            Causes the Window object to render itself and all of it's attached
            children

    */

    //渲染时父窗口及其的子窗口,先渲染父,再渲染其子窗口

    void Window::render()
    {
        // don't do anything if window is not visible
        if (!isVisible())
            return;

        // get rendering context
        RenderingContext ctx;
        getRenderingContext(ctx);

        // clear geometry from surface if it's ours
        if (ctx.owner == this)
            ctx.surface->clearGeometry();

        // redraw if no surface set, or if surface is invalidated
        if (!d_surface || d_surface->isInvalidated())
        {
            // perform drawing for 'this' Window
            drawSelf(ctx);

            // 按顺序取得d_drawList里的所有的子窗口进行渲染

            const size_t child_count = getChildCount();
            for (size_t i = 0; i < child_count; ++i)
                d_drawList[i]->render();
        }

        // do final rendering for surface if it's ours
        if (ctx.owner == this)
            ctx.surface->draw();
    }

     

              综上所述,cegui通过两个vector列表来控制所有的窗口渲染及其渲染顺序。渲染顺序又是通过一个添加窗口及at_back参数控制,at_back 默认是false,即默认添加的新窗口是在最前面,同时受“'always on top”影响。在实际游戏开发中Z值,应该要比这个复杂,并且有一些模态的窗口。我们可以改写addWindowToDrawList 来控制自己窗口实际显示时应在的位置,以达到项目的需求。

             对于模态窗口,以前我们的项目有个“变态”显示方法,每来一个模态的都显示在所有的窗口的最上面,但是鼠标消息却又还在第一个模态的窗口那里抢占着。我觉得应该再建立一个模态的列表,同时加上权重,但同时弹出N个模态的窗口时,选择权重最大的在最上面,即新弹出窗口时,则比较要弹出的模态窗口与显示的模态窗口的权重,如果权重大,则销毁前面的窗口,显示这个。 另一种方案是:如果有模态窗口显示时,不允许再弹出模态窗口。第三种方案是:管理一个要弹出的模态的窗口的列表,当判断有模态窗口显示在最上面时,则将此窗口压到栈里,每释放一个模态窗口时,在里面调一个接口检查是否有没有显示的模态窗口,如果有则显示下一个模态窗口,并从栈去掉该窗口。

  • 相关阅读:
    wavecom短信猫发送短信失败
    中美教育之差异
    Linux系统管理员成长经验:十一大工作心得
    帮忙哈
    用linux命令分析文件-排序-统计(sort, uniq, awk)
    【u202】家庭作业
    【u107】数字游戏(bds)
    【u104】组合数
    【u105】路径计数2
    【u022】车的放置
  • 原文地址:https://www.cnblogs.com/sier/p/5676502.html
Copyright © 2020-2023  润新知