D:/simple_rts/src/UnitSelecter.cpp

Go to the documentation of this file.
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                 // HACK
00046                 //              Create four cubes for showing the bounding corners
00047                 //              Create a cube for showing the right click location
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                         // TODO
00095                         //      Create a vector from the leaders last waypoint to the click position
00096                         //      and use this as an offset to put each and every other unit as well.
00097 
00098                         // Create paths for all other units to the final destination
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                 // If the selection has already started, update the ending portion
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                 // Left Side
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                 // Right Side
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                 // Top Side
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                 // Bottom Side
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                 // Find the intersection with the terrain
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                 // Just put them at the top left if they missed the terrain
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                 // TODO
00229                 //              Clean this approach up a lot
00230                 // Grab all the entities within this rectangle
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                 // TODO
00263                 //              Abstract this into a Cursor class
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                 // The right button was pushed
00281                 if ( inputDevice->getMouseButton( 1 ) && rightUp )
00282                 {
00283                         rightUp = false;
00284                         _moveUnits ();
00285                 }
00286 
00287                 // The left button is currently down
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                 // Otherwise, they aren't trying to select anything
00302                 else
00303                 {
00304                         mFirstPoint = false;
00305 
00306                         mOverlay->hide ();
00307                         mNodes[1]->setVisible( false );
00308                         mNodes[2]->setVisible( false );
00309 
00310                         // Reset our bounds
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                 // Simply replace the entire active group with a blank one
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                 // Cast a ray to find the intersection point
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 }

Generated on Sun Jun 25 19:23:43 2006 for Valors End by  doxygen 1.4.7