CEGUI学习
澹台展鹏
2023-12-01
先来个引子,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(Crazy Eddie’s GUI http://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(基于SGI STL实现的跨编译器版本,详细见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::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" // 例子类 class TDemo0Sample : public CEGuiSample ...{ public: // 用于实现初始化的方法 bool initialiseSample(); // 关闭 void cleanupSample(void); }; #endif //_TDemo0_h_ #include "TDemo0.h" #include "CEGUI.h" #include "CEGuiBaseApplication.h" #include
/**//************************************************************************* 程序入口 *************************************************************************/ int main(int argc, char *argv[]) ...{ TDemo0Sample app; return app.run(); } /**//************************************************************************* 实现初始化方法 *************************************************************************/ bool TDemo0Sample::initialiseSample() ...{ using namespace CEGUI; // 得到窗口管理器 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"); return true; } /**//************************************************************************* *************************************************************************/ void TDemo0Sample::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
int main(int argc, char *argv[])...{ TDemo1 app; return app.run();}/**//**************************************************************************************************************************************************/bool TDemo1::initialiseSample()...{ using namespace CEGUI; // 窗体管理器 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); return true;}/**//**************************************************************************************************************************************************/void TDemo1::cleanupSample()...{ // 啥也不做 } TDemo1.layout
在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文件,可见其为一个树形结构,父子窗体的组织结构比较清晰。
由于使用的是TinyXML作的xml解析器,其是基于DOM的,所以正合适。注意文件当中的Property tag,这个是layout的重点,通过设定这个东西,CEGUI就活起来了。
先写Name,再写Value。如果想在游戏中使用你编辑的layout文件,那么就不是单个文件这么简单了。由于CEGUI当中的窗体名称是一个全局的向量,所以不能有同名的窗体,这样,命名规则就成了一个问题,当游戏制作到了大规模的UI制作阶段,这个问题尤为明显。 我的经验是如下的规则: 规则1 Layout文件命名 layout文件以场景形式组织,每个layout文件对应一个场景下的UI,文件名为场景的英文名称,首字母大写,如SampleScene.layout。 规则2 顶级控件命名&设定 layout文件内部使用Root_场景英文名的defaultWindow作为根窗口(顶级窗口),如示例场景的UI使用Root_SampleScence作为根窗口。顶级窗口大小为整个显示屏幕大小。 规则3 次级控件命名 Root窗口下一级UI控件使用 场景英文名+控件实际用途方式命名,如示例场景下的背景图片命名为SampleSceneBackground。 规则4 其它控件命名 次级以下控件使用 上一级控件名/控件自身控件名 的方式进行命名,如示例场景下的退出按钮命名为 SampleSceneBackground/Quit。 规则5 UI控件命名 UI控件命名规则为 UI控件名含义+控件类型(可选),如设置按钮可命名为SampleSceneBackground/Settings 或者SampleSceneBackground/SettingsButton。 这样一来,只要文件名不同,就保证了UI控件没有重名了。 CEImagesetEditor 除了CELayoutEditor之外,CEGUI官方还提供了一个切图工具,即CEImagesetEditor。这个工具十分有用,减轻了美术很多的负担,它可以生成imageset文件,并可以以鼠标操作图片框。 从CEGUI的0.4版本开始,这个工具就开始提供了。但是那个版本几乎就不能用,有许多问题,如,其右边的工作区居然没有滚动条!另外,它的图片框一旦面积大的把面积小的覆盖之后,面积小的就点不到了。还有许多莫名其妙的崩溃问题。 其实,解决这些问题并不困难,大家发挥一下自己的聪明才智,一定能修改出符合自己项目需要的编辑器,毕竟人家把这个框子搭好了,几千行的代码也不是那么容易写的。 这个编辑器还是使用wxWidgets,配置工程同前文提到的LayoutEditor。 0.5版本的ImagesetEditor编辑器在功能上有所改观,但是问题还是不少。同样,在正式使用之前,需要大家修改和完善它。 在使用ImgesetEditor方面,由于它完成的功能较为简单,因此其使用没有LayoutEditor那么多的说法,只要给切好的图的名字写好就ok了。 本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/bluekane/archive/2009/01/09/3738689.aspx