• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            清源游民  gameogre@gmail.com

            下面直接涉及到相關類


            首先看一下
            ExampleFrameListener, 下面是類間關系圖

             
            ExampleFrameListener 繼承了 FrameListener, 因此擁有了它的兩個方法

            virtual bool frameStarted(constFrameEvent& evt)

            virtual bool frameEnded(constFrameEvent& evt)

            在 ExampleApplication 中將它們注冊到 ogre 中,在適當的時候, ogre 會調用這兩個方法 . 下面是注冊地點與時機

            virtual void ExampleApplication::createFrameListener(void)

                {

                    mFrameListener= newExampleFrameListener(mWindow, mCamera);

                    mFrameListener->showDebugOverlay(true);

                    mRoot->addFrameListener(mFrameListener);

            }

            createFrameListener 在 ExampleApplication::setup() 中被調用.

            ExampleFrameListener 又繼承了 WindowEventListener.

            WindowEventListerner 在ogre 1.4中是新加的。按照手冊:它是一個 Callback class used to send out window events to client app. 它定義以下四個接口,而顯然例子程序中只用到了兩個
            virtual void windowMoved(RenderWindow* rw)   {}

            virtual void windowResized(RenderWindow* rw) {}

            virtual void windowClosed(RenderWindow* rw)  {}

            virtual void windowFocusChange(RenderWindow* rw) {}

            這種所謂的回調類如何實現?下面只說明windows操作系統的情況。

            我們知道,windows操作系統監視系統中發生的一切,通過消息的方式通知相應的窗口。每個窗口類注冊的時候,都指明一個回調過程,在那里處理傳來的消息。應用程序又有各自的消息隊列,從消息隊列中取得消息,然后分開給各窗口.

            不防從ogre的源碼中看看上述windows基本過程如何實現,這有助理解回調類的實現過程:

            首先,ogre可以為我們創建一個窗口:

            mWindow = mRoot->initialise(true);//

            于是我們進入到initialise()中看看吧,它倒底做了些什么事情。

            RenderWindow * Root::initialise(boolautoCreateWindow, constString& windowTitle)

            {

            // ……

            mAutoWindow =  mActiveRenderer->initialise(autoCreateWindow, windowTitle);

            // 這里:RenderSystem* mActiveRenderer

            // ……

            }

            mActivaRenderer 只是接口,不用實際的事情,實際的工作由它的子類完成,現只看DirectX實現:

            RenderWindow * D3D9RenderSystem::initialise( boolautoCreateWindow, constString& windowTitle )

            {

            // ……………………

            autoWindow = this->createRenderWindow( windowTitle, width, height,

                          fullScreen, &miscParams );

            // ………………… ..

            }

            好,繼續下去,看看createRenderWindow做了些什么

                

            RenderWindow * D3D9RenderSystem::createRenderWindow(constString &name,

                   unsigned int width, unsignedintheight, boolfullScreen,

                   const NameValuePairList *miscParams)

            {

            // …………… ..

            RenderWindow * win = newD3D9RenderWindow(mhInstance, mActiveD3DDriver,

                       mPrimaryWindow ? mpD3DDevice : 0);

             

            win ->create( name, width, height, fullScreen, miscParams);

            // ………………

            }

            繼續

            void D3D9RenderWindow::create(constString& name, unsignedintwidth, unsignedintheight,

                   bool fullScreen, constNameValuePairList *miscParams)

            {

            // Register the window class

            // NB allow 4 bytes of window data for D3D9RenderWindow pointer

                WNDCLASS wc = { 0, WindowEventUtilities::_WndProc, 0, 0, hInst,

                       LoadIcon(0, IDI_APPLICATION), LoadCursor(NULL, IDC_ARROW),

                          (HBRUSH)GetStockObject(BLACK_BRUSH), 0, "OgreD3D9Wnd" };

                       RegisterClass(&wc);

            // 定義了窗口類,并且進行注冊,需要注意的是,你看看它把窗口類的回調函數的值設為了什么?先記住,一會兒討論它吧。

                       // Create our main window

                       // Pass pointer to self

                       mIsExternal = false;

                       mHWnd = CreateWindow("OgreD3D9Wnd", title.c_str(), dwStyle,

                          mLeft, mTop, mWidth, mHeight, parentHWnd, 0, hInst, this);

            // 調用win32API把窗口真正Create出來了

            WindowEventUtilities ::_addRenderWindow(this);

            // 這一步也要注意到

            }

            繼續

            void WindowEventUtilities::_addRenderWindow(RenderWindow* window)

            {

                _msWindows.push_back(window);

            }

            _msWindows 定義為:

            typedef std::vector<RenderWindow*> Windows;

             static Windows _msWindows;

            ,沒什么,只是個stl容器,把生成的窗口放進去了.

            到現在,容器類注冊好了,回調函數也指定了,窗口也創建出來了。現在我們繼續思考我們最最初的問題: WindowEventListerner 這個回調類是如何實現所謂的回調機制的,也就是說windowEventListerner不是定義了四個接口,它響應特定的windows事件,我們要討論的就是這四個接口方法如何被調用起來,實現所謂的回調機制。 還記得注冊窗口類的回調函數是什么吧,

            WindowEventUtilities::_WndProc , 呵呵,只要在那里調用上述四個接口函數就好了。

            哪問題又來了,_WndProc到哪里找這四個接口函數呢?

            在 ExampleFrameListener 類的構造函數里我們可以看到如下代碼

            //Register as a Window listener

            WindowEventUtilities::addWindowEventListener(mWindow, this);

            啊,這就是奧秘所在!到源碼中看看吧。

            void WindowEventUtilities::addWindowEventListener( RenderWindow* window, WindowEventListener* listener )

            {

                _msListeners.inser t(std::make_pair(window, listener));

            }

            -msListeners 被定義成這樣子:

            typedef std::multimap<RenderWindow*, WindowEventListener*> WindowEventListeners;

            static WindowEventListeners _msListeners;

            沒有什么,就是STL容器,它使得窗口(RenderWindow)與(WindowEventListener)

            組成了親密派對,窗口有了什么消息,就可以用對應的回調類響應。

            只剩下一點秘密了,到底怎么調用起來的呢,某某某說過,源碼之下,了無秘密,那就看源碼吧:

            LRESULT CALLBACK WindowEventUtilities::_WndProc(HWNDhWnd, UINTuMsg, WPARAMwParam, LPARAMlParam)

            {

            WindowEventListeners ::iteratorstart = _msListeners.lower_bound(win),

                                 end = _msListeners.upper_bound(win);

            // 為遍歷做準備

                switch( uMsg )   // 消息真的來了

              {

            case WM_MOVE:

                   //log->logMessage("WM_MOVE");

                   win->windowMovedOrResized();

                   for( ; start != end; ++start )

                       (start->second)->windowMoved(win);

                   break;

                case WM_SIZE:

                   //log->logMessage("WM_SIZE");

                   win->windowMovedOrResized();

                   for( ; start != end; ++start )

                       (start->second)->windowResized(win);

                   break;

            }

            }

            就這樣,四個接口函數被調用起來了!

            也許,也許,關于消息還有些要說明的。消息如何泵出來的?

            當看到了如下代碼,突然就想找個朋友,會心一笑.

            void WindowEventUtilities::messagePump()

            {

                MSG   msg;

                while( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )

                {

                   TranslateMessage( &msg );

                   DispatchMessage( &msg );

                }

            }

            打破鐵鍋問到底吧,它又如何被調用起來?

            void Root::startRendering(void)

                {

                    while( !mQueuedEnd )

                    {

                       //Pump messages in all registered RenderWindow windows

                       WindowEventUtilities::messagePump();

             

                       if (!renderOneFrame())

                            break;

                    }

            }

            就是這里了。寫的亂七八糟,腦子也亂七八糟,梳理一下吧。

            首先,mWindow = mRoot->initialise(true);初始化,隨便通過一系統連鎖反應create出來一個窗口,并把它的回調函數設定為 WindowEventUtilities::_WndProc.

            ExampleFrameListener 繼承了 WindowEventListener 的四個約定接口函數。并且在它的構造函數里調用 WindowEventUtilities::addWindowEventListener(mWindow, this); 進行了注冊,以便特定窗口消息發生時進行響應. Root ::startRendering ()進入了渲染循環,渲染每一幀前,檢測widnows消息,并進行分發。于是消息進入到窗口類的回調函數_WndProc,在函數內部根據消息的不同,分別調用已注冊的偵聽器的約定接口函數。
            先寫到這里吧,原來只是想寫寫CEGUI的使用,誰知已經寫了這么多了,CEGUI還一字未提。腦子亂了,先休息吧。下面還得說說OIS,CEGUI又得靠后了.


            posted on 2007-03-01 21:47 清源游民 閱讀(2084) 評論(1)  編輯 收藏 引用 所屬分類: OGRE

            FeedBack:
            # re: ORGE(Eihort)學習筆記之GUI Demo 第一部分 例子框架
            2008-12-31 11:30 | ouch
            感謝! 相當清楚 而且好用  回復  更多評論
              
            <2007年3月>
            25262728123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            留言簿(35)

            隨筆分類(78)

            隨筆檔案(74)

            文章檔案(5)

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            久久久久一级精品亚洲国产成人综合AV区 | 久久成人国产精品二三区| 性做久久久久久久| 国产欧美一区二区久久| 免费国产99久久久香蕉| 欧美成人免费观看久久| 精品无码久久久久国产动漫3d| 91精品国产91久久久久福利| 久久久久99这里有精品10 | 伊人久久综在合线亚洲2019| 一本久久免费视频| 国产精品日韩欧美久久综合| 精品久久久久久国产潘金莲| 久久久久久伊人高潮影院| 成人国内精品久久久久影院| 国产午夜精品久久久久九九| 久久99国产精品一区二区| 性做久久久久久久久久久| 国产日韩欧美久久| 亚洲国产精品无码久久久不卡| 国产成人精品久久| 国产99精品久久| 蜜臀av性久久久久蜜臀aⅴ麻豆 | 久久久久久久97| 国産精品久久久久久久| 亚洲人成网亚洲欧洲无码久久| 色狠狠久久综合网| 久久99亚洲综合精品首页| www.久久99| 国内精品九九久久久精品| 日产精品久久久一区二区| 99久久国产亚洲综合精品| 国内精品久久久久影院薰衣草| 午夜精品久久久久久影视777| 国产成人精品久久综合| 97精品国产97久久久久久免费 | 亚洲精品tv久久久久久久久| 国产精品一区二区久久精品涩爱| 久久综合色区| 亚洲国产成人久久一区WWW| 久久夜色精品国产www|