00001 #include "UnitSelecter.h"
00002
00003 #include "Game.h"
00004 #include "Unit.h"
00005 #include "ControlGroup.h"
00006 #include "Team.h"
00007
00008 #include "OgreOverlayManager.h"
00009 #include "OgreOverlayContainer.h"
00010 #include "OgreViewport.h"
00011 #include "OgreEntity.h"
00012 #include "OgreSceneManager.h"
00013 #include "OgreVector3.h"
00014 #include "OgreMath.h"
00015 #include "OgreStringConverter.h"
00016 #include "OgreLogManager.h"
00017
00018 using Ogre::StringConverter;
00019 using Ogre::LogManager;
00020 using Ogre::OverlayManager;
00021 using Ogre::OverlayContainer;
00022 using Ogre::Viewport;
00023 using Ogre::Degree;
00024 using Ogre::EntityFactory;
00025 using Ogre::MovableObject;
00026 using Ogre::SceneNode;
00027 using Ogre::SceneManager;
00028 using Ogre::Vector3;
00029 using Ogre::RaySceneQueryResult;
00030 using Ogre::SceneManager;
00031
00032 #include <vector>
00033 using std::vector;
00034
00035
00036
00037 namespace ASR
00038 {
00039
00040 UnitSelecter::UnitSelecter ( Team* team, Camera* camera )
00041 : mTeam ( team ), mCamera ( camera )
00042 {
00043 SceneManager* sceneMgr = Game::getSingleton().getSceneManager ();
00044
00045
00046
00047
00048 for ( int i = 0; i < 5; i++ )
00049 {
00050 mCubes[i] = sceneMgr->createEntity ( StringConverter::toString(i), "cube.mesh" );
00051 mNodes[i] = sceneMgr->getRootSceneNode ()->createChildSceneNode ( StringConverter::toString(i) );
00052 mNodes[i]->attachObject( mCubes[i] );
00053 mNodes[i]->scale ( 0.15, 0.15, 0.15 );
00054
00055 mNodes[i]->setVisible( false );
00056 }
00057
00058 mOverlay = OverlayManager::getSingleton().getByName("ASR/SelectionOverlay");
00059 mOverlay->hide();
00060
00061 mBounds[0] = Vector2::ZERO;
00062 mBounds[1] = Vector2::ZERO;
00063
00064 mAbsMouse[0] = 0.0f;
00065 mAbsMouse[1] = 0.0f;
00066
00067 mFirstPoint = false;
00068
00069 mRayQuery = sceneMgr->createRayQuery( Ray() );
00070 }
00071
00072
00073
00074 UnitSelecter::~UnitSelecter(void)
00075 {
00076 SceneManager* sceneMgr = Game::getSingletonPtr ()->getSceneManager ();
00077 sceneMgr->destroyQuery ( mRayQuery );
00078 }
00079
00080
00081
00082 void UnitSelecter::_moveUnits ()
00083 {
00084 if ( mTeam->getActiveControlGroup ()->getNumUnits () == 0 )
00085 return;
00086
00087 Vector3 destPos = _getMousePosition();
00088 Unit* leader = mTeam->getActiveControlGroup ()->getLeaderUnit ();
00089
00090 if ( leader->setDestination ( destPos ) )
00091 {
00092 ControlGroup* activeGroup = mTeam->getActiveControlGroup ();
00093
00094
00095
00096
00097
00098
00099 activeGroup->setDestination ( destPos );
00100 activeGroup->update ();
00101
00102
00103 for ( unsigned int i = 1; i < activeGroup->getNumUnits (); i++ )
00104 {
00105 Level::LevelNode* endNode = Level::getSingleton ().getClosestNode ( activeGroup->getUnitDestination ( i ) );
00106 activeGroup->getUnit ( i )->setDestination ( endNode->getWorldPosition () );
00107 }
00108 }
00109
00112 }
00113
00114
00115
00116 void UnitSelecter::_selectUnits ()
00117 {
00118 int screenWidth = mCamera->getViewport()->getActualWidth() / 2;
00119 int screenHeight = mCamera->getViewport()->getActualHeight() / 2;
00120
00121 mOverlay->show ();
00122
00123
00124 if ( !mFirstPoint )
00125 {
00126 mBounds[0].x = mAbsMouse[0];
00127 mBounds[0].y = mAbsMouse[1];
00128
00129 mBounds[1].x = mBounds[0].x;
00130 mBounds[1].y = mBounds[0].y;
00131
00132 mFirstPoint = true;
00133 }
00134 else
00135 {
00136 mBounds[1].x = mAbsMouse[0];
00137 mBounds[1].y = mAbsMouse[1];
00138 }
00139
00140 Vector2 topLeft;
00141 Vector2 bottomRight;
00142
00143 topLeft.x = ( mBounds[0].x < mBounds[1].x ) ? mBounds[0].x : mBounds[1].x;
00144 topLeft.y = ( mBounds[0].y < mBounds[1].y ) ? mBounds[0].y : mBounds[1].y;
00145
00146 bottomRight.x = ( mBounds[0].x > mBounds[1].x ) ? mBounds[0].x : mBounds[1].x;
00147 bottomRight.y = ( mBounds[0].y > mBounds[1].y ) ? mBounds[0].y : mBounds[1].y;
00148
00149 int width = bottomRight.x - topLeft.x;
00150 int height = bottomRight.y - topLeft.y;
00151
00152 OverlayContainer* cont = NULL;
00153
00154
00155 cont = mOverlay->getChild( "ASR/Left" );
00156 cont->setLeft ( topLeft.x + screenWidth );
00157 cont->setTop ( topLeft.y + screenHeight );
00158 cont->setWidth ( 5 );
00159 cont->setHeight ( height );
00160
00161
00162 cont = mOverlay->getChild( "ASR/Right" );
00163 cont->setLeft ( bottomRight.x + screenWidth );
00164 cont->setTop ( topLeft.y + screenHeight );
00165 cont->setWidth ( 5 );
00166 cont->setHeight ( height + 5 );
00167
00168
00169 cont = mOverlay->getChild( "ASR/Top" );
00170 cont->setLeft ( topLeft.x + screenWidth );
00171 cont->setTop ( topLeft.y + screenHeight );
00172 cont->setWidth ( width );
00173 cont->setHeight ( 5 );
00174
00175
00176 cont = mOverlay->getChild( "ASR/Bottom" );
00177 cont->setLeft ( topLeft.x + screenWidth );
00178 cont->setTop ( bottomRight.y + screenHeight );
00179 cont->setWidth ( width + 5 );
00180 cont->setHeight ( 5 );
00181
00182
00183
00184 Ray points[2];
00185 float fLeft = (topLeft.x + screenWidth ) / mCamera->getViewport()->getActualWidth();
00186 float fTop = (topLeft.y + screenHeight ) / mCamera->getViewport()->getActualHeight();
00187
00188 float fRight = (bottomRight.x + screenWidth ) / mCamera->getViewport()->getActualWidth();
00189 float fBottom = (bottomRight.y + screenHeight ) / mCamera->getViewport()->getActualHeight();
00190
00191 points[0] = mCamera->getCameraToViewportRay( fLeft, fTop );
00192 points[1] = mCamera->getCameraToViewportRay( fRight, fBottom );
00193
00194 Vector3 worldPos[2];
00195
00196 mRayQuery->setRay ( points[0] );
00197 RaySceneQueryResult& results = mRayQuery->execute();
00198 RaySceneQueryResult::iterator iter = results.begin();
00199 if ( iter != results.end() && iter->worldFragment )
00200 {
00201 worldPos[0] = iter->worldFragment->singleIntersection;
00202 }
00203
00204 else
00205 {
00206 worldPos[0] = Vector3::ZERO;
00207 }
00208
00209 mRayQuery->setRay ( points[1] );
00210 results = mRayQuery->execute();
00211 iter = results.begin();
00212 if ( iter != results.end() && iter->worldFragment )
00213 {
00214 worldPos[1] = iter->worldFragment->singleIntersection;
00215 }
00216 else
00217 {
00218 worldPos[1] = Vector3::ZERO;
00219 }
00220
00221 mNodes[1]->setPosition( worldPos[0] );
00222 mNodes[1]->setVisible ( true );
00223 mNodes[2]->setPosition( worldPos[1] );
00224 mNodes[2]->setVisible ( true );
00225
00226
00227
00228
00229
00230
00231 SceneManager* sceneMgr = Game::getSingletonPtr ()->getSceneManager ();
00232 SceneNode* root = sceneMgr->getRootSceneNode();
00233
00234
00235 TeamUnits::UnitIterator unitIter = mTeam->getUnitIterator ();
00236 while ( unitIter.hasMoreElements () )
00237 {
00238 Unit* curUnit = unitIter.getNext ();
00239
00240 if ( curUnit->isDead () )
00241 continue;
00242
00243 Vector3 pos = curUnit->getPosition ();
00244 if ( pos.x >= worldPos[0].x && pos.x <= worldPos[1].x )
00245 {
00246 if ( pos.z >= worldPos[0].z && pos.z <= worldPos[1].z )
00247 {
00248 _selectUnit ( curUnit );
00249 mSelectedUnits.push_back( curUnit );
00250 }
00251 }
00252 }
00253 }
00254
00255
00256
00257 bool UnitSelecter::updateBeforeFrame ( const FrameEvent& e, const InputReader* inputDevice )
00258 {
00259 int screenWidth = mCamera->getViewport()->getActualWidth() / 2;
00260 int screenHeight = mCamera->getViewport()->getActualHeight() / 2;
00261
00262
00263
00264 const int MOUSE_SPEED = 2;
00265 mAbsMouse[0] += inputDevice->getMouseRelativeX() * MOUSE_SPEED;
00266 mAbsMouse[1] += inputDevice->getMouseRelativeY() * MOUSE_SPEED;
00267
00268 if ( mAbsMouse[0] < -screenWidth )
00269 mAbsMouse[0] = -screenWidth;
00270 if ( mAbsMouse[0] > screenWidth )
00271 mAbsMouse[0] = screenWidth;
00272
00273 if ( mAbsMouse[1] < -screenHeight )
00274 mAbsMouse[1] = -screenHeight;
00275 if ( mAbsMouse[1] > screenHeight )
00276 mAbsMouse[1] = screenHeight;
00277
00278 static bool rightUp = true;
00279
00280
00281 if ( inputDevice->getMouseButton( 1 ) && rightUp )
00282 {
00283 rightUp = false;
00284 _moveUnits ();
00285 }
00286
00287
00288 else if ( inputDevice->getMouseButton( 0 ) )
00289 {
00290 mSelectedUnits.clear ();
00291
00292 mNodes[1]->setVisible( true );
00293 mNodes[2]->setVisible( true );
00294
00295 _unselectCurrect ();
00296 _selectUnits ();
00297 _createActiveGroup ();
00298
00299 mSelectedUnits.clear ();
00300 }
00301
00302 else
00303 {
00304 mFirstPoint = false;
00305
00306 mOverlay->hide ();
00307 mNodes[1]->setVisible( false );
00308 mNodes[2]->setVisible( false );
00309
00310
00311 mBounds[0].x = -1;
00312 mBounds[1].x = -1;
00313 }
00314
00315 if ( !inputDevice->getMouseButton(1) )
00316 rightUp = true;
00317
00318 _unselectDeadUnits ();
00319
00320 return true;
00321 }
00322
00323
00324
00325 bool UnitSelecter::updateAfterFrame ( const FrameEvent& e, const InputReader* inputDevice )
00326 {
00327 return true;
00328 }
00329
00330
00331
00332 void UnitSelecter::_unselectDeadUnits ()
00333 {
00334 ControlGroup* activeGroup = mTeam->getActiveControlGroup ();
00335 if ( activeGroup->getNumUnits () == 0 )
00336 return;
00337
00338 vector<Unit*> deadUnits;
00339 Unit* curUnit;
00340 for ( unsigned int i = 0; i < activeGroup->getNumUnits(); i++ )
00341 {
00342 curUnit = activeGroup->getUnit(i);
00343 if ( curUnit->isDead() )
00344 {
00345 deadUnits.push_back ( curUnit );
00346 }
00347 }
00348
00349
00350 if ( deadUnits.size() == activeGroup->getNumUnits () )
00351 {
00352 mTeam->destroyActiveControlGroup ();
00353 mTeam->setActiveControlGroup ( mTeam->createControlGroup () );
00354 }
00355 else
00356 {
00357 for ( unsigned int i = 0; i < deadUnits.size(); i++ )
00358 {
00359 activeGroup->removeUnit ( deadUnits[i] );
00360 _unselectUnit ( deadUnits[i] );
00361 }
00362 }
00363 }
00364
00365
00366
00367 Vector3 UnitSelecter::_getMousePosition ()
00368 {
00369 int screenWidth = mCamera->getViewport()->getActualWidth() / 2;
00370 int screenHeight = mCamera->getViewport()->getActualHeight() / 2;
00371
00372
00373 float screenX = (mAbsMouse[0] + screenWidth ) / mCamera->getViewport()->getActualWidth();
00374 float screenY = (mAbsMouse[1] + screenHeight ) / mCamera->getViewport()->getActualHeight();
00375
00376 Ray point = mCamera->getCameraToViewportRay( screenX, screenY );
00377 mRayQuery->setRay ( point );
00378
00379 Vector3 position = Vector3::NEGATIVE_UNIT_X;
00380
00381 RaySceneQueryResult& results = mRayQuery->execute();
00382 RaySceneQueryResult::iterator iter = results.begin();
00383 while ( iter != results.end () )
00384 {
00385 if ( iter->worldFragment )
00386 {
00387 position = iter->worldFragment->singleIntersection;
00388 break;
00389 }
00390 iter++;
00391 }
00392
00393 if ( iter == results.end() )
00394 {
00395 mNodes[0]->setVisible( false );
00396 }
00397 else
00398 {
00399 mNodes[0]->setVisible( true );
00400 mNodes[0]->setPosition ( position );
00401 }
00402
00403 return position;
00404 }
00405
00406
00407
00408 void UnitSelecter::_unselectCurrect ()
00409 {
00410 ControlGroup* activeGroup = mTeam->getActiveControlGroup ();
00411
00412 for ( unsigned int i = 0; i < activeGroup->getNumUnits (); i++ )
00413 {
00414 activeGroup->getUnit( i )->getEntity ()->getParentSceneNode ()->showBoundingBox ( false );
00415 }
00416 }
00417
00418
00419
00420 void UnitSelecter::_createActiveGroup () const
00421 {
00422 ControlGroup* activeGroup;
00423
00424 mTeam->destroyActiveControlGroup ();
00425 activeGroup = mTeam->createControlGroup ();
00426
00427 vector<Unit*>::const_iterator iter = mSelectedUnits.begin();
00428 while ( iter != mSelectedUnits.end() )
00429 {
00430 activeGroup->addUnit ( *iter );
00431 iter++;
00432 }
00433
00434 mTeam->setActiveControlGroup ( activeGroup );
00435 }
00436
00437
00438
00439 void UnitSelecter::_selectUnit ( Unit* unit )
00440 {
00441 SceneNode* parentNode = unit->getEntity()->getParentSceneNode ();
00442 parentNode->showBoundingBox( true );
00443 }
00444
00445
00446
00447 void UnitSelecter::_unselectUnit ( Unit* unit )
00448 {
00449 SceneNode* parentNode = unit->getEntity()->getParentSceneNode ();
00450 parentNode->showBoundingBox( false );
00451 }
00452 }