Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/orxonox/gamestates/GSGraphics.cc @ 1888

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

FIRST THINGS FIRST: Delete or rename your keybindings.ini (def_keybindings.ini already has the most important bindings) or else you won't be able to do anything!

Changes:

  • Multiple joy stick support should now fully work with KeyBinder too (only tested with 0/1 joystick)
  • Reloading the OIS Devices now works with KeyBinder too
  • Modified ConfigValueContainer to accept arbitrary section names
  • added tkeybind to temporary bind a command to a key
  • Fixed dlleport issue in ArgumentCompletionFunctions.h

Internal changes:

  • General cleanup in initialisation of KeyBinder
  • All names of keys/buttons/axes are now statically saved in InputInterfaces.h
  • Move a magic value in KeyBinder to a configValue (MouseWheelStepSize_)
  • Separated ConfigValues from Keybinding ConfigValueContainer in KeyBinder (looks much nicer now ;))
  • Moved some performance critical small function to the inline section
  • Removed the ugly keybind function construct from the InputManager
  • More 'harmonising' work in KeyBinder
  • Property svn:eol-style set to native
File size: 13.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 "GSGraphics.h"
31
[1686]32#include <fstream>
33#include <OgreConfigFile.h>
[1661]34#include <OgreFrameListener.h>
35#include <OgreRoot.h>
[1686]36#include <OgreException.h>
37#include <OgreRenderWindow.h>
[1828]38#include <OgreRenderSystem.h>
[1686]39#include <OgreTextureManager.h>
40#include <OgreViewport.h>
[1661]41#include <OgreWindowEventUtilities.h>
42
[1755]43#include "util/Debug.h"
[1764]44#include "util/Exception.h"
[1662]45#include "core/ConsoleCommand.h"
46#include "core/ConfigValueIncludes.h"
[1686]47#include "core/CoreIncludes.h"
[1661]48#include "core/input/InputManager.h"
[1788]49#include "core/input/KeyBinder.h"
50#include "core/input/ExtendedInputState.h"
[1661]51#include "overlays/console/InGameConsole.h"
52#include "gui/GUIManager.h"
[1686]53#include "tools/WindowEventListener.h"
54#include "Settings.h"
55
56// for compatibility
[1662]57#include "GraphicsEngine.h"
[1661]58
59namespace orxonox
60{
61    GSGraphics::GSGraphics()
[1689]62        : GameState<GSRoot>("graphics")
[1674]63        , ogreRoot_(0)
[1661]64        , inputManager_(0)
65        , console_(0)
66        , guiManager_(0)
[1788]67        , masterKeyBinder_(0)
[1672]68        , frameCount_(0)
[1674]69        , statisticsRefreshCycle_(0)
70        , statisticsStartTime_(0)
71        , statisticsStartCount_(0)
72        , tickTime_(0)
[1661]73    {
[1686]74        RegisterRootObject(GSGraphics);
[1661]75    }
76
77    GSGraphics::~GSGraphics()
78    {
79    }
80
81    void GSGraphics::setConfigValues()
82    {
[1688]83        SetConfigValue(resourceFile_, "resources.cfg").description("Location of the resources file in the data path.");
[1674]84        SetConfigValue(statisticsRefreshCycle_, 200000).description("Sets the time in microseconds interval at which average fps, etc. get updated.");
[1661]85    }
86
87    void GSGraphics::enter()
88    {
[1696]89        Settings::_getInstance().bShowsGraphics_ = true;
90
[1674]91        setConfigValues();
92
[1688]93        this->ogreRoot_ = getParent()->getOgreRoot();
[1661]94
[1686]95        this->declareResources();
96        this->loadRenderer();    // creates the render window
[1661]97        // TODO: Spread this so that this call only initialises things needed for the Console and GUI
[1686]98        this->initialiseResources();
[1661]99
[1686]100
101        // HACK: temporary:
[1688]102        GraphicsEngine* graphicsEngine = getParent()->getGraphicsEngine();
103        graphicsEngine->renderWindow_  = this->renderWindow_;
104        graphicsEngine->root_          = this->ogreRoot_;
105        graphicsEngine->viewport_      = this->viewport_;
[1686]106
107
[1661]108        // Calls the InputManager which sets up the input devices.
109        // The render window width and height are used to set up the mouse movement.
110        inputManager_ = new InputManager();
[1686]111        size_t windowHnd = 0;
112        this->renderWindow_->getCustomAttribute("WINDOW", &windowHnd);
113        inputManager_->initialise(windowHnd, renderWindow_->getWidth(), renderWindow_->getHeight(), true);
[1788]114        // Configure master input state with a KeyBinder
115        //masterKeyBinder_ = new KeyBinder();
[1887]116        //masterKeyBinder_->loadBindings("master_keybindings.ini");
[1788]117        //inputManager_->getMasterInputState()->addKeyHandler(masterKeyBinder_);
[1661]118
119        // Load the InGameConsole
120        console_ = new InGameConsole();
121        console_->initialise();
122
123        // load the CEGUI interface
124        guiManager_ = new GUIManager();
[1686]125        guiManager_->initialise(this->renderWindow_);
[1674]126
127        // reset frame counter
128        this->frameCount_ = 0;
129        this->tickTime_ = 0;
130        statisticsStartTime_ = 0;
131        statisticsStartCount_ = 0;
[1686]132
133        // add console commands
134        FunctorMember<GSGraphics>* functor1 = createFunctor(&GSGraphics::printScreen);
135        functor1->setObject(this);
136        CommandExecutor::addConsoleCommandShortcut(createConsoleCommand(functor1, "printScreen"));
[1661]137    }
138
139    void GSGraphics::leave()
140    {
[1824]141        using namespace Ogre;
142
[1878]143        // remove our WindowEventListener first to avoid bad calls in the procedures
144        Ogre::WindowEventUtilities::removeWindowEventListener(this->renderWindow_, this);
145
[1662]146        delete this->guiManager_;
[1661]147
[1662]148        delete this->console_;
[1661]149
[1788]150        //inputManager_->getMasterInputState()->removeKeyHandler(this->masterKeyBinder_);
151        //delete this->masterKeyBinder_;
[1662]152        delete this->inputManager_;
153
[1824]154        // destroy render window
155        RenderSystem* renderer = this->ogreRoot_->getRenderSystem();
156        renderer->destroyRenderWindow("Orxonox");
[1696]157
[1824]158        // Does the opposite of initialise()
159        ogreRoot_->shutdown();
160
161        // Remove all resources and resource groups
[1825]162        //StringVector groups = ResourceGroupManager::getSingleton().getResourceGroups();
163        //for (StringVector::iterator it = groups.begin(); it != groups.end(); ++it)
164        //{
165        //    ResourceGroupManager::getSingleton().destroyResourceGroup(*it);
166        //}
[1824]167
[1825]168        //ParticleSystemManager::getSingleton().removeAllTemplates();
[1824]169
170        // Shutdown the render system
[1825]171        //this->ogreRoot_->setRenderSystem(0);
[1824]172
[1696]173        Settings::_getInstance().bShowsGraphics_ = false;
[1661]174    }
175
[1662]176    /**
177        Main loop of the orxonox game.
178        We use the Ogre::Timer to measure time since it uses the most precise
179        method an a platform (however the windows timer lacks time when under
180        heavy kernel load!).
181        There is a simple mechanism to measure the average time spent in our
182        ticks as it may indicate performance issues.
183        A note about the Ogre::FrameListener: Even though we don't use them,
184        they still get called. However, the delta times are not correct (except
185        for timeSinceLastFrame, which is the most important). A little research
186        as shown that there is probably only one FrameListener that doesn't even
187        need the time. So we shouldn't run into problems.
188    */
[1674]189    void GSGraphics::ticked(const Clock& time)
[1661]190    {
[1724]191        unsigned long long timeBeforeTick = time.getRealMicroseconds();
[1674]192        float dt = time.getDeltaTime();
193
[1672]194        this->inputManager_->tick(dt);
195        // tick console
196        this->console_->tick(dt);
[1674]197        this->tickChild(time);
198       
[1724]199        unsigned long long timeAfterTick = time.getRealMicroseconds();
[1661]200
[1674]201        tickTime_ += (unsigned int)(timeAfterTick - timeBeforeTick);
202        if (timeAfterTick > statisticsStartTime_ + statisticsRefreshCycle_)
203        {
204            GraphicsEngine::getInstance().setAverageTickTime(
205                (float)tickTime_ * 0.001f / (frameCount_ - statisticsStartCount_));
206            float avgFPS = (float)(frameCount_ - statisticsStartCount_)
207                / (timeAfterTick - statisticsStartTime_) * 1000000.0;
208            GraphicsEngine::getInstance().setAverageFramesPerSecond(avgFPS);
[1661]209
[1674]210            tickTime_ = 0;
211            statisticsStartCount_ = frameCount_;
212            statisticsStartTime_  = timeAfterTick;
213        }
[1661]214
[1672]215        // don't forget to call _fireFrameStarted in ogre to make sure
216        // everything goes smoothly
217        Ogre::FrameEvent evt;
218        evt.timeSinceLastFrame = dt;
219        evt.timeSinceLastEvent = dt; // note: same time, but shouldn't matter anyway
220        ogreRoot_->_fireFrameStarted(evt);
[1661]221
[1672]222        // Pump messages in all registered RenderWindows
223        // This calls the WindowEventListener objects.
224        Ogre::WindowEventUtilities::messagePump();
225        // make sure the window stays active even when not focused
226        // (probably only necessary on windows)
[1686]227        this->renderWindow_->setActive(true);
[1661]228
[1672]229        // render
230        ogreRoot_->_updateAllRenderTargets();
[1661]231
[1672]232        // again, just to be sure ogre works fine
233        ogreRoot_->_fireFrameEnded(evt); // note: uses the same time as _fireFrameStarted
[1661]234
[1672]235        ++frameCount_;
[1661]236    }
[1686]237
238    void GSGraphics::declareResources()
239    {
240        CCOUT(4) << "Declaring Resources" << std::endl;
241        //TODO: Specify layout of data file and maybe use xml-loader
242        //TODO: Work with ressource groups (should be generated by a special loader)
243
244        if (resourceFile_ == "")
245        {
246            COUT(2) << "Warning: Ogre resource file set to \"\". Defaulting to resources.cfg" << std::endl;
247            ModifyConfigValue(resourceFile_, tset, "resources.cfg");
248        }
249
250        // Load resource paths from data file using configfile ressource type
251        Ogre::ConfigFile cf;
252        try
253        {
254            cf.load(Settings::getDataPath() + resourceFile_);
255        }
256        catch (...)
257        {
258            //COUT(1) << ex.getFullDescription() << std::endl;
259            COUT(0) << "Have you forgotten to set the data path in orxnox.ini?" << std::endl;
260            throw;
261        }
262
263        // Go through all sections & settings in the file
264        Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();
265
266        std::string secName, typeName, archName;
267        while (seci.hasMoreElements())
268        {
269            try
270            {
271                secName = seci.peekNextKey();
272                Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
273                Ogre::ConfigFile::SettingsMultiMap::iterator i;
274                for (i = settings->begin(); i != settings->end(); ++i)
275                {
276                    typeName = i->first; // for instance "FileSystem" or "Zip"
277                    archName = i->second; // name (and location) of archive
278
279                    Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
280                        std::string(Settings::getDataPath() + archName), typeName, secName);
281                }
282            }
283            catch (Ogre::Exception& ex)
284            {
285                COUT(1) << ex.getFullDescription() << std::endl;
286            }
287        }
288    }
289
290    void GSGraphics::loadRenderer()
291    {
292        CCOUT(4) << "Configuring Renderer" << std::endl;
293
294        if (!ogreRoot_->restoreConfig())
295            if (!ogreRoot_->showConfigDialog())
296                ThrowException(InitialisationFailed, "Could not show Ogre configuration dialogue.");
297
298        CCOUT(4) << "Creating render window" << std::endl;
299
[1824]300        this->renderWindow_ = ogreRoot_->initialise(true, "Orxonox");
[1686]301
302        Ogre::WindowEventUtilities::addWindowEventListener(this->renderWindow_, this);
303
[1820]304        Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(0);
[1686]305
306        // create a full screen default viewport
307        this->viewport_ = this->renderWindow_->addViewport(0, 0);
308    }
309
310    void GSGraphics::initialiseResources()
311    {
312        CCOUT(4) << "Initialising resources" << std::endl;
313        //TODO: Do NOT load all the groups, why are we doing that? And do we really do that? initialise != load...
[1824]314        //try
315        //{
[1686]316            Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
317            /*Ogre::StringVector str = Ogre::ResourceGroupManager::getSingleton().getResourceGroups();
318            for (unsigned int i = 0; i < str.size(); i++)
319            {
320            Ogre::ResourceGroupManager::getSingleton().loadResourceGroup(str[i]);
321            }*/
[1824]322        //}
323        //catch (...)
324        //{
325        //    CCOUT(2) << "Error: There was a serious error when initialising the resources." << std::endl;
326        //    throw;
327        //}
[1686]328    }
329
330
331    /**
332    @brief
333        Window has moved.
334    @param rw
335        The render window it occured in
336    */
337    void GSGraphics::windowMoved(Ogre::RenderWindow *rw)
338    {
[1755]339        for (ObjectList<orxonox::WindowEventListener>::iterator it = ObjectList<orxonox::WindowEventListener>::begin(); it; ++it)
[1686]340            it->windowMoved();
341    }
342
343    /**
344    @brief
345        Window has resized.
346    @param rw
347        The render window it occured in
348    @note
349        GraphicsEngine has a render window stored itself. This is the same
350        as rw. But we have to be careful when using multiple render windows!
351    */
352    void GSGraphics::windowResized(Ogre::RenderWindow *rw)
353    {
[1755]354        for (ObjectList<orxonox::WindowEventListener>::iterator it = ObjectList<orxonox::WindowEventListener>::begin(); it; ++it)
[1686]355            it->windowResized(this->renderWindow_->getWidth(), this->renderWindow_->getHeight());
356    }
357
358    /**
359    @brief
360        Window focus has changed.
361    @param rw
362        The render window it occured in
363    */
[1878]364    void GSGraphics::windowFocusChange(Ogre::RenderWindow *rw)
[1686]365    {
[1755]366        for (ObjectList<orxonox::WindowEventListener>::iterator it = ObjectList<orxonox::WindowEventListener>::begin(); it; ++it)
[1686]367            it->windowFocusChanged();
[1878]368
369        // instruct InputManager to clear the buffers (core library so we cannot use the interface)
370        InputManager::getInstance().clearBuffers();
[1686]371    }
372
373    /**
374    @brief
375        Window was closed.
376    @param rw
377        The render window it occured in
378    */
379    void GSGraphics::windowClosed(Ogre::RenderWindow *rw)
380    {
381        // using CommandExecutor in order to avoid depending on Orxonox.h.
382        //CommandExecutor::execute("exit", false);
383        this->requestState("root");
384    }
385
386    void GSGraphics::printScreen()
387    {
388        if (this->renderWindow_)
389        {
390            this->renderWindow_->writeContentsToTimestampedFile("shot_", ".jpg");
391        }
392    }
[1661]393}
Note: See TracBrowser for help on using the repository browser.