IntermediateTutorial4Source         Intermediate Tutorial 4 - source

This is the source for Intermediate Tutorial 4.

IntermediateTutorial4.h

#ifndef __IntermediateTutorial4_h_
#define __IntermediateTutorial4_h_

#include "BaseApplication.h"
#include "SelectionBox.h"

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

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

protected:
    virtual void createScene(void);

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

	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);

	void performSelection(const Ogre::Vector2& first, const Ogre::Vector2& second);
	void deselectObjects();
	void selectObject(Ogre::MovableObject* obj);

private:
	Ogre::Vector2 mStart, mStop;
	Ogre::PlaneBoundedVolumeListSceneQuery* mVolQuery;
	std::list<Ogre::MovableObject*> mSelected;
	bool bSelecting;
	CEGUI::OgreRenderer* mGUIRenderer;
	SelectionBox* mSelectionBox;

	static void swap(float& x, float& y);
};

#endif // #ifndef __IntermediateTutorial4_h_


IntermediateTutorial4.cpp

#include "IntermediateTutorial4.h"

//-------------------------------------------------------------------------------------
IntermediateTutorial4::IntermediateTutorial4(void):
mSelecting(false)
{
}

//-------------------------------------------------------------------------------------
IntermediateTutorial4::~IntermediateTutorial4(void)
{
	mSceneMgr->destroyQuery(mVolQuery);

	if(mSelectionBox)
	{
		delete mSelectionBox;
	}
}

//-------------------------------------------------------------------------------------
void IntermediateTutorial4::createScene(void)
{
	//set the ambient light of the scene to white
	mSceneMgr->setAmbientLight(Ogre::ColourValue(1.0f, 1.0f, 1.0f));
	
	//place a bunch of robots on the screen in a tiled formation
	for(int i = 0; i < 10; ++i)
	{
		for(int j = 0; j < 10; ++j)
		{
			Ogre::Entity* ent = mSceneMgr->createEntity("Robot" + Ogre::StringConverter::toString(i+j*10), "robot.mesh");
			Ogre::SceneNode* node = mSceneMgr->getRootSceneNode()->createChildSceneNode(Ogre::Vector3(i * 15, 0, j * 15));
			node->attachObject(ent);
			node->setScale(0.1f, 0.1f, 0.1f);
		}
	}

	//set the camera position and direction
	mCamera->setPosition(-60, 100, -60);
	mCamera->lookAt(60, 0, 60);

	//set up CEGUI
	mGUIRenderer = &CEGUI::OgreRenderer::bootstrapSystem();

	CEGUI::SchemeManager::getSingleton().create((CEGUI::utf8*)"TaharezLook.scheme");
	CEGUI::MouseCursor::getSingleton().setImage("TaharezLook", "MouseArrow");

	mSelectionBox = new SelectionBox("SelectionBox");
	mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(mSelectionBox);

	mVolQuery = mSceneMgr->createPlaneBoundedVolumeQuery(Ogre::PlaneBoundedVolumeList());
}

//-------------------------------------------------------------------------------------
bool IntermediateTutorial4::frameRenderingQueued(const Ogre::FrameEvent& evt)
{
	return BaseApplication::frameRenderingQueued(evt);
}

//-------------------------------------------------------------------------------------
bool IntermediateTutorial4::mouseMoved(const OIS::MouseEvent& arg)
{
	//let CEGUI know that the mouse moved
	CEGUI::System::getSingleton().injectMouseMove(arg.state.X.rel, arg.state.Y.rel);

        if (mSelecting)
        {
		CEGUI::MouseCursor* mouse = CEGUI::MouseCursor::getSingletonPtr();
		mStop.x = mouse->getPosition().d_x / float(arg.state.width);
		mStop.y = mouse->getPosition().d_y / float(arg.state.height);

		mSelectionBox->setCorners(mStart, mStop);
	}

	return true;
}

//-------------------------------------------------------------------------------------
bool IntermediateTutorial4::mousePressed(const OIS::MouseEvent& arg, OIS::MouseButtonID id)
{	
	if (mSelecting) {
		CEGUI::MouseCursor* mouse = CEGUI::MouseCursor::getSingletonPtr();
		mStart.x = mouse->getPosition().d_x / float(arg.state.width);
		mStart.y = mouse->getPosition().d_y / float(arg.state.height);
		mStop = mStart;

		bSelecting = true;
		mSelectionBox->clear();
		mSelectionBox->setVisible(true);
	}
	return true;
}

//-------------------------------------------------------------------------------------
bool IntermediateTutorial4::mouseReleased(const OIS::MouseEvent& arg, OIS::MouseButtonID id)
{	
	if (id == OIS::MB_LEFT) {
		performSelection(mStart, mStop);
		bSelecting = false;
		mSelectionBox->setVisible(false);
		return true;
	}
	return true;
}

//-------------------------------------------------------------------------------------
void IntermediateTutorial4::performSelection(const Ogre::Vector2& first, const Ogre::Vector2& second)
{
	float left = first.x, right = second.x;
	float top = first.y, bottom = second.y;

	if(left > right)
	{
		swap(left, right);
	}
	if(top > bottom)
	{
		swap(top, bottom);
	}

	if((right - left) * (bottom - top) < 0.0001)
	{
		return;
	}

	Ogre::Ray topLeft = mCamera->getCameraToViewportRay(left, top);
	Ogre::Ray topRight = mCamera->getCameraToViewportRay(right, top); 
	Ogre::Ray bottomLeft = mCamera->getCameraToViewportRay(left, bottom);
	Ogre::Ray bottomRight = mCamera->getCameraToViewportRay(right, bottom);

	Ogre::PlaneBoundedVolume vol;

	vol.planes.push_back(Ogre::Plane(topLeft.getPoint(3), topRight.getPoint(3), bottomRight.getPoint(3)));
	vol.planes.push_back(Ogre::Plane(topLeft.getOrigin(), topLeft.getPoint(100), topRight.getPoint(100)));
	vol.planes.push_back(Ogre::Plane(topLeft.getOrigin(), bottomLeft.getPoint(100), topLeft.getPoint(100)));
	vol.planes.push_back(Ogre::Plane(bottomLeft.getOrigin(), bottomRight.getPoint(100), bottomLeft.getPoint(100)));
	vol.planes.push_back(Ogre::Plane(topRight.getOrigin(), topRight.getPoint(100), bottomRight.getPoint(100)));

	Ogre::PlaneBoundedVolumeList volList;
	volList.push_back(vol);

	mVolQuery->setVolumes(volList);	
	Ogre::SceneQueryResult& result = mVolQuery->execute();

	deselectObjects();
	Ogre::SceneQueryResultMovableList::iterator iter;
	for(iter = result.movables.begin(); iter != result.movables.end(); iter++)
	{
		selectObject(*iter);
	}
}

//-------------------------------------------------------------------------------------
void IntermediateTutorial4::deselectObjects()
{
	std::list<Ogre::MovableObject*>::iterator iter;

	for(iter = mSelected.begin(); iter != mSelected.end(); iter++)
	{
		(*iter)->getParentSceneNode()->showBoundingBox(false);
	}
}

//-------------------------------------------------------------------------------------
void IntermediateTutorial4::selectObject(Ogre::MovableObject* obj)
{
	obj->getParentSceneNode()->showBoundingBox(true);
	mSelected.push_back(obj);
}

//-------------------------------------------------------------------------------------
//Simple function that just swaps float values
void IntermediateTutorial4::swap(float& x, float& y)
{
	float temp = x;
	x = y;
	y = temp;
}

//-------------------------------------------------------------------------------------
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
#endif

#ifdef __cplusplus
extern "C" {
#endif

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
	INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
#else
	int main(int argc, char *argv[])
#endif
	{
		// Create application object
		IntermediateTutorial4 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
			std::cerr << "An exception has occured: " <<
				e.getFullDescription().c_str() << std::endl;
#endif
		}

		return 0;
	}

#ifdef __cplusplus
}
#endif


SelectionBox.h

#ifndef __SelectionBox_h_
#define __SelectionBox_h_

#include "OgreManualObject.h"

class SelectionBox : public Ogre::ManualObject
{
public :
	SelectionBox(const Ogre::String& name);
	~SelectionBox(void);

	void setCorners(float left, float top, float right, float bottom);
	void setCorners(const Ogre::Vector2& topLeft, const Ogre::Vector2& topRight);
};

#endif


SelectionBox.cpp

#include "SelectionBox.h"

//-------------------------------------------------------------------------------------
SelectionBox::SelectionBox(const Ogre::String& name): Ogre::ManualObject(name)
{
	setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY);
	setUseIdentityProjection(true);
	setUseIdentityView(true);
	setQueryFlags(0);
}

//-------------------------------------------------------------------------------------
SelectionBox::~SelectionBox()
{
}

//-------------------------------------------------------------------------------------
//sets the actual corners of the box
void SelectionBox::setCorners(float left, float top, float right, float bottom)
{
	left = left * 2 - 1;
	right = right * 2 - 1;
	top = 1 - top * 2;
	bottom = 1 - bottom * 2;

	clear();
	begin("",Ogre::RenderOperation::OT_LINE_STRIP);
		position(left, top, -1);
		position(right, top, -1);
		position(right, bottom, -1);
		position(left, bottom, -1);
		position(left, top, -1);
	end();

	setBoundingBox(Ogre::AxisAlignedBox::BOX_INFINITE);
}

//-------------------------------------------------------------------------------------
//an overridden function to do the same as before but you can pass vector2s instead
void SelectionBox::setCorners(const Ogre::Vector2& topLeft, const Ogre::Vector2& bottomRight)
{
	setCorners(topLeft.x, topLeft.y, bottomRight.x, bottomRight.y);
}