天天看点

OGRE之CEGUI简介

    CEGUI是一个2D的UI渲染库。它支持大部分渲染引擎,不仅支持Ogre,也同样的支持OpenGL和Irrlicht引擎。它同时又是基于XML脚本文件格式应用的一个重量级库。当然,你可以在你的代码中定义所有的UI信息,但如果你在使用XML文件进行UI文件的定义也会非常简单,CEGUI也能够在运行时对这些XML文件进行读取和分析。CEGUI本身有一些例子和支持这些例子的资源。你可以看一看这些例子中是如何使用XML脚本文件,如何进行UI单元的定义的。也可以去看看例子中的 .layout 文件和 .xsd文件,这些会对你学习CEGUI有所帮助。当然,你可能需要在自己的程序中自定义一些UI组件。CIC博客6MK8R%IZQu ?

UI的渲染CIC博客 j{Q8YHd~

"[email protected]        CEGUI在一些四方形网格上渲染它的UI单元,并将它们渲染到一个“屏幕空间”中。那么,将意味着这些承载着UI单元的四方形网格的整个绘制过程是完全不接受任何视角变换和投影变换影响的。这一条是任何2D UI系统运行的基准方法。CEGUI通过“OgreGUIRenderer”类与Ogre进行结合。这个类所在文件存放在Ogre的“Samples”文件夹下,然而却定义在“CEGUI”命名空间内。OgreGUIRenderer简单的取得了CEGUI中的一些绘制命令,并将这些命令转译成Ogre中的网格和材质数据,并将其放置到’层渲染队列(Overlay render queue)’中,通过这种手段Ogre就可以对其进行绘制了,同时,这样可以使UI在我们的渲染场景中永远处于近屏顶端。在我们的程序代码中,我们除了提供一个OgreGUIRenderer类的实体对象给CEGUI,其他的渲染相关部分我们不用操心。CIC博客7z3oQ5P&fs&~

9UGPl1g n,RE0输入系统和CEGUICIC博客2GZ+FRH0[5l!H9O7u5kn

vj };{;m#U0        CEGUI本身没有任何的输入处理,如果我们程序中需要对不同的输入数据进行处理,那么我们必须为它提供整套的输入事件处理系统。这样做有一些好处。其中之一就是你不需要担心UI库会和你的应用程序争夺输入数据的处理权。此外,你可以自由的完全的把CEGUI从“输入循环”中移除出来,并不给它任何输入数据信息。你同样也不需要依赖于任何的第三方IO库和API,你可以自由的选择输入设备:OIS,SDL,DirectInput,Win32, XWindows作为输入库都可以,完全的取决于你。在本文中我们将使用OIS做为CEGUI的输入处理系统。

O:nKjL2[hs [0CEGUI数据文件CIC博客6wM ii-fy,[

CIC博客 r6]v9^%DU.y2v7}9~

        说起来,你可能能够在代码中完美的进行你的UI层的定义。但是用以下几种XML文件做为CEGUI的配置方法将会更加简单和高效。这些文件包括”scheme”, ”looknfeel”, ”layout”, ”imagesets”和CEGUI显示使用的文字”font”。 ?Scheme 定义着在同一个配置下不同的有效UI元件。例如. 我们程序中需要使用的一些按钮Buttons,下拉选菜单ListBoxes等等UI元件都能够在 .scheme 格式的文件中找到。 ?Look-And-Feel 定义着每个需要显示的UI元件的各种属性,包括了它的纹理,颜色,状态属性等。我们可以查看 .looknfeel文件。 ?Layout 定义了UI元件的父层级关系,位置,大小等与其他UI元件可能联系到的属性。我们可以查看 .layout 文件。 ?Imageset 定义了一种配置下的纹理,UV值等信息,我们可以查看 .imageset 文件。 ?font 显而易见。CEGUI需要知道我们POST http://blog.hfut.edu.cn/spacecp.php?action=spacefut.edu.cn/spacecp.php?action=spacegui.zip文件,你能够在里面找到上述所有文件的一些例子。认真查看每个类型的文件,虽然它们都是XML格式的文件,注意它们各自的格式以及包含了UI的什么信息。如果你依旧看不明白,可以去CEGUI的官方站点看看对它们功能的描述。本文将使用” TcharazLookSkin”这套配置。(Tcharaz是创建这个配置的一个人名,他创建了这个配置的.scheme, .look-and-feel, .texture和.imageset)CIC博客7nL(yF;fh9a

CIC博客Cz-P x+P

编码CIC博客v.^L-d&LT

CIC博客!Q Lm*U`

        好了,介绍的足够多了,现在我们看看实际编码。如果你坚持看了Ogre的这系列教程例子,你应该很熟悉如何创建一个按下Esc就退出的Ogre渲染窗口的框架了。在这个例子中,我们用一种主菜单的面版来替代以前的空窗口框架。这个主菜单包含三个按钮,但是我只打算让Quit这个按钮进行事件响应处理。我们除了使用ESC键之外,我们还可以通过Quit按钮退出本程序。不知道通过之前的讲解你是否能明白,CEGUI通过别的输入系统获得用户输入事件后能够将其事件都反映出来,就如本例,我们可以在自己的代码中对鼠标点击事件做出响应。一会你从代码中就能轻易的明白如何在自己的代码中Hook到 CEGUI的事件行为。注意:我们下面的代码操作都是基于C++的,如果你对希望在脚本(例如Lua或其他脚本引擎)中Hook到CEGUI的事件行为,希望你能到CEGUI官方去看看如何做到。

j/g"g6Ee0数据

!wXO A-ph0CIC博客Pbz7~5/,KaJO

        首先,我们来看一下CEGUI中至关重要的数据文件---Layout文件。你可以通过CEGUI的Layout编辑器来生成和编辑该文件,但是在本例中下面这个XML格式的 .layout 文件完全是我手动编写出来的,实际上很简单。在Ogre的Debug文件夹下resource目录下有个压缩包是gui.zip,你在里面会发现一个文件叫”Katana.layout”,下面是该文件的全部内容:CIC博客p7^zh8a s^a9H

0e#Hf~;W*t9z0<?xml version="1.0" ?> <GUILayout> <Window Type="TaharezLook/FrameWindow" Name="Main">CIC博客l8eHI HP

l.MwGv"^5QJ`Q M0           <Property Name="UnifiedAreaRect" Value="{{0.0,0},{0.0,0},{1.0,0},{1.0,0}}" />

Zt"Pc,h0           <Property Name="FrameEnabled" Value="false" />CIC博客7zD[u.|#^

           <Property Name="TitlebarEnabled" Value="false" />

Xc5^kT!_C y,`J.a1b0           <Property Name="CloseButtonEnabled" Value="False" />CIC博客+q&A V?B

m([email protected])p-/2Jv}V0<Window Type="TaharezLook/Button" Name="cmdQuit"> <Property Name="Text" Value="Quit" />

nWZ |Z2O0

!rU_.a^0              <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.7,0},{0.6,0},{0.77,0}}" />

w"~"}8p2_5A)v0CIC博客Z'V9Y_1g'Gk4ON

</Window> <Window Type="TaharezLook/Button" Name="cmdOptions">

QIJ,ZZG0

+f"^ }6[/[email protected],I&[email protected]%v0              <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.6,0},{0.6,0},{0.67,0}}" />

ea(jd4OA0

:HX8p mF _,J#H0<Property Name="Text" Value="Options" /> </Window> <Window Type="TaharezLook/Button" Name="cmdInstantAction">CIC博客@@tgb^B[

CIC博客 Hj S!fPqcj

              <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.5,0},{0.6,0},{0.57,0}}" />CIC博客$z yPD#UXzx,? h

CIC博客A`$^fHt

<Property Name="Text" Value="Instant Action" /> </Window> </Window> </GUILayout>

/Ws&c,HFoix!?0

?1e } J1ijy/^0        你在浏览这些代码的时候,首先可能发现里面那些神秘的数字。在CEGUI 0.5.x版本中,UI元件需要定义的是UI元件的绝对尺寸大小。而在这个layout文件中,我们使用的是统一的相对尺寸范围。Value =”” 中定义了元件的左,右,上,下点的位置。但这个位置我们既可以定义这些点的绝对位置,也可以是定义这些点针对其父容器UI元件的相对位置。例如,下面这个UI元件的区域定义:

S*t0Mq-f,Q QR0CIC博客p`]2r-lK1JJ:I:a

{{0.4,0},{0.5,0},{0.6,0},{0.57,0}}

[email protected]:g,i:T4Ld0

*G g/q(T Fp0        这些数值告诉了CEGUI,这个UI元件在其上一层元件容器中的相对位置和大小。如本例,这个元件左上角将距离其上一层元件容器的左上角的右偏移距离为 (0.4 * 上一层元件容器宽度),这个元件左上角将距离其上一层元件容器的左上角的下偏移距离为 (0.5 * 上一层元件容器高度)。该UI元件宽度将为((0.6 ? 0.4)* 上一层元件宽度 )大小,高度将为( (0.57 ? 0.5) * 上一层元件告诉 )大小。那么,那些参数中的”0”是什么意义呢?如果你想同时指定UI元件的绝对象素位置的话,可以把这些”0”替换为该元件的象素位置。所以这就意味着,你能够根据自己喜好,为UI元件设置相对坐标或者象素的绝对坐标。我想不起来指定象素绝对坐标时这些数值的意义,如果谁看到本例并且知道这些绝对坐标数值意义的话,请帮助补充到本文中。:)不过,如果谁是曾经做过网页的话,将会非常熟悉这些绝对坐标的意义和顺序,因为这俩完全是一个东西。 (补充:译者推荐在游戏制作中使用相对坐标,这样的话在对窗口缩放或对单一UI窗口缩放时会容易的避免一些问题。) 在这个Layout文件中,第一行告诉CEGUI,我们想创建一个顶层的窗口”Main”,而且这个窗口大小是占满整个程序显示区-----它的相对宽高是(1.0 - 0.0 )。我们不希望看到它的标题栏,也不希望看到这个顶层窗口右上边的关闭按钮和其边框。于是,下面我们设置他们的Value为false。(这三项是 FrameWindow框架窗口默认存在的捆绑控件)。接下来,我们在屏幕中放置三个按钮----这样的话,在我们运行程序的时候将会从上到下见到 “Instant Action”“Options”“Quit”三个按钮。按钮控件的名称属性是非常重要的,这是我们在代码中获取该控件行为的唯一标识,这点我们一会就会见到。

o!g8Z p|`|]`0

`.r| G$ICS0接下来,看编码

&m:Cm,~p}!G)sLmO0

1Tg%[email protected] m&Bt8XNK0我将要重点说明在代码中整合CEGUI时有什么更变。首先,在main.cpp中,需要额外加一些头文件。

7EC_*^9rj SjK/0CIC博客L?*d?F^

// 需要能够创建CEGUI渲染接口CIC博客Wmx%z0i(x.VZ

CIC博客 Vt`'^T

   1. include "OgreCEGUIRenderer.h"CIC博客I ?R R/c]%n6ILdL

;YvP_tD1|0// CEGUI 的头文件

R7EB#_+{5I9gE2y0

wB)LDkm(wt4?0   1. include "CEGUISystem.h"

4Fn(g[-i6URR9y0   2. include "CEGUIInputEvent.h"

*rtV|Vw%C[*lsr0   3. include "CEGUIWindow.h"CIC博客9n N3WYi0~Kfd$?/Q

   4. include "CEGUIWindowManager.h"CIC博客y0g)Phr_

   5. include "CEGUISchemeManager.h"

Viy.O:} rW-J ]:B0   6. include "CEGUIFontManager.h"

6i;b!pv`iN0   7. include "elements/CEGUIFrameWindow.h"

Y4~/J*ex!X$N+CDk;V0

%s,QE)Qh)|r0我们将创建GUI渲染器的一个实例,所以我们需要包含OgreCEGUIRenderer.h这个头文件。你可以在OgreSDK或Ogre源代码的Samples/include文件夹下找到该文件。CEGUI的头文件能够在OgreSDK的include/CEGUI文件夹下找到这些文件。(在安装OgreSDK时这些通常被自动设置为默认包含头文件目录了)。如果你在编译时候这里出错,请保证同时添加了包含了这两个目录” include/CEGUI”和”include”。你也可以不包含” elements/CEGUIFrameWindow.h”,它仅仅是老版本的CEGUI中残留的一个习惯,新版本的CEGUI中已经可以不包含它了。不过包含的话也是没什么坏处的。CIC博客"?ll$b|r-PT

初始化CEGUI

7ji*iZ&l'LSY{(/'~;BQ0

d%X#tPq0Main.cppCIC博客5c/5co2V$f

CIC博客.ebF,{ _5i

// 在有一个有效的场景管理器和Windows窗口后,我们可以创建一个GUI渲染器

6[*jH3dqO0CIC博客:dk/HjK

CEGUI::OgreCEGUIRenderer* pGUIRenderer = new CEGUI::OgreCEGUIRenderer {

9oUI;f f9C0CIC博客v U:c&D Dq

Window, // 这个渲染目标窗口应该在之前创建好,CEGUI将会在这个窗口上进行渲染。CIC博客R:dy-~4n9`A:m

oRNgX3nwic0Ogre::RENDER_QUEUE_OVERLAY, // CEGUI将会在这个渲染队列中进行渲染工作

M5~?P9WR{7y0CIC博客8{3uR'Mp&y/V

False; // 渲染队列的排列方式。False代表将一切放置在渲染队列最前,而非最后。CIC博客(X^$x7u3m#he{a

CIC博客 Bb6w/p"xTQd{j

3000, // 这个参数在现在的CEGUI中已经是不必须的了?--它指定UI的最大范围。

%u!L"?VV;R0CIC博客s b:~i;UPs

sceneMgr, // 用这个场景管理器对UI进行管理 };CIC博客&IT'q I o]M

CIC博客4v;as4|+P4P!?E9MS

// 创建一个根CEGUI类CIC博客z,e1RqL _cDB)[email protected]

sMl8TNQ0CEGUI::System* pSystem = new CEGUI::System(pGUIRenderer);

"y$J?c V$d F0CIC博客O#b rd"l ~4u4e

// 设置Log层级,Log中能够提供我们一些Ogre运行的信息,CEGUI.log文件在工作目录下

*eO"q5`:VJqhm0

gx#m!|,Mu8y C-w0CEGUI::Logger::getSingleton().setLoggingLevel(CEGUI::Informative);CIC博客4L~"i_:m&Y

CIC博客:uari |8r(W7tn

// 使用指定的CEGUI配置(关于配置更多的信息可以查看CEGUI的文档)CIC博客o{,s&sq"y

CIC博客-fC8Xu%W+N(| /

CEGUI::SchemeManager::getSingleton().loadScheme((CEGUI::utf8*)"TaharezLookSkin.scheme", (CEGUI::utf8*)"GUI");

Y s2A&o?0

0z+fZIeR#fb4p9|0// 使用指定的CEGUI的鼠标图标 (鼠标信息被定义在look-n-feel中)

'op$Q w x_c ]0CIC博客1tm3E_&g/g&fH*K

pSystem->setDefaultMouseCursor((CEGUI::utf8*)"TaharezLook", (CEGUI::utf8*)"MouseArrow");

|9LK$vn#/6C*X0

zH*M[%{8zN^0// 指定在UI控件中使用的文字字体CIC博客,VN V9rp

CIC博客5aY],V~(js

CEGUI::FontManager::getSingleton().createFont("Tahoma-8.font", (CEGUI::utf8*)"GUI"); pSystem->setDefaultFont((CEGUI::utf8*)"Tahoma-8");CIC博客q[&t3e j$g3Vf B-S

G4JSp ^7c?0// 从 .layout脚本文件读取一个UI布局设计,并将其放置到GUI资源组中。(本例中的.layout文件您可以从 resource/gui.zip 中找到。)

9XTu4WX%v5yC(_#o0CIC博客h!h6^)v*n;e

CEGUI::Window* pLayout = CEGUI::WindowManager::getSingleton().loadWindowLayout("katana.layout", "", "GUI");CIC博客y+k4[s0kSN

CIC博客,n y(~FYj aR*[email protected]

// 接下来我们告诉CEGUI显示哪份UI布局。当然我们可以随时更换显示的UI布局。CIC博客6g7P2y~N J2jJ~Z

;]UQ$e[&D3h0pSystem->setGUISheet(pLayout);CIC博客-F$x_$q$[/

V ?^Z/tL%? @0上面的代码中有大量的注释了,所以这里我不再重复太多。值得注意的是,我们在创建CEGUI渲染器时需要使用”Ogre渲染窗口对象” 和一个”场景管理器”,所以我们之前必须创建好这两个对象。

$]p&Wv h~!e kQ0CEGUI的输入支持

-kj?6QA1t+tJe;}0

qb&b"`t(I$}0我们若是需要修改InputHandle类中的一些input消息来源,则需要一些额外的参数:一个指向我们创建的CEGUI::System实例的一个指针。因为我们需要通过InputHandler将一些外界的消息压入CEGUI消息队列中。 Input.cpp

}3Z&~k vPU)r0

0T1[/L;I jh9IgY0// 鼠标监听 bool InputHandler::mouseMoved(const OIS::MouseEvent &evt) { m_pSystem->injectMouseWheelChange(evt.state.Z.rel);

3g O1zP#D&e s b+E?0

0E.xI] i9C0return m_pSystem->injectMouseMove(evt.state.X.rel, evt.state.Y.rel); }

O-O2r%m7}m4fm.f0CIC博客$H*@!Bn2kfE*r

bool InputHandler::mousePressed(const OIS::MouseEvent &evt, OIS::MouseButtonID btn) { CEGUI::MouseButton button = CEGUI::NoButton;CIC博客;[email protected]]D)v

CIC博客ed%z,N/n

if (btn == OIS::MB_Left) button = CEGUI::LeftButton;CIC博客s-eD%w$A7`|

#jK4SW KI0if (btn == OIS::MB_Middle) button = CEGUI::MiddleButton;

kHh^g[7yr0

U gC?#q o O!Aah&]0if (btn == OIS::MB_Right) button = CEGUI::RightButton;CIC博客%/fsiB#Z

K3l H-Wv./ q0return m_pSystem->injectMouseButtonDown(button); }

6L-V$P Jt!T;p T+Y,l0CIC博客[email protected])`/AG vQ(K

bool InputHandler::mouseReleased(const OIS::MouseEvent &evt, OIS::MouseButtonID btn) { CEGUI::MouseButton button = CEGUI::NoButton;

Wk!bqJ(A-`4~0

+PG$}^+sM0if (btn == OIS::MB_Left) button = CEGUI::LeftButton;

]*`K.S#k~DQNE(u0CIC博客 mLnoN9IR

if (btn == OIS::MB_Middle) button = CEGUI::MiddleButton;

@(]B)D#~IZgX2X0

5c [,xDX#D0if (btn == OIS::MB_Right) button = CEGUI::RightButton;

%lI ZsN0aM0CIC博客nt(m7q5p PkR

return m_pSystem->injectMouseButtonUp(button); }

_Z.R.L"kl$H0CIC博客5BD#s k z-P wSg

8Z[c(h0r6Q0// 键盘监听 bool InputHandler::keyPressed(const OIS::KeyEvent &evt) { unsigned int ch = evt.text;

}f(t ds r:@ j7ry0

b&C'n/~0b/[0m_pSystem->injectKeyDown(evt.key); return m_pSystem->injectChar(ch); }CIC博客L~3nm*C F%F

i*e+l)]2K0bool InputHandler::keyReleased(const OIS::KeyEvent &evt) { if (evt.key == OIS::KC_ESCAPE) m_simulation->requestStateChange(SHUTDOWN);CIC博客'z'T!H3Nu0z

a,B4/w"s%n;P5o`0return m_pSystem->injectKeyUp(evt.key); }CIC博客/e^3cr%/H}K.L

io |Ep0注意:如果用户输入过快,那么injectChar或injectKeyUp时可能会出现字符消息丢失的可能,此时上列函数可能会返回false值。所以,若我们希望上面的函数长期返回true值,尽量使用按键消息缓冲。CIC博客L8K4J4S*e.ET {9U

CIC博客qk9fci(yoX)?

代码中很清楚明确的说明了如何把input事件通知给CEGUI ---- 就是那几个”inject***”的函数调用而已。(这些函数定义才CEGUI::System中)。你同样可以在别的地方进行这几个函数调用。我把它们放在input handler类中是因为这样很方便,并且完全不用担心Input程序是否在休息,也无需去知道它低层实现的细节。---- 总之,它将数据通过某种处理后通知我们的UI使其处理某种行为。 Main.cppCIC博客%jW P"Emk:r`

9OD*kW+u8rX0// InputHandler处理CEGUI的input事件后,我们需要获得它的一个指针,并将给CEGUI::System的一个实例使用。 InputHandler *handler = new InputHandler(pSystem, sim, hWnd);

(P-e"|n+K;]/W(YW0

#[email protected],D5c.mg0// put us into our "main menu" state sim->requestStateChange(GUI); 我们在上面代码中同时把”SIMULATION”状态替换成了”GUI”状态。一般情况下,我们程序中应当在直接进入游戏前提供一个主菜单,通过这个主菜单我们进行游戏状态的变换。所以,我们需要写一个主菜单类专门进行游戏状态的变换,它需要获取UI的信息并进行相应的处理。在本例中,我仅简单的提供一个框架说明这个流程,并为真正的对游戏状态进行变化,所以直接写在main.cpp中了。 // 创建一个主菜单实例 MainMenuDlg* pDlg = new MainMenuDlg(pSystem, pLayout, sim); 在本例中,这个MainMenuDlg的行为处理类在下面的MainMenuDlg.h / .cpp中有声明和定义。

$r]E%xiB+h.w0

0e/~ H.Z"Mf0MainMenuDlg.hCIC博客m E0Rq eXI a*L

CIC博客uFeb1f%Cu

   1. pragma onceCIC博客 p0M/`:v6j

1n?+|k;D| f0   1. include "CEGUIWindow.h"CIC博客%`cA~m9dz

CIC博客p^+{IHR)vt9`r

namespace CEGUI { class System;

[email protected])iQZ lpF AX J0CIC博客7L I1S%H j.b)b

class Window; }CIC博客.DY d3X~X?

d8u-R&]8^(h0class Simulation;CIC博客YU G%iO tq}

CIC博客*hi-RQW(RNR7H1z

class MainMenuDlg { public:CIC博客k0x5X'i Mff/S

CIC博客)k'm n b9e ]_F}

MainMenuDlg(CEGUI::System* pSystem, CEGUI::Window* pSheet, Simulation* pSimulation);CIC博客 n;g9t't'r

I#}2bD4d'Q,}AzF0~MainMenuDlg();CIC博客'F;IBD _0wL,D(O

CIC博客 e EK,hDxv i

// CEGUI事件处理函数说明:函数的命名随便,但是你必须这样声明bool <method name>(const CEGUI::EventArgs &args)CIC博客$]I]7u+B5~ ` t

C /&gr s,G8wN.x'{0bool Quit_OnClick(const CEGUI::EventArgs &args);CIC博客"o/ID6}1n`!k^ Vk

d3k p)D;o/N0bool Options_OnClick(const CEGUI::EventArgs &args);CIC博客&ja5c1t y7xH8Y'~%dx

CIC博客 Kt,/%~E`_*]

bool Launch_OnClick(const CEGUI::EventArgs &args);

s4aLz"c$c+e Ax0CIC博客y4F0hGA

private:

2VkR / x[0c M0

*` j{:?:r6dQ;y |0CEGUI::System* m_pSystem; // 一个CEGUI::System实例的指针

P9Y)s4SM cS(y9rB|0CIC博客|qG Q!p*V

CEGUI::Window* m_pWindow; // 指向一个版面的窗口指针CIC博客ume-q l1V iEp~X

Q sY)C3dK+O0Simulation* m_pSimulation; // 指向一个仿真管理器的指针 };CIC博客u%}3VtzsJ/u

eWu7d#p4i%T%UV0MainMenuDlg.cpp

V4V5s Am&[email protected]CIC博客U*sc|//f6E'}

   1. include "MainMenuDlg.h"CIC博客b-Z/O:c"Q#X

   2. include "Simulation.h"CIC博客U.Cy/k? L

   3. include "CEGUISystem.h"

#H ]@!K%O L&N0   4. include "CEGUIWindow.h"CIC博客-G[1b2H"c2q h

   5. include "CEGUIWindowManager.h"

M(uW g!nMfKn&{M O7n0   6. include "elements/CEGUIPushButton.h"

{q v-n/L2J9A(^0

X/G |-X&ei/M0MainMenuDlg::MainMenuDlg(CEGUI::System *pSystem, CEGUI::Window *pSheet, Simulation *pSimulation) { m_pSystem = pSystem; m_pWindow = pSheet; m_pSimulation = pSimulation;

oc#C MY0CIC博客;cC4_w}"L

// 钩住窗口元件的事件处理函数CIC博客-D*~ _)BO`a

D}[email protected]$U0CEGUI::PushButton* pQuitButton = (CEGUI::PushButton *)CEGUI::WindowManager::getSingleton().getWindow("cmdQuit"); pQuitButton->subscribeEvent(CEGUI::PushButton::EventClicked, CEGUI::Event::Subscriber(&MainMenuDlg::Quit_OnClick, this));CIC博客+_ _XC`BJ @$V

CIC博客puv)y^5l

CEGUI::PushButton* pOptionsButton = (CEGUI::PushButton *)CEGUI::WindowManager::getSingleton().getWindow("cmdOptions"); pOptionsButton->subscribeEvent(CEGUI::PushButton::EventClicked, CEGUI::Event::Subscriber(&MainMenuDlg::Options_OnClick, this));

.]5ine'~F(r0CIC博客/PTh'Ng,P

CEGUI::PushButton* pLaunchButton = (CEGUI::PushButton *)CEGUI::WindowManager::getSingleton().getWindow("cmdInstantAction"); pLaunchButton->subscribeEvent(CEGUI::PushButton::EventClicked, CEGUI::Event::Subscriber(&MainMenuDlg::Launch_OnClick, this)); }CIC博客)c b)a|3OH:x/WL

CIC博客m ?-|rYI/_'KN

MainMenuDlg::~MainMenuDlg() { }CIC博客x;H|;hU

CIC博客 x7y;f s&VO$i"Y,SS1I#s

bool MainMenuDlg::Quit_OnClick(const CEGUI::EventArgs &args) { m_pSimulation->requestStateChange(SHUTDOWN); return true; }

6W nw"{(Rx!hXyj0CIC博客4au4~^3J.X)mU

bool MainMenuDlg::Launch_OnClick(const CEGUI::EventArgs &args) { return true; }CIC博客#PrTn*@/@

CIC博客1XB5zJi Pq;D F

bool MainMenuDlg::Options_OnClick(const CEGUI::EventArgs &args) { return true; }

&m4lF"N~,Cvy,?x0CIC博客R0Cy,G6B!S

这里有两个重要的事情需要说明一下:(a)如何让事件处理函数钩取到CEGUI的事件。(b)在例子中,我们处理了”Quit”按钮按下的消息(象按下ESC键一样处理,让程序关闭)。如果你有兴趣,可以在上面的代码里对Launch_OnClick和Options_OnClick函数补充使其进行实际的消息处理,也可以为更多的GUI元件事件消息进行处理。

2F2F3L P*sx0结束语

)p"}-mA(B:lyC0CIC博客}0E xJq T~r

实际上,也没有更多的事情可做了。---- 何去创建你的UI事件处理,如何将Input事件压入CEGUI都已经告诉你了。你可以用这里的代码,也可以自己去写,但是基础的这些东西是没有变化的。关于CEGUI和Ogre确实也没有更多的可说的了 ---- 你只需要在自己的代码中对其他的一些UI元件事件进行hook后处理就可以了。CIC博客|"D*tL3AP5[

继续阅读