線(xiàn)程 Joining and Detaching相關(guān)函數(shù)4個(gè)
pthread_joinpthread_detach
pthread_attr_setdetachstate
pthread_attr_getdetachstate
Joining的作用
Joining是線(xiàn)程同步的方法之一
當(dāng)且僅當(dāng)線(xiàn)程被設(shè)置為joinable時(shí)其可被Joining
一個(gè)例子:
#include <pthread/pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define NUM_THREADS 4
void *BusyWork(void *t)
{
int i;
long tid;
double result=0.0;
tid = (long)t;
printf("Thread %ld starting
\n",tid);
for (i=0; i<1000000; i++)
{
result = result + sin(i) * tan(i);
}
printf("Thread %ld done. Result = %e\n",tid, result);
pthread_exit((void*) t);
}
int main (int argc, char *argv[])
{
pthread_t thread[NUM_THREADS];
pthread_attr_t attr;
int rc;
long t;
void *status;
//! 設(shè)置線(xiàn)程屬性
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
for(t=0; t<NUM_THREADS; t++)
{
printf("Main: creating thread %ld\n", t);
rc = pthread_create(&thread[t], &attr, BusyWork, (void *)t);
if (rc)
{
printf("ERROR; return code from pthread_create()is %d\n", rc);
exit(-1);
}
}
//! 銷(xiāo)毀線(xiàn)程屬性
pthread_attr_destroy(&attr);
for(t=0; t<NUM_THREADS; t++)
{
rc = pthread_join(thread[t], &status);
if (rc)
{
printf("ERROR; return code from pthread_join()is %d\n", rc);
exit(-1);
}
printf("Main: completed join with thread %ld having a status of %ld\n",t,(long)status);
}
printf("Main: program completed. Exiting.\n");
pthread_exit(NULL);
}
1.使用pthread的理由
2個(gè)字:簡(jiǎn)單
2.pthread組件
thread,
mutex,
condition var
synchronization
3.線(xiàn)程的終止和產(chǎn)生
小例:
#include <pthread/pthread.h>
#include <stdio.h>
#define NUM_THREADS 5
void *PrintHello(void *threadid)
{
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
for(t=0; t<NUM_THREADS; t++)
{
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc)
{
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
pthread_exit(NULL);
return 0;
}
通過(guò)pthread_create來(lái)創(chuàng)建線(xiàn)程
其第一個(gè)參數(shù)為線(xiàn)程id,第二個(gè)為線(xiàn)程屬性,第三個(gè)為線(xiàn)程函數(shù),最后一個(gè)為數(shù)據(jù)參數(shù)
那么線(xiàn)程如何終止呢:
1.從運(yùn)行函數(shù)終止
2.調(diào)用pthread_exit終止
3.調(diào)用pthread_cance
4.進(jìn)程終止
向線(xiàn)程傳遞參數(shù)
#include <pthread/pthread.h>
#include <stdio.h>
#include <string>
#include <iostream>
#define NUM_THREADS 5
struct Data
{
std::string name;
};
Data* data_impl;
void *PrintHello(void* data_ptr)
{
struct Data* data;
data = (Data*)data_ptr;
std::cout<<data->name<<std::endl;
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
data_impl = new Data[NUM_THREADS];
data_impl[0].name = "T1";
data_impl[1] .name= "T2";
data_impl[2] .name= "T3";
data_impl[3] .name= "T4";
data_impl[4] .name= "T5";
for(int t=0; t<NUM_THREADS; t++)
{
int rc = pthread_create(&threads[t], NULL, PrintHello,&data_impl[t]);
}
pthread_exit(NULL);
delete []data_impl;
return 0;
}
其他相關(guān)線(xiàn)程庫(kù):
1.zthread,
2.opentherad
3.boost therad
4.原生態(tài)的平臺(tái)線(xiàn)程函數(shù)
boost是一個(gè)很好的庫(kù)
但是并不是完美的
在使用的時(shí)候需要詳細(xì)注意
std::string tag;
boost::tokenizer<> tok(std::string("貓 狗 豬"));
for(boost::tokenizer<>::iterator beg=tok.begin();beg!=tok.end();++beg)
{
tag += *beg;
tag += "+";
}
std::cout<<tag<<std::endl;
大家說(shuō)說(shuō)結(jié)果吧
1.原DLL分為2個(gè)gcore和device(這樣可以在其他軟件中使用前者)
2.支持xp,vista,win7,linux操作系統(tǒng)
3.支持msvc7.1,8.0,9.0,mingw,bcb,dev++,codeblock編譯器系列
4.提供方便易用的xml序列化框架一個(gè)
5.提供可插式圖形插件接口
6.移除原有的RefPtr對(duì)象改用boost系列智能指針
7.移除原有的Manager對(duì)象
8.修改了filesystem接口
9.在UI中增加了柵格主題,UI工廠,UI_ProgressBar增加了進(jìn)度的顯示
10.粒子系統(tǒng)中增加了粒子工廠
11.移除了原有的Cursor類(lèi)
12.移除線(xiàn)程類(lèi)對(duì)象(改用boost thread.)
13.增加了Helper文件以方便用戶(hù)
14.增加了Sprite2對(duì)象
蓋莫引擎2.3.0算是做完了
不過(guò)這個(gè)做的很不盡人意(不過(guò)沒(méi)關(guān)系咱慢慢做只要堅(jiān)持O(∩_∩)O~)
一個(gè)問(wèn)題就是引擎中的RefPtr設(shè)計(jì)有點(diǎn)問(wèn)題
索性下個(gè)引擎版本就是用boost庫(kù)吧
免得一些基礎(chǔ)需要自己寫(xiě)
要使用boost庫(kù)其中的智能指針必不可少
林林總總有好幾個(gè)類(lèi)型
不過(guò)常用得還是3個(gè)
scoped_ptr,
shared_ptr,
weak_ptr
這里先說(shuō)shared_ptr
它還是引用計(jì)數(shù)類(lèi)型的指針咯
貌似比較好用(但是根本還是在于使用的人)
為了正確使用它需要注意幾個(gè)問(wèn)題
1.多線(xiàn)程環(huán)境和循環(huán)引用
應(yīng)該配合weak_ptr
2.使用了shared_ptr就不應(yīng)該使用其他內(nèi)存管理機(jī)制
3.不要構(gòu)造臨時(shí)的shared_tr作為函數(shù)參數(shù)
4.其他...
摘要: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->【基本介紹】蓋莫音頻引擎SDK1.6.0(類(lèi)似fmod音頻api)原本為蓋莫游戲引擎開(kāi)發(fā)當(dāng)前支持win7,xmp,vista操作系統(tǒng)支持10種音頻格式:mp3,ogg,wav,au,aiff,mod,it...
閱讀全文
接上篇
我們接著說(shuō)UI部分的控件基類(lèi)
控件基類(lèi)應(yīng)該具備的要素
1.按名生成
2.控件尺寸
3.控件大小
4.控件狀態(tài)
5.對(duì)消息事件的處理
6.控件渲染
7.控件檢測(cè)
8.控件文本
然后具體代碼如下:
///////////////////////////////////////////////////////////
/// 定義UI控件基類(lèi)
///////////////////////////////////////////////////////////
class GAPI UI_Widget : public SlotHolder,public UI_EventHandler,public Object
{
public:
typedef std::list<UI_EventListener*> UIEventListener;
typedef std::list<UI_EventListener*>::iterator UIEventListenerItr;
public:
////////////////////////////////////////////////////////
/// 窗體構(gòu)造和析構(gòu)
////////////////////////////////////////////////////////
explicit UI_Widget(UI_Widget* parent = NULL,const engine_wstring& text = L"widget");
virtual ~UI_Widget();
public:
////////////////////////////////////////////////////////
/// 獲取,設(shè)置設(shè)置窗體文本
////////////////////////////////////////////////////////
engine_wstring GetText()const{return text_;}
void SetText(const engine_wstring& text);
public:
////////////////////////////////////////////////////////
/// 窗體大小和尺寸
////////////////////////////////////////////////////////
Size GetSize()const;
void SetSize(const Size& size);
Point GetPosition()const;
void SetPosition(const Point& point);
////////////////////////////////////////////////////////
/// 獲取窗體推薦大小
////////////////////////////////////////////////////////
virtual Size GetRecommendedSize()const;
public:
////////////////////////////////////////////////////////
/// 檢測(cè)給定點(diǎn)下控件
////////////////////////////////////////////////////////
UI_Widget* GetWidgetBelow(int x,int y);
////////////////////////////////////////////////////////
/// 獲取本控件的頂層控件
////////////////////////////////////////////////////////
UI_Widget* GetTopWidget()const;
////////////////////////////////////////////////////////
/// 獲取,設(shè)置父窗體
////////////////////////////////////////////////////////
UI_Widget* GetParentWidget()const;
void SetParentWidget(UI_Widget* parent);
public:
////////////////////////////////////////////////////////
/// 設(shè)置,獲取控件邊框
////////////////////////////////////////////////////////
void SetBorder(const RefPtr<UI_AbstractBorder>& border);
RefPtr<UI_AbstractBorder> GetBorder()const;
////////////////////////////////////////////////////////
/// 設(shè)置,獲取是否渲染邊框
////////////////////////////////////////////////////////
void SetBorderVisible(bool visible);
bool IsBorderVisible();
public:
////////////////////////////////////////////////////////
/// 增加,移除事件消息
////////////////////////////////////////////////////////
void AddEventListener(UI_EventListener* listener);
void RemoveEventListener(UI_EventListener* listener);
////////////////////////////////////////////////////////
/// 消息處理
////////////////////////////////////////////////////////
virtual bool Process(const UI_Event& event);
public:
////////////////////////////////////////////////////////
/// 焦點(diǎn)函數(shù)
////////////////////////////////////////////////////////
bool IsFocusOn()const;
void SetFocusOn(bool focus);
void ChangedFocusOn();
////////////////////////////////////////////////////////
/// 設(shè)置,檢測(cè)是否為活動(dòng)控件
////////////////////////////////////////////////////////
void SetAsActiveWidget();
bool IsActiveWidget()const;
////////////////////////////////////////////////////////
/// 檢測(cè)控件層次關(guān)系
////////////////////////////////////////////////////////
virtual bool DoesHierarchyContain(UI_Widget* widget)const;
public:
////////////////////////////////////////////////////////
/// 顯示,隱藏窗體
////////////////////////////////////////////////////////
void SetVisible(bool visible);
void Show();
void Hide();
bool IsVisible()const;
////////////////////////////////////////////////////////
/// 窗體狀態(tài)函數(shù)
////////////////////////////////////////////////////////
void IsEnable(){enabled_ = true;}
void Disable(){enabled_ = false;}
bool IsEnabled()const{return enabled_;}
public:
////////////////////////////////////////////////////////
/// 窗體渲染
////////////////////////////////////////////////////////
void Render();
////////////////////////////////////////////////////////
/// 當(dāng)窗體關(guān)閉的時(shí)候發(fā)射信號(hào)
////////////////////////////////////////////////////////
Signal0 closed_;
////////////////////////////////////////////////////////
/// 窗體數(shù)據(jù)載入
////////////////////////////////////////////////////////
virtual bool Load(const engine_string& file,const engine_string& widget);
protected:
////////////////////////////////////////////////////////
/// 執(zhí)行函數(shù)
////////////////////////////////////////////////////////
virtual void OnResize(){}
virtual void OnMove(){}
virtual void OnTextChanged(){}
virtual void OnShow(){}
virtual void OnHide(){}
virtual void OnGainedFocus(){}
virtual void OnLostFocus(){}
virtual void OnDraw(){}
private:
UI_Widget* parent_;
UIEventListener message_listeners_;
engine_wstring text_;
Size size_;
Point position_;
bool visible_;
bool enabled_;
RefPtr<UI_AbstractBorder> border_;
bool border_visible_;
private:
DECLARE_OBJECT(UI_Widget)
};
}
#ifdef G_COMPILER_MSVC
#pragma warning(pop)
#endif
需要說(shuō)明的就是這里有3個(gè)父類(lèi)
一個(gè)是Object
一個(gè)是SlotHolder這是消息樁
另外一個(gè)是UI_EventHandler負(fù)責(zé)對(duì)事件的處理
需要說(shuō)明的是UI_Widget總是和UI_WidgetManager配合使用的
畢竟UI上下文最大只能有一個(gè)活動(dòng)控件
接上文:http://www.shnenglu.com/gaimor/archive/2010/09/30/128134.html
本文我們接著說(shuō)UI庫(kù)的消息事件部分:
1.UI基本事件類(lèi)型
基本上就下面幾種:
////////////////////////////////////////////////////////////
/// 枚舉UI消息類(lèi)型
////////////////////////////////////////////////////////////
enum UI_EVENT
{
//! 鼠標(biāo)移動(dòng)
UI_EVENT_MOUSE_MOVE = 0,
//! 鼠標(biāo)點(diǎn)擊
UI_EVENT_MOUSE_CLICK,
//! 鼠標(biāo)進(jìn)入
UI_EVENT_MOUSE_ENTERED,
//! 鼠標(biāo)退出
UI_EVENT_MOUSE_EXITED,
//! 鼠標(biāo)滾輪事件
UI_EVENT_MOUSE_WHEEL,
//! 字符輸入
UI_EVENT_CHAR_INPUT,
//! 鍵盤(pán)按鍵
UI_EVENT_KEY_PRESS,
//! 按鍵退出
UI_EVENT_KEY_RELEASE,
//! 焦點(diǎn)事件
UI_EVENT_LOST_FOCUSE,
UI_EVENT_GAIN_FOCUSE,
//! 滑塊事件
UI_EVENT_SLIDER_MOVE,
//! 編輯事件
UI_EVENT_EDIT,
//! 選擇,反選擇
UI_EVENT_SELECTED,
UI_EVENT_DESELECTED
};
2.
關(guān)于事件一般就3個(gè)相關(guān)對(duì)象:
事件,消息聽(tīng)者和消息處理對(duì)象3個(gè)單元塊:
如下所示:
///////////////////////////////////////////////////////////
/// 定義引擎事件基類(lèi)模板
///////////////////////////////////////////////////////////
template<class EventType = int>
class Event : NonCopyable
{
public:
///////////////////////////////////////////////////////
/// 事件基類(lèi)構(gòu)造函數(shù)
///////////////////////////////////////////////////////
Event(const EventType& type):type_(type){}
////////////////////////////////////////////////////////
/// 事件基類(lèi)析構(gòu)函數(shù)
////////////////////////////////////////////////////////
virtual ~Event(){}
////////////////////////////////////////////////////////
/// 獲取事件類(lèi)型
////////////////////////////////////////////////////////
EventType GetEventType()const{return type_;}
private:
////////////////////////////////////////////////////////
/// 數(shù)據(jù)成員變量
////////////////////////////////////////////////////////
EventType type_;
};
////////////////////////////////////////////////////////////
/// 定義事件聽(tīng)者基類(lèi)
////////////////////////////////////////////////////////////
template<class Event,class Target>
class EventListener
{
public:
////////////////////////////////////////////////////////
/// 事件聽(tīng)者虛析構(gòu)函數(shù)
////////////////////////////////////////////////////////
virtual ~EventListener(){}
////////////////////////////////////////////////////////
/// 消息派送
////////////////////////////////////////////////////////
virtual bool Dispatch(const Event& message,Target object) = 0;
};
////////////////////////////////////////////////////////////
/// 定義事件處理者基類(lèi)
////////////////////////////////////////////////////////////
template<class Event,class EventListener>
class EventHandler
{
public:
////////////////////////////////////////////////////////
/// 事件聽(tīng)者虛析構(gòu)函數(shù)
////////////////////////////////////////////////////////
virtual ~EventHandler(){}
////////////////////////////////////////////////////////
/// 消息處理
////////////////////////////////////////////////////////
virtual bool Process(const Event& message){return false;}
////////////////////////////////////////////////////////
/// 增加,移除事件消息
////////////////////////////////////////////////////////
virtual void AddEventListener(EventListener* listener){}
virtual void RemoveEventListener(EventListener* listener){}
};
然后便是模板實(shí)例:
typedef Event<UI_EVENT> UI_Event;
typedef EventListener<UI_Event,UI_Widget*> UI_EventListener;
typedef EventHandler<UI_Event,UI_EventListener*> UI_EventHandler;
說(shuō)實(shí)話(huà)可以不這樣做而是用boost::function之類(lèi)的函數(shù)綁定
但是沒(méi)法子這樣寫(xiě)我習(xí)慣了 呵呵
2.下面是UI事件的承接部分:
通過(guò)UI管理器承接輸入輸出系統(tǒng)的消息響應(yīng):
{
////////////////////////////////////////////////////////////
/// 蓋莫GUI管理器
////////////////////////////////////////////////////////////
class GAPI UI_WidgetManager : public UI_EventListenerImpl
public:
////////////////////////////////////////////////////////
/// 按鍵處理
////////////////////////////////////////////////////////
bool OnMouseLeftDown(int x,int y);
bool OnMouseLeftUp(int x,int y);
bool OnMouseMiddleDown(int x,int y);
bool OnMouseMiddleUp(int x,int y);
bool OnMouseRightDown(int x,int y);
bool OnMouseRightUp(int x,int y);
bool OnMouseMove(int x,int y);
bool OnChar(wchar_t code);
bool OnKeyDown(int code);
bool OnKeyUp(int code);
bool OnMouseWheel(int z);
public:
3.事件生成:
以上2部分分別是UI事件對(duì)象系列和UI事件輸入部分
下面設(shè)計(jì)UI事件的生成
無(wú)論是鼠標(biāo)還是鍵盤(pán)事件實(shí)際上都相當(dāng)于生成了一個(gè)新的事件
舉例如下:
OnMouseLeftDown(int x,int y)
如果該函數(shù)被調(diào)用
那么就說(shuō)明鼠標(biāo)的左鍵被點(diǎn)擊同時(shí)我們還知道了點(diǎn)擊的位置坐標(biāo)
這樣就生成了一個(gè)UI_MouseClickEvent
對(duì)象
不過(guò)這里需要考慮是鼠標(biāo)雙擊還是單擊
這就要考慮本次點(diǎn)擊和上次點(diǎn)擊的時(shí)間間隔了
這樣就生成了一個(gè)UI鼠標(biāo)事件
那本事件應(yīng)該傳給誰(shuí)?
應(yīng)該是目標(biāo)對(duì)象
直觀一點(diǎn)應(yīng)該是傳給鼠標(biāo)當(dāng)前位置下的控件對(duì)象
但是考慮到實(shí)際情況
這里有一個(gè)聚焦控件和活動(dòng)控件的概念
比如說(shuō)我們打開(kāi)一個(gè)對(duì)話(huà)框(這是一個(gè)聚焦控件)
對(duì)話(huà)框上有1個(gè)按鍵
當(dāng)用戶(hù)點(diǎn)擊本按鍵則消息發(fā)送給這個(gè)按鍵了
但是當(dāng)鼠標(biāo)移出對(duì)話(huà)框之外
一般情況其他控件此時(shí)處于非活動(dòng)狀態(tài)
消息應(yīng)該發(fā)送給聚焦控件
所以這里至少有3各類(lèi)型的控件指針?lè)謩e為:聚焦控件,活動(dòng)控件以及鼠標(biāo)下控件(當(dāng)然他們可以是同一控件)
在這里需要說(shuō)明這三個(gè)控件是這樣切換的
如果發(fā)生特定的uI事件則修改當(dāng)前的聚焦控件等對(duì)象了
4.具體控件對(duì)消息的處理:
生成特定消息,并發(fā)送給相應(yīng)的控件對(duì)象之后那么控件就需要相應(yīng)該消息了:
控件對(duì)象的相關(guān)函數(shù):
///////////////////////////////////////////////////////////
/// 定義UI控件基類(lèi)
///////////////////////////////////////////////////////////
class GAPI UI_Widget : public SlotHolder,public UI_EventHandler,public Object
{
public:
typedef std::list<UI_EventListener*> UIEventListener;
typedef std::list<UI_EventListener*>::iterator UIEventListenerItr;
void RemoveEventListener(UI_EventListener* listener);
////////////////////////////////////////////////////////
/// 消息處理
////////////////////////////////////////////////////////
virtual bool Process(const UI_Event& event)
在這里我們通過(guò)Process函數(shù)來(lái)接受UI管理器傳過(guò)來(lái)的消息對(duì)象.
這里是想要的處理
注意我們并不直接根據(jù)消息響應(yīng)控件的各種狀態(tài)!
而是通過(guò)迭代消息聽(tīng)者鏈表的
如下:
bool UI_Widget::Process(const UI_Event& event)
{
bool ret = false;
if(IsVisible() && IsEnabled())
{
UIEventListenerItr it;
for(it = message_listeners_.begin();it != message_listeners_.end();++it)
{
UI_EventListener* listener = *it;
ret = ret || listener->Dispatch(event,this);
}
//! 處理控件邊框事件
if(border_)
border_->Process(event);
}
return ret;
}
當(dāng)消息傳來(lái)之后我們并不能確定這就是本控件所需要的消息需要驗(yàn)證它
如何驗(yàn)證?
就看當(dāng)前控件是不是可顯示和活動(dòng)的咯
同時(shí)如何控件有邊框?qū)ο笪覀儎t把消息發(fā)給它以改變可能的邊框外觀
下篇:UI設(shè)計(jì)概要4:UI控件對(duì)象
接上文:http://www.shnenglu.com/gaimor/archive/2010/09/27/127900.html
第一篇是關(guān)于UI布局管理器的文章
本文主要說(shuō)說(shuō)引擎UI部分組件的問(wèn)題
在這里UI組件是指UI中的各個(gè)基礎(chǔ)模塊而非UI控件也
在本引擎之中當(dāng)前UI組件有以下幾個(gè)基礎(chǔ)單元
1.UI_Widget UI控件的基類(lèi)
2.UI_AbstractBorder UI控件邊框類(lèi)
3.UI_AbstractLayouter UI布局管理器類(lèi)
4.UI_Event/UI_EventHandler,UI_EventListerner UI事件處理家族
5.UI_Brush UI庫(kù)畫(huà)筆(當(dāng)前基于OpenGL)
6.UI_AbstractTheme UI庫(kù)控件主題
7.UI_ProptyScheme UI庫(kù)主題對(duì)象
8.UI_WidgetManager UI庫(kù)管理器
9.UI_Factory UI庫(kù)工廠對(duì)象
10.其他通用對(duì)象
以上所有對(duì)象構(gòu)成了UI庫(kù)的框架
下面說(shuō)下各個(gè)部分的功能
1.UI_Widget UI基本控件 所有控件的基類(lèi)
2.UI_AbstractBorder 控件控件對(duì)象邊框外觀
3.UI_AbstractTheme 控件主題
以上3著構(gòu)成所見(jiàn)控件外觀
每一個(gè)控件都有一個(gè)主題和邊框?qū)ο?br>所有同質(zhì)控件都采用統(tǒng)一的控件主題以保證統(tǒng)一的外觀
當(dāng)前UI_Border設(shè)計(jì)了2中 一種為線(xiàn)性邊框一種為狀態(tài)邊框
當(dāng)前主題設(shè)計(jì)了3中分別為簡(jiǎn)單主題,位圖主題和矩形主題
UI布局管理器上文已經(jīng)說(shuō)過(guò)當(dāng)前不再贅述
UI事件處理這塊內(nèi)容比較多 下文說(shuō)吧
UI畫(huà)筆的作用是繪制對(duì)象元素比如繪制線(xiàn)條,矩陣設(shè)置顏色等等很簡(jiǎn)單的咯
UI_PertptyShceme是一個(gè)控件主題的集合包含了所有控件類(lèi)型的主題
在渲染控件的時(shí)候調(diào)用對(duì)等的主題繪制控件
控件管理器是UI庫(kù)的中樞
負(fù)責(zé)統(tǒng)一渲染隊(duì)列控件和調(diào)度輸入輸出事件
關(guān)于UI工廠則負(fù)責(zé)按名生成控件指針咯
我一直力圖把UI庫(kù)的實(shí)際簡(jiǎn)單化
但是總是做不到
而且越做越復(fù)雜的
注意當(dāng)前并沒(méi)有涉及腳本,
UI編輯器以及完成所有控件對(duì)象的開(kāi)發(fā)
關(guān)于腳本我想采用得到腳本有l(wèi)ua,anglescrip或者自定義腳本
關(guān)于編輯器我想采用wxwidget or qt
雖然很慢但是我一直在努力 呵呵
下篇:UI設(shè)計(jì)概要3:UI消息
一直想把引擎的UI部分做強(qiáng)做大可是發(fā)現(xiàn)這個(gè)難度還是不小
所以只能一步一步蠶食之
一步一步來(lái)吧
先說(shuō)下控件布局管理器吧
布局管理器的目的是按照一定規(guī)則排列控件于給定范圍內(nèi)
這是其基本目的
很顯然基本的布局管理對(duì)象應(yīng)該包含以下2個(gè)基本功能
1.控件的加入和刪除
2.應(yīng)用布局管理器
當(dāng)然也可以有其他附加功能
比如獲取控件個(gè)數(shù)等等
所以我把抽象控件布局對(duì)象設(shè)計(jì)如下:
///////////////////////////////////////////////////////////
/// 定義引擎UI布局管理器
///////////////////////////////////////////////////////////
class GAPI UI_AbstractLayouter : public Object
{
public:
typedef std::list<UI_Widget*> Widgets;
public:
UI_AbstractLayouter();
virtual ~UI_AbstractLayouter();
public:
////////////////////////////////////////////////////////////
/// 布局管理器加載控件
////////////////////////////////////////////////////////////
void AddWidget(UI_Widget* widget);
////////////////////////////////////////////////////////////
/// 布局管理器移除控件
////////////////////////////////////////////////////////////
void RemoveWidget(UI_Widget* widget);
////////////////////////////////////////////////////////////
/// 布局管理器移除所有子控件
////////////////////////////////////////////////////////////
void RemoveAllWidget();
////////////////////////////////////////////////////////////
/// 布局管理器控件排列
////////////////////////////////////////////////////////////
virtual void ApplyLayouter(UI_Widget* parent) = 0;
protected:
Widgets widgets_;
private:
DECLARE_OBJECT(UI_AbstractLayouter)
};
然后就是具體的幾種布局管理器對(duì)象了
下面是我當(dāng)前弄的4種布局管理器了
分別為:
UI_FlowLayouter
流式布局管理的布局策略是從左到右依次設(shè)定控件位置如果超出父控件則按照設(shè)定的豎直布局換行重新布局(注意它并不改變控件的大小)
UI_GridLayouter
格子布局管理的策略則是工具設(shè)定布局間隔和子控件,父親控件個(gè)數(shù)重寫(xiě)設(shè)置所有的子控件大小(這樣所有的子控件大小就一樣了)然后把所有的子控件放置在一個(gè)一個(gè)的格子中
UI_VLayouter
UI_VLayouter和UI_HLayouter則是我從QT中借鑒來(lái)的
IU_VLayouter把所有子控件按照從上到下的方式依次布局(不改變子控件大小)(可能會(huì)超出父控件喔)
UI_HLayouter
這個(gè)就不說(shuō)了
當(dāng)然還可以定制其他布局管理器了
比如UI_DockLayouter
UI_CenterLayouter等等基本原理都是一樣的
做了游戲引擎這么久說(shuō)實(shí)話(huà)
UI真是一個(gè)大塊頭
對(duì)于UI我的設(shè)計(jì)理念就是使用簡(jiǎn)單,功能豐富
題外話(huà)1:08年11月的時(shí)候我就想設(shè)計(jì)一套UI庫(kù)
之前認(rèn)為游戲UI是使用windows API話(huà)的 呵呵
題外話(huà)2:網(wǎng)上關(guān)于使用一些UI庫(kù)的例子很多但是關(guān)于設(shè)計(jì)UI庫(kù)的例子似乎不多
題外話(huà)3:說(shuō)實(shí)話(huà)我覺(jué)得寫(xiě)博客是交流思想共同探討而非其他