Changeset 2907 for code/branches/questsystem5/src/core/GameState.cc
- Timestamp:
- Apr 8, 2009, 12:36:08 AM (16 years ago)
- Location:
- code/branches/questsystem5
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
code/branches/questsystem5
- Property svn:mergeinfo changed
-
code/branches/questsystem5/src/core/GameState.cc
r1764 r2907 30 30 @file 31 31 @brief 32 Implementation of GameState Baseclass.32 Implementation of GameState class. 33 33 */ 34 34 35 35 #include "GameState.h" 36 #include <cassert> 36 37 #include "util/Debug.h" 37 38 #include "util/Exception.h" 39 #include "Clock.h" 38 40 39 41 namespace orxonox … … 43 45 Constructor only initialises variables and sets the name permanently. 44 46 */ 45 GameState Base::GameStateBase(const std::string& name)47 GameState::GameState(const std::string& name) 46 48 : name_(name) 47 //, parent_(0) 48 , activeChild_(0) 49 //, bPausegetParent()(false) 49 , parent_(0) 50 50 { 51 Operations temp = {false, false, false, false, false}; 52 this->operation_ = temp; 51 this->activity_.activating = false; 52 this->activity_.active = false; 53 this->activity_.deactivating = false; 54 this->activity_.suspended = false; 55 this->activity_.topState = false; 56 this->activity_.updating = false; 53 57 } 54 58 … … 57 61 Destructor only checks that we don't delete an active state. 58 62 */ 59 GameState Base::~GameStateBase()63 GameState::~GameState() 60 64 { 61 OrxAssert(this-> operation_.active == false, "Deleting an active GameState is a very bad idea..");65 OrxAssert(this->activity_.active == false, "Deleting an active GameState is a very bad idea.."); 62 66 } 63 67 … … 69 73 The state to be added. 70 74 */ 71 void GameState Base::addChild(GameStateBase* state)75 void GameState::addChild(GameState* state) 72 76 { 73 if (!state) 74 return; 75 // check if the state/tree to be added has states in it that already exist in this tree. 76 for (std::map<std::string, GameStateBase*>::const_iterator it = state->allChildren_.begin(); 77 it != state->allChildren_.end(); ++it) 77 assert(state != NULL); 78 79 std::map<std::string, GameState*>::const_iterator it = this->children_.find(state->getName()); 80 if (it == this->children_.end()) 78 81 { 79 if (this->getState(it->second->getName())) 80 { 81 ThrowException(GameState, "Cannot add a GameState to the hierarchy twice."); 82 return; 83 } 82 this->children_[state->getName()] = state; 83 // mark us as parent 84 state->setParent(this); 84 85 } 85 if (this->getState(state->name_))86 else 86 87 { 87 ThrowException(GameState, "Cannot add a GameState to the hierarchy twice."); 88 return; 88 ThrowException(GameState, "Cannot add two children with the same name"); 89 89 } 90 // Make sure we don't add a tree that already has an active state.91 if (state->getCurrentState())92 {93 ThrowException(GameState, "Cannot merge a tree that is already active.");94 return;95 }96 97 // merge the child's children into this tree98 for (std::map<std::string, GameStateBase*>::const_iterator it = state->allChildren_.begin();99 it != state->allChildren_.end(); ++it)100 this->grandchildAdded(state, it->second);101 // merge 'state' into this tree102 this->grandchildAdded(state, state);103 104 // mark us as parent105 state->setParent(this);106 90 } 107 91 … … 113 97 GameState by instance pointer 114 98 */ 115 void GameState Base::removeChild(GameStateBase* state)99 void GameState::removeChild(GameState* state) 116 100 { 117 std::map<GameStateBase*, GameStateBase*>::iterator it = this->grandchildrenToChildren_.find(state); 118 if (it != this->grandchildrenToChildren_.end()) 119 { 120 if (state->isInSubtree(getCurrentState())) 121 { 122 ThrowException(GameState, "Cannot remove an active game state child '" 123 + state->getName() + "' from '" + name_ + "'."); 124 //COUT(2) << "Warning: Cannot remove an active game state child '" << state->getName() 125 // << "' from '" << name_ << "'." << std::endl; 126 } 127 else 128 { 129 for (std::map<GameStateBase*, GameStateBase*>::const_iterator it = state->grandchildrenToChildren_.begin(); 130 it != state->grandchildrenToChildren_.end(); ++it) 131 this->grandchildRemoved(it->first); 132 this->grandchildRemoved(state); 133 } 134 } 101 assert(state != NULL); 102 103 std::map<std::string, GameState*>::iterator it = this->children_.find(state->getName()); 104 if (it != this->children_.end()) 105 this->children_.erase(it); 135 106 else 136 107 { 137 108 ThrowException(GameState, "Game state '" + name_ + "' doesn't have a child named '" 138 109 + state->getName() + "'."); 139 //COUT(2) << "Warning: Game state '" << name_ << "' doesn't have a child named '"140 // << state->getName() << "'. Removal skipped." << std::endl;141 110 } 142 111 } 143 112 144 /** 145 @brief 146 Removes a child by name. This splits the tree in two parts, 147 each of them functional on its own. 148 @param state 149 GameState by name 150 */ 151 152 void GameStateBase::removeChild(const std::string& name) 113 void GameState::activateInternal() 153 114 { 154 GameStateBase* state = getState(name); 155 if (state) 156 { 157 removeChild(state); 158 } 159 else 160 { 161 ThrowException(GameState, "GameState '" + name + "' doesn't exist."); 162 //COUT(2) << "Warning: GameState '" << name << "' doesn't exist." << std::endl; 163 } 115 this->activity_.activating = true; 116 this->activate(); 117 this->activity_.activating = false; 118 this->activity_.active = true; 164 119 } 165 120 166 /** 167 @brief 168 Tells a state that one of its children has added a child. This is necessary 169 to fill the internal maps correctly. 170 @param child 171 The child who notices this state. 172 @param grandchild 173 The child that has been added. 174 */ 175 inline void GameStateBase::grandchildAdded(GameStateBase* child, GameStateBase* grandchild) 121 void GameState::deactivateInternal() 176 122 { 177 // fill the two maps correctly. 178 this->allChildren_[grandchild->getName()] = grandchild; 179 this->grandchildrenToChildren_[grandchild] = child; 180 if (this->getParent()) 181 this->getParent()->grandchildAdded(this, grandchild); 123 this->activity_.active = false; 124 this->activity_.deactivating = true; 125 this->activate(); 126 this->activity_.deactivating = false; 127 this->activity_.suspended = false; 128 this->activity_.updating = false; 182 129 } 183 130 184 /** 185 @brief 186 Tells a state that one of its children has removed a child. This is necessary 187 to fill the internal maps correctly. 188 @param child 189 The child who notices this state. 190 @param grandchild 191 The child that has been removed. 192 */ 193 inline void GameStateBase::grandchildRemoved(GameStateBase* grandchild) 131 void GameState::updateInternal(const Clock& time) 194 132 { 195 // adjust the two maps correctly. 196 this->allChildren_.erase(grandchild->getName()); 197 this->grandchildrenToChildren_.erase(grandchild); 198 if (this->getParent()) 199 this->getParent()->grandchildRemoved(grandchild); 200 } 201 202 /** 203 @brief 204 Checks whether a specific game states exists in the hierarchy. 205 @remarks 206 Remember that the every node has a map with all its child nodes. 207 */ 208 GameStateBase* GameStateBase::getState(const std::string& name) 209 { 210 if (this->getParent()) 211 return this->getParent()->getState(name); 212 else 213 { 214 // The map only contains children, so check ourself first 215 if (name == this->name_) 216 return this; 217 // Search in the map. If there is no entry, we can be sure the state doesn't exist. 218 std::map<std::string, GameStateBase*>::const_iterator it = this->allChildren_.find(name); 219 return (it!= this->allChildren_.end() ? it->second : 0); 220 } 221 } 222 223 /** 224 @brief 225 Returns the root node of the tree. 226 */ 227 GameStateBase* GameStateBase::getRoot() 228 { 229 if (this->getParent()) 230 return this->getParent()->getRoot(); 231 else 232 return this; 233 } 234 235 /** 236 @brief 237 Returns the current active state. 238 @remarks 239 Remember that the current active state is the one that does not 240 have active children itself. Many states can be active at once. 241 */ 242 GameStateBase* GameStateBase::getCurrentState() 243 { 244 if (this->operation_.active) 245 { 246 if (this->activeChild_) 247 return this->activeChild_->getCurrentState(); 248 else 249 return this; 250 } 251 else 252 { 253 if (this->getParent()) 254 return this->getParent()->getCurrentState(); 255 else 256 return 0; 257 } 258 } 259 260 /** 261 @brief 262 Determines whether 'state' is in this subtree, including this node. 263 */ 264 bool GameStateBase::isInSubtree(GameStateBase* state) const 265 { 266 return (grandchildrenToChildren_.find(state) != grandchildrenToChildren_.end() 267 || state == this); 268 } 269 270 /** 271 @brief 272 Makes a state transition according to the state tree. You can choose any state 273 in the tree to do the call. The function finds the current state on its own. 274 @param state 275 The state to be entered, has to exist in the tree. 276 */ 277 void GameStateBase::requestState(const std::string& name) 278 { 279 assert(getRoot()); 280 getRoot()->requestState(name); 281 } 282 283 /** 284 @brief 285 Internal method that actually makes the state transition. Since it is internal, 286 the method can assume certain things to be granted (like 'this' is always active). 287 */ 288 void GameStateBase::makeTransition(GameStateBase* source, GameStateBase* destination) 289 { 290 if (source == this->getParent()) 291 { 292 // call is from the parent 293 this->activate(); 294 } 295 else if (source == 0) 296 { 297 // call was just started by root 298 // don't do anyting yet 299 } 300 else 301 { 302 // call is from a child 303 this->activeChild_ = 0; 304 } 305 306 if (destination == this) 307 return; 308 309 // Check for 'destination' in the children map first 310 std::map<GameStateBase*, GameStateBase*>::const_iterator it 311 = this->grandchildrenToChildren_.find(destination); 312 if (it != this->grandchildrenToChildren_.end()) 313 { 314 // child state. Don't use 'state', might be a grandchild! 315 this->activeChild_ = it->second; 316 it->second->makeTransition(this, destination); 317 } 318 else 319 { 320 // parent. We can be sure of this. 321 assert(this->getParent() != 0); 322 323 this->deactivate(); 324 this->getParent()->makeTransition(this, destination); 325 } 326 } 327 328 /** 329 @brief 330 Activates the state. Only sets bActive_ to true and notifies the parent. 331 */ 332 void GameStateBase::activate() 333 { 334 this->operation_.active = true; 335 this->operation_.entering = true; 336 this->enter(); 337 this->operation_.entering = false; 338 } 339 340 /** 341 Activates the state. Only sets bActive_ to false and notifies the parent. 342 */ 343 void GameStateBase::deactivate() 344 { 345 this->operation_.leaving = true; 346 this->leave(); 347 this->operation_.leaving = false; 348 this->operation_.active = false; 349 } 350 351 /** 352 @brief 353 Update method that calls ticked() with enclosed bRunning_ = true 354 If there was a state transition request within ticked() then this 355 method will transition in the end. 356 @param dt Delta time 357 @note 358 This method is not virtual! You cannot override it therefore. 359 */ 360 void GameStateBase::tick(const Clock& time) 361 { 362 this->operation_.running = true; 363 this->ticked(time); 364 this->operation_.running = false; 133 this->activity_.updating = true; 134 this->update(time); 135 this->activity_.updating = false; 365 136 } 366 137 }
Note: See TracChangeset
for help on using the changeset viewer.