Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/gui/src/orxonox/gamestates/GSGraphics.cc @ 1663

Last change on this file since 1663 was 1662, checked in by rgrieder, 16 years ago
  • Changed static Executor/Functor in ConsoleCommand to generic one that enables console commands for member functions. (This is more of a temporary solution, but can be made permanent with right adjustments)
  • The whole GameState thing seems to works so far. But I there's only standalone mode at the moment
  • Console now shows in GUI too. I will have to implement a master InputState in the InputManager (little bit of a break with the concept, but probably necessary)
  • Property svn:eol-style set to native
File size: 7.4 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 "GSGraphics.h"
31
32#include <OgreFrameListener.h>
33#include <OgreRoot.h>
34#include <OgreTimer.h>
35#include <OgreWindowEventUtilities.h>
36
37#include "core/ConsoleCommand.h"
38#include "core/ConfigValueIncludes.h"
39#include "core/input/InputManager.h"
40#include "core/Core.h"
41#include "overlays/console/InGameConsole.h"
42#include "gui/GUIManager.h"
43#include "GraphicsEngine.h"
44
45namespace orxonox
46{
47    GSGraphics::GSGraphics()
48        : GameState("graphics")
49        , timer_(0)
50        , bAbort_(false)
51        , debugRefreshTime_(0.0f)
52        , inputManager_(0)
53        , console_(0)
54        , guiManager_(0)
55    {
56    }
57
58    GSGraphics::~GSGraphics()
59    {
60    }
61
62    void GSGraphics::setConfigValues()
63    {
64        SetConfigValue(debugRefreshTime_, 0.2).description("Sets the time interval at which average fps, etc. get updated.");
65    }
66
67    void GSGraphics::enter()
68    {
69        this->graphicsEngine_ = GraphicsEngine::getInstancePtr();
70
71        graphicsEngine_->loadRenderer();    // creates the render window
72
73        // TODO: Spread this so that this call only initialises things needed for the Console and GUI
74        graphicsEngine_->initialiseResources();
75
76        // Calls the InputManager which sets up the input devices.
77        // The render window width and height are used to set up the mouse movement.
78        inputManager_ = new InputManager();
79        inputManager_->initialise(graphicsEngine_->getWindowHandle(),
80            graphicsEngine_->getWindowWidth(), graphicsEngine_->getWindowHeight(), true);
81
82        // Load the InGameConsole
83        console_ = new InGameConsole();
84        console_->initialise();
85
86        // load the CEGUI interface
87        guiManager_ = new GUIManager();
88        guiManager_->initialise();
89
90        // use the ogre timer class to measure time.
91        timer_ = new Ogre::Timer();
92
93        // add console commands
94        FunctorMember<GSGraphics>* functor = createFunctor(&GSGraphics::exitGame);
95        functor->setObject(this);
96        CommandExecutor::addConsoleCommandShortcut(createConsoleCommand(functor, "exit"));
97    }
98
99    void GSGraphics::leave()
100    {
101        delete this->timer_;
102
103        delete this->guiManager_;
104
105        delete this->console_;
106
107        delete this->inputManager_;
108
109        // TODO: destroy render window
110    }
111
112    /**
113        Main loop of the orxonox game.
114        We use the Ogre::Timer to measure time since it uses the most precise
115        method an a platform (however the windows timer lacks time when under
116        heavy kernel load!).
117        There is a simple mechanism to measure the average time spent in our
118        ticks as it may indicate performance issues.
119        A note about the Ogre::FrameListener: Even though we don't use them,
120        they still get called. However, the delta times are not correct (except
121        for timeSinceLastFrame, which is the most important). A little research
122        as shown that there is probably only one FrameListener that doesn't even
123        need the time. So we shouldn't run into problems.
124    */
125    bool GSGraphics::tick(float dt)
126    {
127        // note: paramter 'dt' is of no meaning
128
129        Ogre::Root& ogreRoot = Ogre::Root::getSingleton();
130
131        unsigned long frameCount = 0;
132
133        const unsigned long refreshTime = (unsigned long)(debugRefreshTime_ * 1000000.0f);
134        unsigned long refreshStartTime = 0;
135        unsigned long tickTime = 0;
136        unsigned long oldFrameCount = 0;
137
138        unsigned long timeBeforeTick = 0;
139        unsigned long timeBeforeTickOld = 0;
140        unsigned long timeAfterTick = 0;
141
142        // TODO: Update time in seconds every 7 seconds to avoid any overflow (7 secs is very tight)
143
144        COUT(3) << "Orxonox: Starting the main loop." << std::endl;
145
146        try
147        {
148            timer_->reset();
149            while (!bAbort_)
150            {
151                // get current time
152                timeBeforeTickOld = timeBeforeTick;
153                timeBeforeTick    = timer_->getMicroseconds();
154                float dt = (timeBeforeTick - timeBeforeTickOld) / 1000000.0;
155
156
157                // tick the core (needs real time for input and tcl thread management)
158                // TODO: ticks of InputManager and tcl thread manager have to be separated.
159                Core::tick(dt);
160
161                // tick child state
162                if (this->getActiveChild())
163                    this->getActiveChild()->tick(dt);
164
165                // tick console
166                this->console_->tick(dt);
167
168                // get current time once again
169                timeAfterTick = timer_->getMicroseconds();
170
171                tickTime += timeAfterTick - timeBeforeTick;
172                if (timeAfterTick > refreshStartTime + refreshTime)
173                {
174                    GraphicsEngine::getInstance().setAverageTickTime(
175                        (float)tickTime * 0.001 / (frameCount - oldFrameCount));
176                    float avgFPS = (float)(frameCount - oldFrameCount) / (timeAfterTick - refreshStartTime) * 1000000.0;
177                    GraphicsEngine::getInstance().setAverageFramesPerSecond(avgFPS);
178
179                    oldFrameCount = frameCount;
180                    tickTime = 0;
181                    refreshStartTime = timeAfterTick;
182                }
183
184                // don't forget to call _fireFrameStarted in ogre to make sure
185                // everything goes smoothly
186                Ogre::FrameEvent evt;
187                evt.timeSinceLastFrame = dt;
188                evt.timeSinceLastEvent = dt; // note: same time, but shouldn't matter anyway
189                ogreRoot._fireFrameStarted(evt);
190
191                // Pump messages in all registered RenderWindows
192                // This calls the WindowEventListener objects.
193                Ogre::WindowEventUtilities::messagePump();
194                // make sure the window stays active even when not focused
195                // (probably only necessary on windows)
196                GraphicsEngine::getInstance().setWindowActivity(true);
197
198                // render
199                ogreRoot._updateAllRenderTargets();
200
201                // again, just to be sure ogre works fine
202                ogreRoot._fireFrameEnded(evt); // note: uses the same time as _fireFrameStarted
203
204                ++frameCount;
205            }
206        }
207        catch (std::exception& ex)
208        {
209            // something went wrong.
210            COUT(1) << ex.what() << std::endl;
211            COUT(1) << "Main loop was stopped by an unhandled exception. Shutting down." << std::endl;
212        }        return true;
213    }
214}
Note: See TracBrowser for help on using the repository browser.