准备CEGUI
没有配置好CEGUI可以回到上一篇文章中重新配置。配置成功后将TutorialApplication初始化。
TutorialApplication.h
1 |
|
TutorialApplication.cpp
1 |
|
初始化CEGUI
在createScene()
方法中加入1
2
3
4
5
6
7
8
9
10
11
12
13//CEGUI的主要渲染器,bootstrapSystem()方法会初始化CEGUI中重要的几个管理器,如OgreRenderer,System,OgreResourceProvider,OgreImageCodec
mRenderer = &CEGUI::OgreRenderer::bootstrapSystem();
//读取资源文件
CEGUI::ImageManager::setImagesetDefaultResourceGroup("Imagesets");
CEGUI::Font::setDefaultResourceGroup("Fonts");
CEGUI::Scheme::setDefaultResourceGroup("Schemes");
CEGUI::WidgetLookManager::setDefaultResourceGroup("LookNFeel");
CEGUI::WindowManager::setDefaultResourceGroup("Layouts");
//选择UI皮肤
CEGUI::SchemeManager::getSingleton().createFromFile("TaharezLook.scheme");
//设置鼠标
CEGUI::System::getSingleton().getDefaultGUIContext().getMouseCursor().setDefaultImage("TaharezLook/MouseArrow");
移除SDKTrays
通过重写createFrameListener()和frameRenderingQueued()移除SDKTrays。(Ogre的logo部分)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45void TutorialApplication::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);
}
//-------------------------------------------------------------------------------------
bool TutorialApplication::frameRenderingQueued(const Ogre::FrameEvent& evt)
{
if(mWindow->isClosed())
return false;
if(mShutDown)
return false;
//Need to capture/update each device
mKeyboard->capture();
mMouse->capture();
//Need to inject timestamps to CEGUI System.
CEGUI::System::getSingleton().injectTimePulse(evt.timeSinceLastFrame);
return true;
}
注入输入事件——键盘和鼠标
CEGUI不会自己处理输入,它不读取鼠标的移动和键盘的输入。相反地,它依赖用户把按键鼠标事件注入到系统,换句话说必须要人为的将其放到事件响应的方法中。CEGUI一般以缓冲模式注入到系统中。
注入键盘响应事件中
1 | //------------------------------------------------------------------------------------- |
注入鼠标响应事件中
鼠标主要有三个响应类型,左键,中键以及右键,所以添加一个根据OIS反馈鼠标的响应类型的函数,把OIS的按钮ID转换为CEGUI的按钮ID1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17CEGUI::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;
}
}
鼠标移动,按下和松开的响应事件1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26//-------------------------------------------------------------------------------------
bool TutorialApplication::mouseMoved( const OIS::MouseEvent &arg )
{
CEGUI::System &sys = CEGUI::System::getSingleton();
//参数分别为x,y的移动距离
sys.getDefaultGUIContext().injectMouseMove(arg.state.X.rel, arg.state.Y.rel);
// 滚轮
if (arg.state.Z.rel)
//滚轮滚过的角度
sys.getDefaultGUIContext().injectMouseWheelChange(arg.state.Z.rel / 120.0f);
return true;
}
//-------------------------------------------------------------------------------------
bool TutorialApplication::mousePressed( const OIS::MouseEvent &arg, OIS::MouseButtonID id )
{
//注入鼠标按下的事件,参数为鼠标的响应类型
CEGUI::System::getSingleton().getDefaultGUIContext().injectMouseButtonDown(convertButton(id));
return true;
}
//-------------------------------------------------------------------------------------
bool TutorialApplication::mouseReleased( const OIS::MouseEvent &arg, OIS::MouseButtonID id )
{
//注入鼠标松开的事件,参数为鼠标的响应类型
CEGUI::System::getSingleton().getDefaultGUIContext().injectMouseButtonUp(convertButton(id));
return true;
}
窗口、表单、组件(Windows, Sheets, and Widgets)
介绍
CEGUI与其它多数GUI系统有所不同。在CEGUI里,所有能显示出来的东西都是CEGUI::Window类的一个子类,而且一个window可以有任意数量的子window。这样会导致一些奇怪的事情发生。你能在一个按钮里面放置另外一个按钮,虽然实际上不会这么干。我提这些的原因是,当你正寻找放在应用程序里的某个特殊的小部件时,它们都被称作Windows,而且可以通过访问Windows的函数来访问。
CEGUI最常用的用法是,你不必在代码里创建每一个单独的对象。而你可以通过一个像CEGUI Layout Editor
这样的编辑器,来为你的程序创建一个GUI布局。根据你的喜好,放置你的窗口、按钮以及其它部件到屏幕上之后,编辑器会把布局保存到一个文本文件里。你就可以之后加载这个布局到GUI sheet里面(它也是CEGUI::Window的一个子类)。
最后,要知道CEGUI包含大量的小部件供你的程序使用。我们在这里不去涉及,所以如果你决定使用CEGUI,最好还是去它们的网站了解更多的信息。
载入表单
在CEGUI里载入一个表单(sheet)是非常容易的事。WindowManager类提供了一个”loadWindowLayout”函数来加载表单,并把它放入CEGUI::Window对象。然后你可以通过CEGUI::System::setGUISheet来显示它。1
2
3// 本次示例程序中不需要添加
CEGUI::Window *guiRoot = CEGUI::WindowManager::getSingleton().loadLayoutFromFile("TextDemo.layout");
CEGUI::System::getSingleton().getDefaultGUIContext().setRootWindow(guiRoot);
手动创建部件
一个可以响应的退出按钮1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18//创建CEGUI窗口
//-----------------------------------------------
//获取窗口管理器
CEGUI::WindowManager &wmgr = CEGUI::WindowManager::getSingleton();
//创建一个默认窗口(DefaultWindow),名字为"CEGUIDemo/Sheet"
CEGUI::Window *sheet = wmgr.createWindow("DefaultWindow", "CEGUIDemo/Sheet");
//创建按钮(样式在TaharezLook文件的Button节点中),名称为"CEGUIDemo/QuitButton"
CEGUI::Window *quit = wmgr.createWindow("TaharezLook/Button", "CEGUIDemo/QuitButton");
//设置文字
quit->setText("Quit");
//设置大小
quit->setSize(CEGUI::USize(CEGUI::UDim(0.15, 0), CEGUI::UDim(0.05, 0)));
//为按钮绑定事件,参数分别为:点击响应,响应的事件
quit->subscribeEvent(CEGUI::PushButton::EventClicked, CEGUI::Event::Subscriber(&TutorialApplication::quit, this));
//将按钮放置在默认窗口上
sheet->addChild(quit);
//设置默认窗口为全局窗口
CEGUI::System::getSingleton().getDefaultGUIContext().setRootWindow(sheet);
quit()
方法1
2
3
4
5
6
7//-------------------------------------------------------------------------------------
bool TutorialApplication::quit(const CEGUI::EventArgs &e)
{
//关闭窗口
mShutDown = true;
return true;
}
渲染到纹理
用CEGUI创建一个纹理窗口的渲染器。这可以让我们能够创建一个可以直接渲染到CEGUI部件的视口。
创建场景
首先创建一个能让我们看见的场景(createScene()方法中)1
2
3
4
5
6//创建模型
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对象提供了一种渲染到纹理的功能。我们用RenderSystem::createRenderTexture
函数创建一个纹理。在这个程序里,我们创建一个512 x 512的纹理1
2
3
4
5
6
7
8
9
10Ogre::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();
创建视口
接下来创建一个摄像机和一个视口,以便察看创建的场景。注意,要关闭Overlays,否则你会看见CEGUI与Ogre在小窗口里面重叠在一起。1
2
3
4
5
6
7
8
9
10 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);
CEGUI::Texture &guiTex = mRenderer->createTexture("textname", tex);
创建图像部件
1 | //CEGUI的图像 |
显示图像
1 | //添加窗口显示图像 |
运行结果
结语
CEGUI具有强大的功能,同时也能够简单上手,给我们开发Ogre提供了很大的便利。