Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/gui/src/orxonox/gamestates/GSLevel.cc @ 2844

Last change on this file since 2844 was 2844, checked in by rgrieder, 15 years ago

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.

  • Property svn:eol-style set to native
File size: 9.0 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 *      Fabian 'x3n' Landau
26 *
27 */
28
29#include "OrxonoxStableHeaders.h"
30#include "GSLevel.h"
31
32#include "core/input/InputManager.h"
33#include "core/input/SimpleInputState.h"
34#include "core/input/KeyBinder.h"
35#include "core/Loader.h"
36#include "core/XMLFile.h"
37#include "core/CommandExecutor.h"
38#include "core/ConsoleCommand.h"
39#include "core/CommandLine.h"
40#include "core/ConfigValueIncludes.h"
41#include "core/CoreIncludes.h"
42#include "core/Core.h"
43#include "objects/Tickable.h"
44#include "objects/Radar.h"
45#include "CameraManager.h"
46#include "GraphicsManager.h"
47#include "LevelManager.h"
48#include "PlayerManager.h"
49#include "core/Game.h"
50
51namespace orxonox
52{
53    AddGameState(GSLevel, "level");
54
55    SetCommandLineArgument(level, "presentation.oxw").shortcut("l");
56
57    GSLevel::GSLevel(const std::string& name)
58        : GameState(name)
59        , keyBinder_(0)
60        , inputState_(0)
61        , radar_(0)
62        , startFile_(0)
63        , cameraManager_(0)
64        , levelManager_(0)
65    {
66        RegisterObject(GSLevel);
67
68        this->ccKeybind_ = 0;
69        this->ccTkeybind_ = 0;
70    }
71
72    GSLevel::~GSLevel()
73    {
74    }
75
76    void GSLevel::setConfigValues()
77    {
78        SetConfigValue(keyDetectorCallbackCode_, "KeybindBindingStringKeyName=");
79    }
80
81    void GSLevel::activate()
82    {
83        setConfigValues();
84
85        if (Core::showsGraphics())
86        {
87            inputState_ = InputManager::getInstance().createInputState<SimpleInputState>("game");
88            keyBinder_ = new KeyBinder();
89            keyBinder_->loadBindings("keybindings.ini");
90            inputState_->setHandler(keyBinder_);
91
92            // create the global CameraManager
93            this->cameraManager_ = new CameraManager(GraphicsManager::getInstance().getViewport());
94
95            // Start the Radar
96            this->radar_ = new Radar();
97        }
98
99        this->playerManager_ = new PlayerManager();
100
101        if (Core::isMaster())
102        {
103            // create the global LevelManager
104            this->levelManager_ = new LevelManager();
105
106            this->loadLevel();
107        }
108
109        if (Core::showsGraphics())
110        {
111            // TODO: insert slomo console command with
112            // .accessLevel(AccessLevel::Offline).defaultValue(0, 1.0).axisParamIndex(0).isAxisRelative(false);
113
114            // keybind console command
115            FunctorMember<GSLevel>* functor1 = createFunctor(&GSLevel::keybind);
116            functor1->setObject(this);
117            ccKeybind_ = createConsoleCommand(functor1, "keybind");
118            CommandExecutor::addConsoleCommandShortcut(ccKeybind_);
119            FunctorMember<GSLevel>* functor2 = createFunctor(&GSLevel::tkeybind);
120            functor2->setObject(this);
121            ccTkeybind_ = createConsoleCommand(functor2, "tkeybind");
122            CommandExecutor::addConsoleCommandShortcut(ccTkeybind_);
123            // set our console command as callback for the key detector
124            InputManager::getInstance().setKeyDetectorCallback(std::string("keybind ") + keyDetectorCallbackCode_);
125
126            // level is loaded: we can start capturing the input
127            InputManager::getInstance().requestEnterState("game");
128        }
129    }
130
131    void GSLevel::deactivate()
132    {
133        // destroy console commands
134        if (this->ccKeybind_)
135        {
136            delete this->ccKeybind_;
137            this->ccKeybind_ = 0;
138        }
139        if (this->ccTkeybind_)
140        {
141            delete this->ccTkeybind_;
142            this->ccTkeybind_ = 0;
143        }
144
145        // this call will delete every BaseObject!
146        // But currently this will call methods of objects that exist no more
147        // The only 'memory leak' is the ParticleSpawer. They would be deleted here
148        // and call a sceneNode method that has already been destroy by the corresponding space ship.
149        //Loader::close();
150
151        if (Core::showsGraphics())
152            InputManager::getInstance().requestLeaveState("game");
153
154        if (Core::isMaster())
155            this->unloadLevel();
156
157        if (this->radar_)
158        {
159            delete this->radar_;
160            this->radar_ = 0;
161        }
162
163        if (this->cameraManager_)
164        {
165            delete this->cameraManager_;
166            this->cameraManager_ = 0;
167        }
168
169        if (this->levelManager_)
170        {
171            delete this->levelManager_;
172            this->levelManager_ = 0;
173        }
174
175        if (this->playerManager_)
176        {
177            delete this->playerManager_;
178            this->playerManager_ = 0;
179        }
180
181        if (Core::showsGraphics())
182        {
183            inputState_->setHandler(0);
184            InputManager::getInstance().requestDestroyState("game");
185            if (this->keyBinder_)
186            {
187                delete this->keyBinder_;
188                this->keyBinder_ = 0;
189            }
190        }
191    }
192
193    void GSLevel::update(const Clock& time)
194    {
195        // Note: Temporarily moved to GSGraphics.
196        //// Call the scene objects
197        //for (ObjectList<Tickable>::iterator it = ObjectList<Tickable>::begin(); it; ++it)
198        //    it->tick(time.getDeltaTime() * this->timeFactor_);
199    }
200
201    void GSLevel::loadLevel()
202    {
203        // call the loader
204        COUT(0) << "Loading level..." << std::endl;
205        std::string levelName;
206        CommandLine::getValue("level", &levelName);
207        startFile_ = new XMLFile(Core::getMediaPathString() + "levels" + '/' + levelName);
208        Loader::open(startFile_);
209    }
210
211    void GSLevel::unloadLevel()
212    {
213        //////////////////////////////////////////////////////////////////////////////////////////
214        // TODO // TODO // TODO // TODO // TODO // TODO // TODO // TODO // TODO // TODO // TODO //
215        //////////////////////////////////////////////////////////////////////////////////////////
216        // Loader::unload(startFile_); // TODO: REACTIVATE THIS IF LOADER::UNLOAD WORKS PROPERLY /
217        //////////////////////////////////////////////////////////////////////////////////////////
218
219        delete this->startFile_;
220    }
221
222    void GSLevel::keybind(const std::string &command)
223    {
224        this->keybindInternal(command, false);
225    }
226
227    void GSLevel::tkeybind(const std::string &command)
228    {
229        this->keybindInternal(command, true);
230    }
231
232    /**
233    @brief
234        Assigns a command string to a key/button/axis. The name is determined via KeyDetector.
235    @param command
236        Command string that can be executed by the CommandExecutor
237        OR: Internal string "KeybindBindingStringKeyName=" used for the second call to identify
238        the key/button/axis that has been activated. This is configured above in activate().
239    */
240    void GSLevel::keybindInternal(const std::string& command, bool bTemporary)
241    {
242        if (Core::showsGraphics())
243        {
244            static std::string bindingString = "";
245            static bool bTemporarySaved = false;
246            static bool bound = true;
247            // note: We use a long name to make 'sure' that the user doesn't use it accidentally.
248            // Howerver there will be no real issue if it happens anyway.
249            if (command.find(keyDetectorCallbackCode_) != 0)
250            {
251                if (bound)
252                {
253                    COUT(0) << "Press any button/key or move a mouse/joystick axis" << std::endl;
254                    InputManager::getInstance().requestEnterState("detector");
255                    bindingString = command;
256                    bTemporarySaved = bTemporary;
257                    bound = false;
258                }
259                //else:  We're still in a keybind command. ignore this call.
260            }
261            else
262            {
263                if (!bound)
264                {
265                    // user has pressed the key
266                    std::string name = command.substr(this->keyDetectorCallbackCode_.size());
267                    COUT(0) << "Binding string \"" << bindingString << "\" on key '" << name << "'" << std::endl;
268                    this->keyBinder_->setBinding(bindingString, name, bTemporarySaved);
269                    InputManager::getInstance().requestLeaveState("detector");
270                    bound = true;
271                }
272                // else: A key was pressed within the same tick, ignore it.
273            }
274        }
275    }
276}
Note: See TracBrowser for help on using the repository browser.