Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/orxonox/gamestates/GSRoot.cc @ 1764

Last change on this file since 1764 was 1764, checked in by rgrieder, 16 years ago

Moved Exception to util now that debug has been moved.

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