Irrlicht学习备忘录——5 UserInterface

5 UserInterface

官方代码($sdk)\examples\05.UserInterface

Irrlicht学习备忘录——5 UserInterface_第1张图片

这个例子是讲irr引擎的用户图形界面。里面只演示了窗口、按钮、滚动条、静态字体和列表框这几样常用的图形界面元素,其实这已经是irr用户图形界面的大部分内容了。irr用户图形界面,个人认为是鸡肋。用它,它太难看了,想要让它好看,得自己写扩展,这基本等于用irr的接口规范自己从新做一遍用户图形界面的基本元素。不用,得自己重新找一套GUI来和irr结合,使用起来不一定有irr原生的那么简单。下面看具体如何使用irrGUI

使用GUI一般都会产生一些用户反馈的交互信息,这些信息就是GUI事件。要想对这些GUI事件进行处理,首先就得获取这些事件。获取GUI事件最简单的方法就是上一个例子里用到的事件接收器,事件接收器所接收的事件就包括GUI事件,只是上个例子里没有使用而已。本例里同样自定义了一个MyEventReceiver事件接收器,只是这次的OnEvent方法里处理的事件换成了EET_GUI_EVENT事件。接收到的GUI事件是以SGUIEvent数据结构存储的。

structSGUIEvent

{

产生GUI事件的GUI元素Caller

gui::IGUIElement*Caller;

Caller一起产生事件的GUI元素,一般不用

gui::IGUIElement*Element;

GUI事件的类型

gui::EGUI_EVENT_TYPEEventType;

};

GUI事件类型定义在EGUI_EVENT_TYPE枚举里

enumEGUI_EVENT_TYPE

{

失去焦点

EGET_ELEMENT_FOCUS_LOST= 0,

获得焦点

EGET_ELEMENT_FOCUSED,

光标停留在GUI元素上

EGET_ELEMENT_HOVERED,

光标离开元素

EGET_ELEMENT_LEFT,

元素关闭

EGET_ELEMENT_CLOSED,

按钮被点击

EGET_BUTTON_CLICKED,

滚动条被移动

EGET_SCROLL_BAR_CHANGED,

复选框发生变化

EGET_CHECKBOX_CHANGED,

列表框发生变化

EGET_LISTBOX_CHANGED,

列表框被再次选择

EGET_LISTBOX_SELECTED_AGAIN,

文件被选择

EGET_FILE_SELECTED,

目录被选择

EGET_DIRECTORY_SELECTED,

文件对话框选择取消

EGET_FILE_CHOOSE_DIALOG_CANCELLED,

消息框YES被按下

EGET_MESSAGEBOX_YES,

消息框NO被按下

EGET_MESSAGEBOX_NO,

消息框OK被按下

EGET_MESSAGEBOX_OK,

消息框取消被按下

EGET_MESSAGEBOX_CANCEL,

文本编辑框里按下回车键

EGET_EDITBOX_ENTER,

文本编辑框内容改变

EGET_EDITBOX_CHANGED,

文本编辑框标记区域改变

EGET_EDITBOX_MARKING_CHANGED,

TAB键控着元素改变

EGET_TAB_CHANGED,

菜单项被选中

EGET_MENU_ITEM_SELECTED,

组合框改变

EGET_COMBO_BOX_CHANGED,

旋转框改变

EGET_SPINBOX_CHANGED,

表格改变

EGET_TABLE_CHANGED,

表格头改变

EGET_TABLE_HEADER_CHANGED,

表格被再次选中

EGET_TABLE_SELECTED_AGAIN,

观察树节点失去选择

EGET_TREEVIEW_NODE_DESELECT,

观察树节点被选中

EGET_TREEVIEW_NODE_SELECT,

观察树节点被展开

EGET_TREEVIEW_NODE_EXPAND,

观察树节点被收拢

EGET_TREEVIEW_NODE_COLLAPSE,

EGET_TREEVIEW_NODE_COLLAPS= EGET_TREEVIEW_NODE_COLLAPSE,

GUI事件总数

EGET_COUNT

};

GUI事件的数据结构可以看出,GUI事件很简单,通过区分GUI事件类型,可以很轻易的筛选出自己关心的GUI事件,再从产生GUI事件的Caller,就可以明确这个事件是不是自己关心的元素产生的。

例子里因为使用的GUI元素较少,同时为了使例子看似去更加简单明了,它为GUI元素设定了几个固定ID,如:GUI_ID_QUIT_BUTTONGUI_ID_NEW_WINDOW_BUTTONGUI_ID_FILE_OPEN_BUTTONGUI_ID_TRANSPARENCY_SCROLL_BAR。这样就不必用全局变量或其他的方法保存动态生成的GUI元素的指针用来筛选是不是自己关注的元素,直接通过CallerID就可以区分出来。但这方法也有缺点,如果GUI是在程序外通过配置文件配置的,不同功能的GUI很有可能使用了相同的ID,这样会导致错误。

创建GUI元素的方法,在《HelloWorld!》例子里已经出现过。首先就是IGUIEnvironment*env =device->getGUIEnvironment(),通过irr设备获取GUI环境;然后再通过GUI环境的addXXXX方法添加不同的GUI元素。

GUI的字体设置,这也是个重要问题。在例子里字体设置部分如下:

获取环境GUI的默认皮肤

IGUISkin*skin = env->getSkin();

读取一个外部字体库

IGUIFont*font = env->getFont("../../media/fonthaettenschweiler.bmp");

将该外部设为默认皮肤的字体

if(font)

skin->setFont(font);

设置提示文字的字体为内嵌的标准字体

skin->setFont(env->getBuiltInFont(),EGDF_TOOLTIP);

但这方法只适合英文,如果要使用其他的文字,得对irr进行文字的扩展,这种载入一张图片作为字库的方法肯定是不行的。

在例子中,还有设置GUI透明度的方法。这部分在自定义的MyEventReceiver类的OnEvent方法中。捕获到EGET_SCROLL_BAR_CHANGED事件后,如下操作。

获取滚动条的位置,将该位置作为设置GUI透明度的参数

s32pos = ((IGUIScrollBar*)event.GUIEvent.Caller)->getPos();

对皮肤里每一种颜色重设透明度

for(u32 i=0; i<EGDC_COUNT ; ++i)

{

获取皮肤的第i个颜色

SColorcol = env->getSkin()->getColor((EGUI_DEFAULT_COLOR)i);

设置颜色的透明度

col.setAlpha(pos);

设置皮肤的第i个颜色

env->getSkin()->setColor((EGUI_DEFAULT_COLOR)i,col);

}

irr里还可以自己扩展IGUIElement,创建出引擎没有的GUI元素,在IGUIElementOnEvent方法里,可以直接从消息循环里直接获取GUI事件,对自己扩展的GUI元素里的子元素事件直接进行相应的处理,不必通过事件接收器处理。如果嫌irrGUI实在难看的话,可以在自己扩展的元素里,用重载draw方法,写一个更漂亮的GUI元素出来。不过这种重载draw方法来使GUI更漂亮的方法也有致命缺陷,就是不能灵活的设计出自己想要的界面,总不能对每一次的一小点需求变化都来进行一次draw的重载吧!如果要强行解决irr界面的美观和灵活性,这就不再是对irr扩展了,而是需要对irr进行改造了。

你可能感兴趣的:(游戏,游戏引擎,游戏编程,3D引擎,Irrlicht)