Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/orxonox/LevelManager.cc @ 7802

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

Making the level list in the LevelManager (and as consequence the level list displayed by the GUI) alphabetically sorted. Also some cleanup and documented LevelManager.

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