CEGUI初级入门.docx
《CEGUI初级入门.docx》由会员分享,可在线阅读,更多相关《CEGUI初级入门.docx(14页珍藏版)》请在冰豆网上搜索。
CEGUI初级入门
CEGUI初级入门
CEGUI初级入门
一CEGUI渲染入门
不管你用的是什么引擎,至少要做如下所示最基础的三步,才能使CEGUI运行起来。
1.创建CEGUI:
:
Renderer对象。
2.创建CEGUI:
:
System对象。
3.调用渲染函数。
当然,真正实现游戏GUI,你还需要装载相关的数据文件、进行一些最基础的初始化(这在装载数据文件和初始化入门一文中进行讲解),你也需要处理用户输入(这在输入处理入门一文中进行讲解)。
1.创建CEGUI:
:
Renderer对象
这一步相当直观,对于所支持的渲染组件(比如:
Direct3D9,OpenGL,Ogre3D等),这步应该没有问题。
当然,要记得包含所使用渲染组件的头文件。
还有,Ogre3D现在已经将它的渲染组件改为Ogre而不是CEGUI。
(切记:
在程序结束的时候,要删除此Renderder对象)创建CEGUI:
:
Renderer对象代码如下:
Ogre3D:
CEGUI:
:
OgreCEGUIRenderer*myRenderer=
newCEGUI:
:
OgreCEGUIRenderer(myRenderWindow);
2.创建CEGUI:
:
System对象来对系统进行初始化
这一步更简单。
只需new一个CEGUI:
:
System对象,并把刚创建的CEGUI:
:
Renderer对象的指针传送给它即可。
这时整个系统将自动初始化。
newCEGUI:
:
System(myRenderer);
3.调用渲染函数
这一步有点特殊,所使用的引擎不同,此步的代码也会不同。
不过,说白了,你所要做的只是在每帧渲染后调用CEGUI:
:
System:
:
renderGUI而已。
使用Ogre3D的同学该高兴了,因为它将由Ogre3D自动完成。
二资源管理入门
如果你已经读了CEGUI渲染入门这篇文章,你已经知道:
要想让CEGUI跑起来,至少要对CEGUI进行最基础的初始化,并调用System:
:
renderGUI方法,这看起来很不错。
可是,你仍然不能让程序画任何东西!
为了达到胜利的彼岸,下一步是设置资源管理器组(resourceprovidergroups),我们将用它们装载一些文件供CEGUI在渲染的时候使用。
ResourceProvider是什么?
CEGUI使用了一个工具对象,我们叫它“ResourceProvider”。
此对象提供了一组接口负责CEGUI与其他的文件装载系统通信。
例如:
Ogre和Irrlicht都有它们自己的资源管理/文件装载子系统,通过实现特定的ResourceProvider对象,CEGUI的渲染模块就可以和那些子系统无缝的组合起来。
那样,CEGUI的数据文件就可以通过那些子系统装载了。
但是,更底层的库(Direct3D和OpenGL)没有那样的资源管理系统,所以,CEGUI为它们提供了默认资源管理系统(defaultresourceprovider)。
DefaultResourceProvider相关说明
CEGUI:
:
DefaultResourceProvider----CEGUI的默认资源管理系统,是为那些目前还没有的库提供基础帮助的系统。
它不仅提供了CEGUI装载文件、数据时所需的函数,而且对“资源组(resourcegroups)”也提供了初步的支持。
这里的“资源组”其实是一个标签,它代表系统的某个文件夹路径。
这就使得我们可以将文件夹中的文件按其逻辑类型进行分组,然后可以通过一个简单的标签而不是硬编码的路径去指定它。
也就是说:
当数据文件的路径有改动的时候,只需更新资源组的路径而不必更改代码和XML文件中的路径信息。
指定资源组和路径
DefaultResourceProvider允许你定义任意数目的资源组,并为每个资源组指定一个路径。
也就是说:
你可以创建一个资源组,比如“imagesets”,并为它指定一个路径,假设是
“./mygame/datafiles/gui/imagesets/”。
然后,当你通过ImagesetManager装载Imageset的时候,就可以指定“imagesets”为它将要使用的资源组,这样,系统就会在预定义的路径中寻找资源。
目前,每个资源组只能被赋予一个路径。
下面给一个小例子来说明。
以前,在没用资源组的时候,你可能这么做:
Imageset*wlis=ImagesetManager:
:
getSingleton().createImageset(
用了资源组以后,在初始化阶段,你可以用默认的资源管理器像这样创建资源组:
DefaultResourceProvider*rp=static_cast(
CEGUI:
:
System:
:
getSingleton().getResourceProvider());
rp->setResourceGroupDirectory(
然后,当你需要载入imageset的时候,你可以这样指定要使用的资源组:
Imageset*wlis=ImagesetManager:
:
getSingleton().createImageset(
注意:
你不需要提供任何路径信息,因为在你指定的资源组中已经包含了相关的路径信息。
比如上面例子中的
另一个需要注意的是:
数据文件不应该包含任何的相对路径信息,一般它们只需包含文件名。
默认资源组
系统定义的任何代表可装载资源的资源类,都有获取和设置默认资源组的静态函数。
当需要载入数据文件的时候,它就用那个默认资源组。
比如:
对于Imageset类,默认的资源组应该指向一个存储imagesetxml文件和材质文件的文件夹。
对于每个资源类,它们获取、设置资源组的静态函数的名字都是一样的(xerces是个例外,下面会解释):
constString&getDefaultResourceGroup();
voidsetDefaultResourceGroup(constString&groupname);
如下是资源类的一个列表,后面是它们各自管理的资源类型:
CEGUI:
:
Imageset-Imagesetxmlandtextureimagefiles.
CEGUI:
:
Font-Fontxmlandttffontfiles.
CEGUI:
:
Scheme-Schemexmlfiles.
CEGUI:
:
WindowManager-Windowlayoutxmlfiles.
CEGUI:
:
WidgetLookManager-LookNFeelxmlfiles
CEGUI:
:
ScriptModule-Scriptfilesinwhicheverscriptedlangauge.
上面提到过,xerces是个例外,它是“基于Xerces-C的XML解释器(Xerces-CbasedXMLparser)”。
对此,有一个特殊的资源组设置文件,它指明schema文件在哪里(它们是用来检查xml的.xsd文件)。
对于这个特殊情况,它的静态成员如下:
constString&XercesParser:
:
getSchemaDefaultResourceGroup();
voidXercesParser:
:
setSchemaDefaultResourceGroup(constString&
groupname);
需要注意的最后一点是:
资源管理类也有一个默认的资源组。
当一个资源类没有显示指定资源组的时候,系统就使用它。
当你把所有的数据文件都放到一个文件夹里的时候,这点就很方便了。
一个完整的例子:
配置DefaultResourceProvider
作为结尾,我将用一个完整的例子向你展示CEGUI的例子框架是怎样初始化资源组、初始化它们的目标路径以及怎样为所有的资源类型设置默认资源组的。
像往常一样初始化CEGUI:
:
System对象,我们设置一组资源组和它们的路径:
//为DefaultResourceProvider设置所需的路径
CEGUI:
:
DefaultResourceProvider*rp=static_cast
(CEGUI:
:
System:
:
getSingleton().getResourceProvider());
rp->setResourceGroupDirectory(
rp->setResourceGroupDirectory(
rp->setResourceGroupDirectory(
rp->setResourceGroupDirectory(
rp->setResourceGroupDirectory(
//这步仅当你使用Xerces作为XML解析器的时候才需要
rp->setResourceGroupDirectory(
完成这步以后,我们就把资源组和它们的路径都设置好了。
最后,为了让系统使用新设置的路径,我们来设置默认资源组:
//设置默认资源组
CEGUI:
:
Imageset:
:
setDefaultResourceGroup(
CEGUI:
:
Font:
:
setDefaultResourceGroup(
CEGUI:
:
Scheme:
:
setDefaultResourceGroup(
CEGUI:
:
WidgetLookManager:
:
setDefaultResourceGroup(
CEGUI:
:
WindowManager:
:
setDefaultResourceGroup(
CEGUI:
:
ScriptModule:
:
setDefaultResourceGroup(
//仅当你用xerces做XML解析器,并为它定义了一个资源组的时候使用
CEGUI:
:
XercesParser:
:
setSchemaDefaultResourceGroup(
三装载数据文件和初始化入门
Ok。
目前你已经学习了CEGUI渲染入门和资源管理入门,下一步就要开始学习装载数据文件了。
只有装载了相关数据文件,CEGUI才会产生想要的输出!
CEGUI使用多种类型的数据文件。
刚开始学的时候,可能搞不清:
它们是什么,它们之间怎样联系以及它们怎样被载入。
所以,我决定先介绍一下这些数据文件:
它们是什么,它们将被用来干什么以及它们是如何被载入CEGUI的。
XML,XSD?
都是XML!
CEGUI所使用的数据文件绝大多数都是XML格式的,除了那些特殊的图片文件(.tag等)以及可载入模块文件(DLL等)。
说到这里大家可能会想到那个特殊的.xsd文件。
尽管现在CEGUI的默认XML解析库是ExpatXML解析库,可是CEGUI以前一直用Xerces-C++库作为它的默认XML解析库,CrazyEddies本人也更喜欢这个库。
这个库的优势是它提供模式验证(schemavalidation)。
通过模式验证,我们可以在解析期间检测输入的文件是否包含需要的数据以及数据是否被正确的设置。
系统需要一些额外的文件才能做这个,它们就是以.xsd作为后缀的模式文件--CEGUI的模式文件存放在cegui_mk2/XMLRefSchema/目录下。
目前,对于.xsd文件,你只需知道:
当把Xerce-C++用作XML解析器的时候,必须让ResourceProvider系统能够找到它们。
要做到这点很简单,只需设置一个资源组,把此资源组关联到一个包含相关.xsd文件的文件夹,并把这个资源组设置为CEGUI:
:
XercesParser装载.xsd文件时所使用的默认资源组。
(相关方法参看资源管理入门)
数据文件正如前面提到的,CEGUI所用的数据文件除了少数的特殊情况外都是XML格式的。
但是,为了清晰的说明数据文件代表什么类型的资源,数据文件并不是以“.xml”作为后缀,而是用更有意义的后缀名。
比如,Imageset的后缀名是.imageset,Font的后缀名是.font,等等。
下面将对每种文件类型做个简要的说明,以后将对它们进行更深入的讨论。
Imageset这么说吧,通常,为了提到效率,我们需要把材质等图片组合成一个大的材质图片。
在使用的时候就需要在它上面截取得到各个小材质。
而这个Imageset就是保存各个小材质在整张源图片上的区域信息(源图片同样在Imageset中指定了)。
每个区域信息都有一个独一无二的名字,当提到它们的名字的时候,系统就把它们当作图片处理。
所以,也可以说Imageset中定义了一系列的图片。
通过修改Imageset中的源图片名、各个小区域的位置和大小,就可以很轻松的改变所画GUI的外观。
Font显而易见,Font文件定义了CEGUI使用的字体。
所能定义的字体类型有两种:
FreeTypeFont这是一种基于true-type(.ttf)的字体文件。
从CEGUI0.5.0开始,在.font文件中用Type=
PixmapFont这种字体就是众所周知的位图字体,这种字体基于一个定义了文字图片的Imageset。
从CEGUI0.5.0开始,在.font文件中用Type=
SchemeScheme文件是把其他数据文件联系到一起的主要手段,同时它也是装载和定义各种控件最方便的方法。
一个Scheme文件可以包含下面的一种或多种文件(当Scheme被载入的时候,它所包含的文件也将被载入并初始化):
Imageset(eitherafullImagesetviaXML,orasingleimageviaanimagefile)FontWindowSetWindowRendererSetWindowAlias
FalagardMapping
ImagesetandFont已经被提到过了。
这列出来仅仅为了说明scheme可以包含它们。
WindowSet主要用来指明一个可载入模块(.dll,.so等)的名字,并列出它所使用的控件中你想注册的控件的名字。
如果没有列出任何控件名,那么模块中所有的控件都将被注册。
WindowRendererSet指明一个可载入模块(.dll等)的名字,并列出它所使用的窗口渲染器(windowrenderer)中你想注册的窗口渲染器的名字。
如果没有列出任何窗口渲染器名,那么模块中所有的窗口渲染器都将被注册。
“窗口渲染器”是一个可以控制基本窗口类型渲染的东西。
所有的窗口渲染器都是利用'Falagard'蒙皮系统进行渲染的(尽管这不是非常必须的)。
WindowAlias提供通过别名指定一个窗口/控件类型的方法。
用此方法,也可以用另一个控件类型来“替代”一个已经注册的控件类型,这样就达到隐藏已注册控件的效果。
FalagardMapping用来创建一个可用的WindowType类型。
包含三个部分:
TargetType---指定基类(具有相关功能);Renderer---指定窗口渲染器(可以控制渲染指定的TargetType);LookNFeel---指定要使用的皮肤(一般这个它们是通过XML格式的looknfeel文件指定)。
LayoutLayout文件用XML描述一个窗口的布局。
每个镶嵌的“Window”元素定义一个要创建的窗口或控件,“Property”元素为每个定义的窗口设置相关属性。
ConfigCEGUI支持使用配置文件。
这个文件允许你定义一些默认参数,比如:
默认载入的Scheme,默认载入的Layout,初始化和终止脚本文件(ScriptModule中使用),以及其他没有提到的东西。
载入基本的文件
为了成功显示GUI,你需要载入一些文件。
至少要载入下面这些:
Imageset
Scheme
值得高兴的是,Scheme文件能自动的载入其他两个文件。
介于本教程,我们将载入一个
scheme文件和一个font文件---scheme文件自动帮我们载入一个Imageset文件。
代码如下:
//载入scheme文件,它将自动载入TaharezLookimageset
CEGUI:
:
SchemeManager:
:
getSingleton().loadScheme(
//载入font文件。
第一个被载入的字体文件将自动成为默认字体。
if(!
CEGUI:
:
FontManager:
:
getSingleton().isFontPresent(
CEGUI:
:
FontManager:
:
getSingleton().createFont(
上面的代码假设资源组以及默认资源组都按照资源管理入门中描述的方法设置完了。
简单的默认设置
最后,你需要设置一些默认值。
这么做是为了确保系统总是有可用的字体和鼠标指针,以防某个窗口或控件没有特别设置它自己的字体和鼠标指针。
实际上,我们不再需要指定一个默认字体,因为FontManager会自动的设置第一个被载入的字体为默认字体。
如果它不是你想要的默认字体,你可以设置为其他的。
设置的代码如下:
System:
:
getSingleton().setDefaultFont(
另一个你需要设置默认值的是鼠标指针。
这么做是为了确保当鼠标位于那些没有设置指针的控件上时不至于消失。
设置默认鼠标指针的代码如下(本示例使用由上面的scheme载入的TaharezLookimageset):
System:
:
getSingleton().setDefaultMouseCursor(
如果你打算用工具提示,则需要指明你想用的基于ToolTip的控件类型名。
尽管通常情况下是不需要这么做的,这也超出了这个基础教程的范围,其实可以在每个窗口基础上设置它。
设置工具提示窗口类型代码如下:
System:
:
getSingleton().setDefaultToolTip(
目前,我们已经讨论了关于CEGUI所用的数据文件最基础的东西:
它们是什么,它们是怎样被载入的,以及最少要做的初始化工作。
以后将要对每种数据文件类型做深入的讨论,发掘关于它们更高级的用法。
四创建CEGUI窗口入门
本课将讲述如何创建并显示一个简单的CEGUI窗口。
在继续之前,请确保你已经通读并完全理解了前面的几篇教程:
CEGUI渲染入门,资源管理入门和装载数据文件和初始化入门。
这非常重要,因为本教程是建立在那些教程的基础之上的。
概念介绍:
窗口和控件
在进行教程之前,你必须了解一些重要的概念。
所有的控件都是窗口这是最重要的概念。
所有的控件类都是从Window这个基类派生出来的,所以,在此教程中,每当我提到一个窗口的时候,它可以是一个按钮也可以是一个滚动条控件。
很多的设置都会被继承下去CEGUI中,窗口的很多的设置和属性都会按窗口父子等级向下传递。
比如:
如果你将一个窗口的alpha透明度设置为0.5,那么,默认情况下,所有附属于那
个窗口的子窗口/组件都将受到影响。
同时要注意:
子窗口的实际设置并没有改变----最终的属性值通常是由最顶层到当前窗口所有属性值组合而成的。
好多东西都有这个规律,比如窗口的销毁:
默认情况下,一个窗口在销毁的时候将销毁它的所有子窗口。
这一机制最大的优点是:
通过改变根窗口的alpha透明度、显示/隐藏、激活/禁用状态等可以很轻易的控制整个GUI;通过简单的销毁根窗口就可以轻松的清空整个GUI。
当个别窗口需要更精确的控制或有更好的管理技术用的时候,可以更改这一默认继承机制。
聊够了!
我们开始吧。
有两种方法来创建窗口:
通过C++硬编码实现和通过XML布局文件实现。
下面将讨论这两种方法。
通过C++硬编码实现GUICEGUI的所有窗口都是被WindowManager这一对象创建的。
你可以通过getSingleton函数获得这个对象,代码如下:
usingnamespaceCEGUI;WindowManager&wmgr=WindowManager:
:
getSingleton();
一般情况,你将用DefaultWindow(或者它的老名字:
DefaultGUISheet)作为GUI的“root”窗口。
这点并不是必须的,但它是使用CEGUI很好的习惯,而且可以帮助简化布局。
下一步,我们将创建一个DefaultWindow作为GUI的根窗口(这里sheet是root的意思)。
Window*myRoot=wmgr.createWindow(
System:
:
getSingleton().setGUISheet(myRoot);
WindowManager:
:
createWindow函数有两个string类型的参数。
第一个参数,本例中为“DefaultWindow”,告诉系统你要创建的窗口类型或类。
通常,你可以使用的窗口类型是那些当你载入scheme文件的时候注册的窗口类。
而有些像DefaultWindow这样的是全局类型,它们总是可用的。
第二个参数,本例中为“root”,是一个将要赋予这个窗口的独一无二的名字。
以后可以通过这个名字获取指向这个窗口的指针。
注意:
并不是一定要给你的根窗口命名为“root”,但这是通常的命名约定。
System:
:
setGUISheet函数用来指定一个窗口作为GUI的根窗口。
这将替换掉当前的根窗口,但是要注意:
之前的一系列窗口/控件并没有被销毁,只是从当前的显示链中摘除----通过使用setGUISheet函数,你可以轻松的在多个GUI中切换。
现在,你已经创建了第一个窗口并把它附着在GUI系统上,当系统画GUI的时候,它将把这个窗口作为GUI的根。
但是,如果你编译运行这些代码,你依然不会看到任何东西。
怎么了?
你的程序没有任何问题,问题在:
我们刚才创建的DefaultWindow是隐藏的!
这就是为什么
DefaultWindow那么适合做根窗口的原因:
它仅仅被用作供其他的窗口和控件依附的空画布。
那么,我们再加把劲吧。
。
。
现在,我们将要创建一个框架窗口:
这个窗口和你桌面上的窗口很类似,它有一个标题栏,也可以移动和改变大小。
代码如下:
FrameWindow*fWnd=(FrameWindow*)wmgr.createWindow(
此代码创建了一个“TaharezLook/FrameWindow”窗口。
整个系统都使用这种命名约定:
窗口类型以组件组名做为前缀(假如你载入了WindowsLookscheme,你就可以创建一个
“WindowsLook/FrameWindow”对象)。
我们为这个新窗口命名为“testWindow”。
需要注意的是:
那个类型转换的使用,由于createWindow函数总是返回Window基类指针,尽管对于此例以及其他情况,返回这个Window指针就足够了,但是有时你需要访问子类的方法,所以使用CEGUI的时候示例中的类型转换是很常见的。
为了让系统能够用我们的新窗口做一些有用的事情,我们还需要做一些事情。
首先,我们必须把这个新窗口附着到我们上面指定的根窗口上,代码如下:
myRoot->addChildWindow(fWnd);
现在,我们可以设置它的位置和大小。
CEGUI使用一个“统一的(unified)”坐标系,使得可以同时使用相对部分和绝对部分----这就是为什么你看到的每个坐标都由两个部分组成。
想了解更多请看Introductionandoverviewofcore