您的位置:首页 > 产品设计 > UI/UE

学习CEGUI基本知识

2009-01-09 09:54 260 查看
先来个引子,CEGUI是一个游戏UI库,开源,使用XML作资源定位,支持lua脚本,支持多字节语言的显示,其功能可以说是十分强大的,而且非常灵活,目前的稳定版本是0.5,可见其离发布还有一段距离,bug和未完成的东西都不少,然而这也是它的魅力之一,我们可以对其进行修改和扩充。使用CEGUI完全可以制作出一流水准的游戏UI来。
其次,也是比较主要的,它有几款指定的编辑器,其实UI库都差不多,关键就是看这个东西有没有编辑器,没有编辑器再好的戏也出不来,虽然它的这几个编辑器的bug比它本身还多,呵呵。
在对游戏引擎的支持上,Orge和CEGUI整合得非常好,是Orge的官方指定特约UI库。在更换接口部分之后,CEGUI理论上可以支持所有引擎。
其整个代码实现相当复杂,刚开始会觉得有点乱,但是捋一捋之后就会发现其实还是比较清晰的,只不过是因为其要实现的东西有点多,没办法,代码的复杂度也就上来了。
相关链接:
CEGUI:http://www.cegui.org.uk/
WxWidgets:http://www.wxwidgets.org/
简介
CEGUI(CrazyEddie’sGUIhttp://www.cegui.org.uk)是一个自由免费的GUI库,基于LGPL协议,使用C++实现,完全面向对象设计。CEGUI开发者的目的是希望能够让游戏开发人员从繁琐的GUI实现细节中抽身出来,以便有更多的开发时间可以放在游戏性上。
CEGUI的渲染需要3D图形API的支持,如OpenGL或Direct3D。另外,使用更高级的图形库也是可以的,像是OGRE、Irrlicht和RenderWare,关键需求可以简化为二点:
1.纹理(Texture)的支持
2.直接写屏(RHW的顶点格式、正交投影、或者使用shader实现)
本文截止日时,CEGUI的最新版本是0.4.1(本文的讨论也是基于此版本),提供了SDK和全部源码的下载,同时为了适应不同的使用需求,还根据STL的使用区分为Native(VC自带的P.J.版STL)和STLport(基于SGISTL实现的跨编译器版本,详细见http://www.stlport.org),以及VC6.0、VC7.0、VC7.1和VC8.0几种。
除此之外,CEGUI还同步提供了官方界面编辑器LayoutEditor,以方便UI的制作,下载地址:http://www.2dgame-tutorial.com/d...itorSetup_0.4.1.exe。作为界面编辑器,它需要系统级界面以提供编辑器操作,在此之前的0.3.0版是基于MFC实现的;而在0.4.1版本中,改为基于wxWidgets(跨平台的本地UI框架,这里的UI指Window操作系统底层,如:Windows、Unix和Mac,详见http://www.wxwidgets.org)实现。
OGRE作为目前最活跃的开源3D引擎,许多公司开始使用它进行游戏开发,原因也是其功能非常得全面和强大。在最初,OGRE曾经实现过一版UI,但是最后却放弃自己的实现而选择了CEGUI。

CEGUI的文件结构
CEGUI从根本上说,是由图片支持的,也就是说,这么庞大的系统说白了就是要正确地操作图片,抛弃了原来惯用的ini文件,CEGUI使用了更加先进的xml文件作为其配置文件,使用tga图片,这个是内嵌的,当然如果有需要,可以使用其它解码器。其文件结构很简单,共定义了四种格式的xml文件:scheme,looknfeel,imageset和layout。在CEGUI给的例子当中,其组织形式是这样的。
datafiles
schemes
looknfeel
imageset
layout
这样可以基本保证文件井然有序,建议就用这个结构,在你的游戏工程资源目录下增加这么一个datafiles文件夹。
这里首先介绍一下这几种文件的作用。
Scheme,它是CEGUI首先调用的一个文件,内容包括要使用的imageset文件、所对应的looknfeel文件,以及将要在looknfeel定义的控件的类型、工厂、渲染器和在looknfeel中的名字。
Looknfeel。它定义了控件的细节,我觉得在CEGUI自己给的那个例子looknfeel(TaharezLook)中写的就不错,很多时候可以模仿它来写。
Imageset,这个东西很简单,就是要把tga图片上的位置信息记录下来,位置信息由左上角横纵坐标,长宽信息组成。
另外,在Imageset文件夹下,还存放tga图片。
以上就是CEGUI的文件结构,多数情况下是不用动它的。

你的第一个CEGUI程序

强烈建议仔细研究CEGUISample程序!因为那里介绍了它的一些基本用法,其实最后在游戏当中出现的,也就是这些例子的变化而已。
这里我会引导你写一个第一个自己的简单的CEGUI程序,它使用CEGUISampleHelper提供的框架,使用OpenGL渲染。
这是在CEGUI自己给的Sample程序基础上简化、简化、再简化得出的,目的是让大家对CEGUI程序有一个简单明了的认识,其实就是这么简单。里面只定义了一个背景,一个静态文本,写着“Hello!CEGUI”。
具体的,有几块重要的东西。有一些包含在框架里了,如下:
DefaultResourceProvider,这个是CEGUI的一个全局的东西,可以在任何地方操作它的指针,但是一般只需要在一开始操作它。
在CEGuiOpenGLBaseApplication当中,你可以看见下面这样的代码,这就是在使用DefaultResourceProvider的指针在设置资源的路径,你可以毫不客气地复制粘贴到你的工程里

CEGUI::DefaultResourceProvider*rp=static_cast<CEGUI::DefaultResourceProvider*>

(CEGUI::System::getSingleton().getResourceProvider());

rp->setResourceGroupDirectory("schemes","../datafiles/schemes/");

rp->setResourceGroupDirectory("imagesets","../datafiles/imagesets/");

rp->setResourceGroupDirectory("fonts","../datafiles/fonts/");

rp->setResourceGroupDirectory("layouts","../datafiles/layouts/");

rp->setResourceGroupDirectory("looknfeels","../datafiles/looknfeel/");

rp->setResourceGroupDirectory("lua_scripts","../datafiles/lua_scripts/");

下面是整个的代码:

#ifndef_TDemo0_h_

#define_TDemo0_h_

#include"CEGuiSample.h"

#include"CEGUI.h"

//例子类

classTDemo0Sample:publicCEGuiSample

...{

public:

//用于实现初始化的方法

boolinitialiseSample();

//关闭

voidcleanupSample(void);

};

#endif//_TDemo0_h_

#include"TDemo0.h"

#include"CEGUI.h"

#include"CEGuiBaseApplication.h"

#include<cstdlib>

/**//*************************************************************************

程序入口

*************************************************************************/

intmain(intargc,char*argv[])

...{

TDemo0Sampleapp;

returnapp.run();

}

/**//*************************************************************************

实现初始化方法

*************************************************************************/

boolTDemo0Sample::initialiseSample()

...{

usingnamespaceCEGUI;

//得到窗口管理器

WindowManager&winMgr=WindowManager::getSingleton();

//装载资源,只说一下scheme就行,其它的system自己去调

SchemeManager::getSingleton().loadScheme("TaharezLook.scheme");

//鼠标指针很特殊,但是其实是一样的用法

System::getSingleton().setDefaultMouseCursor("TaharezLook","MouseArrow");

//字体

FontManager::getSingleton().createFont("Commonwealth-10.font");

//这里创建了一个window。第一个参数指定了这个window的类型,第二个参数是名字。

Window*background=winMgr.createWindow("TaharezLook/StaticImage","background_wnd");

//设置位置和大小

background->setPosition(UVector2(cegui_reldim(0),cegui_reldim(0)));

background->setSize(UVector2(cegui_reldim(1),cegui_reldim(1)));

//这就要把刚才那个background用作最底层的窗口了

System::getSingleton().setGUISheet(background);

//其实这个在这里没啥用,我认为,只是多了一层窗口。在任何UI系统当中所有的窗口都是一样的。

Window*sheet=winMgr.createWindow("DefaultWindow","root_wnd");

//叠加上

background->addChildWindow(sheet);

//又创建了一个窗口,这回是一个静态的文本

Window*st=winMgr.createWindow("TaharezLook/StaticText","TextWindow/Static");

sheet->addChildWindow(st);

st->setPosition(UVector2(cegui_reldim(0.45f),cegui_reldim(0.23f)));

st->setSize(UVector2(cegui_reldim(0.15f),cegui_reldim(0.05f)));

st->setText("Hello!CEGUI");

returntrue;

}

/**//*************************************************************************

*************************************************************************/

voidTDemo0Sample::cleanupSample()

...{

//啥事也不做

}

好了,现在可以新建一个工程,模仿其它例子的工程结构,然后用这个代码,编译,就OK了。
这就是(或者几乎是一个)最简单的CEGUI程序,其实就是这么简单。

在CEGUI中使用layout文件(1)

CEGUI支持两种方式的资源使用,一种就是在前文可见的直接在c++文件当中创建窗体,使用窗体;另一种方式就是在layout文件当中定制窗体。从理论上讲,两种方式都能达到相同的目的。
在不使用layout文件时,CEGUI是不太方便的,因为要定位控件,常常得修改文件当中的参数,如果在c++文件当中修改,每次都编译,很恶心(尤其是在有编辑器的情况下,使用c++就不能使用了)。
所以如果你要使用CEGUI,对layout文件的使用和编辑都是必修课。
下面这个就是一个简单的使用layout文件的例子,作的仅仅是把文件读进来、显示在窗口里了。

#include"TDemo1.h"#include"CEGUI.h"#include"CEGuiBaseApplication.h"#include<cstdlib>intmain(intargc,char*argv[])...{TDemo1app;returnapp.run();}/**//**************************************************************************************************************************************************/boolTDemo1::initialiseSample()...{usingnamespaceCEGUI;//窗体管理器WindowManager&winMgr=WindowManager::getSingleton();//载入资源SchemeManager::getSingleton().loadScheme("TaharezLook.scheme");System::getSingleton().setDefaultMouseCursor("TaharezLook","MouseArrow");FontManager::getSingleton().createFont("Commonwealth-10.font");//在此载入layout文件//这个就是要在实际当中经常使用的Window*sheet=winMgr.loadWindowLayout("TDemo1.layout");System::getSingleton().setGUISheet(sheet);returntrue;}/**//**************************************************************************************************************************************************/voidTDemo1::cleanupSample()...{//啥也不做}
TDemo1.layout
<?xmlversion="1.0"encoding="UTF-8"?><GUILayout><WindowType="DefaultWindow"Name="root"><PropertyName="UnifiedMaxSize"Value="{{1,0},{1,0}}"/><PropertyName="UnifiedAreaRect"Value="{{0,0},{0,0},{1,0},{1,0}}"/><WindowType="TaharezLook/FrameWindow"Name="TDemo1/Window1"><PropertyName="Text"Value="TDemo1"/><PropertyName="UnifiedMaxSize"Value="{{0.8,0},{0.8,0}}"/><PropertyName="UnifiedMinSize"Value="{{0.2,0},{0.2,0}}"/><PropertyName="UnifiedAreaRect"Value="{{0.4,0},{0.1,0},{0.9,0},{0.7,0}}"/><PropertyName="CloseButtonEnabled"Value="False"/></Window></Window></GUILayout>
在CEGUI中使用layout文件(2)
前文中我讲解了在CEGUI中最简单的layout文件的使用方法。写好layout文件,是把CEGUI用好的一个关键。
在没有编辑器的情况下,任何引擎的UI系统,或者单独的UI系统,都是比较难用的,(有时,有没有编辑器,甚至是评价一个引擎好坏的标准之一)。
幸运的是,CEGUI提供了这方面的支持,它的官方网站提供了一个编辑器(CELayoutEditor),虽然下载下来弄一下,你会发现它基本上是危险重重,难以使用,但是有,总比没有好,写一个编辑器的工作量是不小的。
将CELayoutEditor
的工程下载下来,仿照CEGUI的目录形式配置一下这个工程,即,将工程文件放到makefiles/premake/Tools/CELayoutEditor下,将源代码放在Tools/CELayoutEditor目录下,并配置相应的路径。
这个编辑器是使用wxWidgets作的框架,所以你还得下载wxWidgets,看一下你下载的CELayoutEditor需要的wx版本,然后选一个正确的下载。推荐学习一下wxWidgets,这个UI库很好,并且更新的速度很快,况且将来可能用它制作其他的编辑器框架。
编译通过之后,运行exe文件。这个时候需要选择工作路径,选择与bin文件夹同级的那个datafiles文件夹,这时,所用的文件都是这个文件夹所包含的,在对CELayoutEditor进行修改的过程中,可能经常由于选择这个文件夹错误而发生错误,此时删除Tools/bin文件夹下的CELayoutEditor.ini文件,重新选择,就OK了。
然后,就进入了CELayoutEditor的主界面,它是由一个对话框和一个Frame组成的。试着使用一下这个编辑器,它支持支持一般的windows界面编辑器的大部分鼠标操作,因此,如果没有大的问题,它是可以很好的使用的。
下面就是对其进行改进了,这个在此就不一一细说了。首先就是让他不那么容易崩溃,其次就是一些细节问题,可以结合着测试部门的测试对其进行改造。
在CEGUI中使用layout文件(3)

打开任意一个layout文件,可见其为一个树形结构,父子窗体的组织结构比较清晰。

<?xmlversion="1.0"encoding="UTF-8"?>
<GUILayout>
<WindowType="type1"Name="window1">
<WindowType="type2"Name="window1">
</Window>
</Window>
</GUILayout>


由于使用的是TinyXML作的xml解析器,其是基于DOM的,所以正合适。

注意文件当中的Propertytag,这个是layout的重点,通过设定这个东西,CEGUI就活起来了。
<PropertyName="Font"Value="SimHei-12"/>
先写Name,再写Value。
如果想在游戏中使用你编辑的layout文件,那么就不是单个文件这么简单了。
由于CEGUI当中的窗体名称是一个全局的向量,所以不能有同名的窗体,这样,命名规则就成了一个问题,当游戏制作到了大规模的UI制作阶段,这个问题尤为明显。

我的经验是如下的规则:

规则1Layout文件命名
layout文件以场景形式组织,每个layout文件对应一个场景下的UI,文件名为场景的英文名称,首字母大写,如SampleScene.layout。

规则2顶级控件命名&设定
layout文件内部使用Root_场景英文名的defaultWindow作为根窗口(顶级窗口),如示例场景的UI使用Root_SampleScence作为根窗口。顶级窗口大小为整个显示屏幕大小。

规则3次级控件命名
Root窗口下一级UI控件使用场景英文名+控件实际用途方式命名,如示例场景下的背景图片命名为SampleSceneBackground。

规则4其它控件命名
次级以下控件使用 上一级控件名/控件自身控件名 的方式进行命名,如示例场景下的退出按钮命名为SampleSceneBackground/Quit。
规则5UI控件命名
UI控件命名规则为UI控件名含义+控件类型(可选),如设置按钮可命名为SampleSceneBackground/Settings 或者SampleSceneBackground/SettingsButton。

这样一来,只要文件名不同,就保证了UI控件没有重名了。

CEImagesetEditor

除了CELayoutEditor之外,CEGUI官方还提供了一个切图工具,即CEImagesetEditor。这个工具十分有用,减轻了美术很多的负担,它可以生成imageset文件,并可以以鼠标操作图片框。
从CEGUI的0.4版本开始,这个工具就开始提供了。但是那个版本几乎就不能用,有许多问题,如,其右边的工作区居然没有滚动条!另外,它的图片框一旦面积大的把面积小的覆盖之后,面积小的就点不到了。还有许多莫名其妙的崩溃问题。
其实,解决这些问题并不困难,大家发挥一下自己的聪明才智,一定能修改出符合自己项目需要的编辑器,毕竟人家把这个框子搭好了,几千行的代码也不是那么容易写的。
这个编辑器还是使用wxWidgets,配置工程同前文提到的LayoutEditor。
0.5版本的ImagesetEditor编辑器在功能上有所改观,但是问题还是不少。同样,在正式使用之前,需要大家修改和完善它。
在使用ImgesetEditor方面,由于它完成的功能较为简单,因此其使用没有LayoutEditor那么多的说法,只要给切好的图的名字写好就ok了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: