根據我對msvc系列和mingw編譯器的了解
具體差異如下:
1.在編譯源文件過程中,2者對涉及的相關頭文件有所不同
比如:
#ifdef G_MSVC
#include <GEngine/Template/Vector.hpp>
#endif
這是蓋莫引擎中math.hpp包含的頭文件
其中有一個函數:
////////////////////////////////////////////////////////
/// 給定差量t(0<=t<=1)獲取線性插值點p(0) = p1,p(1) = p2
////////////////////////////////////////////////////////
template<class T>
static Vector3<T> GetPoint(const Vector3<T> &from,const Vector3<T> &to,float t);
在編譯的Math的時候MinGW需要先"編譯"Vector文件
2.2者在處理函數返回值上的不同
比如:
int GetValue()
{
}
msvc需要顯式的給定函數返回值
而mingw不需要(具有默認值)
3.對待函數參數的不同
比如
template<class T>
void Add(T a,T a);
4.基本數據結構類型有所不同
5.在獲取原始數據上的區別如下:
const int MAXINT = std::numeric_limits<int>::max;
const double MAXDOUBLE = (std::numeric_limits<double>::max)();
6.其他請大家補充吧
摘要: 這是最新設計的蓋莫音頻音頻(API)(c++)(1.5.5)當前提供一個簡易版本的播放器(使用了Skinse界面庫)界面如下:當前提供的功能如下:蓋莫音頻API1.5.5 功能更為強勁蓋莫音頻引擎(API) 是使用標準c++寫的音頻播放軟件支持devc++,codeblock,vc6,vc7.1,vc8.,vc9編譯器平臺支持xp,vista,win7 當前支持ogg,mp3,wav,au,aif...
閱讀全文
這是剛改動的蓋莫游戲引擎-UI小圖
可以看出
好看了很多
具體的做法就是每一個控件對象都有一個對于的渲染描述符
包含控件邊框和控件背景
當然只有改動控件的描述配置就可以改變控件的外觀了(典型的裝飾器啊)
具體小圖如下:

1.

下一步我并不打算加入更多的控件(控件很多?)
還是先做做UI編輯器吧
提高一下生產率吧
本著簡單,易用的設計原則
我給蓋莫引擎加入了一個簡單的插件系統
插件基類如下:
class Plugin : public virtual RefCount
{
public:
virtual ~Plugin(){}
virtual PLUGIN_FORMAT GetFormat()const = 0;
virtual engine_string GetMaker()const = 0;
virtual engine_string GetDescription()const = 0;
virtual void GetVersion(int &main,int &sub,int &pitch) = 0;
private:
virtual bool Init(void* data) = 0;
virtual void Deinit(void* data) = 0;
friend class PluginFactory;
};
可以看出基本的插件方法有獲取插件格式,插件作者,插件描述,插件版本等
下面的是簡單的插件工廠
////////////////////////////////////////////////////////////
/// 定義引擎插件工廠(管理器)
////////////////////////////////////////////////////////////
class GAPI PluginFactory : public Singleton<PluginFactory>
{
public:
bool RegisterPlugin(Plugin* plugin);
void UnRegisterPlugin(Plugin* plugin);
};
這是一個簡單的單件
它只有2個函數注冊和反注冊插件
使用的時候只要獲取插件指針
然后傳入插件工廠注冊之后即可使用
(注冊的本質就是根據插件類型設置必要的插件上下文數據)
這種插件方法有它的弊端 不過在我看來最大的好處就是簡單咯
下面是簡單的視頻播放插件咯
////////////////////////////////////////////////////////////
/// 定義引擎視頻播放器(全局唯一)
////////////////////////////////////////////////////////////
class VideoPlayer : public Plugin
{
public:
///////////////////////////////////////////////////////
/// 構造,析構視頻播放器
///////////////////////////////////////////////////////
VideoPlayer(){}
virtual ~VideoPlayer(){}
///////////////////////////////////////////////////////
/// 播放指定視頻
///////////////////////////////////////////////////////
virtual bool Play(const engine_string& video) = 0;
///////////////////////////////////////////////////////
/// 視頻更新每幀調用
///////////////////////////////////////////////////////
virtual bool Update() = 0;
///////////////////////////////////////////////////////
/// 停止并卸載視頻
///////////////////////////////////////////////////////
virtual void Stop() = 0;
///////////////////////////////////////////////////////
/// 獲取,設置視頻當前音量(0-1)
///////////////////////////////////////////////////////
virtual float GetVolume()const = 0;
virtual void SetVolume(float volume) = 0;
};
1.先說下Ui的input部分
在GUI部分輸入輸出通常是需要采用回調函數來處理的
比如:
void G_CALL MousePosCallBack(int x,int y)
{
UIWidgetManager::Instance().OnMouseMove(x, y);
}
所以我就先給引擎的Input部分加入了幾個輸入輸出回調函數以方便使用
2.然后上幾個UI小圖

當鼠標劃過按鈕時:
.

相關的代碼:
void RenderGUI();

RefPtr<Device> device;
RefPtr<Input> input;
Panel *panel = NULL;
ProgressBar *progressbar = NULL;
Button *button1 = NULL;
Button *button2 = NULL;
Button *button3 = NULL;
Button *button4 = NULL;
void G_CALL MouseStateCallBack(int mouse,int action)


{
int x,y;
input->GetMousePosition(x,y);
if(action == KEY_PRESS && mouse == MOUSE_BUTTON_LEFT)

{
UIWidgetManager::Instance().OnLeftButtonDown(x,y);
}
else if(action == KEY_PRESS && mouse == MOUSE_BUTTON_RIGHT)

{
UIWidgetManager::Instance().OnRightButtonDown(x,y);
}
else if(action == KEY_RELEASE && mouse == MOUSE_BUTTON_LEFT)

{
UIWidgetManager::Instance().OnLeftButtonUp(x,y);
}
else if(action == KEY_RELEASE && mouse == MOUSE_BUTTON_RIGHT)

{
UIWidgetManager::Instance().OnRightButtonUp(x,y);
}
}

void G_CALL MousePosCallBack(int x,int y)


{
UIWidgetManager::Instance().OnMouseMove(x, y);
}
bool G_CALL IsShiftPressed()


{
return false;
}

bool G_CALL IsAltPressed()


{
return false;
}

bool G_CALL IsCtrlPressed()


{
return false;
}

void SettingPanel();

int main()


{
device = InitDevice("UI測試1");
input = device->GetInput();
input->AttachMouseState(&MouseStateCallBack);
input->AttachMousePos(&MousePosCallBack);
core::TextDesc::SetDefaultFont(engine_string("simhei.ttf"));
UIWidgetManager::Instance().Initialize(&IsShiftPressed,&IsAltPressed,&IsCtrlPressed);
UIWidgetManager::Instance().AppResized(640,480);
SettingPanel();
BEGIN_LOOP(device)
glClearColor(0.1,0.1,0.2,1.0f);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
RenderGUI();
END_LOOP(device)
return 0;
}

void SettingPanel()


{
panel = new Panel(Rectf(10,75,180,180),NULL);
button1 = new Button(panel,L"寮€濮嬫父鎴?);
button2 = new Button(panel,L"淇濆瓨娓告垙");
button3 = new Button(panel,L"杞藉叆娓告垙");
button4 = new Button(panel,L"閫€鍑烘父鎴?);
progressbar = new ProgressBar(panel,Rectf(150,90,40,220),UI_DIRECTION_VERTICAL);
progressbar->SetPercentage(65.0f);
panel->AddChildWidget(button1);
panel->AddChildWidget(button2);
panel->AddChildWidget(button3);
panel->AddChildWidget(button4);
panel->AddChildWidget(progressbar);
button1->SetSize(Vector2f(120,40));
button2->SetSize(Vector2f(120,40));
button3->SetSize(Vector2f(120,40));
button4->SetSize(Vector2f(120,40));
button1->SetPosition(Vector2f(20,90));
button2->SetPosition(Vector2f(20,150));
button3->SetPosition(Vector2f(20,210));
button4->SetPosition(Vector2f(20,270));
UIWidgetManager::Instance().AddWidget(panel);
}

void RenderGUI()


{
float precent = progressbar->GetPercentage();
precent += 1.0f;
if(precent >= 100.0f)
precent = 0.0f;
progressbar->SetPercentage(precent);
UIWidgetManager::Instance().Update();
}



對于UI部分基本上所有的常見器件都需要一個一個設計
一次性做完太難了
而且設計的不好就需要重新設計
所以我決定先設計以下幾個器件 Widget,Panel,StaticText,SliderBar
其余的等把基本框架做成熟了再做吧
當前引擎基本框架功能都已經完備了
接下來的開發將不再強調功能上的大而全
想強調精致,易用性
將優先考慮虛擬仿真上的易用喔
當前在做引擎的GUI部分
設計的的首要原則是先做出來,如果有什么問題以后再改
當然GUI消息事件是這樣設計的
事件和聽者是2個模板
///////////////////////////////////////////////////////////
/// 定義引擎事件基類模板
///////////////////////////////////////////////////////////
template<class EventType = int>
class Event : NonCopyable
{
public:
///////////////////////////////////////////////////////
/// 事件基類構造函數
///////////////////////////////////////////////////////
Event(const EventType& type):type_(type){}
////////////////////////////////////////////////////////
/// 事件基類析構函數
////////////////////////////////////////////////////////
virtual ~Event(){}
////////////////////////////////////////////////////////
/// 獲取事件類型
////////////////////////////////////////////////////////
EventType GetEventType()const{return type_;}
private:
////////////////////////////////////////////////////////
/// 數據成員變量
////////////////////////////////////////////////////////
EventType type_;
};
////////////////////////////////////////////////////////////
/// 定義事件聽者基類
////////////////////////////////////////////////////////////
template<class Event,class Object>
class EventListener
{
public:
////////////////////////////////////////////////////////
/// 事件聽者虛析構函數
////////////////////////////////////////////////////////
virtual ~EventListener(){}
////////////////////////////////////////////////////////
/// 消息派送
////////////////////////////////////////////////////////
virtual bool Dispatch(const Event& message,Object* object) = 0;
};
可以看出這并不屬于GUI部分
在GUI中有
typedef Event<UI_EVENT> UIEvent;
typedef EventListener<UIEvent,Widget> UIEventListener;
每一個控件可能都需要處理消息
所以控件有一個函數
////////////////////////////////////////////////////////
/// 消息處理
////////////////////////////////////////////////////////
virtual bool Process(const UIEvent& event);
來響應消息事件
基本的GUI事件有2類 一個是鼠標事件 一個是按鍵事件
所有有2個對象
class KeyEvent
class MouseEvent
對于鼠標還有幾個派生的對象比如雙擊事件等
控件需要處理UI事件那么在GUI的某個部分需要生成UI事件
當然事件的生產在UIWidgetManager中
啟用管理器的事件載入Input指針參數
然后不斷檢查鼠標和按鍵狀態生成相關事件然后傳遞給相關控件
我認為GUI設計有點難度
但是相對來說GUI編輯器應該更難
小注:理想的編輯器應該是這樣
通過編輯器生成控件配置文件(比如xml)
使用的時候只需要調用配置文件動態生成對等的控件,當然包含事件處理嘍
最后上一個半成品的圖圖

(cppblog似乎對firefox兼容不好?)
下一篇說控件Surface和Border部分
也許你在使用c++的時候會出現問題:has no member named '...'
意思就是類沒有成員變量XXA
實際上類是具有成員變量XX的
問題的原因在于工程中定義的變量和系統頭文件定義的宏沖突所致
解決方案有2個
1.
#ifdef XXX
#undef XXX
#endif
2.包含對象定義所在頭文件于調用系統頭文件之前.
這里的XXX在具體情況中可能為GetObject,LoadImage等等
GUI系統 布局管理器
1.布局管理器存在的理由:可以避免手動或者逐個調整控件位置
2.布局管理器的基本功能:調整同一容器下同一層次下各個控件的位置
3.布局管理器的基本接口:
A.控件加入
B.控件移除
C.控件排列
4.布局管理器和控件的關系
A.一個布局管理器負責1個或則多個控件的排列
B.具有控件容器語義的控件(例如面板)持有一個布局管理器
5.合適調用布局管理之布局?
A.持有的控件尺寸變化,移動或者用戶顯示的調用之時
6.可能的布局管理器類型
A>流式,中央布局,盒子,復雜類型,...
7.簡單的布局管理器接口
///////////////////////////////////////////////////////////
/// UI布局信息基類
///////////////////////////////////////////////////////////
class UILayoutInfo
{
public:
UILayoutInfo(){}
virtual ~UILayoutInfo(){}
public:
virtual engine_string GetLayouttType()const = 0;
};
///////////////////////////////////////////////////////////
/// 定義UI布局管理器基類
///////////////////////////////////////////////////////////
class UILayouter
{
public:
UILayouter(){}
virtual ~UILayouter(){}
public:
////////////////////////////////////////////////////////
/// 增加一個窗體到布局管理區
////////////////////////////////////////////////////////
virtual UILayouter& AddWidget(Widget* widget) = 0;
virtual UILayouter& AddWidget(Widget* widget,const UILayoutInfo&)
{
AddWidget(widget);
return *this;
}
////////////////////////////////////////////////////////
/// 控件移除和重新排列
////////////////////////////////////////////////////////
virtual UILayouter& RemoveWidget(Widget* widget) = 0;
virtual UILayouter& Arrange(Widget* parent) = 0;
};
所有類型的布局管理器都需要繼承于UILayouter
其成員函數Arrange負責調配parent控件下的所有控件單元.
需要說明的是當容器控件加入一個新的控件的時候,其布局管理器就會調用AddWidget負責把新的控件加入布局管理器對象
舉一個UI面板的例子:
////////////////////////////////////////////////////////////
/// UI面板(容器)
////////////////////////////////////////////////////////////
class G_DLL_API Panel : public Widget
{
public:
Panel(const Rectf& rect,Widget* parent,const engine_string& text = "Panel");
virtual ~Panel();
public:
////////////////////////////////////////////////////////
/// 加入一個子窗體
////////////////////////////////////////////////////////
Panel& AddChildWidget(Widget* widget)
{
windows_.push_back(widget);
layouter_->AddWidget(widget);
return *this;
}
Panel& AddChildWidget(Widget* widget,const UILayoutInfo& info)
{
windows_.push_back(widget);
layouter_->AddWidget(widget,info);
return *this;
}
////////////////////////////////////////////////////////
/// 控件移除
////////////////////////////////////////////////////////
Panel& RemoveChildWidget(Widget* widget)
{
windows_.remove(widget);
layouter_->RemoveWidget(widget);
return *this;
}
////////////////////////////////////////////////////////
/// 控件排列
////////////////////////////////////////////////////////
Panel& ArrangeChildren()
{
layouter_->Arrange(this);
return *this;
}
////////////////////////////////////////////////////////
/// 加載布局管理器
////////////////////////////////////////////////////////
Panel& SetLayouter(UILayouter* layouter);
在我設計的時候主要參考了2個GUI庫,glooey,opengl gui lib
目前商業上使用的開源CEGUI過于復雜 比很多游戲引擎都大 讓人難以容忍
引擎之GUI將會是當前引擎開發的當務之急(做完這個我想使用引擎做游戲)
那么GUI屆時將提供那里功能和特點呢?
如下:
1.可以使用腳本(當前為xml配置GUI屬性)
2.統一的GUI畫面風格
3.配備專有的GUI編輯器
4.盡可能的和引擎保持獨立以便讓第三方使用和學習
5.必要的控件裝飾器和布局管理器設計以增強UI設計的便利
6.使用信號插槽處理消息(似乎都是這樣做的)
7.應該最少支持vc9,devc++2個編譯器
7.做完之后的風格表現應該不遜于下圖:

使用xml配置之后變成了;

另外一組圖面:

2.

GUI庫網上很多
但是我覺得還是自己弄一個比較好
附注L:去年我設計了半個GUI庫后面放棄了問題太多嘍