Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/gui/src/core/RootGameState.cc @ 1690

Last change on this file since 1690 was 1690, checked in by rgrieder, 16 years ago

Added support to specify the command line arguments in start.ini (uses the same formatting). '#' is the comment character.

  • Property svn:eol-style set to native
File size: 6.4 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Reto Grieder
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29#include "RootGameState.h"
30
31#include "util/String.h"
32#include "util/SubString.h"
33#include "Clock.h"
34#include "Debug.h"
35#include "Exception.h"
36#include "CommandLine.h"
37
38namespace orxonox
39{
40    SetCommandLineArgument(state, "gui").setShortcut("s");
41
42    RootGameState::RootGameState(const std::string& name)
43        : GameState<GameStateBase>(name)
44        , stateRequest_("")
45    {
46    }
47
48    RootGameState::~RootGameState()
49    {
50    }
51
52    /**
53    @brief
54        Internal method that actually makes the state transition. Since it is internal,
55        the method can assume certain things to be granted (like 'this' is always active).
56    */
57    void RootGameState::makeTransition(GameStateBase* source, GameStateBase* destination)
58    {
59        if (source != 0)
60        {
61            // transition was not initiated by root itself
62            this->activeChild_ = 0;
63        }
64
65        if (destination == this)
66        {
67            // this marks the end of the game.
68            return;
69        }
70
71        // Check for 'destination' in the children map first
72        std::map<GameStateBase*, GameStateBase*>::const_iterator it
73            = this->grandchildrenToChildren_.find(destination);
74        if (it != this->grandchildrenToChildren_.end())
75        {
76            OrxAssert(dynamic_cast<GameStateBase*>(it->second) != 0,
77                "There was a mix with RootGameState and GameState, could not cast.");
78            GameStateBase* child = static_cast<GameStateBase*>(it->second);
79            // child state. Don't use 'state', might be a grandchild!
80            this->activeChild_ = child;
81            child->makeTransition(this, destination);
82        }
83        else
84        {
85            // root doesn't have a parent..
86            OrxAssert(false, "GameState '" + destination->getName() + "' not found in children list of Root.");
87        }
88    }
89
90    void RootGameState::gotoState(const std::string& name)
91    {
92        GameStateBase* request = getState(name);
93        if (request)
94        {
95            GameStateBase* current = getCurrentState();
96            if (current)
97            {
98                current->makeTransition(0, request);
99            }
100            else
101            {
102                // Root is not yet active. This is a violation.
103                ThrowException(GameState, "Activate Root before requesting a state.");
104            }
105        }
106        else
107        {
108            COUT(2) << "Warning: GameState '" << name << "' doesn't exist." << std::endl;
109        }
110    }
111
112    /**
113    @brief
114        Makes a state transition according to the state tree. You can choose any state
115        in the tree to do the call. The function finds the current state on its own.
116    @param state
117        The state to be entered, has to exist in the tree.
118    */
119    void RootGameState::requestState(const std::string& name)
120    {
121        this->stateRequest_ = name;
122    }
123
124    /**
125    @brief
126        Starts the game. The little 'while' denotes the main loop.
127        Whenever the root state is selected, the game ends.
128    @param name
129        State to start with (usually main menu or specified by command line)
130    */
131    void RootGameState::start(int argc, char** argv)
132    {
133        parseArguments(argc, argv);
134
135        this->activate();
136
137        // get initial state from command line
138        std::string initialState;
139        CommandLine::getValue<std::string>("state", &initialState);
140        gotoState(initialState);
141
142        Clock clock;
143        while (this->activeChild_)
144        {
145            clock.capture();
146
147            this->tick(clock);
148
149            if (this->stateRequest_ != "")
150                gotoState(stateRequest_);
151        }
152
153        this->deactivate();
154    }
155
156    /**
157    @brief
158        Parses both command line and start.ini for CommandLineArguments.
159    */
160    void RootGameState::parseArguments(int argc, char** argv)
161    {
162        // parse command line first
163        std::vector<std::string> args;
164        for (int i = 1; i < argc; ++i)
165            args.push_back(argv[i]);
166
167        try
168        {
169            orxonox::CommandLine::parse(args);
170        }
171        catch (orxonox::ArgumentException& ex)
172        {
173            COUT(1) << ex.what() << std::endl;
174            COUT(0) << "Usage:" << std::endl << "orxonox " << CommandLine::getUsageInformation() << std::endl;
175        }
176
177        // look for additional arguments in start.ini
178        std::ifstream file;
179        file.open("start.ini");
180        args.clear();
181        if (file)
182        {
183            while (!file.eof())
184            {
185                std::string line;
186                std::getline(file, line);
187                line = removeTrailingWhitespaces(line);
188                //if (!(line[0] == '#' || line[0] == '%'))
189                //{
190                SubString tokens(line, " ", " ", false, 92, false, 34, false, 40, 41, false, '#');
191                for (unsigned i = 0; i < tokens.size(); ++i)
192                    if (tokens[i][0] != '#')
193                        args.push_back(tokens[i]);
194                //args.insert(args.end(), tokens.getAllStrings().begin(), tokens.getAllStrings().end());
195                //}
196            }
197            file.close();
198        }
199
200        try
201        {
202            orxonox::CommandLine::parse(args);
203        }
204        catch (orxonox::ArgumentException& ex)
205        {
206            COUT(1) << "An Exception occured while parsing start.ini" << std::endl;
207            COUT(1) << ex.what() << std::endl;
208            COUT(0) << "Usage:" << std::endl << "orxonox " << CommandLine::getUsageInformation() << std::endl;
209        }
210    }
211}
Note: See TracBrowser for help on using the repository browser.