CEGUI學習筆記五-- 如何如何擴展CEGUI庫(一)

本文以FrameWindow爲對象,粗略的講述瞭如何擴展CEGUI庫,從而添加一個全新的基礎控件類型。


--------------------------------------------------------------------------------

需求:
如果你使用過FrameWindow,那麼你一定可以發現,FrameWindow的4個角落都可以進行縮放。

如果我們需要固定某個角呢?比如製作一個聊天框,它可以放大縮小,但是左下角錨定。

最開始我一個個的看例子,似乎除了4角全縮放,就是不能縮放,看來例子裏沒有我們需要的。

再去看FrameWindow的頭文件和CPP文件,只有一個關於設置是否可以縮放的函數SetSizingEnable(bool Setting),和幾個protected屬性、根據鼠標座標來判斷是否進行縮放的函數。

看來FrameWindow派生時,沒有做錨定某個角的處理。那麼就去Window的頭文件和CPP文件裏找找吧。

很可惜結果也是沒有。


--------------------------------------------------------------------------------

現在的解決方法有2種:

1、修改或繼承FrameWindow,使之支持錨定角落。

2、編寫函數,響應EventMouse DOWN、Move、UP事件,使具體對象支持錨定縮放。

我選擇了前者。因爲這樣修改之後的FrameWindow更加方便,而且我也討厭去計算那些煩人的座標,何況FrameWindow裏本身就有計算這些座標的內部方法。

OK,我們需要做的就是定義下規則:

// AchorCorner
#define AnchorLeftTop                     0x01
#define AnchorLeftBottom               0x02
#define AnchorRightTop                  0x04
#define AnchorRightBottom            0x08

然後我們定義關於錨定的變量

private:
    int d_anchorCorner;

之後我們需要在構造函數裏添加關於我們的變量的初始化。因爲我們希望對FrameWindow的改變不會對其原有的行爲有所影響。因此我們將錨定點設置爲:

d_anchorCorner = 0;

再來我們定義關於設置錨定的方法:

public:
     void setAnchorCorner( int anchorCorner);
     int    getAnchorCorner( void);

並且實現他們,先是獲取對象的錨定狀態:

int FrameWindow::getAnchorCorner(void)
{
     return d_anchorCorner;
}

然後是設置錨定,在這裏,我採用以下規則:“錨定角由用戶給出,如果該角落已經被設置,則將這個角取消”。這樣,我們的set函數就可以給對象既添加錨定信息,又可以刪除錨定信息了:

void FrameWindow::setAnchorCorner( int anchorCorner)
{
    if ( d_anchorCorner  &  anchorCorner)
              d_anchorCorner  ^= anchorCorner;
    else
              d_anchorCorner  |= anchorCorner;
}

現在我們重新編譯一下CEGUI工程裏的CEGUIBase,讓它重新生成一個dll(DEBUG)和LIB(DEBUG_Static)。並且將原來的替換掉,就可以使用我們剛剛修改的FrameWindow了--只是在代碼裏。

好吧,現在我們已經開始往CEGUI的源代碼裏胡亂加代碼了,因此一切都會變的不那麼順暢。實際上我想說的就是,你的LayoutEdit識別不出來這個FrameWindow了,如果要Add的話,會使勁的拋異常!

你可以試試不用佈局器,而是寫代碼來進行界面佈局。相信我,你一定會被統一座標系統弄瘋。

我的解決方案就是:全盤COPY一次FrameWindow的代碼,然後添加改動,把它改個名字,比如frame2,然後作爲一個新的控件使用。但是沒完,我們還需要爲這個控件添加屬性。這個可以全盤照抄FrameWindowProperty.h和.cpp。

上個步驟不難,不過在這裏還是想提醒下大家,注意命名的統一。

接着,爲了配合我們的新控件frame2,我們需要
在Scheme文件裏Copy映射,並修改相應名稱。
你也可以在視感文件裏COPY FrameWindow的外觀配置,然後嘗試着修改一下。(我嘗試將默認背景改爲透明背景時,這一步對我來說異常痛苦...我恨XML...),或者直接使用FrameWindow的外觀來作爲frame2的外觀--它們倆長的完全一樣!(在這裏我使用Taharez風格的相關文件進行的實驗。)

去LayoutEdit看看,它還是拋異常。肯定有什麼不對勁的地方,從異常提示的信息可以看到,我們的frame2不在WindowFactory的創建列表裏面。

OK,這表明我們還沒有完全的COPY FrameWindow。爲了能讓WindowFactory順順當當的創建我們的frame2,接着找找關於FrameWindow的代碼,看看我們有沒有漏掉什麼include ,或者 大規模的添加控件的代碼。通過搜索整個解決方案,有以下幾個文件跟工廠和FrameWindow相關:

CEGUI.h(75)
CEGUIBaseFactories.cpp(43)
CEGUIBaseFactories.h(45)
CEGUIBaseFactories.h(80)
CEGUIForwardRefs.h(88)

照着改就行。

先在代碼裏測試下frame2這個新玩意,如果我沒有漏掉什麼的話,你應該可以用代碼創建一個frame2窗口,它和FrameWindow一模一樣,除了多了個縮放錨定功能。


--------------------------------------------------------------------------------

以上做的事對我來說有點煩瑣,或者中間穿插了一些別的事情,總之我弄了1天...最後思維敏捷度降爲負數,人完全處於放空狀態了.oO。現在回頭再看我做的事情,只記得當時人搞的暈暈的,但好象都是些CVCV,然後修改下名字...

照着FrameWindow做個frame2出來不難,同時這也是很好的練習目標,在完成之前,我在這裏等你。


--------------------------------------------------------------------------------

好了,現在我不得不告訴你一個噩耗:LayoutEdit依然不支持我們的frame2!而且報的錯誤還是frame2這個類型在工廠裏不存在。

恩,LayoutEdit的文件夾下面有個ceguibase.dll,讓我們來編譯一個Release版本的dll扔進去看看?

滿懷希望的運行LayoutEdit,結果還是報錯!

OK,肯定還有什麼地方是我沒研究到的,不過這已經屬於輔助工具開發的範疇了。當然將來在項目運用中,肯定會修改LayoutEdit,使它更加完善和強大,但這不是研究CEGUI本身的事情,所以對這個問題,我覺得暫時就放一放吧。等將來更加熟悉CEGUI的時候再回頭來解決我們一路遺留下來的知識盲點。

可是總得有個解決方案,不是嗎?以下是我的解決方法:

假設你在Scheme文件裏將frame2映射爲“Taharez/Frame2”,
那麼你可以在LayoutEdit裏添加FrameWindow,
然後手工修改.layout文件裏面的Taharez/FrameWindow,改爲Taharez/Frame2。
這樣,在載入文件的時候,程序就生成的是我們的frame2了。


--------------------------------------------------------------------------------

我迫切希望與大家交流,一同研究這個CEGUI,上班的時候不能上QQ,只能上MSN:[email protected]。我MSN上一個好友都沒有,它還不支持QQ一樣的查找和羣....555

在這裏對下一步的主要學習方向做個展望。
舉個例子:StaticImage和StaticText 都是DefaultWindow,DefaultWindow從代碼上來看,就是Window。那就是說全部的控件都可以顯示一個背景圖片咯?但是爲什麼這倆個對象一個可以顯示圖片,一個不能顯示圖片呢?
是誰在控制這些具體控件類型的表現形式?在Scheme文件裏,我們可以看到,這2個控件類型的FalagardRender不同,這個渲染器模塊是如何工作的?

顯然我們對frame2的擴展工作還沒有結束!

 

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/kun1234567/archive/2008/04/17/2300755.aspx

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章