Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Moved most of the GraphicsEngine code to GSRoot and GSGraphics.
GraphicsEngine is now more of a legacy object to ensure functionality until there is a new solution.

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