Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Mar 25, 2009, 5:23:00 PM (16 years ago)
Author:
rgrieder
Message:

Implemented new GameState concept. It doesn't differ that much from the old one, but there's still lots of changes.
The most important change is that one GameState can occur multiple times in the hierarchy.

Short log:

  • No RootGameState anymore. Simply the highest is root.
  • Game::requestGameState(name) can refer to the parent, grandparent, great-grandparent, etc. or one of the children.
  • Requested states are saved. So if you select "level", the next request (even right after the call) will be relative to "level"
  • Game::popState() will simply unload the current one
  • Re added Main.cc again because Game as well as GameState have been moved to the core
  • Adapted all GameStates to the new system

Things should already work, except for network support because standalone only works with a little hack.
We can now start creating a better hierarchy.

Location:
code/branches/gui/src/core
Files:
2 deleted
4 edited
2 moved

Legend:

Unmodified
Added
Removed
  • code/branches/gui/src/core/CMakeLists.txt

    r2710 r2844  
    2424  Core.cc
    2525  Event.cc
     26  Game.cc
    2627  GameState.cc
    2728  Language.cc
     
    2930  ObjectListBase.cc
    3031  OrxonoxClass.cc
    31   RootGameState.cc
    3232
    3333  # command
  • code/branches/gui/src/core/CorePrereqs.h

    r2817 r2844  
    166166
    167167  // game states
     168  class Game;
    168169  class GameState;
    169   class RootGameState;
     170  struct GameStateTreeNode;
    170171
    171172  // input
  • code/branches/gui/src/core/Game.cc

    r2843 r2844  
    3333*/
    3434
    35 #include "OrxonoxStableHeaders.h"
    3635#include "Game.h"
    3736
     
    4140#include "util/Debug.h"
    4241#include "util/Exception.h"
    43 #include "core/CommandLine.h"
    44 #include "core/ConsoleCommand.h"
    45 #include "core/Core.h"
    46 #include "core/Identifier.h"
    47 #include "core/CoreIncludes.h"
    48 #include "core/ConfigValueIncludes.h"
    49 
    50 #include "gamestates/GSRoot.h"
    51 #include "gamestates/GSGraphics.h"
    52 #include "gamestates/GSStandalone.h"
    53 #include "gamestates/GSServer.h"
    54 #include "gamestates/GSClient.h"
    55 #include "gamestates/GSDedicated.h"
    56 #include "gamestates/GSGUI.h"
    57 #include "gamestates/GSIOConsole.h"
    58 
    59 /*
    60 @brief
    61     Main method. Game starts here (except for static initialisations).
    62 */
    63 int main(int argc, char** argv)
    64 {
    65     {
    66         orxonox::Game orxonox(argc, argv);
    67         orxonox.run();
    68         // objects gets destroyed here!
    69     }
    70 
    71     // Clean up class hierarchy stuff (identifiers, xmlport, configvalue, consolecommand)
    72     // Needs to be done after Game destructor because of ~OrxonoxClass
    73     orxonox::Identifier::destroyAllIdentifiers();
    74 
    75     return 0;
    76 }
     42#include "Clock.h"
     43#include "CommandLine.h"
     44#include "ConsoleCommand.h"
     45#include "Core.h"
     46#include "CoreIncludes.h"
     47#include "ConfigValueIncludes.h"
     48#include "GameState.h"
    7749
    7850namespace orxonox
     
    8355    }
    8456
     57    struct _CoreExport GameStateTreeNode
     58    {
     59        GameState*                      state_;
     60        GameStateTreeNode*              parent_;
     61        std::vector<GameStateTreeNode*> children_;
     62    };
     63
    8564    SetCommandLineArgument(state, "gui").shortcut("s");
     65    SetCommandLineSwitch(startWithConsole);
    8666    SetConsoleCommandShortcutExternAlias(stop_game, "exit");
    8767
     68    std::map<std::string, GameState*> Game::allStates_s;
    8869    Game* Game::singletonRef_s = 0;
    8970
     
    9677        assert(singletonRef_s == 0);
    9778        singletonRef_s = this;
     79
     80        this->rootStateNode_ = 0;
     81        this->activeStateNode_ = 0;
    9882
    9983        this->abort_ = false;
     
    121105        // Destroy pretty much everyhting left
    122106        delete this->core_;
     107
     108        // Delete all GameStates created by the macros
     109        for (std::map<std::string, GameState*>::const_iterator it = allStates_s.begin(); it != allStates_s.end(); ++it)
     110            delete it->second;
    123111
    124112        assert(singletonRef_s);
     
    144132    void Game::run()
    145133    {
    146         // create the gamestates
    147         GSRoot root;
    148         GSGraphics graphics;
    149         GSStandalone standalone;
    150         GSServer server;
    151         GSClient client;
    152         GSDedicated dedicated;
    153         GSGUI gui;
    154         GSIOConsole ioConsole;
    155 
    156         // make the hierarchy
    157         root.addChild(&graphics);
    158         graphics.addChild(&standalone);
    159         graphics.addChild(&server);
    160         graphics.addChild(&client);
    161         graphics.addChild(&gui);
    162         root.addChild(&ioConsole);
    163         root.addChild(&dedicated);
    164 
    165         root.activate();
    166 
    167         // get initial state from command line
    168         root.gotoState(CommandLine::getValue("state"));
     134        // </EXPORT THIS>
     135        this->setStateHierarchy(
     136        "root"
     137        " graphics"
     138        "  gui"
     139        "  standalone"
     140        "   level"
     141        "  server"
     142        "   level"
     143        "  client"
     144        "   level"
     145        " dedicated"
     146        "  level"
     147        " ioConsole"
     148        );
     149        // </EXPORT THIS>
     150
     151
     152        // Always start with the root state
     153        this->requestedStateNodes_.push_back(this->rootStateNode_);
     154        this->activeStateNode_ = this->rootStateNode_;
     155        this->loadState(this->rootStateNode_->state_);
     156
     157        // <EXPORT THIS>
     158        if (CommandLine::getValue("startWithConsole").getBool())
     159        {
     160            // Start the game in the console
     161            this->requestState("ioConsole");
     162        }
     163        else
     164        {
     165            // Start in GUI main menu
     166            this->requestState("graphics");
     167            this->requestState("gui");
     168        }
     169        // </EXPORT THIS>
    169170
    170171        this->gameClock_->capture(); // first delta time should be about 0 seconds
    171         while (!this->abort_)
     172        while (!this->abort_ && !this->activeStates_.empty())
    172173        {
    173174            this->gameClock_->capture();
     
    179180            this->periodTime_ += this->gameClock_->getDeltaTimeMicroseconds();
    180181
    181             // UPDATE
    182             root.tick(*this->gameClock_);
     182            // UPDATE STATE STACK
     183            while (this->requestedStateNodes_.size() > 1)
     184            {
     185                // Note: this->requestedStateNodes_.front() is the currently active state node
     186                std::vector<GameStateTreeNode*>::iterator it = this->requestedStateNodes_.begin() + 1;
     187                if (*it == this->activeStateNode_->parent_)
     188                    this->unloadState(this->activeStateNode_->state_);
     189                else // has to be child
     190                    this->loadState((*it)->state_);
     191                this->activeStateNode_ = *it;
     192                this->requestedStateNodes_.erase(this->requestedStateNodes_.begin());
     193            }
     194
     195            // UPDATE, bottom to top in the stack
     196            for (std::vector<GameState*>::const_iterator it = this->activeStates_.begin();
     197                it != this->activeStates_.end(); ++it)
     198                (*it)->update(*this->gameClock_);
    183199
    184200            // STATISTICS
     
    206222                this->periodTime_ -= this->statisticsRefreshCycle_;
    207223            }
    208 
    209             if (root.stateRequest_ != "")
    210                 root.gotoState(root.stateRequest_);
    211         }
    212 
    213         root.gotoState("root");
    214         root.deactivate();
     224        }
     225
     226        // Unload all remaining states
     227        while (!this->activeStates_.empty())
     228            this->unloadState(this->activeStates_.back());
     229        this->activeStateNode_ = 0;
     230        this->requestedStateNodes_.clear();
    215231    }
    216232
     
    226242        this->periodTickTime_+=length;
    227243    }
     244
     245
     246    /***** GameState related *****/
     247
     248    void Game::requestState(const std::string& name)
     249    {
     250        GameState* state = this->getState(name);
     251        if (state == NULL || this->activeStateNode_ == NULL)
     252            return;
     253
     254        GameStateTreeNode* requestedNode = 0;
     255
     256        // this->requestedStateNodes_.back() is the currently active state
     257        GameStateTreeNode* lastRequestedNode = this->requestedStateNodes_.back();
     258
     259        // Already the active node?
     260        if (state == lastRequestedNode->state_)
     261        {
     262            COUT(2) << "Warning: Requesting the currently active state! Ignoring." << std::endl;
     263            return;
     264        }
     265
     266        // Check children first
     267        for (unsigned int i = 0; i < lastRequestedNode->children_.size(); ++i)
     268        {
     269            if (lastRequestedNode->children_[i]->state_ == state)
     270            {
     271                requestedNode = lastRequestedNode->children_[i];
     272                break;
     273            }
     274        }
     275
     276        // Check parent and all its grand parents
     277        GameStateTreeNode* currentNode = lastRequestedNode;
     278        while (requestedNode == NULL && currentNode->parent_ != NULL)
     279        {
     280            if (currentNode->state_ == state)
     281                requestedNode = currentNode;
     282            currentNode = currentNode->parent_;
     283        }
     284
     285        if (requestedNode == NULL)
     286            COUT(1) << "Error: Requested GameState transition is not allowed. Ignoring." << std::endl;
     287        else
     288            this->requestedStateNodes_.push_back(requestedNode);
     289    }
     290
     291    void Game::popState()
     292    {
     293        if (this->activeStateNode_ != NULL && this->requestedStateNodes_.back()->parent_)
     294            this->requestState(this->requestedStateNodes_.back()->parent_->state_->getName());
     295        else
     296            COUT(2) << "Warning: Could not pop GameState. Ignoring." << std::endl;
     297    }
     298
     299    GameState* Game::getState(const std::string& name)
     300    {
     301        std::map<std::string, GameState*>::const_iterator it = allStates_s.find(name);
     302        if (it != allStates_s.end())
     303            return it->second;
     304        else
     305        {
     306            COUT(1) << "Error: Could not find GameState '" << name << "'. Ignoring." << std::endl;
     307            return 0;
     308        }
     309    }
     310
     311    void Game::setStateHierarchy(const std::string& str)
     312    {
     313        // Split string into pieces of the form whitespacesText
     314        std::vector<std::pair<std::string, unsigned> > stateStrings;
     315        size_t pos = 0;
     316        size_t startPos = 0;
     317        while (pos < str.size())
     318        {
     319            unsigned indentation = 0;
     320            while(pos < str.size() && str[pos] == ' ')
     321                ++indentation, ++pos;
     322            startPos = pos;
     323            while(pos < str.size() && str[pos] != ' ')
     324                ++pos;
     325            stateStrings.push_back(std::pair<std::string, unsigned>(
     326                str.substr(startPos, pos - startPos), indentation));
     327        }
     328        unsigned int currentLevel = 0;
     329        GameStateTreeNode* currentNode = 0;
     330        for (std::vector<std::pair<std::string, unsigned> >::const_iterator it = stateStrings.begin(); it != stateStrings.end(); ++it)
     331        {
     332            std::string newStateName = it->first;
     333            unsigned newLevel = it->second;
     334            GameState* newState = this->getState(newStateName);
     335            if (!newState)
     336                ThrowException(GameState, std::string("GameState with name '") + newStateName + "' not found!");
     337            if (newLevel == 0)
     338            {
     339                // root
     340                if (this->rootStateNode_ != NULL)
     341                    ThrowException(GameState, "No two root GameStates are allowed!");
     342                GameStateTreeNode* newNode = new GameStateTreeNode;
     343                newNode->state_ = newState;
     344                newNode->parent_ = 0;
     345                this->rootStateNode_ = newNode;
     346                currentNode = this->rootStateNode_;
     347            }
     348            else if (currentNode)
     349            {
     350                GameStateTreeNode* newNode = new GameStateTreeNode;
     351                newNode->state_ = newState;
     352                if (newLevel < currentLevel)
     353                {
     354                    // Get down the hierarchy
     355                    do
     356                        currentNode = currentNode->parent_;
     357                    while (newLevel < --currentLevel);
     358                }
     359                if (newLevel == currentLevel)
     360                {
     361                    // same level
     362                    newNode->parent_ = currentNode->parent_;
     363                    newNode->parent_->children_.push_back(newNode);
     364                }
     365                else if (newLevel == currentLevel + 1)
     366                {
     367                    // child
     368                    newNode->parent_ = currentNode;
     369                    currentNode->children_.push_back(newNode);
     370                }
     371                else
     372                    ThrowException(GameState, "Indentation error while parsing the hierarchy.");
     373                currentNode = newNode;
     374                currentLevel = newLevel;
     375            }
     376            else
     377            {
     378                ThrowException(GameState, "No root GameState specified!");
     379            }
     380        }
     381    }
     382
     383    /*** Internal ***/
     384
     385    void Game::loadState(GameState* state)
     386    {
     387        state->activate();
     388        this->activeStates_.push_back(state);
     389    }
     390
     391    void Game::unloadState(orxonox::GameState* state)
     392    {
     393        state->deactivate();
     394        this->activeStates_.pop_back();
     395    }
     396
     397    /*static*/ bool Game::addGameState(GameState* state)
     398    {
     399        std::map<std::string, GameState*>::const_iterator it = allStates_s.find(state->getName());
     400        if (it == allStates_s.end())
     401            allStates_s[state->getName()] = state;
     402        else
     403            ThrowException(GameState, "Cannot add two GameStates with the same name to 'Game'.");
     404
     405        // just a required dummy return value
     406        return true;
     407    }
    228408}
  • code/branches/gui/src/core/Game.h

    r2843 r2844  
    3636#define _Game_H__
    3737
    38 #include "OrxonoxPrereqs.h"
     38#include "CorePrereqs.h"
    3939#include <cassert>
    4040#include <list>
    41 #include "core/OrxonoxClass.h"
     41#include <map>
     42#include <vector>
     43#include "OrxonoxClass.h"
     44
     45#define AddGameState(classname, name, ...) \
     46    static bool bGameStateDummy_##classname##__LINE__ = orxonox::Game::addGameState(new classname(name, __VA_ARGS__))
    4247
    4348namespace orxonox
     
    4752        Main class responsible for running the game.
    4853    */
    49     class _OrxonoxExport Game : public OrxonoxClass
     54    class _CoreExport Game : public OrxonoxClass
    5055    {
    5156    public:
     
    5459        void setConfigValues();
    5560
     61        void setStateHierarchy(const std::string& str);
     62        GameState* getState(const std::string& name);
     63
    5664        void run();
    5765        void stop();
     66
     67        void requestState(const std::string& name);
     68        void popState();
    5869
    5970        float getAvgTickTime() { return this->avgTickTime_; }
     
    6273        void addTickTime(uint32_t length);
    6374
     75        static bool addGameState(GameState* state);
    6476        static Game& getInstance() { assert(singletonRef_s); return *singletonRef_s; }
    6577
     
    7385        Game(Game&); // don't mess with singletons
    7486
    75         Core* core_;
    76         Clock* gameClock_;
     87        void loadState(GameState* state);
     88        void unloadState(GameState* state);
    7789
    78         bool abort_;
     90        std::vector<GameState*>         activeStates_;
     91        GameStateTreeNode*              rootStateNode_;
     92        GameStateTreeNode*              activeStateNode_;
     93        std::vector<GameStateTreeNode*> requestedStateNodes_;
     94
     95        Core*                           core_;
     96        Clock*                          gameClock_;
     97
     98        bool                            abort_;
    7999
    80100        // variables for time statistics
    81         uint64_t              statisticsStartTime_;
    82         std::list<statisticsTickInfo>
    83                               statisticsTickTimes_;
    84         uint32_t              periodTime_;
    85         uint32_t              periodTickTime_;
    86         float                 avgFPS_;
    87         float                 avgTickTime_;
     101        uint64_t                        statisticsStartTime_;
     102        std::list<statisticsTickInfo>   statisticsTickTimes_;
     103        uint32_t                        periodTime_;
     104        uint32_t                        periodTickTime_;
     105        float                           avgFPS_;
     106        float                           avgTickTime_;
    88107
    89108        // config values
    90         unsigned int          statisticsRefreshCycle_;
    91         unsigned int          statisticsAvgLength_;
     109        unsigned int                    statisticsRefreshCycle_;
     110        unsigned int                    statisticsAvgLength_;
    92111
     112        static std::map<std::string, GameState*> allStates_s;
    93113        static Game* singletonRef_s;        //!< Pointer to the Singleton
    94114    };
  • code/branches/gui/src/core/GameState.cc

    r2817 r2844  
    3434
    3535#include "GameState.h"
     36#include <cassert>
    3637#include "util/Debug.h"
    3738#include "util/Exception.h"
     39#include "Clock.h"
    3840
    3941namespace orxonox
     
    4648        : name_(name)
    4749        , parent_(0)
    48         , activeChild_(0)
    49         //, bPausegetParent()(false)
    5050    {
    51         Operations temp = {false, false, false, false, false};
    52         this->operation_ = temp;
     51        State temp = {false, false, false, false, false};
     52        this->activity_ = temp;
    5353    }
    5454
     
    5959    GameState::~GameState()
    6060    {
    61         OrxAssert(this->operation_.active == false, "Deleting an active GameState is a very bad idea..");
     61        OrxAssert(this->activity_.active == false, "Deleting an active GameState is a very bad idea..");
    6262    }
    6363
     
    7171    void GameState::addChild(GameState* state)
    7272    {
    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, GameState*>::const_iterator it = state->allChildren_.begin();
    77             it != state->allChildren_.end(); ++it)
     73        assert(state != NULL);
     74
     75        std::map<std::string, GameState*>::const_iterator it = this->children_.find(state->getName());
     76        if (it == this->children_.end())
    7877        {
    79             if (this->getState(it->second->getName()))
    80             {
    81                 ThrowException(GameState, "Cannot add a GameState to the hierarchy twice.");
    82                 return;
    83             }
     78            this->children_[state->getName()] = state;
     79            // mark us as parent
     80            state->setParent(this);
    8481        }
    85         if (this->getState(state->name_))
     82        else
    8683        {
    87             ThrowException(GameState, "Cannot add a GameState to the hierarchy twice.");
    88             return;
     84            ThrowException(GameState, "Cannot add two children with the same name");
    8985        }
    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 tree
    98         for (std::map<std::string, GameState*>::const_iterator it = state->allChildren_.begin();
    99             it != state->allChildren_.end(); ++it)
    100             this->grandchildAdded(state, it->second);
    101         // merge 'state' into this tree
    102         this->grandchildAdded(state, state);
    103 
    104         // mark us as parent
    105         state->setParent(this);
    10686    }
    10787
     
    11595    void GameState::removeChild(GameState* state)
    11696    {
    117         std::map<GameState*, GameState*>::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<GameState*, GameState*>::const_iterator it = state->grandchildrenToChildren_.begin();
    130                     it != state->grandchildrenToChildren_.end(); ++it)
    131                     this->grandchildRemoved(it->first);
    132                 this->grandchildRemoved(state);
    133             }
    134         }
     97        assert(state != NULL);
     98
     99        std::map<std::string, GameState*>::iterator it = this->children_.find(state->getName());
     100        if (it != this->children_.end())
     101            this->children_.erase(it);
    135102        else
    136103        {
    137104            ThrowException(GameState, "Game state '" + name_ + "' doesn't have a child named '"
    138105                + state->getName() + "'.");
    139             //COUT(2) << "Warning: Game state '" << name_ << "' doesn't have a child named '"
    140             //    << state->getName() << "'. Removal skipped." << std::endl;
    141106        }
    142107    }
    143108
    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 GameState::removeChild(const std::string& name)
     109    void GameState::activateInternal()
    153110    {
    154         GameState* 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         }
     111        this->activity_.activating = true;
     112        this->activate();
     113        this->activity_.activating = false;
     114        this->activity_.active = true;
    164115    }
    165116
    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 GameState::grandchildAdded(GameState* child, GameState* grandchild)
     117    void GameState::deactivateInternal()
    176118    {
    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);
     119        this->activity_.active = false;
     120        this->activity_.deactivating = true;
     121        this->activate();
     122        this->activity_.deactivating = false;
     123        this->activity_.suspended = false;
     124        this->activity_.updating = false;
    182125    }
    183126
    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 GameState::grandchildRemoved(GameState* grandchild)
     127    void GameState::updateInternal(const Clock& time)
    194128    {
    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     GameState* GameState::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, GameState*>::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     GameState* GameState::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     GameState* GameState::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 GameState::isInSubtree(GameState* 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 GameState::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 GameState::makeTransition(GameState* source, GameState* 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<GameState*, GameState*>::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 GameState::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 GameState::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 GameState::tick(const Clock& time)
    361     {
    362         this->operation_.running = true;
    363         this->ticked(time);
    364         this->operation_.running = false;
     129        this->activity_.updating = true;
     130        this->update(time);
     131        this->activity_.updating = false;
    365132    }
    366133}
  • code/branches/gui/src/core/GameState.h

    r2817 r2844  
    3939
    4040#include <string>
    41 #include <vector>
    4241#include <map>
    43 #include <cassert>
    44 #include "Clock.h"
     42#include "CorePrereqs.h"
    4543
    4644namespace orxonox
     
    6260    class _CoreExport GameState
    6361    {
    64         friend class RootGameState;
    65         // Hack
    6662        friend class Game;
    6763
     
    7167            Gives information about what the GameState is currently doing
    7268        */
    73         struct Operations
     69        struct State
    7470        {
    75             unsigned active    : 1;
    76             unsigned entering  : 1;
    77             unsigned leaving  : 1;
    78             unsigned running   : 1;
    79             unsigned suspended : 1;
     71            unsigned active       : 1;
     72            unsigned activating   : 1;
     73            unsigned deactivating : 1;
     74            unsigned updating     : 1;
     75            unsigned suspended    : 1;
    8076        };
    8177
     
    8581
    8682        const std::string& getName() const { return name_; }
    87         const Operations getOperation() const { return this->operation_; }
    88         bool isInSubtree(GameState* state) const;
    89 
    90         GameState* getState(const std::string& name);
    91         GameState* getRoot();
    92         //! Returns the currently active game state
    93         virtual GameState* getCurrentState();
    94 
    95         virtual void requestState(const std::string& name);
     83        const State getActivity() const    { return this->activity_; }
     84        GameState* getParent() const       { return this->parent_; }
    9685
    9786        void addChild(GameState* state);
    9887        void removeChild(GameState* state);
    99         void removeChild(const std::string& name);
    10088
    10189    protected:
    102         virtual void enter() = 0;
    103         virtual void leave() = 0;
    104         virtual void ticked(const Clock& time) = 0;
    105 
    106         GameState* getActiveChild() { return this->activeChild_; }
    107 
    108         void tickChild(const Clock& time) { if (this->getActiveChild()) this->getActiveChild()->tick(time); }
    109 
    110         GameState* getParent() const     { return this->parent_; }
    111         void setParent(GameState* state) { this->parent_ = state; }
     90        virtual void activate() = 0;
     91        virtual void deactivate() = 0;
     92        virtual void update(const Clock& time) = 0;
    11293
    11394    private:
    114         //! Performs a transition to 'destination'
    115         virtual void makeTransition(GameState* source, GameState* destination);
    116 
    117         void grandchildAdded(GameState* child, GameState* grandchild);
    118         void grandchildRemoved(GameState* grandchild);
    119 
    120         void tick(const Clock& time);
    121         void activate();
    122         void deactivate();
     95        void setParent(GameState* state) { this->parent_ = state; }
     96        void setActivity(State activity);
     97        void activateInternal();
     98        void deactivateInternal();
     99        void updateInternal(const Clock& time);
    123100
    124101        const std::string                        name_;
    125         Operations                               operation_;
     102        State                                    activity_;
    126103        GameState*                               parent_;
    127         GameState*                               activeChild_;
    128         //bool                                     bPauseParent_;
    129         std::map<std::string, GameState*>        allChildren_;
    130         std::map<GameState*, GameState*>         grandchildrenToChildren_;
     104        std::map<std::string, GameState*>        children_;
    131105    };
    132106}
Note: See TracChangeset for help on using the changeset viewer.