当前位置: 首页 > 工具软件 > CEGUI > 使用案例 >

学习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的指针在设置资源的路径,你可以毫不客气地复制粘贴到你的工程里
  1. CEGUI::DefaultResourceProvider* rp = static_cast<CEGUI::DefaultResourceProvider*>
  2.         (CEGUI::System::getSingleton().getResourceProvider());
  3.     rp->setResourceGroupDirectory("schemes""../datafiles/schemes/");
  4.     rp->setResourceGroupDirectory("imagesets""../datafiles/imagesets/");
  5.     rp->setResourceGroupDirectory("fonts""../datafiles/fonts/");
  6.     rp->setResourceGroupDirectory("layouts""../datafiles/layouts/");
  7.     rp->setResourceGroupDirectory("looknfeels""../datafiles/looknfeel/");
  8.     rp->setResourceGroupDirectory("lua_scripts""../datafiles/lua_scripts/");
下面是整个的代码:
  1. #ifndef _TDemo0_h_
  2. #define _TDemo0_h_
  3. #include "CEGuiSample.h"
  4. #include "CEGUI.h"
  5. // 例子类
  6. class TDemo0Sample : public CEGuiSample
  7. ...{
  8. public:
  9.     // 用于实现初始化的方法
  10.     bool initialiseSample();
  11.     // 关闭
  12.     void cleanupSample(void);   
  13. };
  14. #endif //_TDemo0_h_
  15. #include "TDemo0.h"
  16. #include "CEGUI.h"
  17. #include "CEGuiBaseApplication.h"
  18. #include <cstdlib>
  19. /**//*************************************************************************
  20.     程序入口
  21. *************************************************************************/
  22. int main(int argc, char *argv[])
  23. ...{
  24.     TDemo0Sample app;
  25.     return app.run();
  26. }
  27. /**//*************************************************************************
  28.     实现初始化方法
  29. *************************************************************************/
  30. bool TDemo0Sample::initialiseSample()
  31. ...{
  32.     using namespace CEGUI;
  33.     // 得到窗口管理器
  34.     WindowManager& winMgr = WindowManager::getSingleton();
  35.     // 装载资源,只说一下scheme就行,其它的system自己去调
  36.     SchemeManager::getSingleton().loadScheme("TaharezLook.scheme");
  37.     // 鼠标指针很特殊,但是其实是一样的用法
  38.     System::getSingleton().setDefaultMouseCursor("TaharezLook""MouseArrow");
  39.     // 字体
  40.     FontManager::getSingleton().createFont("Commonwealth-10.font");
  41.     // 这里创建了一个window。第一个参数指定了这个window的类型,第二个参数是名字。
  42.     Window* background = winMgr.createWindow("TaharezLook/StaticImage""background_wnd");
  43.     
  44.     // 设置位置和大小
  45.     background->setPosition(UVector2(cegui_reldim(0), cegui_reldim( 0)));
  46.     background->setSize(UVector2(cegui_reldim(1), cegui_reldim( 1)));
  47.     // 这就要把刚才那个background用作最底层的窗口了
  48.     System::getSingleton().setGUISheet(background);
  49.     // 其实这个在这里没啥用,我认为,只是多了一层窗口。在任何UI系统当中所有的窗口都是一样的。
  50.     Window* sheet = winMgr.createWindow("DefaultWindow""root_wnd");
  51.     // 叠加上
  52.     background->addChildWindow(sheet);
  53.     // 又创建了一个窗口,这回是一个静态的文本
  54.     Window* st = winMgr.createWindow("TaharezLook/StaticText""TextWindow/Static");
  55.     sheet->addChildWindow(st);
  56.     st->setPosition(UVector2(cegui_reldim(0.45f), cegui_reldim( 0.23f)));
  57.     st->setSize(UVector2(cegui_reldim(0.15f), cegui_reldim( 0.05f)));
  58.     st->setText("Hello!CEGUI");
  59.    
  60.     return true;
  61. }
  62. /**//*************************************************************************
  63. *************************************************************************/
  64. void TDemo0Sample::cleanupSample()
  65. ...{
  66.     // 啥事也不做
  67. }

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

 

  1. #include "TDemo1.h"
  2. #include "CEGUI.h"
  3. #include "CEGuiBaseApplication.h"
  4. #include <cstdlib>
  5. int main(int argc, char *argv[])
  6. ...{
  7.     TDemo1 app;
  8.     return app.run();
  9. }
  10. /**//*************************************************************************
  11. *************************************************************************/
  12. bool TDemo1::initialiseSample()
  13. ...{
  14.     using namespace CEGUI;
  15.     // 窗体管理器
  16.     WindowManager& winMgr = WindowManager::getSingleton();
  17.     // 载入资源
  18.     SchemeManager::getSingleton().loadScheme("TaharezLook.scheme");
  19.     System::getSingleton().setDefaultMouseCursor("TaharezLook", "MouseArrow");
  20.     FontManager::getSingleton().createFont("Commonwealth-10.font");
  21.     // 在此载入layout文件
  22.     // 这个就是要在实际当中经常使用的
  23.     Window* sheet = winMgr.loadWindowLayout("TDemo1.layout");
  24.     System::getSingleton().setGUISheet(sheet);
  25.     return true;
  26. }
  27. /**//*************************************************************************
  28. *************************************************************************/
  29. void TDemo1::cleanupSample()
  30. ...{
  31.     // 啥也不做
  32. }

 

 

TDemo1.layout

 

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <GUILayout>
  3.     <Window Type="DefaultWindow" Name="root">
  4.         <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
  5.         <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />        
  6.         <Window Type="TaharezLook/FrameWindow" Name="TDemo1/Window1" >
  7.             <Property Name="Text" Value="TDemo 1" />
  8.             <Property Name="UnifiedMaxSize" Value="{{0.8,0},{0.8,0}}" />
  9.             <Property Name="UnifiedMinSize" Value="{{0.2,0},{0.2,0}}" />
  10.             <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.1,0},{0.9,0},{0.7,0}}" />
  11.             <Property Name="CloseButtonEnabled" Value="False" />          
  12.         </Window>
  13.     </Window>
  14. </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文件,可见其为一个树形结构,父子窗体的组织结构比较清晰。
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <GUILayout >
  3.     <Window Type="type1" Name="window1" >
  4.               <Window Type="type2" Name=" window1" >
  5.         </Window>
  6.     </Window>
  7. </GUILayout>
 
由于使用的是TinyXML作的xml解析器,其是基于DOM的,所以正合适。

注意文件当中的Property tag,这个是layout的重点,通过设定这个东西,CEGUI就活起来了。
<Property Name="Font" Value="SimHei-12" />
先写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了。
 
 
 
 类似资料: