Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/usability/src/orxonox/LevelManager.cc @ 7997

Last change on this file since 7997 was 7997, checked in by rgrieder, 13 years ago

Added warning for the case two Levels had the same identification (name).
—> 3 warnings popping up now :P

  • Property svn:eol-style set to native
File size: 9.8 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            while(this->nextIndex_ != index)
221            {
222                this->nextIndex_++;
223                this->nextLevel_++;
224            }
225            this->nextIndex_++;
226            std::set<LevelInfoItem*, LevelInfoCompare>::iterator it = this->nextLevel_;
227            this->nextLevel_++;
228            return *it;
229        }
230    }
231
232    /**
233    @brief
234        Compile the list of available Levels.
235        Iterates over all *.oxw files, loads the LevelInfo objects in them and from that it creates the LevelInfoItems which are inserted in a list.
236    */
237    void LevelManager::compileAvailableLevelList()
238    {
239        // Get all files matching the level criteria
240        Ogre::StringVectorPtr levels = Resource::findResourceNames("*.oxw");
241
242        // We only want to load as little as possible
243        ClassTreeMask mask;
244        mask.exclude(Class(BaseObject));
245        mask.include(Class(LevelInfo));
246
247        // Iterate over all the found *.oxw files
248        COUT(3) << "Loading LevelInfos..." << std::endl;
249        for (Ogre::StringVector::const_iterator it = levels->begin(); it != levels->end(); ++it)
250        {
251            // TODO: Replace with tag?
252            if (it->find("old/") != 0)
253            {
254                LevelInfoItem* info = NULL;
255
256                // Load the LevelInfo object from the level file.
257                XMLFile file = XMLFile(*it);
258                Loader::load(&file, mask, false, true);
259
260                // Find the LevelInfo object we've just loaded (if there was one)
261                for(ObjectList<LevelInfo>::iterator item = ObjectList<LevelInfo>::begin(); item != ObjectList<LevelInfo>::end(); ++item)
262                    if(item->getXMLFilename() == *it)
263                        info = item->copy();
264
265                // We don't need the loaded stuff anymore
266                Loader::unload(&file, mask);
267
268                if(info == NULL) 
269                {
270                    // Create a default LevelInfoItem object that merely contains the name
271                    std::string filenameWOExtension = it->substr(0, it->find(".oxw"));
272                    info = new LevelInfoItem(filenameWOExtension, *it);
273                }
274
275                // Warn about multiple items so that it gets fixed quickly
276                if(availableLevels_.find(info) != availableLevels_.end())
277                    COUT(2) << "Warning: Multiple levels with name '" << info->getName() << "' found!" << std::endl;
278
279                this->availableLevels_.insert(info);
280            }
281        }
282    }
283
284    /**
285    @brief
286        Update the list of available Levels.
287    */
288    void LevelManager::updateAvailableLevelList(void)
289    {
290        //TODO: Implement some kind of update?
291    }
292}
Note: See TracBrowser for help on using the repository browser.