Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Changeset 3243


Ignore:
Timestamp:
Jun 28, 2009, 6:22:40 PM (15 years ago)
Author:
rgrieder
Message:

Moved GameState construction from pre-main() to after Core creation. That makes it possible to use Core features (like configValues) in the GameState constructor.

Location:
code/branches/core4/src
Files:
24 edited

Legend:

Unmodified
Added
Removed
  • code/branches/core4/src/core/CorePrereqs.h

    r3196 r3243  
    165165    // game states
    166166    class Game;
     167    struct GameStateConstrParams;
    167168    class GameState;
    168169    struct GameStateTreeNode;
  • code/branches/core4/src/core/Game.cc

    r3238 r3243  
    5454    using boost::weak_ptr;
    5555
    56     std::map<std::string, GameState*> Game::allStates_s;
    57     Game* Game::singletonRef_s = 0;
    58 
    5956    static void stop_game()
    6057        { Game::getInstance().stop(); }
    6158    SetConsoleCommandShortcutExternAlias(stop_game, "exit");
    62     // Add an empty gamestate that serves as internal root state
    63     AddGameState(GameState, "emptyRootGameState");
    6459
    6560    struct _CoreExport GameStateTreeNode
     
    6964        std::vector<shared_ptr<GameStateTreeNode> > children_;
    7065    };
     66
     67    std::map<std::string, Game::GameStateInfo> Game::gameStateDeclarations_s;
     68    Game* Game::singletonRef_s = 0;
    7169
    7270    /**
     
    7674    Game::Game(int argc, char** argv)
    7775    {
    78         assert(singletonRef_s == 0);
     76        if (singletonRef_s != 0)
     77        {
     78            COUT(0) << "Error: The Game singleton cannot be recreated! Shutting down." << std::endl;
     79            abort();
     80        }
    7981        singletonRef_s = this;
    8082
    8183        this->bAbort_ = false;
    8284        bChangingState_ = false;
    83         // The empty root state is ALWAYS loaded!
    84         this->rootStateNode_ = shared_ptr<GameStateTreeNode>(new GameStateTreeNode());
    85         this->rootStateNode_->state_ = getState("emptyRootGameState");
    86         this->activeStateNode_ = this->rootStateNode_;
    87         this->activeStates_.push_back(this->rootStateNode_->state_);
     85
     86        // Create an empty root state
     87        declareGameState<GameState>("GameState", "emptyRootGameState", true, false);
    8888
    8989        // reset statistics
     
    9898        this->gameClock_ = new Clock();
    9999
     100        // Create the Core
    100101        this->core_ = new orxonox::Core();
    101102        this->core_->initialise(argc, argv);
    102103
     104        // After the core has been created, we can safely instantiate the GameStates
     105        for (std::map<std::string, GameStateInfo>::const_iterator it = gameStateDeclarations_s.begin();
     106            it != gameStateDeclarations_s.end(); ++it)
     107        {
     108            // Only create the states appropriate for the game mode
     109            //if (GameMode::showsGraphics || !it->second.bGraphicsMode)
     110            GameStateConstrParams params = { it->second.stateName, it->second.bIgnoreTickTime };
     111            gameStates_[getLowercase(it->second.stateName)] = GameStateFactory::fabricate(it->second.className, params);
     112        }
     113
     114        // The empty root state is ALWAYS loaded!
     115        this->rootStateNode_ = shared_ptr<GameStateTreeNode>(new GameStateTreeNode());
     116        this->rootStateNode_->state_ = getState("emptyRootGameState");
     117        this->activeStateNode_ = this->rootStateNode_;
     118        this->activeStates_.push_back(this->rootStateNode_->state_);
     119
     120        // Do this after Core creation!
    103121        RegisterRootObject(Game);
    104122        this->setConfigValues();
     
    110128    Game::~Game()
    111129    {
    112         // Destroy pretty much everyhting left
     130        // Destroy the GameStates (note that the nodes still point to them, but doesn't matter)
     131        for (std::map<std::string, GameState*>::const_iterator it = gameStates_.begin();
     132            it != gameStates_.end(); ++it)
     133            delete it->second;
     134
     135        // Destroy the Core and with it almost everything
    113136        delete this->core_;
    114 
    115137        delete this->gameClock_;
    116138
    117         assert(singletonRef_s);
    118         singletonRef_s = 0;
     139        // Also, take care of the GameStateFactories
     140        GameStateFactory::destroyFactories();
     141
     142        // Don't assign singletonRef_s with NULL! Recreation is not supported
    119143    }
    120144
     
    165189
    166190            // STATISTICS
    167             statisticsTickInfo tickInfo = {currentTime, 0};
     191            StatisticsTickInfo tickInfo = {currentTime, 0};
    168192            statisticsTickTimes_.push_back(tickInfo);
    169193            this->periodTime_ += this->gameClock_->getDeltaTimeMicroseconds();
     
    240264            if (this->periodTime_ > statisticsRefreshCycle_)
    241265            {
    242                 std::list<statisticsTickInfo>::iterator it = this->statisticsTickTimes_.begin();
     266                std::list<StatisticsTickInfo>::iterator it = this->statisticsTickTimes_.begin();
    243267                assert(it != this->statisticsTickTimes_.end());
    244268                int64_t lastTime = currentTime - this->statisticsAvgLength_;
     
    356380    GameState* Game::getState(const std::string& name)
    357381    {
    358         std::map<std::string, GameState*>::const_iterator it = allStates_s.find(getLowercase(name));
    359         if (it != allStates_s.end())
     382        std::map<std::string, GameState*>::const_iterator it = gameStates_.find(getLowercase(name));
     383        if (it != gameStates_.end())
    360384            return it->second;
    361385        else
     
    448472    }
    449473
    450     /*static*/ bool Game::addGameState(GameState* state)
    451     {
    452         std::map<std::string, GameState*>::const_iterator it = allStates_s.find(getLowercase(state->getName()));
    453         if (it == allStates_s.end())
    454             allStates_s[getLowercase(state->getName())] = state;
    455         else
    456             ThrowException(GameState, "Cannot add two GameStates with the same name to 'Game'.");
    457 
    458         // just a required dummy return value
    459         return true;
    460     }
    461 
    462     /*static*/ void Game::destroyStates()
    463     {
    464         // Delete all GameStates created by the macros
    465         for (std::map<std::string, GameState*>::const_iterator it = allStates_s.begin(); it != allStates_s.end(); ++it)
     474    std::map<std::string, Game::GameStateFactory*> Game::GameStateFactory::factories_s;
     475
     476    /*static*/ GameState* Game::GameStateFactory::fabricate(const std::string& className, const GameStateConstrParams& params)
     477    {
     478        std::map<std::string, GameStateFactory*>::const_iterator it = factories_s.find(className);
     479        assert(it != factories_s.end());
     480        return it->second->fabricate(params);
     481    }
     482
     483    /*static*/ void Game::GameStateFactory::destroyFactories()
     484    {
     485        for (std::map<std::string, GameStateFactory*>::const_iterator it = factories_s.begin(); it != factories_s.end(); ++it)
    466486            delete it->second;
    467         allStates_s.clear();
     487        factories_s.clear();
    468488    }
    469489}
  • code/branches/core4/src/core/Game.h

    r3238 r3243  
    4646#include <boost/preprocessor/cat.hpp>
    4747
     48#include "util/Debug.h"
    4849#include "OrxonoxClass.h"
    4950
     
    5354    and every following paramter is a constructor argument (which is usually non existent)
    5455*/
    55 #define AddGameState(classname, ...) \
    56     static bool BOOST_PP_CAT(bGameStateDummy_##classname, __LINE__) = orxonox::Game::addGameState(new classname(__VA_ARGS__))
     56#define DeclareGameState(className, stateName, bIgnoreTickTime, bGraphicsMode) \
     57    static bool BOOST_PP_CAT(bGameStateDummy_##className, __LINE__) = orxonox::Game::declareGameState<className>(#className, stateName, bIgnoreTickTime, bGraphicsMode)
    5758
    5859// tolua_begin
     
    9192        void addTickTime(uint32_t length);
    9293
    93         static bool addGameState(GameState* state);
    94         static void destroyStates();
     94        template <class T>
     95        static bool declareGameState(const std::string& className, const std::string& stateName, bool bIgnoreTickTime, bool bConsoleMode);
    9596        static Game& getInstance() { assert(singletonRef_s); return *singletonRef_s; } //tolua_export
    9697
     
    99100
    100101    private:
    101         struct statisticsTickInfo
     102        class _CoreExport GameStateFactory
     103        {
     104        public:
     105            virtual ~GameStateFactory() { }
     106            static GameState* fabricate(const std::string& className, const GameStateConstrParams& params);
     107            template <class T>
     108            static void createFactory(const std::string& className)
     109                { factories_s[className] = new TemplateGameStateFactory<T>(); }
     110            static void destroyFactories();
     111        private:
     112            virtual GameState* fabricate(const GameStateConstrParams& params) = 0;
     113            static std::map<std::string, GameStateFactory*> factories_s;
     114        };
     115        template <class T>
     116        class TemplateGameStateFactory : public GameStateFactory
     117        {
     118        public:
     119            GameState* fabricate(const GameStateConstrParams& params)
     120                { return new T(params); }
     121        };
     122
     123        struct GameStateInfo
     124        {
     125            std::string stateName;
     126            std::string className;
     127            bool bIgnoreTickTime;
     128            bool bGraphicsMode;
     129        };
     130
     131        struct StatisticsTickInfo
    102132        {
    103133            uint64_t    tickTime;
     
    110140        void unloadState(GameState* state);
    111141
    112         std::vector<GameState*>         activeStates_;
     142        std::map<std::string, GameState*>    gameStates_;
     143        std::vector<GameState*>              activeStates_;
    113144        boost::shared_ptr<GameStateTreeNode> rootStateNode_;
    114145        boost::shared_ptr<GameStateTreeNode> activeStateNode_;
     
    123154        // variables for time statistics
    124155        uint64_t                        statisticsStartTime_;
    125         std::list<statisticsTickInfo>   statisticsTickTimes_;
     156        std::list<StatisticsTickInfo>   statisticsTickTimes_;
    126157        uint32_t                        periodTime_;
    127158        uint32_t                        periodTickTime_;
     
    134165        std::string                     levelName_;
    135166
    136         static std::map<std::string, GameState*> allStates_s;
     167        static std::map<std::string, GameStateInfo> gameStateDeclarations_s;
    137168        static Game* singletonRef_s;        //!< Pointer to the Singleton
    138         // tolua_begin
    139     };
    140 }
    141 //tolua_end
     169    }; // tolua_export
     170
     171    template <class T>
     172    /*static*/ bool Game::declareGameState(const std::string& className, const std::string& stateName, bool bIgnoreTickTime, bool bGraphicsMode)
     173    {
     174        std::map<std::string, GameStateInfo>::const_iterator it = gameStateDeclarations_s.find(getLowercase(stateName));
     175        if (it == gameStateDeclarations_s.end())
     176        {
     177            GameStateInfo& info = gameStateDeclarations_s[getLowercase(stateName)];
     178            info.stateName = stateName;
     179            info.className = className;
     180            info.bIgnoreTickTime = bIgnoreTickTime;
     181            info.bGraphicsMode = bGraphicsMode;
     182        }
     183        else
     184        {
     185            COUT(0) << "Error: Cannot declare two GameStates with the same name." << std::endl;
     186            COUT(0) << "       Ignoring second one ('" << stateName << "')." << std::endl;
     187        }
     188
     189        // Create a factory to delay GameState creation
     190        GameStateFactory::createFactory<T>(className);
     191
     192        // just a required dummy return value
     193        return true;
     194    }
     195} // tolua_export
     196
    142197#endif /* _Game_H__ */
  • code/branches/core4/src/core/GameState.cc

    r3238 r3243  
    4545        Constructor only initialises variables and sets the name permanently.
    4646    */
    47     GameState::GameState(const std::string& name, bool ignoreTickTime)
    48         : name_(name)
    49         , bIgnoreTickTime_(ignoreTickTime)
     47    GameState::GameState(const GameStateConstrParams& params)
     48        : name_(params.name)
     49        , bIgnoreTickTime_(params.bIgnoreTickTime)
    5050        , parent_(0)
    5151    {
  • code/branches/core4/src/core/GameState.h

    r3238 r3243  
    4545    /**
    4646    @brief
     47        Helper class to group construction parameters for better genericity.
     48    */
     49    struct GameStateConstrParams
     50    {
     51        std::string name;
     52        bool bIgnoreTickTime;
     53    };
     54
     55    /**
     56    @brief
    4757        An implementation of a tree to manage game states.
    4858        This leads to a certain hierarchy that is created at runtime.
     
    7787
    7888    public:
    79         GameState(const std::string& name, bool ignoreTicktime = false);
     89        GameState(const GameStateConstrParams& params);
    8090        virtual ~GameState();
    8191
  • code/branches/core4/src/orxonox/Main.cc

    r3238 r3243  
    7070        orxonox.requestState("root");
    7171        orxonox.run();
    72 
    73         // destroy the GameStates created pre-mainly
    74         orxonox::Game::destroyStates();
    75     } // orxonox gets destroyed right here!
     72    }
    7673
    7774    // Clean up class hierarchy stuff (identifiers, xmlport, configvalue, consolecommand)
  • code/branches/core4/src/orxonox/gamestates/GSClient.cc

    r3196 r3243  
    3838namespace orxonox
    3939{
    40     AddGameState(GSClient, "client");
     40    DeclareGameState(GSClient, "client", false, true);
    4141
    4242    SetCommandLineArgument(ip, "127.0.0.1").information("#.#.#.#");
    4343
    44     GSClient::GSClient(const std::string& name)
    45         : GameState(name)
     44    GSClient::GSClient(const GameStateConstrParams& params)
     45        : GameState(params)
    4646        , client_(0)
    4747    {
  • code/branches/core4/src/orxonox/gamestates/GSClient.h

    r3196 r3243  
    4040    {
    4141    public:
    42         GSClient(const std::string& name);
     42        GSClient(const GameStateConstrParams& params);
    4343        ~GSClient();
    4444
  • code/branches/core4/src/orxonox/gamestates/GSDedicated.cc

    r3205 r3243  
    5151    const unsigned int MAX_COMMAND_LENGTH = 255;
    5252   
    53     AddGameState(GSDedicated, "dedicated");
     53    DeclareGameState(GSDedicated, "dedicated", false, false);
    5454   
    5555    termios* GSDedicated::originalTerminalSettings_;
    5656
    57     GSDedicated::GSDedicated(const std::string& name)
    58         : GameState(name)
     57    GSDedicated::GSDedicated(const GameStateConstrParams& params)
     58        : GameState(params)
    5959        , server_(0)
    6060        , timeSinceLastUpdate_(0)
  • code/branches/core4/src/orxonox/gamestates/GSDedicated.h

    r3198 r3243  
    4848    {
    4949    public:
    50         GSDedicated(const std::string& name);
     50        GSDedicated(const GameStateConstrParams& params);
    5151        ~GSDedicated();
    5252
  • code/branches/core4/src/orxonox/gamestates/GSGraphics.cc

    r3238 r3243  
    5757namespace orxonox
    5858{
    59     AddGameState(GSGraphics, "graphics", true);
    60 
    61     GSGraphics::GSGraphics(const std::string& name, bool countTickTime)
    62         : GameState(name, countTickTime)
     59    DeclareGameState(GSGraphics, "graphics", true, true);
     60
     61    GSGraphics::GSGraphics(const GameStateConstrParams& params)
     62        : GameState(params)
    6363        , inputManager_(0)
    6464        , console_(0)
  • code/branches/core4/src/orxonox/gamestates/GSGraphics.h

    r3196 r3243  
    5252    {
    5353    public:
    54         GSGraphics(const std::string& name, bool countTickTime);
     54        GSGraphics(const GameStateConstrParams& params);
    5555        ~GSGraphics();
    5656        void setConfigValues();
  • code/branches/core4/src/orxonox/gamestates/GSIOConsole.cc

    r3196 r3243  
    3636namespace orxonox
    3737{
    38     AddGameState(GSIOConsole, "ioConsole");
     38    DeclareGameState(GSIOConsole, "ioConsole", false, false);
    3939
    40     GSIOConsole::GSIOConsole(const std::string& name)
    41         : GameState(name)
     40    GSIOConsole::GSIOConsole(const GameStateConstrParams& params)
     41        : GameState(params)
    4242    {
    4343    }
  • code/branches/core4/src/orxonox/gamestates/GSIOConsole.h

    r2896 r3243  
    3838    {
    3939    public:
    40         GSIOConsole(const std::string& name);
     40        GSIOConsole(const GameStateConstrParams& params);
    4141        ~GSIOConsole();
    4242
  • code/branches/core4/src/orxonox/gamestates/GSLevel.cc

    r3196 r3243  
    5656namespace orxonox
    5757{
    58     AddGameState(GSLevel, "level");
     58    DeclareGameState(GSLevel, "level", false, true);
    5959
    6060    SetCommandLineArgument(level, "").shortcut("l");
     
    6363    XMLFile* GSLevel::startFile_s = NULL;
    6464
    65     GSLevel::GSLevel(const std::string& name)
    66         : GameState(name)
     65    GSLevel::GSLevel(const GameStateConstrParams& params)
     66        : GameState(params)
    6767        , keyBinder_(0)
    6868        , gameInputState_(0)
  • code/branches/core4/src/orxonox/gamestates/GSLevel.h

    r3196 r3243  
    4141    {
    4242    public:
    43         GSLevel(const std::string& name);
     43        GSLevel(const GameStateConstrParams& params);
    4444        ~GSLevel();
    4545        void setConfigValues();
  • code/branches/core4/src/orxonox/gamestates/GSMainMenu.cc

    r3196 r3243  
    4343namespace orxonox
    4444{
    45     AddGameState(GSMainMenu, "mainMenu");
     45    DeclareGameState(GSMainMenu, "mainMenu", false, true);
    4646
    47     GSMainMenu::GSMainMenu(const std::string& name)
    48         : GameState(name)
     47    GSMainMenu::GSMainMenu(const GameStateConstrParams& params)
     48        : GameState(params)
    4949        , inputState_(0)
    5050    {
  • code/branches/core4/src/orxonox/gamestates/GSMainMenu.h

    r3196 r3243  
    4040    {
    4141    public:
    42         GSMainMenu(const std::string& name);
     42        GSMainMenu(const GameStateConstrParams& params);
    4343        ~GSMainMenu();
    4444
  • code/branches/core4/src/orxonox/gamestates/GSRoot.cc

    r3238 r3243  
    4040namespace orxonox
    4141{
    42     AddGameState(GSRoot, "root", true);
     42    DeclareGameState(GSRoot, "root", true, false);
    4343    SetCommandLineSwitch(console);
    4444    // Shortcuts for easy direct loading
     
    4848    SetCommandLineSwitch(standalone);
    4949
    50     GSRoot::GSRoot(const std::string& name, bool countTickTime)
    51         : GameState(name, countTickTime)
     50    GSRoot::GSRoot(const GameStateConstrParams& params)
     51        : GameState(params)
    5252        , timeFactor_(1.0f)
    5353        , bPaused_(false)
  • code/branches/core4/src/orxonox/gamestates/GSRoot.h

    r3196 r3243  
    3838    {
    3939    public:
    40         GSRoot(const std::string& name, bool countTickTime);
     40        GSRoot(const GameStateConstrParams& params);
    4141        ~GSRoot();
    4242
  • code/branches/core4/src/orxonox/gamestates/GSServer.cc

    r3196 r3243  
    3737namespace orxonox
    3838{
    39     AddGameState(GSServer, "server");
     39    DeclareGameState(GSServer, "server", false, true);
    4040
    4141    SetCommandLineArgument(port, 55556).shortcut("p").information("0-65535");
    4242
    43     GSServer::GSServer(const std::string& name)
    44         : GameState(name)
     43    GSServer::GSServer(const GameStateConstrParams& params)
     44        : GameState(params)
    4545        , server_(0)
    4646    {
  • code/branches/core4/src/orxonox/gamestates/GSServer.h

    r3196 r3243  
    4040    {
    4141    public:
    42         GSServer(const std::string& name);
     42        GSServer(const GameStateConstrParams& params);
    4343        ~GSServer();
    4444
  • code/branches/core4/src/orxonox/gamestates/GSStandalone.cc

    r3196 r3243  
    3434namespace orxonox
    3535{
    36     AddGameState(GSStandalone, "standalone");
     36    DeclareGameState(GSStandalone, "standalone", false, true);
    3737
    38     GSStandalone::GSStandalone(const std::string& name)
    39         : GameState(name)
     38    GSStandalone::GSStandalone(const GameStateConstrParams& params)
     39        : GameState(params)
    4040    {
    4141    }
  • code/branches/core4/src/orxonox/gamestates/GSStandalone.h

    r2896 r3243  
    3838    {
    3939    public:
    40         GSStandalone(const std::string& name);
     40        GSStandalone(const GameStateConstrParams& params);
    4141        ~GSStandalone();
    4242
Note: See TracChangeset for help on using the changeset viewer.