前几章为了简单方便,把教程里的代码一股脑儿全堆在一个.cpp文件中,这只是初学者的做法,到以后我们做项目,就要学会分清结构。前面几个例子的代码太少不方便分开,这一课的代码分开就比较清晰了,请注意:这很重要。
首先,像以前一样先搞懂我们要做什么,这一节我们没有3D场景,只需添加一个退出按钮,再给按钮加上事件,看上去简单
然后,看一下结构:
Main.cpp(项目入口,教程中说不改这里的代码,但是这个东东可以很简单几句话就行了,算了我们还是听教程的好)
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "Headfile.h"
#include "windows.h"
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
#else
int main(int argc, char **argv)
#endif
{
// Create application object
TutorialApplication app;
try {
app.go();
} catch( Ogre::Exception& e ) {
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK |
MB_ICONERROR | MB_TASKMODAL);
#else
fprintf(stderr, "An exception has occured: %s\n",e.getFullDescription().c_str());
#endif
}
return 0;
}
Headfile.h(此文件中是必要的包含文件)
#ifndef HEADFILE_H
#define HEADFILE_H
//........
//........
#endif
#ifndef HEADFILE_H
#define HEADFILE_H
//CEGUI包含文件
#include <CEGUI/CEGUIImageset.h>
#include <CEGUI/CEGUISystem.h>
#include <CEGUI/CEGUILogger.h>
#include <CEGUI/CEGUISchemeManager.h>
#include <CEGUI/CEGUIWindowManager.h>
#include <CEGUI/CEGUIWindow.h>
#include <CEGUI/elements/CEGUIPushButton.h>
#include "OgreCEGUIRenderer.h"
#include "OgreCEGUIResourceProvider.h"
//regular mem handler
#include "ExampleApplication.h"
// OIS输入输出系统头文件
#include <OIS/OIS.h>
using namespace OIS;
//本项目文件
#include "FrameListener.h"
#include "ExampleApp.h"
#endif
ExampleApp.h
#ifndef EXAMPLEAPP_H
#define EXAMPLEAPP_H
#include "Headfile.h"
class TutorialApplication : public ExampleApplication
{
private:
CEGUI::OgreCEGUIRenderer* mGUIRenderer;
CEGUI::System* mGUISystem;
CEGUI::Window* mEditorGuiSheet;
public:
TutorialApplication();
~TutorialApplication();
void setupEventHandlers(void);
bool handleQuit(const CEGUI::EventArgs& e);
protected:
void createScene(void);
void createFrameListener(void);
};
#endif
ExampleApp.cpp
#include "ExampleApp.h"
TutorialApplication::TutorialApplication()
: mGUIRenderer(0),
mGUISystem(0),
mEditorGuiSheet(0)
{
}
TutorialApplication::~TutorialApplication()
{
if(mEditorGuiSheet)
{
CEGUI::WindowManager::getSingleton().destroyWindow(mEditorGuiSheet);
}
if(mGUISystem)
{
delete mGUISystem;
mGUISystem = 0;
}
if(mGUIRenderer)
{
delete mGUIRenderer;
mGUIRenderer = 0;
}
}
void TutorialApplication::createScene(void)
{
// Set ambient light
mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
// 初始化GUI
mGUIRenderer = new CEGUI::OgreCEGUIRenderer(mWindow, Ogre::RENDER_QUEUE_OVERLAY, false, 3000, mSceneMgr);
mGUISystem = new CEGUI::System(mGUIRenderer);
CEGUI::Logger::getSingleton().setLoggingLevel(CEGUI::Informative);
CEGUI::SchemeManager::getSingleton().loadScheme((CEGUI::utf8*)"TaharezLookSkin.scheme");
mGUISystem->setDefaultMouseCursor((CEGUI::utf8*)"TaharezLook",(CEGUI::utf8*)"MouseArrow");
CEGUI::MouseCursor::getSingleton().setImage("TaharezLook","MouseMoveCursor");
mGUISystem->setDefaultFont((CEGUI::utf8*)"BlueHighway-12");
mEditorGuiSheet=CEGUI::WindowManager::getSingleton().createWindow((CEGUI::utf8*)"DefaultWindow",
(CEGUI::utf8*)"Sheet");
mGUISystem->setGUISheet(mEditorGuiSheet);
//手动新建一个退出按钮,设置它的大小、位置
//CEGUI::PushButton* quitButton =
// (CEGUI::PushButton*)CEGUI::WindowManager::getSingleton().createWindow
// ("TaharezLook/Button", (CEGUI::utf8*)"Quit");
//mEditorGuiSheet->addChildWindow(quitButton);
quitButton->setPosition(CEGUI::Point(0.35f, 0.45f));
quitButton->setSize(CEGUI::Size(0.3f, 0.1f));
//quitButton->setPosition(CEGUI::UVector2(cegui_reldim(0.35f), cegui_reldim( 0.45f)) );
//quitButton->setSize(CEGUI::UVector2(cegui_reldim(0.35f), cegui_reldim( 0.1f)) );
//quitButton->setText("Quit");
//*************************************************************************************************************
// 用.xml创建界面
mEditorGuiSheet = CEGUI::WindowManager::getSingleton().loadWindowLayout((CEGUI::utf8*)"TutoralGui.xml");
mGUISystem->setGUISheet(mEditorGuiSheet);
CEGUI::PushButton* quitButton=(CEGUI::PushButton*)CEGUI::
WindowManager::getSingleton().getWindow((CEGUI::utf8*)"Quit");
setupEventHandlers();
}
void TutorialApplication::createFrameListener(void)
{
mFrameListener = new GuiFrameListener(mWindow, mCamera, mGUIRenderer);
mRoot->addFrameListener(mFrameListener);
}
void TutorialApplication::setupEventHandlers(void)
{
CEGUI::WindowManager& wmgr = CEGUI::WindowManager::getSingleton();
wmgr.getWindow((CEGUI::utf8*)"Quit")->subscribeEvent(CEGUI::PushButton::EventClicked,
CEGUI::Event::Subscriber
(&TutorialApplication::handleQuit, this));
}
bool TutorialApplication::handleQuit(const CEGUI::EventArgs& e)
{
static_cast<GuiFrameListener*>(mFrameListener)->requestShutdown();
return true;
}
其中有地方用到了“TutoralGui.xml”文件
复制下面xml代码到记事本,并将其以“TutoralGui.xml”命名另存在“\media\gui”文件夹下
<?xml version="1.0" ?>
<GUILayout>
<Window Type="DefaultWindow" Name="Tutorial Gui">
<Window Type="TaharezLook/Button" Name="Quit">
<Property Name="UnifiedPosition" Value="{{0.35,0},{0.45,0}}" />
<Property Name="UnifiedSize" Value="{{0.3,0},{0.1,0}}" />
<Property Name="Text" Value="Quit" />
</Window>
</Window>
</GUILayout>
这样做的效果跟手动创建GUI是一样的,其实.xml文件可以很方便得产生,下一节介绍怎样用CELayoutEditor制作界面FrameListener.h
#ifndef GUILISTENER_H
#define GUILISTENER_H
#include "Headfile.h"
class GuiFrameListener : public ExampleFrameListener, public OIS::MouseListener, public OIS::KeyListener
{
private:
CEGUI::Renderer* mGUIRenderer;
bool mShutdownRequested;
public:
GuiFrameListener(RenderWindow* win, Camera* cam, CEGUI::Renderer* renderer);
void requestShutdown(void);
bool frameEnded(const FrameEvent& evt);
bool mouseMoved( const OIS::MouseEvent &e );
bool mousePressed (const OIS::MouseEvent &e, OIS::MouseButtonID id);
bool mouseReleased( const OIS::MouseEvent &e, OIS::MouseButtonID id );
bool keyPressed( const OIS::KeyEvent &e );
bool keyReleased( const OIS::KeyEvent &e );
};
#endif
FrameListener.cpp
#include "Headfile.h"
#include "FrameListener.h"
CEGUI::MouseButton convertOgreButtonToCegui(int buttonID)
{
using namespace OIS;
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;
}
}
// NB using buffered input
GuiFrameListener::GuiFrameListener(RenderWindow* win, Camera* cam, CEGUI::Renderer* renderer)
: ExampleFrameListener(win, cam, true, true),
mGUIRenderer(renderer),
mShutdownRequested(false)
{
mMouse->setEventCallback( this );
mKeyboard->setEventCallback( this );
}
// Tell the frame listener to exit at the end of the next frame
void GuiFrameListener::requestShutdown(void)
{
mShutdownRequested = true;
}
bool GuiFrameListener::frameEnded(const FrameEvent& evt)
{
if (mShutdownRequested)
return false;
else
return ExampleFrameListener::frameEnded(evt);
}
bool GuiFrameListener::mouseMoved( const OIS::MouseEvent &e )
{
using namespace OIS;
CEGUI::System::getSingleton().injectMouseMove(e.state.X.rel,e.state.Y.rel);
return true;
}
bool GuiFrameListener::mousePressed (const OIS::MouseEvent &e, OIS::MouseButtonID id)
{
CEGUI::System::getSingleton().injectMouseButtonDown(convertOgreButtonToCegui(id));
return true;
}
bool GuiFrameListener::mouseReleased( const OIS::MouseEvent &e, OIS::MouseButtonID id )
{
CEGUI::System::getSingleton().injectMouseButtonUp(convertOgreButtonToCegui(id));
return true;
}
bool GuiFrameListener::keyPressed( const OIS::KeyEvent &e )
{
if(e.key == OIS::KC_ESCAPE)
{
mShutdownRequested = true;
return true;
}
CEGUI::System::getSingleton().injectKeyDown(e.key);
CEGUI::System::getSingleton().injectChar(e.text);
return true;
}
bool GuiFrameListener::keyReleased( const OIS::KeyEvent &e )
{
CEGUI::System::getSingleton().injectKeyUp(e.key);
return true;
}
最后的效果: