【Ogre编程入门与进阶】第十七章 Ogre3D 和CEGUI 的结合

本文详细介绍了如何将CEGUI与Ogre3D进行结合,从选择合适的GUI库到配置CEGUI环境,再到CEGUI与Ogre3D的整合步骤,包括资源管理、组件创建、XML布局文件的使用,以及CEGUI中文显示的设置。通过实例展示了如何在Ogre3D中创建窗口和按钮,并处理键盘和鼠标事件。最后,文章还探讨了CEGUI中文显示和输入的实现方法,包括字体配置、乱码问题的解决,以及中文输入的改进。
摘要由CSDN通过智能技术生成

17.1 UI库         

        Ogre中提供给我们的二维处理能力还不足以方便我们构建出一套完美的UI界面,而目前很多成熟的GUI库都可以很好的整合到Ogre3D中,这样很大程度上节省了我们定制UI界面的时间,每一种GUI库都有它存在的理由,我们不可能很明确的说那一个最好,或者说哪一个最适合用于Ogre3D中,我们只能根据自己的所求在适当时候选择适合自己所需的GUI库。

         目前存在着很多流行的GUI库,下面我们来简单了解一下:

(1)CEGUI

         CEGUI是一个免费的GUI库,它基于LGPL协议,使用C++实现,采用完全面向对象的方式设计。在作者写这本书期间,CEGUI的版本已经由0.7.5过渡到了0.7.6。CEGUI开发者的目的是希望能够让游戏开发人员从繁琐的GUI实现细节中抽身出来,以便有更多的开发时间可以放在游戏性上。CEGUI也是官方Ogre官方推荐使用的界面库,Ogre1.6及以前的版本都是内置支持的。使用它的商业游戏业非常多,比如天龙八部、火炬之光、仙剑四等。

(2)Ogre SDKTray

         从Ogre1.7开始,Ogre3D就不再内置支持CEGUI了,转而使用Ogre自己的SDKTray,这也是为什么我们使用1.6以前的版本不需要配置CEGUI,而使用1.7之后的版本还需要配置CEGUI环境的原因。SDKTray是在Ogre的Overlay和material的基础上实现的,很容易理解和使用,不过目前来说它还是个半成品,无法应用到商业游戏中。虽然Ogre3D不再内置CEGUI了,不过Ogre3D和CEGUI的整合很简单,这不是我们学习CEGUI的障碍。

(3)QuickGUI

         QuickGUI的最新版本是10.01,专为Ogre3D写的UI库,它被设计一个易于使用、有效且强大的GUI库,QuickGUI的更新速度很快,每个几个月就会发布一个新的版本。

(4)Hikari

         Hikari也是完全免费的,而且允许用户使用目前广泛流行且方便使用的Flash来制作界面,它通过Flash.ocx将swf渲染成Ogre的Texture,然后我们就可以任意操纵这个Texture了。另外,Hikari支持Flash的所有版本,不存在兼容性问题,由于Flash本身就支持多国语言(包括中文),因此使用Hikari来实现中文的显示自然是轻而易举的一件事,不过Hikari效率比较低,而且它使用的是Flash的 ocx,先将动画内容渲染到DC上,然后拷到Texture中,所以很运行速度会比较慢,而且将动画内容渲染到DC上这一步是造成其运行速度比较慢的主要原因,这使得Flash优秀的脏矩形优势无法发挥,根本无法应用到商业游戏中。

(5)Scaleform

        Scaleform跟Hikari有类似之处,都是用Flash来制作游戏界面,不过它的效率要比Hikari高很多,可以说是游戏界面的最强工具了,而且它对亚洲语言显示和输入的支持都堪称完美。据统计,有超过600多款的游戏使用Scaleform制作界面,比如:StarCraft II,Crysis,Fable II,CivilizationIV等。唯一遗憾的是, Scaleform是收费的,且费用很高。

(6)MyGUI

         MyGUI的最新版本是3.2.0,它的优点是:高效、轻便、灵活等;它的缺点是:注释和文档不是很完善,相关资料比较缺乏,效果有时不太理想,目前还没有太多商业游戏使用这个库,但是MyGUI目前越来越受到广大游戏开发者的关注,相信不久后也会有良好的发展。

         了解了这么多UI库,其实就像笔者前面说的,每一种库都有各自的优缺点,我们在选择的时候只有选择适合自己的才是对的,由于我们本书是一本介绍Ogre3D知识的书,所以不可能过多的把重点放到每个GUI的具体讲解上,因为上面我们提到的每一款GUI库都完全可以当做一本书来写,所以如果读者朋友想深入了解某一款GUI,还需多搜集一些它们相关的资料。

         由于Ogre3D和CEGUI的结合已经算是老搭档了,而且CEGUI在各方面的使用不管是从个人还是商业引擎方面都已经比较成熟,学习的人比较多,而且读者朋友在学习的时候遇到麻烦也会有很多热心朋友的帮助,所以本书主要采用CEGUI作为我们的界面库。本章我们主要讲解一些CEGUI的知识,让大家对CEGUI有个逐步的了解,希望在本章结束的时候读者朋友能做出一些比较复杂的界面来。

 

 

17.2 CEGUI环境的配置

        在Ogre中使用CEGUI的第一步当然是需要我们首先配置CEGUI环境。

笔者提示:

CEGUI下载地址:

https://sourceforge.net/projects/crayzedsgui/files/CEGUI%20Mk-2/0.7.5/CEGUI-0.7.5.zip/download

CEGUI依赖库下载地址:

https://sourceforge.net/projects/crayzedsgui/files/CEGUI%20Mk-2%20MSVC%2B%2B%20Dependencies/0.7.x/CEGUI-DEPS-0.7.x-r2-vc9.zip/download

 

        解压CEGUI压缩文件到任意目录,如我们这里:

        然后进行CEGUI依赖库的添加,添加到如下目录:


        然后进入到如下目录:

        用文本编辑器(为了更好的显示,建议用UltraEdit等功能比较强的文本编辑器打开)打开目录下的config.lua,找到下面几行:

        改为:(注意:具体目录根据自己Ogre安装目录确定)

        找到CEGUI_OLD_OIS_API变量,设置为false(我们这里用的这个版本默认已经是false了

        找到OGRE_RENDERER变量,设置为true

        找到SAMPLES_OGRE变量,设置为true

        如下所示:

        保存此文件!

        然后进入目录D:\CEGUI-0.7.5\projects\premake,运行build_vs2008.bat(或对应的其他版本),你将看到CEGUI.sln,继续运行build_samples_vs2008.bat(或对应的其他版本),你将看到CEGUISamples.sln;

        然后向我们以前添加OGRE_HOME环境变量一样,这里我们可以添加一个环境变量CEGUI_HOME用来代替CEGUI根目录。


        打开VS2008,选择菜单栏:工具---选项(当然,我们也可以在每个工程属性页中进行包含路径的添加,具体请参看Ogre环境配置一节)

在  包含文件  一项中,配置CEGUI相关的如下一些路径:

        (1)$(CEGUI_HOME)\cegui\include

        (2)$(CEGUI_HOME)\Samples\common\include

        (3)$(CEGUI_HOME)\dependencies\include

 

        同理,在  库文件  一项中,配置如下:

        (1)$(CEGUI_HOME)\lib

        (2)$(CEGUI_HOME)\dependencies\lib\dynamic


        然后到如下目录(根据自己CEGUI安装目录而定)打开CEGUI.sln选择Debug和Release两种模型,分别编译

编译成功后,再对CEGUI Samples.sln的Debug和Release分别编译,编译成功后,可以查看CEGUI.sln里面的实例,可以选取其中一个工程,点击右键设为启动项目,如下所示:

        然后运行,正常情况下会弹出这样的对话框:解决方法如下:

D:\CEGUI-0.7.5\dependencies\bin(根据自己CEGUI的安装目录决定) 这个目录会看到如下一些文件:

        为了使用方便,可以把这个目录下的所有dll文件拷贝到:D:\CEGUI-0.7.5\bin(根据自己CEGUI的安装目录决定)这个目录下,同时到D:\ogre\ogre_src_v1-7-2\bin\debug和D:\ogre\ogre_src_v1-7-2\bin\release(根据自己Ogre的安装目录决定)两个这个目录下,分别拷贝:OgreMain_d.dll和OIS_d.dll以及OgreMain.dll和OIS.dll,到D:\CEGUI-0.7.5\bin(根据自己CEGUI的安装目录决定)这个目录下,然后再次运行示例工程,可以看到如下启动界面,选择OpenGLRenderer或者DirectX运行:


        到了这里还是会弹出无法运行的对话框,如下:

        我们需要到解决方案一栏全部选择所有工程,点击右键----属性:

        然后选择配置属性----调试:

        在工作目录一栏中选择下拉菜单,选择浏览,找到CEGUI对应的datafiles文件夹:


        点击确定,重新运行,如果按照上述方式,应该可以成功运行了~~~~

        效果如下:

        这样总算是把CEGUI也算是配置好了。

 

 

 

 

 

 

17.2 CEGUI简介及入门

        前面我们已经简单介绍过CEGUI,它的功能是非常强大的,而且使用也非常的灵活,可以和脚本配合。可以通过配置文件自定义窗口外观。通过布局文件实现窗口布局等等特性,使得游戏的界面开发更加方便。另外,和Ogre3D一样,CEGUI的开源特性让我们在开发过程中可以随时查看源代码,更好的了解整个软件的工作流程。

        CEGUI的担当的职责是UI功能,它在软件中提供一些用户界面的组件,如按钮、列表框、文本框、滚动条等等。

        CEGUI设计了许多接口,程序可以通过实现接口来为CEGUI提供服务。比如说渲染接口定义好了以后,就使得CEGUI与具体的渲染平台无关。不管是OpenGL还是Direct3D,无论是Windows还是Linux,只要在那个平台上实现了CEGUI的渲染接口。当然CEGUI库也必须在那个平台下编译才行。

        本章假设你已经编译好了CEGUI库,如果读者还没有成功编译CEGUI,请参照CEGUI配置的相关部分编译配置成功再继续往下学习。好了,下面我们就通过一个例子来看一下如何编写CEGUI程序。

        第一步,我们新建一个Win32控制台应用程序的空项目,名叫CEGUITest(名字任意);

        第二步,新建一个cpp文件,名叫Main(名字任意);

        记得我们在写Ogre3D程序的时候为了方便,我们经常继承一个ExampleApplication的类,CEGUI也一样,为我们提供了一个这样的类,省去了我们不少工作,不过如果读者朋友想一探究竟,看看这个类到底为我们做了一些什么工作的话,就需要查看实现代码了;

        第三步,加入我们需要的头文件:

#include "CEGuiSample.h"

#include "CEGUI.h"

        第四步,加入对应的库文件:CEGUISampleHelper.libCEGUIBase.lib,并设置工作目录为(你的CEGUI根目录)\bin:

 

笔者注:

        如果你在编译程序之前,请确保你正确配置了CEGUI的各个包含目录和库目录,否则会遇到找不到头文件或者其它类似的错误提示,具体配置方法请参看CEGUI配置一节。

 

        第五步,定义一个新的类MyFirstWindowExample,让它继承自CEGuiSample类:

class MyFirstWindowSample : public CEGuiSample

{

        第六步,重新CEGuiSample中的两个方法:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

bool initialiseSample()

{

     using namespace CEGUI;

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

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

     WindowManager& winMgr = WindowManager::getSingleton();

     DefaultWindow* root = (DefaultWindow*)winMgr.createWindow("DefaultWindow","Root");

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

     FrameWindow* wnd = (FrameWindow*)winMgr.createWindow("TaharezLook/FrameWindow","Demo Window");

     root->addChildWindow(wnd);

     wnd->setPosition(UVector2(UDim(0.25f,0),UDim( 0.25f,0)));

     wnd->setSize(UVector2(UDim(0.5f,0),UDim( 0.5f,0)));

     wnd->setText("Hello IMedia!");  

return true;

}

void cleanupSample()

{

}

        第七步,编写main函数:

void main()

{

     MyFirstWindowSample app;

     app.run();

}

        到此,我们的所有工作都做完了,编译并运行我们的程序,你将会看到如下效果:

        选择Direct3D或者OpenGL渲染(不要选择Ogre),你将会看到如下效果:

        代码分析:

        我们可以看到,通过简单的几行代码,我们就可以实现这么棒的效果,其实大部分工作都在CEGuiSample这个类里给我们封装好了。

        不管我们使用的是什么引擎,在使用CEGUI时,至少要做如下所示的最基础的三部,才能使CEGUI运行起来。

        第一步,创建CEGUI::Render对象。这其中会根据我们选择的是OpenGL还是Direct3D或者是Ogre渲染,选择我们最终要使用的渲染选择器,比如说这里我们选择了Direct3D方式渲染,那么在CEGuiSample中会为我们生成一个CEGuiD3D9BaseApplication对象的实例,在这个类的构造函数中会创建对应的Direct3D9Renderer渲染器然后这个实例对象会通过它的一个execute函数反过来调用我们重写的这个initialiseSample函数,这样我们的代码就能被调用到了,初始化工作也就完成了;

        第二步,创建CEGUI::System对象。在一些初始化工作完成之后,CEGUI会调用下面这样的代码来完成System对象的创建:

CEGUI::System&guiSystem =CEGUI::System::getSingleton();

        第三步,调用渲染函数进行渲染。现在我们有了System对象,因此就可以开始进行渲染了,方法很简单,我们可以调用System的renderGUI函数开始我们的渲染,这样我们的程序就真正工作起来了。

        虽然上面仅仅是简单的三步,其实要想是CEGUI真正运作起来还需要一些其它的操作,但是上面三步是一个主要的流程,详细读者朋友理解了这三步,查看源代码的时候就会很容量理解整个流程了。下面我们通过一个简单的流程图再来理一下我们的思路。




17.3 CEGUI中的资源管理及其相应组件的创建

        理解了基本的渲染流程,现在让我们来看一下CEGUI中的资源管理及其相应组件的创建。

17.3.1 资源管理

        CEGUI中用资源组管理器装载一些文件共其在渲染的时候使用,它使用到了一个工具对象,我们把它叫做“ResourceProvider”,此对象提供了一组接口负责CEGUI与其它的文件装载系统通信。例如,我们知道Ogre也有自己的资源管理/文件装载子系统,通过实习特定的ResourceProvider对象,CEGUI的渲染模块就可以和那些子系统无缝的组合起来,那样CEGUI的数据文件就可以通过那些子系统装载了。但是我们知道更底层的库(Direct3D和OpenGL)没有那样的资源管理系统,所以,CEGUI会为它们提供默认的资源管理系统(Default Resource Provider)。

        由于现在我们还没有把CEGUI和Ogre结合,所以我们先来了解一下CEGUI的默认资源管理系统:CEGUI::DefaultResourceProvider,它是为那些目前还没有的库提供基础帮助的系统。它不仅提供了CEGUI装载文件、数据时所需的函数,而且对“资源组(Resource Groups)”也提供了初步的支持。这里的“资源组”其实是一个标签,它代表系统的某个文件夹路径,这就使得我们可以将文件夹中的文件按其逻辑类型进行分组,然后可以通过一个简单的标签而不是硬编码的路径去指定它。也就是说,当数据文件的路径有改动的时候,只需要更新资源组的路径而不必更改代码和XML文件中的路径信息。

        DefaultResourceProvider允许你定义任意数目的资源组,并为每个资源组指定一个路径。也就是说:你可以创建一个资源组,比如“imagesets”,并为它指定一个路径,假设是“datafiles/imagesets”,然后,当你通过ImagesetManager装载Imageset的时候,就可以指定“imagesets”为它将要使用的资源组,这样,系统就会再预定义的路径中寻找资源。目前,每个资源组只能被赋予一个路径。

        这里,我们举一个小例子来说明,以前,如果我们在没使用资源组的时候,你可能这么做:

Imageset* imset = ImagesetManager::getSingleton().createImageset("datafiles/imagesets/TaharezLook.imageset");

 

        用了资源组以后,在初始化阶段,我们可以用默认的资源管理器像下面这样创建资源组:

CEGUI::DefaultResourceProvider*rp =static_cast<CEGUI::DefaultResourceProvider*>(CEGUI::System::getSingleton().getResourceProvider());

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

 

        然后当你需要载入imageset的时候,你可以这样指定要使用的资源组:

Imageset* imset = ImagesetManager::getSingleton().createImageset("TaharezLook.imageset", "imagesets");

 

        这里你不需要提供任何路径信息,因为在你指定的资源组中已经包含了相关的路径信息,一般它们只包含文件名。

        系统定义的任何代表可装载资源的资源类,都有获取和设置默认资源组的静态函数,当需要载入数据文件的时候,它就用那个默认资源组。比如,

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值