Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/objecthierarchy2/src/orxonox/gamestates/GSRoot.cc @ 2422

Last change on this file since 2422 was 2406, checked in by landauf, 16 years ago

Added TimeFactorListener to properly handle changes of the global time factor (makes the game faster or slower). Currently supported in Backlight, ParticleInterface and Timer, which were all critical classes I could think of (all other classes are already covered by the adjustment of dt in tick(dt)). It seems to work well, both with small values (0.1, 0.01) and great values (10, 100). Even pausing the game (0) works fine.

  • Property svn:eol-style set to native
File size: 7.5 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 "util/Exception.h"
33#include "util/Debug.h"
34#include "core/Core.h"
35#include "core/Factory.h"
36#include "core/ConfigValueIncludes.h"
37#include "core/CoreIncludes.h"
38#include "core/ConsoleCommand.h"
39#include "core/CommandLine.h"
40#include "core/Shell.h"
41#include "core/TclBind.h"
42#include "core/TclThreadManager.h"
43#include "core/LuaBind.h"
44#include "tools/Timer.h"
45#include "objects/Tickable.h"
46#include "Settings.h"
47
48#if ORXONOX_PLATFORM == ORXONOX_PLATFORM_WIN32
49#  ifndef WIN32_LEAN_AND_MEAN
50#    define WIN32_LEAN_AND_MEAN
51#  endif
52#  include "windows.h"
53
54   //Get around Windows hackery
55#  ifdef max
56#    undef max
57#  endif
58#  ifdef min
59#    undef min
60#  endif
61#endif
62
63namespace orxonox
64{
65    SetCommandLineArgument(dataPath, "").information("PATH");
66    SetCommandLineArgument(limitToCPU, 1).information("0: off | #cpu");
67
68    GSRoot::GSRoot()
69        : RootGameState("root")
70        , timeFactor_(1.0f)
71        , settings_(0)
72        , tclBind_(0)
73        , tclThreadManager_(0)
74        , shell_(0)
75    {
76        RegisterRootObject(GSRoot);
77        setConfigValues();
78
79        this->ccSetTimeFactor_ = 0;
80    }
81
82    GSRoot::~GSRoot()
83    {
84    }
85
86    void GSRoot::setConfigValues()
87    {
88    }
89
90    void GSRoot::enter()
91    {
92        // creates the class hierarchy for all classes with factories
93        Factory::createClassHierarchy();
94
95        // reset game speed to normal
96        timeFactor_ = 1.0f;
97
98        // Create the lua interface
99        this->luaBind_ = new LuaBind();
100
101        // instantiate Settings class
102        this->settings_ = new Settings();
103
104        std::string dataPath = CommandLine::getValue("dataPath");
105        if (dataPath != "")
106        {
107            if (*dataPath.end() != '/' && *dataPath.end() != '\\')
108                Settings::tsetDataPath(dataPath + "/");
109            else
110                Settings::tsetDataPath(dataPath);
111        }
112
113        // initialise TCL
114        this->tclBind_ = new TclBind(Settings::getDataPath());
115        this->tclThreadManager_ = new TclThreadManager(tclBind_->getTclInterpreter());
116
117        // create a shell
118        this->shell_ = new Shell();
119
120        // limit the main thread to the first core so that QueryPerformanceCounter doesn't jump
121        // do this after ogre has initialised. Somehow Ogre changes the settings again (not through
122        // the timer though).
123        int limitToCPU = CommandLine::getValue("limitToCPU");
124        if (limitToCPU > 0)
125            setThreadAffinity((unsigned int)(limitToCPU - 1));
126
127        // add console commands
128        FunctorMember<GSRoot>* functor1 = createFunctor(&GSRoot::exitGame);
129        functor1->setObject(this);
130        ccExit_ = createConsoleCommand(functor1, "exit");
131        CommandExecutor::addConsoleCommandShortcut(ccExit_);
132
133        // add console commands
134        FunctorMember01<GameStateBase, const std::string&>* functor2 = createFunctor(&GameStateBase::requestState);
135        functor2->setObject(this);
136        ccSelectGameState_ = createConsoleCommand(functor2, "selectGameState");
137        CommandExecutor::addConsoleCommandShortcut(ccSelectGameState_);
138
139        // time factor console command
140        FunctorMember<GSRoot>* functor = createFunctor(&GSRoot::setTimeFactor);
141        functor->setObject(this);
142        ccSetTimeFactor_ = createConsoleCommand(functor, "setTimeFactor");
143        CommandExecutor::addConsoleCommandShortcut(ccSetTimeFactor_).accessLevel(AccessLevel::Offline).defaultValue(0, 1.0);;
144    }
145
146    void GSRoot::leave()
147    {
148        // destroy console commands
149        delete this->ccExit_;
150        delete this->ccSelectGameState_;
151
152        delete this->shell_;
153        delete this->tclThreadManager_;
154        delete this->tclBind_;
155
156        delete this->settings_;
157        delete this->luaBind_;
158
159        if (this->ccSetTimeFactor_)
160        {
161            delete this->ccSetTimeFactor_;
162            this->ccSetTimeFactor_ = 0;
163        }
164    }
165
166    void GSRoot::ticked(const Clock& time)
167    {
168        TclThreadManager::getInstance().tick(time.getDeltaTime());
169
170        for (ObjectList<TimerBase>::iterator it = ObjectList<TimerBase>::begin(); it; ++it)
171            it->tick(time);
172
173        /*** HACK *** HACK ***/
174        // Call the Tickable objects
175        for (ObjectList<Tickable>::iterator it = ObjectList<Tickable>::begin(); it; ++it)
176            it->tick(time.getDeltaTime() * this->timeFactor_);
177        /*** HACK *** HACK ***/
178
179        this->tickChild(time);
180    }
181
182    /**
183    @note
184        The code of this function has been copied and adjusted from OGRE, an open source graphics engine.
185            (Object-oriented Graphics Rendering Engine)
186        For the latest info, see http://www.ogre3d.org/
187
188        Copyright (c) 2000-2008 Torus Knot Software Ltd
189
190        OGRE is licensed under the LGPL. For more info, see OGRE license.
191    */
192    void GSRoot::setThreadAffinity(unsigned int limitToCPU)
193    {
194#if ORXONOX_PLATFORM == ORXONOX_PLATFORM_WIN32
195        // Get the current process core mask
196        DWORD procMask;
197        DWORD sysMask;
198#  if _MSC_VER >= 1400 && defined (_M_X64)
199        GetProcessAffinityMask(GetCurrentProcess(), (PDWORD_PTR)&procMask, (PDWORD_PTR)&sysMask);
200#  else
201        GetProcessAffinityMask(GetCurrentProcess(), &procMask, &sysMask);
202#  endif
203
204        // If procMask is 0, consider there is only one core available
205        // (using 0 as procMask will cause an infinite loop below)
206        if (procMask == 0)
207            procMask = 1;
208
209        // if the core specified with limitToCPU is not available, take the lowest one
210        if (!(procMask & (1 << limitToCPU)))
211            limitToCPU = 0;
212
213        // Find the lowest core that this process uses and limitToCPU suggests
214        DWORD threadMask = 1;
215        while ((threadMask & procMask) == 0 || (threadMask < (1u << limitToCPU)))
216            threadMask <<= 1;
217
218        // Set affinity to the first core
219        SetThreadAffinityMask(GetCurrentThread(), threadMask);
220#endif
221    }
222
223    /**
224    @brief
225        Changes the speed of Orxonox
226    */
227    void GSRoot::setTimeFactor(float factor)
228    {
229        if (Core::isMaster())
230        {
231            TimeFactorListener::timefactor_s = factor;
232
233            for (ObjectList<TimeFactorListener>::iterator it = ObjectList<TimeFactorListener>::begin(); it != ObjectList<TimeFactorListener>::end(); ++it)
234                it->changedTimeFactor(factor, this->timeFactor_);
235
236            this->timeFactor_ = factor;
237        }
238    }
239
240    ////////////////////////
241    // TimeFactorListener //
242    ////////////////////////
243    float TimeFactorListener::timefactor_s = 1.0f;
244
245    TimeFactorListener::TimeFactorListener()
246    {
247        RegisterRootObject(TimeFactorListener);
248    }
249}
Note: See TracBrowser for help on using the repository browser.