Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

changed return type of ConfigFileManager::getInstance() to ConfigFileManager& (from pointer before).

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