Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/tutoriallevel/src/orxonox/LevelManager.cc @ 8257

Last change on this file since 8257 was 7828, checked in by dafrick, 14 years ago

Fixed bug in LevelManager.

  • Property svn:eol-style set to native
File size: 9.6 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 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      Damian 'Mozork' Frick
26 *
27 */
28
29/**
30    @file LevelManager.cc
31    @brief Implementation of the LevelManager singleton.
32*/
33
34#include "LevelManager.h"
35
36#include <map>
37
38#include "util/ScopedSingletonManager.h"
39#include "core/ClassTreeMask.h"
40#include "core/CommandLineParser.h"
41#include "core/ConfigValueIncludes.h"
42#include "core/CoreIncludes.h"
43#include "core/Loader.h"
44#include "core/Resource.h"
45#include "core/XMLFile.h"
46#include "Level.h"
47#include "PlayerManager.h"
48
49namespace orxonox
50{
51    SetCommandLineArgument(level, "").shortcut("l").information("Default level file (overrides LevelManager::defaultLevelName_ configValue)");
52
53    ManageScopedSingleton(LevelManager, ScopeID::Root, false);
54
55    /**
56    @brief
57        Constructor. Registers the object, sets config values and initializes variables.
58    */
59    LevelManager::LevelManager()
60    {
61        RegisterRootObject(LevelManager);
62        this->setConfigValues();
63
64        // check override
65        if (!CommandLineParser::getArgument("level")->hasDefaultValue())
66        {
67            ModifyConfigValue(defaultLevelName_, tset, CommandLineParser::getValue("level").getString());
68        }
69
70        this->compileAvailableLevelList();
71        this->nextIndex_ = 0;
72        this->nextLevel_ = this->availableLevels_.begin();
73    }
74
75    LevelManager::~LevelManager()
76    {
77    }
78
79    /**
80    @brief
81        Set the config values for this object.
82    */
83    void LevelManager::setConfigValues()
84    {
85        SetConfigValue(defaultLevelName_, "presentationDM.oxw")
86            .description("Sets the pre selection of the level in the main menu.");
87    }
88
89    /**
90    @brief
91        Request activity for the input Level.
92        The Level will be added to the list of Levels whose activity is requested. The list is accessed in a FIFO manner.
93        If the Level is the only Level in the list it will be immediately activated. If not it will be activated as soon as it reaches the front of the list.
94    @param level
95        A pointer to the Level whose activity is requested.
96    */
97    void LevelManager::requestActivity(Level* level)
98    {
99        assert( std::find(this->levels_.begin(), this->levels_.end(), level)==this->levels_.end() );
100        // If the level is already in list.
101        if( std::find(this->levels_.begin(), this->levels_.end(), level)!=this->levels_.end() )
102            return;
103        // If it isn't insert it at the back.
104        this->levels_.push_back(level);
105        // If it is the only level in the list activate it.
106        if (this->levels_.size() == 1)
107            this->activateNextLevel();
108    }
109
110    /**
111    @brief
112        Release activity for the input Level.
113        Removes the Level from the list. If the Level was the one currently active, it is deactivated and the next Level in line is activated.
114    @param level
115        A pointer to the Level whose activity is to be released.
116    */
117    void LevelManager::releaseActivity(Level* level)
118    {
119        if (this->levels_.size() > 0)
120        {
121            // If the level is the active level in the front of the list.
122            if (this->levels_.front() == level)
123            {
124                // Deactivate it, remove it from the list and activate the next level in line.
125                level->setActive(false);
126                this->levels_.pop_front();
127                this->activateNextLevel();
128            }
129            else // Else just remove it from the list.
130                this->levels_.erase(std::find(this->levels_.begin(), this->levels_.end(), level));
131        }
132    }
133
134    /**
135    @brief
136        Get the currently active Level.
137    @return
138        Returns a pointer to the currently active level or NULL if there currently are no active Levels.
139    */
140    Level* LevelManager::getActiveLevel()
141    {
142        if (this->levels_.size() > 0)
143            return this->levels_.front();
144        else
145            return 0;
146    }
147
148    /**
149    @brief
150        Activate the next Level.
151    */
152    void LevelManager::activateNextLevel()
153    {
154        if (this->levels_.size() > 0)
155        {
156            // Activate the level that is the first in the list of levels whose activity has been requested.
157            this->levels_.front()->setActive(true);
158            // Make every player enter the newly activated level.
159            for (std::map<unsigned int, PlayerInfo*>::const_iterator it = PlayerManager::getInstance().getClients().begin(); it != PlayerManager::getInstance().getClients().end(); ++it)
160                this->levels_.front()->playerEntered(it->second);
161        }
162    }
163
164    /**
165    @brief
166        Set the default Level.
167    @param levelName
168        The filename of the default Level.
169    */
170    void LevelManager::setDefaultLevel(const std::string& levelName)
171    {
172        ModifyConfigValue(defaultLevelName_, set, levelName);
173    }
174
175    /**
176    @brief
177        Get the number of available Levels.
178        Also updates the list of available Levels.
179    @return
180        Returns the number of available Levels.
181    */
182    unsigned int LevelManager::getNumberOfLevels()
183    {
184        this->updateAvailableLevelList();
185
186        return this->availableLevels_.size();
187    }
188
189    /**
190    @brief
191        Get the LevelInfoItem at the given index in the list of available Levels.
192        The LevelInfoItems are sorted in alphabetical order accoridng to the name of the Level.
193        This method is most efficiently called with consecutive indices (or at least ascending indices).
194    @param index
195        The index of the item that should be returned.
196    @return
197        Returns a pointer to the LevelInfoItem at the given index.
198    */
199    LevelInfoItem* LevelManager::getAvailableLevelListItem(unsigned int index)
200    {
201        if(index >= this->availableLevels_.size())
202            return NULL;
203
204        // If this index directly follows the last we can optimize a lot.
205        if(index == this->nextIndex_)
206        {
207            this->nextIndex_++;
208            std::set<LevelInfoItem*, LevelInfoCompare>::iterator it = this->nextLevel_;
209            this->nextLevel_++;
210            return *it;
211        }
212        else
213        {
214            // If this index is bigger than the last, we can optimize a little.
215            if(index < this->nextIndex_)
216            {
217                this->nextIndex_ = 0;
218                this->nextLevel_ = this->availableLevels_.begin();
219            }
220
221            while(this->nextIndex_ != index)
222            {
223                this->nextIndex_++;
224                this->nextLevel_++;
225            }
226            this->nextIndex_++;
227            std::set<LevelInfoItem*, LevelInfoCompare>::iterator it = this->nextLevel_;
228            this->nextLevel_++;
229            return *it;
230        }
231    }
232
233    /**
234    @brief
235        Compile the list of available Levels.
236        Iterates over all *.oxw files, loads the LevelInfo objects in them and from that it creates the LevelInfoItems which are inserted in a list.
237    */
238    void LevelManager::compileAvailableLevelList()
239    {
240        Ogre::StringVectorPtr levels = Resource::findResourceNames("*.oxw");
241        // Iterate over all *.oxw level files.
242        COUT(3) << "Loading LevelInfos..." << std::endl;
243        for (Ogre::StringVector::const_iterator it = levels->begin(); it != levels->end(); ++it)
244        {
245            //TODO: Replace with tag?
246            if (it->find("old/") != 0)
247            {
248                size_t pos = it->find(".oxw");
249
250                // Load the LevelInfo object from the level file.
251                bool infoExists = false;
252                XMLFile file = XMLFile(*it);
253                ClassTreeMask mask = ClassTreeMask();
254                mask.exclude(ClassIdentifier<BaseObject>::getIdentifier());
255                mask.include(ClassIdentifier<LevelInfo>::getIdentifier());
256                Loader::load(&file, mask, false);
257                // Iterate over all LevelInfos.
258                for(ObjectList<LevelInfo>::iterator item = ObjectList<LevelInfo>::begin(); item != ObjectList<LevelInfo>::end(); ++item)
259                {
260                    LevelInfoItem* info = item->copy();
261                    if(info->getXMLFilename() == *it) // If the LevelInfo for this level exists we insert it into the list of available levels.
262                    {
263                        this->availableLevels_.insert(info);
264                        infoExists = true;
265                    }
266                }
267                Loader::unload(&file, mask);
268                if(!infoExists) // If the LevelInfo for this level doesn't exist, we create a new one and insert it into the list of available levels.
269                    this->availableLevels_.insert(new LevelInfoItem(it->substr(0, pos), *it));
270            }
271        }
272    }
273
274    /**
275    @brief
276        Update the list of available Levels.
277    */
278    void LevelManager::updateAvailableLevelList(void)
279    {
280        //TODO: Implement some kind of update?
281    }
282}
Note: See TracBrowser for help on using the repository browser.