Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/buildsystem/src/orxonox/gamestates/GSRoot.cc @ 2518

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

Applied long created patch that removes plugins.cfg and puts the content into orxonox.ini
This also allows to specify the media path for each 'distribution' individually because orxonox.ini has been added to the default files.

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