Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/gui/src/orxonox/gamestates/GSRoot.cc @ 1689

Last change on this file since 1689 was 1689, checked in by rgrieder, 16 years ago
  • renamed:

GameState —> GameStateBase
GameStateTyped<T> —> GameState

  • moved command line parsing from GSRoot to RootGameState.
  • Property svn:eol-style set to native
File size: 10.2 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 *      ...
26 *
27 */
28
29#include "OrxonoxStableHeaders.h"
30#include "GSRoot.h"
31
32#include <OgreLogManager.h>
33#include <OgreRoot.h>
34
35//#include "util/SubString.h"
36#include "core/Factory.h"
37#include "core/ConfigFileManager.h"
38#include "core/ConfigValueIncludes.h"
39#include "core/CoreIncludes.h"
40#include "core/ConsoleCommand.h"
41#include "core/CommandLine.h"
42#include "core/Debug.h"
43#include "core/Exception.h"
44#include "core/TclBind.h"
45#include "core/TclThreadManager.h"
46#include "GraphicsEngine.h"
47#include "Settings.h"
48
49#if ORXONOX_PLATFORM == ORXONOX_PLATFORM_WIN32
50#  ifndef WIN32_LEAN_AND_MEAN
51#    define WIN32_LEAN_AND_MEAN
52#  endif
53#  include "windows.h"
54
55   //Get around Windows hackery
56#  ifdef max
57#    undef max
58#  endif
59#  ifdef min
60#    undef min
61#  endif
62#endif
63
64namespace orxonox
65{
66    SetCommandLineArgument(dataPath, "").setInformation("PATH");
67
68    GSRoot::GSRoot()
69        : RootGameState("root")
70        , settings_(0)
71        , ogreRoot_(0)
72        , ogreLogger_(0)
73        , graphicsEngine_(0)
74    {
75        RegisterRootObject(GSRoot);
76    }
77
78    GSRoot::~GSRoot()
79    {
80    }
81
82    void GSRoot::setConfigValues()
83    {
84        SetConfigValue(ogreConfigFile_,  "ogre.cfg").description("Location of the Ogre config file");
85        SetConfigValue(ogrePluginsFile_, "plugins.cfg").description("Location of the Ogre plugins file");
86        SetConfigValue(ogreLogFile_,     "ogre.log").description("Logfile for messages from Ogre. \
87                                                                 Use \"\" to suppress log file creation.");
88        SetConfigValue(ogreLogLevelTrivial_ , 5).description("Corresponding orxonox debug level for ogre Trivial");
89        SetConfigValue(ogreLogLevelNormal_  , 4).description("Corresponding orxonox debug level for ogre Normal");
90        SetConfigValue(ogreLogLevelCritical_, 2).description("Corresponding orxonox debug level for ogre Critical");
91    }
92
93    void GSRoot::enter()
94    {
95#if ORXONOX_DEBUG_MODE == 1
96        ConfigFileManager::getSingleton()->setFile(CFT_Settings, "orxonox_d.ini");
97#else
98        ConfigFileManager::getSingleton()->setFile(CFT_Settings, "orxonox.ini");
99#endif
100
101        // do this after the previous call..
102        setConfigValues();
103
104        // creates the class hierarchy for all classes with factories
105        Factory::createClassHierarchy();
106
107        // instantiate Settings class
108        this->settings_ = new Settings();
109
110        std::string dataPath;
111        CommandLine::getValue("dataPath", &dataPath);
112        if (dataPath != "")
113        {
114            if (*dataPath.end() != '/' && *dataPath.end() != '\\')
115                Settings::tsetDataPath(dataPath + "/");
116            else
117                Settings::tsetDataPath(dataPath);
118        }
119
120        // initialise TCL
121        TclBind::getInstance().setDataPath(Settings::getDataPath());
122        TclThreadManager::getInstance();
123
124        setupOgre();
125
126        // initialise graphics engine. Doesn't load the render window yet!
127        graphicsEngine_ = new GraphicsEngine();
128
129        // limit the main thread to the first core so that QueryPerformanceCounter doesn't jump
130        // do this after ogre has initialised. Somehow Ogre changes the settings again (not through
131        // the timer though).
132        setThreadAffinity();
133
134        // add console commands
135        FunctorMember<GSRoot>* functor1 = createFunctor(&GSRoot::exitGame);
136        functor1->setObject(this);
137        CommandExecutor::addConsoleCommandShortcut(createConsoleCommand(functor1, "exit"));
138
139        // add console commands
140        FunctorMember01<GameStateBase, const std::string&>* functor2 = createFunctor(&GameStateBase::requestState);
141        functor2->setObject(this);
142        CommandExecutor::addConsoleCommandShortcut(createConsoleCommand(functor2, "selectGameState"));
143    }
144
145    void GSRoot::leave()
146    {
147        delete graphicsEngine_;
148
149        delete this->ogreRoot_;
150
151#if ORXONOX_PLATFORM == ORXONOX_PLATFORM_WIN32
152        // delete the ogre log and the logManager (since we have created it).
153        this->ogreLogger_->getDefaultLog()->removeListener(this);
154        this->ogreLogger_->destroyLog(Ogre::LogManager::getSingleton().getDefaultLog());
155        delete this->ogreLogger_;
156#endif
157
158        delete settings_;
159
160        // TODO: remove and destroy console commands
161    }
162
163    void GSRoot::ticked(const Clock& time)
164    {
165        TclThreadManager::getInstance().tick(time.getDeltaTime());
166
167        this->tickChild(time);
168    }
169
170    /**
171    @note
172        The code of this function has been copied from OGRE, an open source graphics engine.
173            (Object-oriented Graphics Rendering Engine)
174        For the latest info, see http://www.ogre3d.org/
175
176        Copyright (c) 2000-2008 Torus Knot Software Ltd
177       
178        OGRE is licensed under the LGPL. For more info, see ogre license info.
179    */
180    void GSRoot::setThreadAffinity()
181    {
182#if ORXONOX_PLATFORM == ORXONOX_PLATFORM_WIN32
183        // Get the current process core mask
184            DWORD procMask;
185            DWORD sysMask;
186#if _MSC_VER >= 1400 && defined (_M_X64)
187            GetProcessAffinityMask(GetCurrentProcess(), (PDWORD_PTR)&procMask, (PDWORD_PTR)&sysMask);
188#else
189            GetProcessAffinityMask(GetCurrentProcess(), &procMask, &sysMask);
190#endif
191
192            // If procMask is 0, consider there is only one core available
193            // (using 0 as procMask will cause an infinite loop below)
194            if (procMask == 0)
195                    procMask = 1;
196
197            // Find the lowest core that this process uses
198        DWORD threadMask = 1;
199            while ((threadMask & procMask) == 0)
200                    threadMask <<= 1;
201
202            // Set affinity to the first core
203            SetThreadAffinityMask(GetCurrentThread(), threadMask);
204#endif
205    }
206
207    /**
208    @brief
209        Creates the Ogre Root object and sets up the ogre log.
210    */
211    void GSRoot::setupOgre()
212    {
213        COUT(3) << "Setting up Ogre..." << std::endl;
214
215        // TODO: LogManager doesn't work on oli platform. The why is yet unknown.
216#if ORXONOX_PLATFORM == ORXONOX_PLATFORM_WIN32
217        // create a new logManager
218        ogreLogger_ = new Ogre::LogManager();
219        COUT(4) << "Ogre LogManager created" << std::endl;
220
221        // create our own log that we can listen to
222        Ogre::Log *myLog;
223        if (this->ogreLogFile_ == "")
224            myLog = ogreLogger_->createLog("ogre.log", true, false, true);
225        else
226            myLog = ogreLogger_->createLog(this->ogreLogFile_, true, false, false);
227        COUT(4) << "Ogre Log created" << std::endl;
228
229        myLog->setLogDetail(Ogre::LL_BOREME);
230        myLog->addListener(this);
231#endif
232
233        // Root will detect that we've already created a Log
234        COUT(4) << "Creating Ogre Root..." << std::endl;
235
236        if (ogrePluginsFile_ == "")
237        {
238            COUT(2) << "Warning: Ogre plugins file set to \"\". Defaulting to plugins.cfg" << std::endl;
239            ModifyConfigValue(ogrePluginsFile_, tset, "plugins.cfg");
240        }
241        if (ogreConfigFile_ == "")
242        {
243            COUT(2) << "Warning: Ogre config file set to \"\". Defaulting to config.cfg" << std::endl;
244            ModifyConfigValue(ogreConfigFile_, tset, "config.cfg");
245        }
246        if (ogreLogFile_ == "")
247        {
248            COUT(2) << "Warning: Ogre log file set to \"\". Defaulting to ogre.log" << std::endl;
249            ModifyConfigValue(ogreLogFile_, tset, "ogre.log");
250        }
251
252        // check for config file existence because Ogre displays (caught) exceptions if not
253        std::ifstream probe;
254        probe.open(ogreConfigFile_.c_str());
255        if (!probe)
256        {
257            // create a zero sized file
258            std::ofstream creator;
259            creator.open(ogreConfigFile_.c_str());
260            creator.close();
261        }
262        else
263            probe.close();
264
265        ogreRoot_ = new Ogre::Root(ogrePluginsFile_, ogreConfigFile_, ogreLogFile_);
266
267#if 0 // Ogre 1.4.3 doesn't yet support setDebugOutputEnabled(.)
268#if ORXONOX_PLATFORM != ORXONOX_PLATFORM_WIN32
269        // tame the ogre ouput so we don't get all the mess in the console
270        Ogre::Log* defaultLog = Ogre::LogManager::getSingleton().getDefaultLog();
271        defaultLog->setDebugOutputEnabled(false);
272        defaultLog->setLogDetail(Ogre::LL_BOREME);
273        defaultLog->addListener(this);
274#endif
275#endif
276
277        COUT(3) << "Ogre set up done." << std::endl;
278    }
279
280    /**
281    @brief
282        Method called by the LogListener interface from Ogre.
283        We use it to capture Ogre log messages and handle it ourselves.
284    @param message
285        The message to be logged
286    @param lml
287        The message level the log is using
288    @param maskDebug
289        If we are printing to the console or not
290    @param logName
291        The name of this log (so you can have several listeners
292        for different logs, and identify them)
293    */
294    void GSRoot::messageLogged(const std::string& message,
295        Ogre::LogMessageLevel lml, bool maskDebug, const std::string& logName)
296    {
297        int orxonoxLevel;
298        switch (lml)
299        {
300        case Ogre::LML_TRIVIAL:
301            orxonoxLevel = this->ogreLogLevelTrivial_;
302            break;
303        case Ogre::LML_NORMAL:
304            orxonoxLevel = this->ogreLogLevelNormal_;
305            break;
306        case Ogre::LML_CRITICAL:
307            orxonoxLevel = this->ogreLogLevelCritical_;
308            break;
309        default:
310            orxonoxLevel = 0;
311        }
312        OutputHandler::getOutStream().setOutputLevel(orxonoxLevel)
313            << "Ogre: " << message << std::endl;
314    }
315}
Note: See TracBrowser for help on using the repository browser.