Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Merged buildsystem3 containing buildsystem2 containing Adi's buildsystem branch back to the trunk.
Please update the media directory if you were not using buildsystem3 before.

  • Property svn:eol-style set to native
File size: 10.5 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
[1764]32#include "util/Exception.h"
33#include "util/Debug.h"
[2662]34#include "core/Core.h"
[1661]35#include "core/Factory.h"
36#include "core/ConfigValueIncludes.h"
[1686]37#include "core/CoreIncludes.h"
[1661]38#include "core/ConsoleCommand.h"
[1664]39#include "core/CommandLine.h"
[1792]40#include "core/Shell.h"
[1661]41#include "core/TclBind.h"
[1672]42#include "core/TclThreadManager.h"
[2662]43#include "core/LuaBind.h"
[1826]44#include "tools/Timer.h"
[2171]45#include "objects/Tickable.h"
[1661]46
[2710]47#ifdef ORXONOX_PLATFORM_WINDOWS
[1674]48#  ifndef WIN32_LEAN_AND_MEAN
49#    define WIN32_LEAN_AND_MEAN
50#  endif
51#  include "windows.h"
52
53   //Get around Windows hackery
54#  ifdef max
55#    undef max
56#  endif
57#  ifdef min
58#    undef min
59#  endif
60#endif
61
[1661]62namespace orxonox
63{
[2087]64    SetCommandLineArgument(limitToCPU, 1).information("0: off | #cpu");
[1663]65
[1661]66    GSRoot::GSRoot()
[1672]67        : RootGameState("root")
[2662]68        , timeFactor_(1.0f)
69        , bPaused_(false)
70        , timeFactorPauseBackup_(1.0f)
[1792]71        , tclBind_(0)
72        , tclThreadManager_(0)
73        , shell_(0)
[1661]74    {
[1686]75        RegisterRootObject(GSRoot);
[1891]76        setConfigValues();
[2662]77
78        this->ccSetTimeFactor_ = 0;
79        this->ccPause_ = 0;
[1661]80    }
81
82    GSRoot::~GSRoot()
83    {
84    }
85
[1686]86    void GSRoot::setConfigValues()
87    {
[2662]88        SetConfigValue(statisticsRefreshCycle_, 250000)
89            .description("Sets the time in microseconds interval at which average fps, etc. get updated.");
90        SetConfigValue(statisticsAvgLength_, 1000000)
91            .description("Sets the time in microseconds interval at which average fps, etc. gets calculated.");
[1686]92    }
93
[1661]94    void GSRoot::enter()
95    {
96        // creates the class hierarchy for all classes with factories
97        Factory::createClassHierarchy();
98
[2662]99        // reset game speed to normal
100        timeFactor_ = 1.0f;
101
102        // reset frame counter
103        this->statisticsStartTime_ = 0;
104        this->statisticsTickTimes_.clear();
105        this->periodTickTime_ = 0;
106        this->avgFPS_ = 0.0f;
107        this->avgTickTime_ = 0.0f;
108
109        // Create the lua interface
110        this->luaBind_ = new LuaBind();
111
[1661]112        // initialise TCL
[2710]113        this->tclBind_ = new TclBind(Core::getMediaPathPOSIXString());
[1792]114        this->tclThreadManager_ = new TclThreadManager(tclBind_->getTclInterpreter());
[1661]115
[1792]116        // create a shell
117        this->shell_ = new Shell();
118
[1674]119        // limit the main thread to the first core so that QueryPerformanceCounter doesn't jump
120        // do this after ogre has initialised. Somehow Ogre changes the settings again (not through
121        // the timer though).
[2087]122        int limitToCPU = CommandLine::getValue("limitToCPU");
[1691]123        if (limitToCPU > 0)
124            setThreadAffinity((unsigned int)(limitToCPU - 1));
[1674]125
[2662]126        {
127            // add console commands
128            FunctorMember<GSRoot>* functor = createFunctor(&GSRoot::exitGame);
129            functor->setObject(this);
130            this->ccExit_ = createConsoleCommand(functor, "exit");
131            CommandExecutor::addConsoleCommandShortcut(this->ccExit_);
132        }
[1664]133
[2662]134        {
135            // add console commands
136            FunctorMember01<GameStateBase, const std::string&>* functor = createFunctor(&GameStateBase::requestState);
137            functor->setObject(this);
138            this->ccSelectGameState_ = createConsoleCommand(functor, "selectGameState");
139            CommandExecutor::addConsoleCommandShortcut(this->ccSelectGameState_);
140        }
141
142        {
143            // time factor console command
144            FunctorMember<GSRoot>* functor = createFunctor(&GSRoot::setTimeFactor);
145            functor->setObject(this);
146            this->ccSetTimeFactor_ = createConsoleCommand(functor, "setTimeFactor");
147            CommandExecutor::addConsoleCommandShortcut(this->ccSetTimeFactor_).accessLevel(AccessLevel::Offline).defaultValue(0, 1.0);
148        }
149
150        {
151            // time factor console command
152            FunctorMember<GSRoot>* functor = createFunctor(&GSRoot::pause);
153            functor->setObject(this);
154            this->ccPause_ = createConsoleCommand(functor, "pause");
155            CommandExecutor::addConsoleCommandShortcut(this->ccPause_).accessLevel(AccessLevel::Offline);
156        }
[1661]157    }
158
159    void GSRoot::leave()
160    {
[2662]161        // destroy console commands
162        delete this->ccExit_;
163        delete this->ccSelectGameState_;
[1792]164
165        delete this->shell_;
166        delete this->tclThreadManager_;
167        delete this->tclBind_;
168
[2662]169        delete this->luaBind_;
[1663]170
[2662]171        if (this->ccSetTimeFactor_)
172        {
173            delete this->ccSetTimeFactor_;
174            this->ccSetTimeFactor_ = 0;
175        }
176
177        if (this->ccPause_)
178        {
179            delete this->ccPause_;
180            this->ccPause_ = 0;
181        }
[1661]182    }
183
[1674]184    void GSRoot::ticked(const Clock& time)
[1661]185    {
[2662]186        uint64_t timeBeforeTick = time.getRealMicroseconds();
187
[1674]188        TclThreadManager::getInstance().tick(time.getDeltaTime());
[1662]189
[1826]190        for (ObjectList<TimerBase>::iterator it = ObjectList<TimerBase>::begin(); it; ++it)
191            it->tick(time);
192
[2171]193        /*** HACK *** HACK ***/
194        // Call the Tickable objects
[2662]195        float leveldt = time.getDeltaTime();
196        if (leveldt > 1.0f)
197        {
198            // just loaded
199            leveldt = 0.0f;
200        }
[2171]201        for (ObjectList<Tickable>::iterator it = ObjectList<Tickable>::begin(); it; ++it)
[2662]202            it->tick(leveldt * this->timeFactor_);
[2171]203        /*** HACK *** HACK ***/
204
[2662]205        uint64_t timeAfterTick = time.getRealMicroseconds();
206
207        // STATISTICS
208        assert(timeAfterTick - timeBeforeTick >= 0 );
209        statisticsTickInfo tickInfo = {timeAfterTick, timeAfterTick - timeBeforeTick};
210        statisticsTickTimes_.push_back(tickInfo);
211        assert(statisticsTickTimes_.back().tickLength==tickInfo.tickLength);
212        this->periodTickTime_ += tickInfo.tickLength;
213
214        // Ticks GSGraphics or GSDedicated
[1674]215        this->tickChild(time);
[2662]216
217        if (timeAfterTick > statisticsStartTime_ + statisticsRefreshCycle_)
218        {
219            std::list<statisticsTickInfo>::iterator it = this->statisticsTickTimes_.begin();
220            assert(it != this->statisticsTickTimes_.end());
221            int64_t lastTime = timeAfterTick - statisticsAvgLength_;
222            if ((int64_t)it->tickTime < lastTime)
223            {
224                do
225                {
226                    assert(this->periodTickTime_ > it->tickLength);
227                    this->periodTickTime_ -= it->tickLength;
228                    ++it;
229                    assert(it != this->statisticsTickTimes_.end());
230                } while ((int64_t)it->tickTime < lastTime);
231                this->statisticsTickTimes_.erase(this->statisticsTickTimes_.begin(), it);
232            }
233
234            uint32_t framesPerPeriod = this->statisticsTickTimes_.size();
235            this->avgFPS_ = (float)framesPerPeriod / (timeAfterTick - this->statisticsTickTimes_.front().tickTime) * 1000000.0;
236            this->avgTickTime_ = (float)this->periodTickTime_ / framesPerPeriod / 1000.0;
237
238            statisticsStartTime_ = timeAfterTick;
239        }
240
[1662]241    }
[1674]242
243    /**
244    @note
[1691]245        The code of this function has been copied and adjusted from OGRE, an open source graphics engine.
[1674]246            (Object-oriented Graphics Rendering Engine)
247        For the latest info, see http://www.ogre3d.org/
248
249        Copyright (c) 2000-2008 Torus Knot Software Ltd
[2662]250
[2087]251        OGRE is licensed under the LGPL. For more info, see OGRE license.
[1674]252    */
[1691]253    void GSRoot::setThreadAffinity(unsigned int limitToCPU)
[1674]254    {
[2710]255#ifdef ORXONOX_PLATFORM_WINDOWS
[1674]256        // Get the current process core mask
[2662]257        DWORD procMask;
258        DWORD sysMask;
[1891]259#  if _MSC_VER >= 1400 && defined (_M_X64)
[2662]260        GetProcessAffinityMask(GetCurrentProcess(), (PDWORD_PTR)&procMask, (PDWORD_PTR)&sysMask);
[1891]261#  else
[2662]262        GetProcessAffinityMask(GetCurrentProcess(), &procMask, &sysMask);
[1891]263#  endif
[1674]264
[2662]265        // If procMask is 0, consider there is only one core available
266        // (using 0 as procMask will cause an infinite loop below)
267        if (procMask == 0)
268            procMask = 1;
[1674]269
[1691]270        // if the core specified with limitToCPU is not available, take the lowest one
271        if (!(procMask & (1 << limitToCPU)))
272            limitToCPU = 0;
273
[2662]274        // Find the lowest core that this process uses and limitToCPU suggests
[1674]275        DWORD threadMask = 1;
[2662]276        while ((threadMask & procMask) == 0 || (threadMask < (1u << limitToCPU)))
277            threadMask <<= 1;
[1674]278
[2662]279        // Set affinity to the first core
280        SetThreadAffinityMask(GetCurrentThread(), threadMask);
[1674]281#endif
282    }
[2662]283
284    /**
285    @brief
286        Changes the speed of Orxonox
287    */
288    void GSRoot::setTimeFactor(float factor)
289    {
290        if (Core::isMaster())
291        {
292            if (!this->bPaused_)
293            {
294                TimeFactorListener::timefactor_s = factor;
295
296                for (ObjectList<TimeFactorListener>::iterator it = ObjectList<TimeFactorListener>::begin(); it != ObjectList<TimeFactorListener>::end(); ++it)
297                    it->changedTimeFactor(factor, this->timeFactor_);
298
299                this->timeFactor_ = factor;
300            }
301            else
302                this->timeFactorPauseBackup_ = factor;
303        }
304    }
305
306    void GSRoot::pause()
307    {
308        if (Core::isMaster())
309        {
310            if (!this->bPaused_)
311            {
312                this->timeFactorPauseBackup_ = this->timeFactor_;
313                this->setTimeFactor(0.0f);
314                this->bPaused_ = true;
315            }
316            else
317            {
318                this->bPaused_ = false;
319                this->setTimeFactor(this->timeFactorPauseBackup_);
320            }
321        }
322    }
323
324    ////////////////////////
325    // TimeFactorListener //
326    ////////////////////////
327    float TimeFactorListener::timefactor_s = 1.0f;
328
329    TimeFactorListener::TimeFactorListener()
330    {
331        RegisterRootObject(TimeFactorListener);
332    }
[1661]333}
Note: See TracBrowser for help on using the repository browser.