【3D技术宅公社】XR数字艺术论坛  XR技术讨论 XR互动电影 定格动画

 找回密码
 立即注册

QQ登录

只需一步,快速开始

调查问卷
论坛即将给大家带来全新的技术服务,面向三围图形学、游戏、动画的全新服务论坛升级为UTF8版本后,中文用户名和用户密码中有中文的都无法登陆,请发邮件到324007255(at)QQ.com联系手动修改密码

3D技术论坛将以计算机图形学为核心,面向教育 推出国内的三维教育引擎该项目在持续研发当中,感谢大家的关注。

查看: 4198|回复: 5

[转帖]学习CEGUI

[复制链接]
发表于 2007-11-12 17:58:55 | 显示全部楼层 |阅读模式
先来个引子,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的文件结构
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的文件结构,多数情况下是不用动它的。
 楼主| 发表于 2007-11-12 17:59:23 | 显示全部楼层
代码:
你的第一个CEGUI程序
强烈建议仔细研究CEGUISample程序!因为那里介绍了它的一些基本用法,其实最后在游戏当中出现的,也就是这些例子的变化而已。
这里我会引导你写一个第一个自己的简单的CEGUI程序,它使用CEGUISampleHelper提供的框架,使用OpenGL渲染。
这是在CEGUI自己给的Sample程序基础上简化、简化、再简化得出的,目的是让大家对CEGUI程序有一个简单明了的认识,其实就是这么简单。里面只定义了一个背景,一个静态文本,写着“Hello!CEGUI”。
具体的,有几块重要的东西。有一些包含在框架里了,如下:
DefaultResourceProvider,这个是CEGUI的一个全局的东西,可以在任何地方操作它的指针,但是一般只需要在一开始操作它。
在CEGuiOpenGLBaseApplication当中,你可以看见下面这样的代码,这就是在使用DefaultResourceProvider的指针在设置资源的路径,你可以毫不客气地复制粘贴到你的工程里
CEGUI:efaultResourceProvider* rp = static_cast<CEGUI:efaultResourceProvider*>
        (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 <cstdlib>

/**//*************************************************************************
    程序入口
*************************************************************************/
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程序,其实就是这么简单。
跟着看完,还算通俗易懂
 楼主| 发表于 2007-11-12 17:59:34 | 显示全部楼层
在CEGUI中使用layout文件(1)
CEGUI支持两种方式的资源使用,一种就是在前文可见的直接在c++文件当中创建窗体,使用窗体;另一种方式就是在layout文件当中定制窗体。从理论上讲,两种方式都能达到相同的目的。
在不使用layout文件时,CEGUI是不太方便的,因为要定位控件,常常得修改文件当中的参数,如果在c++文件当中修改,每次都编译,很恶心(尤其是在有编辑器的情况下,使用c++就不能使用了)。
所以如果你要使用CEGUI,对layout文件的使用和编辑都是必修课。
下面这个就是一个简单的使用layout文件的例子,作的仅仅是把文件读进来、显示在窗口里了。

#include "TDemo1.h"
#include "CEGUI.h"
#include "CEGuiBaseApplication.h"

#include <cstdlib>

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



<?xml version="1.0" encoding="UTF-8"?>
<GUILayout>
    <Window Type="DefaultWindow" Name="root">
        <roperty Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
        <roperty Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />        
        <Window Type="TaharezLook/FrameWindow" Name="TDemo1/Window1" >
            <roperty Name="Text" Value="TDemo 1" />
            <roperty Name="UnifiedMaxSize" Value="{{0.8,0},{0.8,0}}" />
            <roperty Name="UnifiedMinSize" Value="{{0.2,0},{0.2,0}}" />
            <roperty Name="UnifiedAreaRect" Value="{{0.4,0},{0.1,0},{0.9,0},{0.7,0}}" />
            <roperty Name="CloseButtonEnabled" Value="False" />         
        </Window>
    </Window>
</GUILayout>
 楼主| 发表于 2007-11-12 17:59:53 | 显示全部楼层
在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界面编辑器的大部分鼠标操作,因此,如果没有大的问题,它是可以很好的使用的。
下面就是对其进行改进了,这个在此就不一一细说了。首先就是让他不那么容易崩溃,其次就是一些细节问题,可以结合着测试部门的测试对其进行改造。
 楼主| 发表于 2007-11-12 18:00:15 | 显示全部楼层
代码:
在CEGUI中使用layout文件(3)
打开任意一个layout文件,可见其为一个树形结构,父子窗体的组织结构比较清晰。
<?xml version="1.0" encoding="UTF-8"?>

<GUILayout >

    <Window Type="type1" Name="window1" >

              <Window Type="type2" Name=" window1" >

        </Window>

    </Window>

</GUILayout>


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

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

1.         规则1 Layout文件命名
layout文件以场景形式组织,每个layout文件对应一个场景下的UI,文件名为场景的英文名称,首字母大写,如SampleScene.layout。
2.         规则2 顶级控件命名&设定
layout文件内部使用Root_场景英文名的defaultWindow作为根窗口(顶级窗口),如示例场景的UI使用Root_SampleScence作为根窗口。顶级窗口大小为整个显示屏幕大小。
3.         规则3 次级控件命名
Root窗口下一级UI控件使用 场景英文名+控件实际用途方式命名,如示例场景下的背景图片命名为SampleSceneBackground。
4.         规则4 其它控件命名
次级以下控件使用 上一级控件名/控件自身控件名 的方式进行命名,如示例场景下的退出按钮命名为 SampleSceneBackground/Quit。
5.         规则 5 UI控件命名
UI控件命名规则为 UI控件名含义+控件类型(可选),如设置按钮可命名为SampleSceneBackground/Settings 或者SampleSceneBackground/SettingsButton。

这样一来,只要文件名不同,就保证了UI控件没有重名了。
 楼主| 发表于 2007-11-12 18:00:29 | 显示全部楼层
CEImagesetEditor
除了CELayoutEditor之外,CEGUI官方还提供了一个切图工具,即CEImagesetEditor。这个工具十分有用,减轻了美术很多的负担,它可以生成imageset文件,并可以以鼠标操作图片框。
从CEGUI的0.4版本开始,这个工具就开始提供了。但是那个版本几乎就不能用,有许多问题,如,其右边的工作区居然没有滚动条!另外,它的图片框一旦面积大的把面积小的覆盖之后,面积小的就点不到了。还有许多莫名其妙的崩溃问题。
其实,解决这些问题并不困难,大家发挥一下自己的聪明才智,一定能修改出符合自己项目需要的编辑器,毕竟人家把这个框子搭好了,几千行的代码也不是那么容易写的。
这个编辑器还是使用wxWidgets,配置工程同前文提到的LayoutEditor。
0.5版本的ImagesetEditor编辑器在功能上有所改观,但是问题还是不少。同样,在正式使用之前,需要大家修改和完善它。
在使用ImgesetEditor方面,由于它完成的功能较为简单,因此其使用没有LayoutEditor那么多的说法,只要给切好的图的名字写好就ok了
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|3D数字艺术论坛 ( 沪ICP备14023054号 )

GMT+8, 2025-5-6 11:25

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表