Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/cpp11_v2/src/orxonox/gamestates/GSLevel.cc @ 10994

Last change on this file since 10994 was 10920, checked in by landauf, 10 years ago

no static functions anymore in ObjectList. you need to instantiate an ObjectList to use it.
this allows for prettier for-loop syntax when iterating over an ObjectList of a specific context: for (T* object : ObjectList<T>(context)) { … }

  • Property svn:eol-style set to native
File size: 9.5 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 *      Benjamin Knecht
27 *
28 */
29
30#include "GSLevel.h"
31#include "GSLevelMemento.h"
32
33#include <OgreCompositorManager.h>
34
35#include "util/Clock.h"
36#include "core/input/InputManager.h"
37#include "core/input/InputState.h"
38#include "core/input/KeyBinderManager.h"
39#include "core/Core.h"
40#include "core/CoreIncludes.h"
41#include "core/Game.h"
42#include "core/GameMode.h"
43#include "core/GUIManager.h"
44#include "core/Loader.h"
45#include "core/XMLFile.h"
46#include "core/command/ConsoleCommandIncludes.h"
47
48#include "LevelManager.h"
49#include "Level.h"
50#include "PlayerManager.h"
51#include "GSRoot.h"
52
53namespace orxonox
54{
55    DeclareGameState(GSLevel, "level", false, false);
56
57    static const std::string __CC_startMainMenu_name = "startMainMenu";
58    static const std::string __CC_changeGame_name = "changeGame";
59    static const std::string __CC_reloadLevel_name = "reloadLevel";
60
61    SetConsoleCommand(__CC_startMainMenu_name, &GSLevel::startMainMenu).deactivate();
62    SetConsoleCommand(__CC_changeGame_name, &GSLevel::changeGame).defaultValues("").deactivate();
63    SetConsoleCommand(__CC_reloadLevel_name, &GSLevel::reloadLevel).deactivate();
64
65    GSLevel::GSLevel(const GameStateInfo& info)
66        : GameState(info)
67        , gameInputState_(nullptr)
68        , guiMouseOnlyInputState_(nullptr)
69        , guiKeysOnlyInputState_(nullptr)
70        , startFile_(nullptr)
71        , bShowIngameGUI_(false)
72    {
73    }
74
75    GSLevel::~GSLevel()
76    {
77    }
78
79    void GSLevel::activate()
80    {
81        orxout(user_status) << "Loading level" << endl;
82
83        if (GameMode::showsGraphics())
84        {
85            gameInputState_ = InputManager::getInstance().createInputState("game");
86            gameInputState_->setMouseExclusive(true);
87            gameInputState_->setHandler(KeyBinderManager::getInstance().getDefaultAsHandler());
88            KeyBinderManager::getInstance().setToDefault();
89
90            guiMouseOnlyInputState_ = InputManager::getInstance().createInputState("guiMouseOnly");
91            guiMouseOnlyInputState_->setMouseExclusive(true);
92            guiMouseOnlyInputState_->setMouseHandler(&GUIManager::getInstance());
93
94            guiKeysOnlyInputState_ = InputManager::getInstance().createInputState("guiKeysOnly");
95            guiKeysOnlyInputState_->setKeyHandler(&GUIManager::getInstance());
96        }
97
98        this->prepareObjectTracking();
99
100        if (GameMode::isMaster())
101        {
102            this->loadLevel();
103        }
104
105        if (GameMode::showsGraphics())
106        {
107            // level is loaded: we can start capturing the input
108            InputManager::getInstance().enterState("game");
109
110            // connect the HumanPlayer to the game
111            PlayerManager::getInstance().clientConnected(0);
112
113            ModifyConsoleCommand(__CC_startMainMenu_name).activate();
114        }
115
116        if (GameMode::isStandalone())
117        {
118            ModifyConsoleCommand(__CC_changeGame_name).activate();
119            ModifyConsoleCommand(__CC_reloadLevel_name).setObject(this).activate();
120        }
121    }
122
123    void GSLevel::deactivate()
124    {
125        if (GameMode::showsGraphics())
126            InputManager::getInstance().leaveState("game");
127
128        // disconnect all HumanPlayers
129        PlayerManager::getInstance().disconnectAllClients();
130
131        if (GameMode::isMaster())
132            this->unloadLevel();
133        else
134            this->unloadLevelAsClient();
135
136        this->performObjectTracking();
137
138        if (GameMode::showsGraphics())
139        {
140#if OGRE_VERSION < 0x010700
141            // unload all compositors (this is only necessary because we don't yet destroy all resources!)
142            Ogre::CompositorManager::getSingleton().removeAll();
143#endif
144
145            gameInputState_->setHandler(nullptr);
146            guiMouseOnlyInputState_->setHandler(nullptr);
147            guiKeysOnlyInputState_->setHandler(nullptr);
148            InputManager::getInstance().destroyState("game");
149            InputManager::getInstance().destroyState("guiKeysOnly");
150            InputManager::getInstance().destroyState("guiMouseOnly");
151
152            ModifyConsoleCommand(__CC_startMainMenu_name  ).deactivate();
153        }
154
155        if (GameMode::isStandalone())
156        {
157            ModifyConsoleCommand(__CC_changeGame_name).deactivate();
158            ModifyConsoleCommand(__CC_reloadLevel_name).setObject(nullptr).deactivate();
159        }
160    }
161
162    void GSLevel::update(const Clock& time)
163    {
164        // Note: Temporarily moved to GSRoot.
165        //// Call the scene objects
166        //for (Tickable* tickable : ObjectList<Tickable>())
167        //    tickable->tick(time.getDeltaTime() * this->timeFactor_);
168    }
169
170    void GSLevel::prepareObjectTracking()
171    {
172        for (BaseObject* baseObject : ObjectList<BaseObject>())
173            this->staticObjects_.insert(baseObject);
174    }
175
176    void GSLevel::performObjectTracking()
177    {
178        orxout(internal_info) << "Remaining objects:" << endl;
179        unsigned int i = 0;
180        for (BaseObject* baseObject : ObjectList<BaseObject>())
181        {
182            std::set<BaseObject*>::const_iterator find = this->staticObjects_.find(baseObject);
183            if (find == this->staticObjects_.end())
184            {
185                orxout(internal_warning) << ++i << ": " << baseObject->getIdentifier()->getName() << " (" << baseObject << "), references: " << baseObject->getReferenceCount() << endl;
186            }
187        }
188        if (i == 0)
189            orxout(internal_info) << i << " objects remaining. Well done!" << endl;
190        else
191            orxout(internal_warning) << i << " objects remaining. Try harder!" << endl;
192    }
193
194    void GSLevel::loadLevel()
195    {
196        // call the loader
197        startFile_ = new XMLFile(LevelManager::getInstance().getDefaultLevel());
198        bool loaded = Loader::getInstance().load(startFile_);
199
200        Core::getInstance().getConfig()->updateLastLevelTimestamp();
201        if(!loaded)
202            GSRoot::delayedStartMainMenu();
203    }
204
205    void GSLevel::unloadLevel()
206    {
207        Loader::getInstance().unload(startFile_);
208        delete startFile_;
209    }
210
211    /**
212     * Unloads a level when the game instance is (or was) a client in a multiplayer session.
213     * In this case, cleanup after unloading a level is done differently because certain things (e.g. the xml file) are unknown.
214     */
215    void GSLevel::unloadLevelAsClient()
216    {
217        ObjectList<Level> listLevel;
218        for (ObjectList<Level>::iterator it = listLevel.begin(); it != listLevel.end(); )
219        {
220            StrongPtr<Level> level = *(it++); // StrongPtr prevents that the Level gets destroyed while we loop over it
221            ObjectList<BaseObject> listBaseObject(level);
222            for (ObjectList<BaseObject>::iterator it = listBaseObject.begin(); it != listBaseObject.end(); )
223                (it++)->destroy();
224        }
225
226        ObjectList<Synchronisable> listSynchronisable;
227        for (ObjectList<Synchronisable>::iterator it = listSynchronisable.begin(); it != listSynchronisable.end(); )
228        {
229            if (it->getSyncMode() != 0x0)
230                (it++)->destroy();
231            else
232                ++it;
233        }
234    }
235
236    void GSLevel::reloadLevel()
237    {
238        // export all states
239        std::vector<GSLevelMementoState*> states;
240        for (GSLevelMemento* memento : ObjectList<GSLevelMemento>())
241        {
242            GSLevelMementoState* state = memento->exportMementoState();
243            if (state)
244                states.push_back(state);
245        }
246
247        // reload level (or better: reload the whole gamestate)
248        this->deactivate();
249        this->activate();
250
251        // import all states
252        for (GSLevelMemento* memento : ObjectList<GSLevelMemento>())
253            memento->importMementoState(states);
254
255        // delete states
256        for (GSLevelMementoState* state : states)
257            delete state;
258    }
259
260    /**
261    @brief
262        Starts the MainMenu.
263    */
264    /*static*/ void GSLevel::startMainMenu(void)
265    {
266        // HACK
267        Game::getInstance().popState();
268        Game::getInstance().popState();
269    }
270
271    /**
272    @brief
273        Terminates the current game and starts a new game.
274    @param level
275        The filename of the level to be started.
276    */
277    /*static*/ void GSLevel::changeGame(const std::string& level)
278    {
279        if(level != "")
280            LevelManager::getInstance().setDefaultLevel(level);
281
282        // HACK
283        Game::getInstance().popState();
284        Game::getInstance().popState();
285        Game::getInstance().requestStates("standalone, level");
286    }
287
288
289
290    ///////////////////////////////////////////////////////////////////////////
291
292    RegisterAbstractClass(GSLevelMemento).inheritsFrom<OrxonoxInterface>();
293
294    GSLevelMemento::GSLevelMemento()
295    {
296        RegisterObject(GSLevelMemento);
297    }
298}
Note: See TracBrowser for help on using the repository browser.