初学CEGUI和OGRE

OGRE 3D教程七:CEGUI和OGRE (Ogre1.7.1版本)(zhuan)

简介 
(本篇教程对应Ogre1.7.1 + CEGUI 0.7.1)本文的原文地址: 
http://www.ogre3d.org/tikiwiki/Basic+Tutorial+7&structure=Tutorials 

在这篇教程中,我们将介绍如何在Ogre项目中使用 CEGUI。 NOTE: 这篇教程在CEGUI方面只是一个开始,我们并没有尝试去深入CEGUI,如果你有需求,可以去他们的主页 更多更生如的介绍CEGUI的文档和教程,请去http://www.cegui.org.uk/api_reference/

前提条件 
1.这篇教程将假设你有C++编程经验,并且能够构建和编译一个Ogre程序。
2.这篇教程也假设你已经使用过 OGRE Wiki Tutorial Framework,或者手动使用CMake和 Ogre AppWizard创建过项目。
3.这篇教程需要前面几篇教程的知识基础,我们假设你已经学习过前面的教程。
你可以在 这里找到本篇教程的代码,请跟着教程,把它们加进你自己的项目中,查看编译后的结果。 

入门 
初始化代码段:请按照下面的代码段,来编辑你的头文件。 

BasicTutorial7 头文件 

#include <CEGUI/CEGUI.h>
#include <CEGUI/RendererModules/Ogre/CEGUIOgreRenderer.h>

class BasicTutorial7 : public BaseApplication
{
public:
    BasicTutorial7(void);
    virtual ~BasicTutorial7(void);

protected:
    CEGUI::OgreRenderer* mRenderer;

    virtual void createScene(void);

    virtual void createFrameListener(void);

    // Ogre::FrameListener
    virtual bool frameRenderingQueued(const Ogre::FrameEvent& evt);

    // OIS::KeyListener
    virtual bool keyPressed( const OIS::KeyEvent &arg );
    virtual bool keyReleased( const OIS::KeyEvent &arg );
    // OIS::MouseListener
    virtual bool mouseMoved( const OIS::MouseEvent &arg );
    virtual bool mousePressed( const OIS::MouseEvent &arg, OIS::MouseButtonID id );
    virtual bool mouseReleased( const OIS::MouseEvent &arg, OIS::MouseButtonID id );

    bool quit(const CEGUI::EventArgs &e);
};
请按照下面的代码段,来编辑你的实现文件。 

BasicTutorial7 实现文件 

//-------------------------------------------------------------------------------------
BasicTutorial7::BasicTutorial7(void)
{
}
//-------------------------------------------------------------------------------------
BasicTutorial7::~BasicTutorial7(void)
{
}
//-------------------------------------------------------------------------------------
void BasicTutorial7::createScene(void)
{
}
//-------------------------------------------------------------------------------------
void BasicTutorial7::createFrameListener(void)
{
    BaseApplication::createFrameListener();
}
//-------------------------------------------------------------------------------------
bool BasicTutorial7::frameRenderingQueued(const Ogre::FrameEvent& evt)
{
    return BaseApplication::frameRenderingQueued(evt);
}
//-------------------------------------------------------------------------------------
bool BasicTutorial7::keyPressed( const OIS::KeyEvent &arg )
{
    return BaseApplication::keyPressed(arg);
}
//-------------------------------------------------------------------------------------
bool BasicTutorial7::keyReleased( const OIS::KeyEvent &arg )
{
    return BaseApplication::keyReleased(arg);
}
//-------------------------------------------------------------------------------------
bool BasicTutorial7::mouseMoved( const OIS::MouseEvent &arg )
{
    return BaseApplication::mouseMoved(arg);
}
//-------------------------------------------------------------------------------------
bool BasicTutorial7::mousePressed( const OIS::MouseEvent &arg, OIS::MouseButtonID id )
{
    return BaseApplication::mousePressed(arg, id);
}
//-------------------------------------------------------------------------------------
bool BasicTutorial7::mouseReleased( const OIS::MouseEvent &arg, OIS::MouseButtonID id )
{
    return BaseApplication::mouseReleased(arg, id);
}
//-------------------------------------------------------------------------------------
bool BasicTutorial7::quit(const CEGUI::EventArgs &e)
{
    return true;
}



项目设置 
你必须使用你现在正在使用的Ogre版本,来编译生成 CEGUI。请查阅 构建CEGUI,然后你需要把CEGUI的头文件路径添加进你的项目的include目录中。 

编译好CEGUI后,你可以把编译好的文件拷贝到其他地方,作为一个SDK来使用。如果你的CEGUI头文件的路径上,没有‘CEGUI’,那么请在你的头文件的include里,删去‘CEGUI’字段。 

项目包含目录:请加入下面的两行,到你的include目录。 

CEGUI_HOME/include
CEGUI_HOME/include/CEGUI
外加库目录 

CEGUI_HOME/lib
依赖库(windows下) Debug 

CEGUIBase_d.lib
CEGUIOgreRenderer_d.lib
Release 

CEGUIBase.lib
CEGUIOgreRenderer.lib
移动 DLL 在Windows系统下,你需要拷贝以下Dll到你的工作目录中 

Debug 

CEGUIBase_d.dll
CEGUIFalagardWRBase_d.dll
CEGUIOgreRenderer_d.dll
CEGUIExpatParser_d.dll
Release 

CEGUIBase.dll
CEGUIFalagardWRBase.dll
CEGUIOgreRenderer.dll
CEGUIExpatParser.dll
最后一个DLL,假定你为CEGUI使用了默认的Expat XML解析器。 




编译代码 
程序现在只是显示一个黑色的屏幕,并不做任何其他的事情(知道你按下 Escape键退出。)如果出现了编译或者运行错误,请检查你的设置。请确定你的代码在全部编译和运行通过之后再继续下面的教程。 




CEGUI简介 
CEGUI是一个全功能的GUI库。它可以支持 Ogre (也支持 OpenGL,DirectX 和 Lrrlicht)。 Ogre只是一个图形库(它没有声音,物理引擎等),同样的,CEGUI只是一个GUI库,这意味着它没有自己的渲染库,并且无法hook 鼠标和键盘事件。实际上,为了让CEGUI可以渲染,你必选提供一个渲染器给它(这也是 CEGUIOgreRenderer库所提供的功能)为了让系统监听到鼠标和键盘事件,你也必须手动的去把这些事件传递给系统,这看起来比较麻烦,但实际上很少的代码就可以完成这些功能。它也可以让你在渲染和输入方面拥有完全控制权,CEGUI在这里非常方便。 

CEGUI还有很多方面会让你感到奇怪(即使你使用过其他GUI系统),在这篇教程里,我将慢慢的带你体验。 




定义CEGUI的资源组 
CEGUI和Ogre 一样,也需要使用一些类型的资源,它有一些资源管理器(和Ogre相似),用来找到它们各自的资源路径。所以,你需要去定义一些重要的资源组,并在 resources.cfg 中写好他们的路径。 

增加以下内容到你的 resources.cfg (用指向CEGUI datafiles文件夹的路径替换掉 ‘path_to_cegui’) 

[Imagesets]
FileSystem=path_to_cegui/imagesets
[Fonts]
FileSystem=path_to_cegui/fonts
[Schemes]
FileSystem=path_to_cegui/schemes
[LookNFeel]
FileSystem=path_to_cegui/looknfeel
[Layouts]
FileSystem=path_to_cegui/layouts



初始化 CEGUI 
找到 createScene函数,并增加如下代码 

mRenderer = &CEGUI::OgreRenderer::bootstrapSystem();
现在 CEGUI 已经初始化了,我们需要为每一个CEGUI资源管理器设置默认的资源组:请添加以下代码 

CEGUI::Imageset::setDefaultResourceGroup("Imagesets");
CEGUI::Font::setDefaultResourceGroup("Fonts");
CEGUI::Scheme::setDefaultResourceGroup("Schemes");
CEGUI::WidgetLookManager::setDefaultResourceGroup("LookNFeel");
CEGUI::WindowManager::setDefaultResourceGroup("Layouts");
如你所见,我们使用了在 resource.cfg文件中定义的资源组。 

CEGUI是可高度定制的,而且允许你自己定义程序的皮肤(在scheme文件中定义)这篇教程并没有涉及到如何去给CEGUI库换肤,若你需要这方面的知识,请去CEGUI官网。 

以下代码选择皮肤: 

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

接下来我们设置默认的鼠标图标: 

CEGUI::System::getSingleton().setDefaultMouseCursor("TaharezLook", "MouseArrow");
第一个参数指向了所要使用的 Imageset,第二个参数则指向 Imageset中的图片。 

在本系列的教程中,我们将使用CEGUI来显示一个鼠标的光标。你也可以使用其他GUI库赖渲染一个鼠标光标,或者直接简单的使用OGRE创建一个你自己的鼠标光标(后者会有一点复杂)。如果你只是使用CEGUI来显示鼠标光标,并且你很关注你的游戏的硬盘开销,那么你也可以寻则其他的选项来替换掉CEGUI。 

最后请注意: 在上面的代码中,我们设置了默认的鼠标光标,但此时鼠标是不可见的,我们并可以使用MouseCursor::setImage 来让鼠标可见。 

CEGUI::MouseCursor::getSingleton().setImage( CEGUI::System::getSingleton().getDefaultMouseCursor());



移除 SDKTrays 
在继续我们的教程前,我们先从我们的程序中移除掉 OgreBites SDKTrays。我们需要重写以下两个函数: createFrameListener frameRenderingQueued 




createFrameListener 
拷贝 BaseApplication::createFrameListener 到TutorialApplication7::createFrameListener,并删除 SDKTrays的相关代码,修改后将是如下代码: 

void BasicTutorial7::createFrameListener(void)
{
   Ogre::LogManager::getSingletonPtr()->logMessage("*** Initializing OIS ***");
   OIS::ParamList pl;
   size_t windowHnd = 0;
   std::ostringstream windowHndStr;

   mWindow->getCustomAttribute("WINDOW", &windowHnd);
   windowHndStr << windowHnd;
   pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));

   mInputManager = OIS::InputManager::createInputSystem( pl );

   mKeyboard = static_cast<OIS::Keyboard*>(mInputManager->createInputObject( OIS::OISKeyboard, true ));
   mMouse = static_cast<OIS::Mouse*>(mInputManager->createInputObject( OIS::OISMouse, true ));

   mMouse->setEventCallback(this);
   mKeyboard->setEventCallback(this);

   //Set initial mouse clipping size
   windowResized(mWindow);

   //Register as a Window listener
   Ogre::WindowEventUtilities::addWindowEventListener(mWindow, this);

   mRoot->addFrameListener(this);
}



frameRenderingQueued 
我们还需要移除掉BaseApplication::frameRenderingQueued 移除后代码如下: 

bool BasicTutorial7::frameRenderingQueued(const Ogre::FrameEvent& evt)
{
   if(mWindow->isClosed())
       return false;

   if(mShutDown)
       return false;

   //Need to capture/update each device
   mKeyboard->capture();
   mMouse->capture();

   return true;
}
我们只是移除了mTrayMgr 和 mDetailsPanel。 

注入 键盘事件 
CEGUI 不处理任何输入,它不会去读入 鼠标事件或者键盘输入。所以兄弟们,我们必须自己手动把键盘事件和鼠标事件注入的系统中去,让系统来处理这些事件。 

如果你在使用CEGUI,你将会需要鼠标和键盘事件的缓冲模式,这样你可以直接把接收到的事件注入系统。 

找到 keyPressed 函数,并把下面的代码加入进去: 

CEGUI::System &sys = CEGUI::System::getSingleton();
sys.injectKeyDown(arg.key);
sys.injectChar(arg.text);
在得到CEGUI::System的对象后,我们需要做两件事: 

1.注入key down 事件到CEGUI
2.注入 实际上按下的键
有一个很重要的问题,在你注入 key down 事件时,注入的字符,并不一样会得到你想要的结果,如果在使用非 英语字符的键盘时,我们必须考虑在设计时支持Unicode。 

现在我们需要注入 key up 事件到system中去。找到 keyReleased 函数并添加以下代码: 

CEGUI::System::getSingleton().injectKeyUp(arg.key);
注意: 我们并不需要注入字符,在 key up事件注入时。 

注入鼠标事件 
现在我们已经完成了对键盘输入的操作,我们还需要去操作鼠标输入。当我们输入一个 key up 或者 key down 事件到CEGUI中去时,我们对于 OIS和CEGUI中,使用的键值是不需要转换的,但是在鼠标事件里,我们需要转换一下,所以我们需要写一个函数来转换 OIS 和 CEGUI 的键 ID 

加入以下的代码到 BasicApplication7.Cpp 

CEGUI::MouseButton convertButton(OIS::MouseButtonID buttonID)
{
   switch (buttonID)
   {
   case OIS::MB_Left:
       return CEGUI::LeftButton;

   case OIS::MB_Right:
       return CEGUI::RightButton;

   case OIS::MB_Middle:
       return CEGUI::MiddleButton;

   default:
       return CEGUI::LeftButton;
   }
}
它可以作为一个 static方法,所以不需要再到头文件中去声明它。 

现在我们可以把鼠标事件注入到系统中去了。找到 mousePressed 函数,并把下面的代码加入进去。 

CEGUI::System::getSingleton().injectMouseButtonDown(convertButton(id));
这句代码是很明显的,我们把OIS得到的鼠标键的ID,转换成 CEGUI的 button ID。 

然后我们找到 mouseReleased 函数,并把下面的代码添加进去。 

CEGUI::System::getSingleton().injectMouseButtonUp(convertButton(id));



最后,我们需要注入 鼠标的运动 (mouse motion)到CEGUI。 

CEGUI::System 对象 拥有一个 injectMouseMove 函数来预期相对的鼠标运动。 

OIS::mouseMoved对象会把 相对的运动 放在 state.X.rel 和 state.Y.rel 这两个变量中。
找到 mouseMoved 函数,并且把下面的代码添加进去: 

CEGUI::System &sys = CEGUI::System::getSingleton();
sys.injectMouseMove(arg.state.X.rel, arg.state.Y.rel);
// Scroll wheel.
if (arg.state.Z.rel)
    sys.injectMouseWheelChange(arg.state.Z.rel / 120.0f);
120是一个‘神奇数字’,现在使用的更多。 OIS 使用了这个神奇数字,好了,现在 CEGUI 已经完整的得到了 鼠标和键盘事件。 




Windows, Sheets, and Widgets 
CEGUI 和大多数 GUI系统不一样。在CEGUI中,所有的东西都是 CEGUI::Window 类的子类,一个 window 可以拥有多个子window。这就是说,当你创建一个 frame来容纳多个按钮时,这个frame,实际上就是一个window。这也会导致一些奇怪的结果。比如,你可以把一个button,放进另一个button中,这在其他实践中,是不可能发生的。这导致的结果是: 当你在寻找一个你放置在程序中的特定的部件,他们都被称为 Windows,并且你可以通过 函数来 找到并访问他们。 

在绝大多数 CEGUI程序中,你并不需要自己在代码中去创建每一个对象,你只要使用 CEGUI Layout Editor来编辑一个GUI layout 即可,编辑完成后,Editor 会自己保存到一个 文本文件中。然后你可以通过读取这个文件到CEGUI中,来生成一个GUI sheet(同样,这也是一个 CEGUI::Window的子类。) 

最后,CEGUI 包含了大量的部件,可以让你用在你的程序里。当然,我们不可能全部介绍一遍,如果你需要,可以去他们的网站得到更多的相关信息。 

读取一个Sheet 
在CEGUI中,读取一个sheet 是非常简单的。 WindowManager类提供了一个 ‘loadWindowLayout’方法来读取sheet,然后放进一个 CEGUI::Window的对象中。然后你可以通过CEGUI::System::setGUISheet 来显示它。我们不会在这个教程中来使用这个,不过我会给予一个例子。 

不要把这些代码放进你的程序中(或izhezai你看完结果后删除它们) 

// Do not add this to the program
CEGUI::Window *guiRoot = CEGUI::WindowManager::getSingleton().loadWindowLayout("TextDemo.layout"); 
CEGUI::System::getSingleton().setGUISheet(guiRoot);

这些代码让 一个 sheet显示出来。在程序的其他地方,你可以使用 System::getGUISheet,来找回这张sheet。你也可以使用 setGUISheet来无缝的替换成其他的 Sheet(请确保你保存好了当前sheet的指针,以保证你以后想要替换回来。) 







手动创建一个Object 
如我前面说过,绝大多数时间,你使用CEGUI时,会使用 editor创建的 GUI sheet。但不管怎样,你会需要学习手动的来创建一个部件,并把它放置到屏幕上。在这个例子中,我们将放置一个退出按钮,之后我们会来编写它的功能。 

首先,我们需要创建一个默认的 CEGUI::Window 。请把以下代码,增加到 createScene 函数。 

CEGUI::WindowManager &wmgr = CEGUI::WindowManager::getSingleton();
CEGUI::Window *sheet = wmgr.createWindow("DefaultWindow", "CEGUIDemo/Sheet");
在代码中,我们使用了 WindowManager 来创建了一个名叫CEGUIDemo/Sheet 的 ‘DefaultWindow’。当然,我们可以给它随便取一个名字,但是,分级取名,比如‘SomeApp/MainMenu/Submenu3/CancelButton’这种形式,是非常普遍的。 

然后,我们创建一个退出按钮,并给它设置 大小。 

CEGUI::Window *quit = wmgr.createWindow("TaharezLook/Button", "CEGUIDemo/QuitButton");
quit->setText("Quit");
quit->setSize(CEGUI::UVector2(CEGUI::UDim(0.15, 0), CEGUI::UDim(0.05, 0)));
这有点难以理解。 CEGUI使用了统一的尺寸( "unified dimension")来定义大小和位置。我们设置尺寸时,你需要创建一个 UDim对象,并告知它大小。第一个参数是它在它的父窗口中的相对大小,第二个参数是这个对象的绝对大小。(单位:像素)重要的是,你只能设置UDim的一个参数,而另一个参数,必须为0。所以,在这里,我们设置这个button为宽为父窗口的 15%, 高为父窗口的 5%。如果我们想要指定它为 20*5像素,那么我们就需要设置第二个参数了。 

最后,我们必须把这个 button 固定到 我们创建的sheet上,然后把这个sheet设为当前GUI sheet。 

sheet->addChildWindow(quit);
CEGUI::System::getSingleton().setGUISheet(sheet);
现在,如果你编译运行程序,你将看到一个推出按钮。但是你点击时,它不会做任何事。 

Events 
Events的使用,在 CEGUI中,是很灵活的。它使用回调机制,把 事件的句柄,绑定在一些 public function 上。但是,这也导致了注册这些事件,会有一点复杂。我们现在就把 点击了退出按钮的这个事件的句柄,注册到退出程序这个功能上。这里,我们会需要使用到一个指向退出按钮的指针。 

请添加以下代码到 BasicTutorial7::createScene中创建退出按钮的代码的后面: 

quit->subscribeEvent(CEGUI::PushButton::EventClicked, CEGUI::Event::Subscriber(&BasicTutorial7::quit, this));
现在我们得到了一个指向这个按钮的指针,我们需要预定一个点击事件。 CEGUI中的每个部件,都有一套事件,它们都以‘Event’打头,以下的代码,我们用来绑定事件到按钮上: 

quit->subscribeEvent(CEGUI::PushButton::EventClicked,
                     CEGUI::Event::Subscriber(&TutorialListener::quit, this));

第一个参数是被预定的事件,是这事件本身。第二个参数是一个 Event::subscriber 的对象当我们创建一个 Subcriber的对象,我们首先需要一个能操作这个事件的函数的指针。然后,我们要指出是谁来操作这个事件,(在这里,就是这个按钮本身,我们填写: this)好了!我们的 TutorialListener::quit 函数(需要提前定义好) 将会来操作这次的鼠标点击事件,并且退出程序。 

编译并运行你的程序,看看是否能有此效果。 

注意: 我们可以创建大量的函数来操作CEGUI的事件。但是,唯一需要注意的是: 这些函数必须返回一个bool值,并且它们只能有一个类型为 “const CEGUI::EventArgs &”的参数。更多的关于 事件(events),并且如何注销它们,请阅读 CEGUI网站的相关文档。 




渲染纹理 
这是一件比较有趣的事,我们可以用 CEGUI 来创建一个渲染器来渲染一个window的纹理。 CEGUI允许我们创建第二个视口(Viewport)来直接渲染到CEGUI的部件。为了完成这个步骤,首先我们需要建立一个场景(scene)。 

添加以下代码到 createScene函数的底部: 

mSceneMgr->setAmbientLight(Ogre::ColourValue(1, 1, 1));
mSceneMgr->setSkyDome(true, "Examples/CloudySky", 5, 8);
Ogre::Entity* ogreHead = mSceneMgr->createEntity("Head", "ogrehead.mesh");
Ogre::SceneNode* headNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(Ogre::Vector3(0, 0, -300));
headNode->attachObject(ogreHead);

现在我们可以创建一个渲染纹理。 RenderSystem对象提供了功能来帮助我们渲染一个纹理。我们可以通过 TextureManager::createManual 函数来创建一个纹理。 

我们首先创建一个 512*512像素的纹理: 

Ogre::TexturePtr tex = mRoot->getTextureManager()->createManual(
   "RTT",
   Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
   Ogre::TEX_TYPE_2D,
   512,
   512,
   0,
   Ogre::PF_R8G8B8,
   Ogre::TU_RENDERTARGET);
Ogre::RenderTexture *rtex = tex->getBuffer()->getRenderTarget();



请查看API reference 来获取此函数的更多信息。 

然后我们创建一个 Camera 和一个Viewport 来观察我们所创建的场景。请注意,我们已经改变了一些视口的选项,包括关闭了 Overlays。。。这是一个很重要的操作,当你将在我们的小 window中使用 CEGUI和Ogre 的overlays。 

Ogre::Camera *cam = mSceneMgr->createCamera("RTTCam");
cam->setPosition(100, -100, -400);
cam->lookAt(0, 0, -300);
Ogre::Viewport *v = rtex->addViewport(cam);
v->setOverlaysEnabled(false);
v->setClearEveryFrame(true);
v->setBackgroundColour(Ogre::ColourValue::Black);

请注意,我们增加了一个ViewPort到这个纹理上(我们并没有在 RenderWindow上,而是创建在纹理上,这是一个比较通用的做法) 

现在我们已经创建了csene 和我们的texture,我们现在需要把他们嵌入到CEGUI中去。 

你可以使用 CEGUI::OgreRenderer::createTexture 函数来从任何 Ogre的 texture,来创建一个 CEGUI::Texture。 

CEGUI::Texture &guiTex = mRenderer->createTexture(tex);
不幸的是,这将使得我们的处理变得复杂。在CEGUI中,你永远不需要去处理一个单个的 Texture 或者一个单个的图片。 CEGUI在工作中使用了图片组,而不是单个的图片。当你定义一个皮肤的外观时,使用整个图片表,将是非常方便的。(你可以去看一下在CEGUI SDK里,datefiles/imagesets文件夹中的 TaharezLook.tga,将会了解到如何使用这个图片组) 

不管怎样,当你试图去只创建一个单个的图片(image)时,你也必须创建一个整个的图片组(image set)。 

以下代码可以实现这个功能: 

CEGUI::Imageset &imageSet =
  CEGUI::ImagesetManager::getSingleton().create("RTTImageset", guiTex);
imageSet.defineImage("RTTImage",
                    CEGUI::Point(0.0f, 0.0f),
                    CEGUI::Size(guiTex.getSize().d_width,
                                guiTex.getSize().d_height),
                    CEGUI::Point(0.0f, 0.0f));
第一行代码从 我们提供的 texture,创建了一个 image set (我们给它取名为 RTTImageset)。接下来一行代码(defineImage方法),指向了第一张,也是唯一的一张图片(我们取名为 RTTImage),它和我们提供的 整个 guiTex 一样大。 

最后,我们需要创建创建一个 StaticImage 部件,来防止这个 渲染器的 texture。 

以下这段代码和创建其他 window并无区别: 

CEGUI::Window *si = CEGUI::WindowManager::getSingleton().createWindow("TaharezLook/StaticImage", "RTTWindow");
si->setSize(CEGUI::UVector2(CEGUI::UDim(0.5f, 0),
                            CEGUI::UDim(0.4f, 0)));
si->setPosition(CEGUI::UVector2(CEGUI::UDim(0.5f, 0),
                                CEGUI::UDim(0.0f, 0)));
现在我们需要指定这个 StaticImage 部件去指向哪张image 再一次的,大家已经知道了,CEGUI只操作整个 Image set,而不是操作单张的图片,所以我们需要找到这张图片在 Image set 中的name,然后把图片显示出来。 

si->setProperty("Image", CEGUI::PropertyHelper::imageToString(&imageSet.getImage("RTTImage")));
这种做法就好比是:我们先把一个纹理打包进 image set,然后在使用的时候,再去解包解出来。这种做法,在 CEGUI中,并不是最简单或者说是最能让人理解的。 

最后,我们需要把这个 StaticImage 部件,放入我们前面创建出来的 GUI sheet中去,就OK了。 

sheet->addChildWindow(si);

现在,我们大功告成了!编译并且运行你的程序吧! 

结尾 
除了 CEGUI,我们实际上还有其他的选择: 

• QuickGUI
• MyGUI

本文转自:http://www.onlinegamediy.com/thread-88-1-1.html
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值