Advanced Ogre Framework         A young Ogre programmers Advanced Framework
Print

AppState.hpp

In this file, two classes are defined:

  • AppStateListener and
  • AppState

 
The first class will later be inherited by the application state manager, but has to be defined here due to design reasons.

  • AppStateListener(): Constructor
  • ~AppStateListener(): Destructor
  • manageGameState(): Function to later add a new state to the manager
  • changeAppState(): Exits the current app state and starts the one specified as the parameter
  • pushAppState(): Puts a new app state on the active state stack that will then be excecuted
  • popGameState(): Removes the top active state from the stack, which results in returning to the one below
  • shutdown(): Well, guess what happens here...
  • popAllAndPushAppState(): Removes all current app states from the stack and moves to the given new state

 
The second class is the app state blueprint from which each actual application state will inherit:

  • some functions to enter, exit, pause, resume and update the state
  • some functions to call other states (orders the manager to start them)
  • a pointer to the manager (which is also a AppStateListener)
  • own Camera and SceneManager

 
The last part of this file is a big #define statement. It defines the macro DECLARE_APPSTATE_CLASS via that you can later create the game states.

Note: The backslashes there are very important as they tell the compiler to take those lines as one big one. Otherwise you would get compiler errors...

//|||||||||||||||||||||||||||||||||||||||||||||||
 
#ifndef APP_STATE_HPP
#define APP_STATE_HPP
 
//|||||||||||||||||||||||||||||||||||||||||||||||
 
#include "AdvancedOgreFramework.hpp"
 
class AppState;
 
//|||||||||||||||||||||||||||||||||||||||||||||||
 
class AppStateListener
{
public:
	AppStateListener(){};
	virtual ~AppStateListener(){};
 
	virtual void manageAppState(Ogre::String stateName, AppState* state) = 0;
 
	virtual AppState*	findByName(Ogre::String stateName) = 0;
	virtual void		changeAppState(AppState *state) = 0;
	virtual bool		pushAppState(AppState* state) = 0;
	virtual void		popAppState() = 0;
	virtual void		pauseAppState() = 0;
	virtual void		shutdown() = 0;
        virtual void            popAllAndPushAppState(AppState* state) = 0;
};
 
//|||||||||||||||||||||||||||||||||||||||||||||||
 
class AppState : public OIS::KeyListener, public OIS::MouseListener, public OgreBites::SdkTrayListener
{
public:
	static void create(AppStateListener* parent, const Ogre::String name){};
 
	void destroy(){delete this;}
 
	virtual void enter() = 0;
	virtual void exit() = 0;
	virtual bool pause(){return true;}
	virtual void resume(){};
	virtual void update(double timeSinceLastFrame) = 0;
 
protected:
	AppState(){};
 
	AppState*	findByName(Ogre::String stateName){return m_pParent->findByName(stateName);}
	void		changeAppState(AppState* state){m_pParent->changeAppState(state);}
	bool		pushAppState(AppState* state){return m_pParent->pushAppState(state);}
	void		popAppState(){m_pParent->popAppState();}
	void		shutdown(){m_pParent->shutdown();}
        void            popAllAndPushAppState(AppState* state){m_pParent->popAllAndPushAppState(state);}
 
	AppStateListener*	m_pParent;
 
	Ogre::Camera*		m_pCamera;
	Ogre::SceneManager*	m_pSceneMgr;
        Ogre::FrameEvent        m_FrameEvent;
};
 
//|||||||||||||||||||||||||||||||||||||||||||||||
 
#define DECLARE_APPSTATE_CLASS(T)					\
static void create(AppStateListener* parent, const Ogre::String name)	\
{									\
	T* myAppState = new T();					\
	myAppState->m_pParent = parent;					\
	parent->manageAppState(name, myAppState);			\
}
 
//|||||||||||||||||||||||||||||||||||||||||||||||
 
#endif
 
//|||||||||||||||||||||||||||||||||||||||||||||||

 

AppStateManager.hpp

The class AppStateManager inherits from the class AppStateListener shown above and mainly implements its abstract methods. Furthermore it contains:

  • a std::vector for all existing states (m_States)
  • a std::vector for the active states, so the stack of those states currently is use (m_ActiveStateStack)

 

//|||||||||||||||||||||||||||||||||||||||||||||||
 
#ifndef APP_STATE_MANAGER_HPP
#define APP_STATE_MANAGER_HPP
 
//|||||||||||||||||||||||||||||||||||||||||||||||
 
#include "AppState.hpp"
 
//|||||||||||||||||||||||||||||||||||||||||||||||
 
class AppStateManager : public AppStateListener
{
public:
	typedef struct
	{
		Ogre::String name;
		AppState* state;
	} state_info;
 
	AppStateManager();
	~AppStateManager();
 
	void manageAppState(Ogre::String stateName, AppState* state);
 
	AppState* findByName(Ogre::String stateName);
 
	void start(AppState* state);
	void changeAppState(AppState* state);
	bool pushAppState(AppState* state);
	void popAppState();
	void pauseAppState();
	void shutdown();
        void popAllAndPushAppState(AppState* state);
 
protected:
	void init(AppState *state);
 
	std::vector<AppState*>		m_ActiveStateStack;
	std::vector<state_info>		m_States;
	bool				m_bShutdown;
};
 
//|||||||||||||||||||||||||||||||||||||||||||||||
 
#endif
 
//|||||||||||||||||||||||||||||||||||||||||||||||

 

AppStateManager.cpp

  • AppStateManager(): Constructor, just setting the shutdown indicator
  • ~AppStateManager(): Destructor, exiting all active application states and emptying the std::vectors

 

//|||||||||||||||||||||||||||||||||||||||||||||||
 
#include "AppStateManager.hpp"
 
#include <OgreWindowEventUtilities.h>
 
//|||||||||||||||||||||||||||||||||||||||||||||||
 
AppStateManager::AppStateManager()
{
	m_bShutdown = false;
}
 
//|||||||||||||||||||||||||||||||||||||||||||||||
 
AppStateManager::~AppStateManager()
{
	state_info si;
 
        while(!m_ActiveStateStack.empty())
	{
		m_ActiveStateStack.back()->exit();
		m_ActiveStateStack.pop_back();
	}
 
	while(!m_States.empty())
	{
		si = m_States.back();
                si.state->destroy();
                m_States.pop_back();
	}
}

 

  • manageAppState(): Called from within the state creation macro and sets some information of the new state, as well as pushing it on the active states stack
void AppStateManager::manageAppState(Ogre::String stateName, AppState* state)
{
	try
	{
		state_info new_state_info;
		new_state_info.name = stateName;
		new_state_info.state = state;
		m_States.push_back(new_state_info);		
	}
	catch(std::exception& e)
	{
		delete state;
		throw Ogre::Exception(Ogre::Exception::ERR_INTERNAL_ERROR, "Error while trying to manage a new AppState\n" + Ogre::String(e.what()), "AppStateManager.cpp (39)");
	}
}

 

  • findByName(): Returns a pointer to the state with the respective name
AppState* AppStateManager::findByName(Ogre::String stateName)
{
	std::vector<state_info>::iterator itr;
 
	for(itr=m_States.begin();itr!=m_States.end();itr++)
	{
		if(itr->name==stateName)
			return itr->state;
	}
 
	return 0;
}

 

  • start(): Main loop of the application that does the following steps:
  1. change to the state specified
  2. start loop
  3. capture keyboard and mouse input
  4. update the current state (the top most of the stack)
  5. call the OgreFramework class to update and render
void AppStateManager::start(AppState* state)
{
	changeAppState(state);
 
	int timeSinceLastFrame = 1;
	int startTime = 0;
 
	while(!m_bShutdown)
	{
		if(OgreFramework::getSingletonPtr()->m_pRenderWnd->isClosed())m_bShutdown = true;
 
		Ogre::WindowEventUtilities::messagePump();
 
		if(OgreFramework::getSingletonPtr()->m_pRenderWnd->isActive())
		{
			startTime = OgreFramework::getSingletonPtr()->m_pTimer->getMillisecondsCPU();
 
			OgreFramework::getSingletonPtr()->m_pKeyboard->capture();
			OgreFramework::getSingletonPtr()->m_pMouse->capture();
 
			m_ActiveStateStack.back()->update(timeSinceLastFrame);
 
			OgreFramework::getSingletonPtr()->updateOgre(timeSinceLastFrame);
			OgreFramework::getSingletonPtr()->m_pRoot->renderOneFrame();
 
			timeSinceLastFrame = OgreFramework::getSingletonPtr()->m_pTimer->getMillisecondsCPU() - startTime;
		}
		else
		{
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
            Sleep(1000);
#else
            sleep(1);
#endif
		}
	}
 
	OgreFramework::getSingletonPtr()->m_pLog->logMessage("Main loop quit");
}

 

  • changeAppState(): Exits the current state (if there is any) and starts the new specified one
void AppStateManager::changeAppState(AppState* state)
{
	if(!m_ActiveStateStack.empty())
	{
		m_ActiveStateStack.back()->exit();
		m_ActiveStateStack.pop_back();
	}
 
	m_ActiveStateStack.push_back(state);
	init(state);
	m_ActiveStateStack.back()->enter();
}

 

  • pushAppState(): Puts an new state on the top of the stack and starts it
bool AppStateManager::pushAppState(AppState* state)
{
	if(!m_ActiveStateStack.empty())
	{
		if(!m_ActiveStateStack.back()->pause())
			return false;
	}
 
	m_ActiveStateStack.push_back(state);
	init(state);
	m_ActiveStateStack.back()->enter();
 
	return true;
}

 

  • popAppState(): Removes the top most state and resumes the one below if there is one, otherwise shutdown the application
void AppStateManager::popAppState()
{
	if(!m_ActiveStateStack.empty())
	{
		m_ActiveStateStack.back()->exit();
		m_ActiveStateStack.pop_back();
	}
 
	if(!m_ActiveStateStack.empty())
	{
		init(m_ActiveStateStack.back());
		m_ActiveStateStack.back()->resume();
	}
    else
		shutdown();
}

 

  • popAllAndPushAppState(): Exits all existing app state on the stack and enters the given new state
void AppStateManager::popAllAndPushAppState(AppState* state)
{
    while(!m_ActiveStateStack.empty())
    {
        m_ActiveStateStack.back()->exit();
        m_ActiveStateStack.pop_back();
    }
 
    pushAppState(state);
}

 

  • pauseAppState(): Pauses the current app state and resumes the one in the stack below
void AppStateManager::pauseAppState()
{
	if(!m_ActiveStateStack.empty())
	{
		m_ActiveStateStack.back()->pause();
	}
 
	if(m_ActiveStateStack.size() > 2)
	{
		init(m_ActiveStateStack.at(m_ActiveStateStack.size() - 2));
		m_ActiveStateStack.at(m_ActiveStateStack.size() - 2)->resume();
	}
}

 

  • shutdown(): Exits the application
void AppStateManager::shutdown()
{
	m_bShutdown = true;
}

 

  • init(): Initializes a new state and links the input and SDKTrays callback on it, as well as resetting the Ogre statistics (FPS?, triangle count, batch count, ...)
void AppStateManager::init(AppState* state)
{
    OgreFramework::getSingletonPtr()->m_pKeyboard->setEventCallback(state);
	OgreFramework::getSingletonPtr()->m_pMouse->setEventCallback(state);
    OgreFramework::getSingletonPtr()->m_pTrayMgr->setListener(state);
 
	OgreFramework::getSingletonPtr()->m_pRenderWnd->resetStatistics();
}

 

The MenuState class is one of the actual AppState class implementations. By inheriting from AppState it is assured that it will have the same common functions enter(), exit(), pause(), resume() and update().

  • DECLARE_APPSTATE_CLASS(MenuState): This line calls the macro defined in AppState.hpp, making this class a valid application state

 

//|||||||||||||||||||||||||||||||||||||||||||||||
 
#ifndef MENU_STATE_HPP
#define MENU_STATE_HPP
 
//|||||||||||||||||||||||||||||||||||||||||||||||
 
#include "AppState.hpp"
 
//|||||||||||||||||||||||||||||||||||||||||||||||
 
class MenuState : public AppState
{
public:
    MenuState();
 
	DECLARE_APPSTATE_CLASS(MenuState)
 
	void enter();
	void createScene();
	void exit();
 
	bool keyPressed(const OIS::KeyEvent &keyEventRef);
	bool keyReleased(const OIS::KeyEvent &keyEventRef);
 
	bool mouseMoved(const OIS::MouseEvent &evt);
	bool mousePressed(const OIS::MouseEvent &evt, OIS::MouseButtonID id);
	bool mouseReleased(const OIS::MouseEvent &evt, OIS::MouseButtonID id);
 
	void buttonHit(OgreBites::Button* button);
 
	void update(double timeSinceLastFrame);
 
private:
	bool m_bQuit;
};
 
//|||||||||||||||||||||||||||||||||||||||||||||||
 
#endif
 
//|||||||||||||||||||||||||||||||||||||||||||||||

 

  • enter(): Always called when starting this state and does the following steps:
  1. create SceneManager
  2. create a Camera
  3. set input callbacks
  4. build GUI
  5. call createScene() to fill the scene with content
//|||||||||||||||||||||||||||||||||||||||||||||||
 
#include "MenuState.hpp"
 
//|||||||||||||||||||||||||||||||||||||||||||||||
 
using namespace Ogre;
 
//|||||||||||||||||||||||||||||||||||||||||||||||
 
MenuState::MenuState()
{
    m_bQuit         = false;
    m_FrameEvent    = Ogre::FrameEvent();
}
 
//|||||||||||||||||||||||||||||||||||||||||||||||
 
void MenuState::enter()
{
    OgreFramework::getSingletonPtr()->m_pLog->logMessage("Entering MenuState...");
 
    m_pSceneMgr = OgreFramework::getSingletonPtr()->m_pRoot->createSceneManager(ST_GENERIC, "MenuSceneMgr");
    m_pSceneMgr->setAmbientLight(Ogre::ColourValue(0.7f, 0.7f, 0.7f));
 
    m_pCamera = m_pSceneMgr->createCamera("MenuCam");
    m_pCamera->setPosition(Vector3(0, 25, -50));
    m_pCamera->lookAt(Vector3(0, 0, 0));
    m_pCamera->setNearClipDistance(1);
 
    m_pCamera->setAspectRatio(Real(OgreFramework::getSingletonPtr()->m_pViewport->getActualWidth()) /
        Real(OgreFramework::getSingletonPtr()->m_pViewport->getActualHeight()));
 
    OgreFramework::getSingletonPtr()->m_pViewport->setCamera(m_pCamera);
 
    OgreFramework::getSingletonPtr()->m_pTrayMgr->destroyAllWidgets();
    OgreFramework::getSingletonPtr()->m_pTrayMgr->showFrameStats(OgreBites::TL_BOTTOMLEFT);
    OgreFramework::getSingletonPtr()->m_pTrayMgr->showLogo(OgreBites::TL_BOTTOMRIGHT);
    OgreFramework::getSingletonPtr()->m_pTrayMgr->showCursor();
    OgreFramework::getSingletonPtr()->m_pTrayMgr->createButton(OgreBites::TL_CENTER, "EnterBtn", "Enter GameState", 250);
    OgreFramework::getSingletonPtr()->m_pTrayMgr->createButton(OgreBites::TL_CENTER, "ExitBtn", "Exit AdvancedOgreFramework", 250);
    OgreFramework::getSingletonPtr()->m_pTrayMgr->createLabel(OgreBites::TL_TOP, "MenuLbl", "Menu mode", 250);
 
    createScene();
}

 

  • createScene(): Fill the scene with content (no content in the MenuState here)
  • exit(): Destroys the Camera and the SceneManager as well as the GUI elements
void MenuState::createScene()
{
}
 
//|||||||||||||||||||||||||||||||||||||||||||||||
 
void MenuState::exit()
{
    OgreFramework::getSingletonPtr()->m_pLog->logMessage("Leaving MenuState...");
 
    m_pSceneMgr->destroyCamera(m_pCamera);
    if(m_pSceneMgr)
        OgreFramework::getSingletonPtr()->m_pRoot->destroySceneManager(m_pSceneMgr);
 
    OgreFramework::getSingletonPtr()->m_pTrayMgr->clearAllTrays();
    OgreFramework::getSingletonPtr()->m_pTrayMgr->destroyAllWidgets();
    OgreFramework::getSingletonPtr()->m_pTrayMgr->setListener(0);
}

 

Input handling functions:

  • keyPressed(): Quits on Escape and forwards the unhandled input to the OgreFramework class
  • keyReleased(): Only forwards to the OgreFramework class
  • mouseMoved(): Injects the mouse movements to the GUI
  • mousePressed(): Injects the mouse clicks to the GUI
  • mouseReleased(): Injects the mouse clicks to the GUI
bool MenuState::keyPressed(const OIS::KeyEvent &keyEventRef)
{
    if(OgreFramework::getSingletonPtr()->m_pKeyboard->isKeyDown(OIS::KC_ESCAPE))
    {
        m_bQuit = true;
        return true;
    }
 
    OgreFramework::getSingletonPtr()->keyPressed(keyEventRef);
    return true;
}
 
//|||||||||||||||||||||||||||||||||||||||||||||||
 
bool MenuState::keyReleased(const OIS::KeyEvent &keyEventRef)
{
    OgreFramework::getSingletonPtr()->keyReleased(keyEventRef);
    return true;
}
 
//|||||||||||||||||||||||||||||||||||||||||||||||
 
bool MenuState::mouseMoved(const OIS::MouseEvent &evt)
{
    if(OgreFramework::getSingletonPtr()->m_pTrayMgr->injectMouseMove(evt)) return true;
    return true;
}
 
//|||||||||||||||||||||||||||||||||||||||||||||||
 
bool MenuState::mousePressed(const OIS::MouseEvent &evt, OIS::MouseButtonID id)
{
    if(OgreFramework::getSingletonPtr()->m_pTrayMgr->injectMouseDown(evt, id)) return true;
    return true;
}
 
//|||||||||||||||||||||||||||||||||||||||||||||||
 
bool MenuState::mouseReleased(const OIS::MouseEvent &evt, OIS::MouseButtonID id)
{
    if(OgreFramework::getSingletonPtr()->m_pTrayMgr->injectMouseUp(evt, id)) return true;
    return true;
}

 

  • update(): Updates the GUI and checks whether the state is to be quit.
void MenuState::update(double timeSinceLastFrame)
{
    m_FrameEvent.timeSinceLastFrame = timeSinceLastFrame;
    OgreFramework::getSingletonPtr()->m_pTrayMgr->frameRenderingQueued(m_FrameEvent);
 
    if(m_bQuit == true)
    {
        shutdown();
        return;
    }
}

 

  • buttonHit(): Callback function that gets triggered when a button is hit.
void MenuState::buttonHit(OgreBites::Button *button)
{
    if(button->getName() == "ExitBtn")
        m_bQuit = true;
    else if(button->getName() == "EnterBtn")
        changeAppState(findByName("GameState"));
}

 



Contributors to this page: Hazzr762 points  , Spacegaier6073 points  , Slappy251 points  , progman118 points  , jacmoe180265 points  , fsxfreak260 points  and DarkAnt347 points  .
Page last modified on Tuesday 10 of September, 2013 16:04:13 UTC by Hazzr762 points .


The content on this page is licensed under the terms of the Creative Commons Attribution-ShareAlike License.
As an exception, any source code contributed within the content is released into the Public Domain.