Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Apr 8, 2009, 12:58:47 AM (16 years ago)
Author:
dafrick
Message:

Reverted to revision 2906 (because I'm too stupid to merge correctly, 2nd try will follow shortly. ;))

Location:
code/branches/questsystem5
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • code/branches/questsystem5

  • code/branches/questsystem5/src/orxonox/gamestates/GSGraphics.cc

    r2907 r2908  
    2323 *      Reto Grieder
    2424 *   Co-authors:
    25  *      Benjamin Knecht
    26  *
    27  */
    28 
    29 /**
    30     @file
    31     @brief Implementation of Graphics GameState class.
     25 *      ...
     26 *
    3227 */
    3328
     
    3530#include "GSGraphics.h"
    3631
     32#include <fstream>
    3733#include <boost/filesystem.hpp>
     34
     35#include <OgreCompositorManager.h>
     36#include <OgreConfigFile.h>
     37#include <OgreFrameListener.h>
     38#include <OgreRoot.h>
     39#include <OgreLogManager.h>
     40#include <OgreException.h>
    3841#include <OgreRenderWindow.h>
    39 
     42#include <OgreRenderSystem.h>
     43#include <OgreTextureManager.h>
     44#include <OgreViewport.h>
     45#include <OgreWindowEventUtilities.h>
     46
     47#include "SpecialConfig.h"
    4048#include "util/Debug.h"
     49#include "util/Exception.h"
     50#include "util/String.h"
     51#include "util/SubString.h"
     52#include "core/ConsoleCommand.h"
    4153#include "core/ConfigValueIncludes.h"
    42 #include "core/Clock.h"
    43 #include "core/ConsoleCommand.h"
     54#include "core/CoreIncludes.h"
    4455#include "core/Core.h"
    45 #include "core/CoreIncludes.h"
    46 #include "core/Game.h"
    47 #include "core/GameMode.h"
    4856#include "core/input/InputManager.h"
    4957#include "core/input/KeyBinder.h"
    50 #include "core/input/SimpleInputState.h"
     58#include "core/input/ExtendedInputState.h"
    5159#include "core/Loader.h"
    5260#include "core/XMLFile.h"
    5361#include "overlays/console/InGameConsole.h"
    5462#include "gui/GUIManager.h"
    55 #include "GraphicsManager.h"
     63#include "tools/WindowEventListener.h"
     64
     65// for compatibility
     66#include "GraphicsEngine.h"
    5667
    5768namespace orxonox
    5869{
    59     AddGameState(GSGraphics, "graphics");
    60 
    61     GSGraphics::GSGraphics(const std::string& name)
    62         : GameState(name)
     70    GSGraphics::GSGraphics()
     71        : GameState<GSRoot>("graphics")
     72        , renderWindow_(0)
     73        , viewport_(0)
     74        , bWindowEventListenerUpdateRequired_(false)
    6375        , inputManager_(0)
    6476        , console_(0)
    6577        , guiManager_(0)
    66         , graphicsManager_(0)
     78        , ogreRoot_(0)
     79        , ogreLogger_(0)
     80        , graphicsEngine_(0)
    6781        , masterKeyBinder_(0)
    68         , masterInputState_(0)
    6982        , debugOverlay_(0)
    7083    {
    7184        RegisterRootObject(GSGraphics);
     85        setConfigValues();
    7286    }
    7387
     
    7690    }
    7791
    78     /**
    79     @brief
    80         this function does nothing
    81 
    82         Indeed. Here goes nothing.
    83     */
    8492    void GSGraphics::setConfigValues()
    8593    {
    86     }
    87 
    88     /**
    89     @brief
    90         This function is called when we enter this game state.
    91 
    92         Since graphics is very important for our game this function does quite a lot:
    93         \li starts graphics manager
    94         \li loads debug overlay
    95         \li manages render window
    96         \li creates input manager
    97         \li loads master key bindings
    98         \li loads ingame console
    99         \li loads GUI interface (GUIManager)
    100         \li creates console command to toggle GUI
    101     */
    102     void GSGraphics::activate()
    103     {
    104         GameMode::setShowsGraphics(true);
    105 
    106         setConfigValues();
    107 
    108         // initialise graphics manager. Doesn't load the render window yet!
    109         this->graphicsManager_ = new GraphicsManager();
    110         this->graphicsManager_->initialise();
     94        SetConfigValue(resourceFile_,    "resources.cfg")
     95            .description("Location of the resources file in the data path.");
     96        SetConfigValue(ogreConfigFile_,  "ogre.cfg")
     97            .description("Location of the Ogre config file");
     98        SetConfigValue(ogrePluginsFolder_, ORXONOX_OGRE_PLUGINS_FOLDER)
     99            .description("Folder where the Ogre plugins are located.");
     100        SetConfigValue(ogrePlugins_, ORXONOX_OGRE_PLUGINS)
     101            .description("Comma separated list of all plugins to load.");
     102        SetConfigValue(ogreLogFile_,     "ogre.log")
     103            .description("Logfile for messages from Ogre. Use \"\" to suppress log file creation.");
     104        SetConfigValue(ogreLogLevelTrivial_ , 5)
     105            .description("Corresponding orxonox debug level for ogre Trivial");
     106        SetConfigValue(ogreLogLevelNormal_  , 4)
     107            .description("Corresponding orxonox debug level for ogre Normal");
     108        SetConfigValue(ogreLogLevelCritical_, 2)
     109            .description("Corresponding orxonox debug level for ogre Critical");
     110    }
     111
     112    void GSGraphics::enter()
     113    {
     114        Core::setShowsGraphics(true);
     115
     116        // initialise graphics engine. Doesn't load the render window yet!
     117        graphicsEngine_ = new GraphicsEngine();
     118
     119        // Ogre setup procedure
     120        setupOgre();
     121        // load all the required plugins for Ogre
     122        loadOgrePlugins();
     123        // read resource declaration file
     124        this->declareResources();
     125        // Reads ogre config and creates the render window
     126        this->loadRenderer();
     127
     128        // TODO: Spread this so that this call only initialises things needed for the Console and GUI
     129        this->initialiseResources();
     130
     131        // We want to get informed whenever an object of type WindowEventListener is created
     132        // in order to later update the window size.
     133        bWindowEventListenerUpdateRequired_ = false;
     134        RegisterConstructionCallback(GSGraphics, orxonox::WindowEventListener, requestWindowEventListenerUpdate);
    111135
    112136        // load debug overlay
     
    115139        Loader::open(debugOverlay_);
    116140
     141        // Calls the InputManager which sets up the input devices.
    117142        // The render window width and height are used to set up the mouse movement.
     143        inputManager_ = new InputManager();
    118144        size_t windowHnd = 0;
    119         Ogre::RenderWindow* renderWindow = GraphicsManager::getInstance().getRenderWindow();
    120         renderWindow->getCustomAttribute("WINDOW", &windowHnd);
    121 
    122         // Calls the InputManager which sets up the input devices.
    123         inputManager_ = new InputManager();
    124         inputManager_->initialise(windowHnd, renderWindow->getWidth(), renderWindow->getHeight(), true);
    125 
    126         // load master key bindings
    127         masterInputState_ = InputManager::getInstance().createInputState<SimpleInputState>("master", true);
     145        this->renderWindow_->getCustomAttribute("WINDOW", &windowHnd);
     146        inputManager_->initialise(windowHnd, renderWindow_->getWidth(), renderWindow_->getHeight(), true);
     147        // Configure master input state with a KeyBinder
    128148        masterKeyBinder_ = new KeyBinder();
    129149        masterKeyBinder_->loadBindings("masterKeybindings.ini");
    130         masterInputState_->setKeyHandler(masterKeyBinder_);
     150        inputManager_->getMasterInputState()->addKeyHandler(masterKeyBinder_);
    131151
    132152        // Load the InGameConsole
    133153        console_ = new InGameConsole();
    134         console_->initialise(renderWindow->getWidth(), renderWindow->getHeight());
     154        console_->initialise(this->renderWindow_->getWidth(), this->renderWindow_->getHeight());
    135155
    136156        // load the CEGUI interface
    137157        guiManager_ = new GUIManager();
    138         guiManager_->initialise(renderWindow);
    139 
    140         // add console command to toggle GUI
    141         FunctorMember<GSGraphics>* functor = createFunctor(&GSGraphics::toggleGUI);
    142         functor->setObject(this);
    143         this->ccToggleGUI_ = createConsoleCommand(functor, "toggleGUI");
    144         CommandExecutor::addConsoleCommandShortcut(this->ccToggleGUI_);
    145 
    146         // enable master input
    147         InputManager::getInstance().requestEnterState("master");
    148     }
    149 
    150     /**
    151     @brief
    152         This function is called when the game state is left
    153 
    154         Created references, input states and console commands are deleted.
    155     */
    156     void GSGraphics::deactivate()
    157     {
    158 
    159         if (this->ccToggleGUI_)
    160         {
    161             delete this->ccToggleGUI_;
    162             this->ccToggleGUI_ = 0;
    163         }
    164 
    165         masterInputState_->setHandler(0);
    166         InputManager::getInstance().requestDestroyState("master");
     158        guiManager_->initialise(this->renderWindow_);
     159
     160        // add console commands
     161        FunctorMember<GSGraphics>* functor1 = createFunctor(&GSGraphics::printScreen);
     162        functor1->setObject(this);
     163        ccPrintScreen_ = createConsoleCommand(functor1, "printScreen");
     164        CommandExecutor::addConsoleCommandShortcut(ccPrintScreen_);
     165    }
     166
     167    void GSGraphics::leave()
     168    {
     169        using namespace Ogre;
     170
     171        delete this->ccPrintScreen_;
     172
     173        // remove our WindowEventListener first to avoid bad calls after the window has been destroyed
     174        Ogre::WindowEventUtilities::removeWindowEventListener(this->renderWindow_, this);
     175
     176        delete this->guiManager_;
     177
     178        delete this->console_;
     179
     180        //inputManager_->getMasterInputState()->removeKeyHandler(this->masterKeyBinder_);
    167181        delete this->masterKeyBinder_;
    168 
    169         delete this->guiManager_;
    170         delete this->console_;
     182        delete this->inputManager_;
    171183
    172184        Loader::unload(this->debugOverlay_);
    173185        delete this->debugOverlay_;
    174186
    175         delete this->inputManager_;
    176         this->inputManager_ = 0;
    177 
    178         delete graphicsManager_;
    179 
    180         GameMode::setShowsGraphics(false);
    181     }
    182 
    183     /**
    184     @brief
    185         Toggles the visibility of the current GUI
    186 
    187         This function just executes a Lua function in the main script of the GUI by accessing the GUIManager.
    188         For more details on this function check out the Lua code.
    189     */
    190     void GSGraphics::toggleGUI()
    191     {
    192             GUIManager::getInstance().executeCode("toggleGUI()");
     187        // unload all compositors
     188        Ogre::CompositorManager::getSingleton().removeAll();
     189
     190        // destroy render window
     191        RenderSystem* renderer = this->ogreRoot_->getRenderSystem();
     192        renderer->destroyRenderWindow("Orxonox");
     193
     194        /*** CODE SNIPPET, UNUSED ***/
     195        // Does the opposite of initialise()
     196        //ogreRoot_->shutdown();
     197        // Remove all resources and resource groups
     198        //StringVector groups = ResourceGroupManager::getSingleton().getResourceGroups();
     199        //for (StringVector::iterator it = groups.begin(); it != groups.end(); ++it)
     200        //{
     201        //    ResourceGroupManager::getSingleton().destroyResourceGroup(*it);
     202        //}
     203
     204        //ParticleSystemManager::getSingleton().removeAllTemplates();
     205
     206        // Shutdown the render system
     207        //this->ogreRoot_->setRenderSystem(0);
     208
     209        delete this->ogreRoot_;
     210
     211        // delete the ogre log and the logManager (since we have created it).
     212        this->ogreLogger_->getDefaultLog()->removeListener(this);
     213        this->ogreLogger_->destroyLog(Ogre::LogManager::getSingleton().getDefaultLog());
     214        delete this->ogreLogger_;
     215
     216        delete graphicsEngine_;
     217
     218        Core::setShowsGraphics(false);
    193219    }
    194220
     
    201227        need the time. So we shouldn't run into problems.
    202228    */
    203     void GSGraphics::update(const Clock& time)
    204     {
    205         if (this->getActivity().topState)
    206         {
    207             // This state can not 'survive' on its own.
    208             // Load a user interface therefore
    209             Game::getInstance().requestState("mainMenu");
    210         }
    211 
     229    void GSGraphics::ticked(const Clock& time)
     230    {
    212231        uint64_t timeBeforeTick = time.getRealMicroseconds();
    213232
    214         this->inputManager_->update(time);        // tick console
    215         this->console_->update(time);
    216         this->guiManager_->update(time);
     233        float dt = time.getDeltaTime();
     234
     235        this->inputManager_->tick(dt);
     236        // tick console
     237        this->console_->tick(dt);
     238        this->tickChild(time);
     239
     240        if (this->bWindowEventListenerUpdateRequired_)
     241        {
     242            // Update all WindowEventListeners for the case a new one was created.
     243            this->windowResized(this->renderWindow_);
     244            this->bWindowEventListenerUpdateRequired_ = false;
     245        }
    217246
    218247        uint64_t timeAfterTick = time.getRealMicroseconds();
    219248
    220         // Also add our tick time
    221         Game::getInstance().addTickTime(timeAfterTick - timeBeforeTick);
    222 
    223         // Render
    224         this->graphicsManager_->update(time);
     249        // Also add our tick time to the list in GSRoot
     250        this->getParent()->addTickTime(timeAfterTick - timeBeforeTick);
     251
     252        // Update statistics overlay. Note that the values only change periodically in GSRoot.
     253        GraphicsEngine::getInstance().setAverageFramesPerSecond(this->getParent()->getAvgFPS());
     254        GraphicsEngine::getInstance().setAverageTickTime(this->getParent()->getAvgTickTime());
     255
     256        // don't forget to call _fireFrameStarted in ogre to make sure
     257        // everything goes smoothly
     258        Ogre::FrameEvent evt;
     259        evt.timeSinceLastFrame = dt;
     260        evt.timeSinceLastEvent = dt; // note: same time, but shouldn't matter anyway
     261        ogreRoot_->_fireFrameStarted(evt);
     262
     263        // Pump messages in all registered RenderWindows
     264        // This calls the WindowEventListener objects.
     265        Ogre::WindowEventUtilities::messagePump();
     266        // make sure the window stays active even when not focused
     267        // (probably only necessary on windows)
     268        this->renderWindow_->setActive(true);
     269
     270        // render
     271        ogreRoot_->_updateAllRenderTargets();
     272
     273        // again, just to be sure ogre works fine
     274        ogreRoot_->_fireFrameEnded(evt); // note: uses the same time as _fireFrameStarted
     275    }
     276
     277    /**
     278    @brief
     279        Creates the Ogre Root object and sets up the ogre log.
     280    */
     281    void GSGraphics::setupOgre()
     282    {
     283        COUT(3) << "Setting up Ogre..." << std::endl;
     284
     285        if (ogreConfigFile_ == "")
     286        {
     287            COUT(2) << "Warning: Ogre config file set to \"\". Defaulting to config.cfg" << std::endl;
     288            ModifyConfigValue(ogreConfigFile_, tset, "config.cfg");
     289        }
     290        if (ogreLogFile_ == "")
     291        {
     292            COUT(2) << "Warning: Ogre log file set to \"\". Defaulting to ogre.log" << std::endl;
     293            ModifyConfigValue(ogreLogFile_, tset, "ogre.log");
     294        }
     295
     296        boost::filesystem::path ogreConfigFilepath(Core::getConfigPath() / this->ogreConfigFile_);
     297        boost::filesystem::path ogreLogFilepath(Core::getLogPath() / this->ogreLogFile_);
     298
     299        // create a new logManager
     300        // Ogre::Root will detect that we've already created a Log
     301        ogreLogger_ = new Ogre::LogManager();
     302        COUT(4) << "Ogre LogManager created" << std::endl;
     303
     304        // create our own log that we can listen to
     305        Ogre::Log *myLog;
     306        myLog = ogreLogger_->createLog(ogreLogFilepath.string(), true, false, false);
     307        COUT(4) << "Ogre Log created" << std::endl;
     308
     309        myLog->setLogDetail(Ogre::LL_BOREME);
     310        myLog->addListener(this);
     311
     312        COUT(4) << "Creating Ogre Root..." << std::endl;
     313
     314        // check for config file existence because Ogre displays (caught) exceptions if not
     315        if (!boost::filesystem::exists(ogreConfigFilepath))
     316        {
     317            // create a zero sized file
     318            std::ofstream creator;
     319            creator.open(ogreConfigFilepath.string().c_str());
     320            creator.close();
     321        }
     322
     323        // Leave plugins file empty. We're going to do that part manually later
     324        ogreRoot_ = new Ogre::Root("", ogreConfigFilepath.string(), ogreLogFilepath.string());
     325
     326        COUT(3) << "Ogre set up done." << std::endl;
     327    }
     328
     329    void GSGraphics::loadOgrePlugins()
     330    {
     331        // just to make sure the next statement doesn't segfault
     332        if (ogrePluginsFolder_ == "")
     333            ogrePluginsFolder_ = ".";
     334
     335        boost::filesystem::path folder(ogrePluginsFolder_);
     336        // Do some SubString magic to get the comma separated list of plugins
     337        SubString plugins(ogrePlugins_, ",", " ", false, 92, false, 34, false, 40, 41, false, '\0');
     338        // Use backslash paths on Windows! file_string() already does that though.
     339        for (unsigned int i = 0; i < plugins.size(); ++i)
     340            ogreRoot_->loadPlugin((folder / plugins[i]).file_string());
     341    }
     342
     343    void GSGraphics::declareResources()
     344    {
     345        CCOUT(4) << "Declaring Resources" << std::endl;
     346        //TODO: Specify layout of data file and maybe use xml-loader
     347        //TODO: Work with ressource groups (should be generated by a special loader)
     348
     349        if (resourceFile_ == "")
     350        {
     351            COUT(2) << "Warning: Ogre resource file set to \"\". Defaulting to resources.cfg" << std::endl;
     352            ModifyConfigValue(resourceFile_, tset, "resources.cfg");
     353        }
     354
     355        // Load resource paths from data file using configfile ressource type
     356        Ogre::ConfigFile cf;
     357        try
     358        {
     359            cf.load((Core::getMediaPath() / resourceFile_).string());
     360        }
     361        catch (...)
     362        {
     363            //COUT(1) << ex.getFullDescription() << std::endl;
     364            COUT(0) << "Have you forgotten to set the data path in orxnox.ini?" << std::endl;
     365            throw;
     366        }
     367
     368        // Go through all sections & settings in the file
     369        Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();
     370
     371        std::string secName, typeName, archName;
     372        while (seci.hasMoreElements())
     373        {
     374            try
     375            {
     376                secName = seci.peekNextKey();
     377                Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
     378                Ogre::ConfigFile::SettingsMultiMap::iterator i;
     379                for (i = settings->begin(); i != settings->end(); ++i)
     380                {
     381                    typeName = i->first; // for instance "FileSystem" or "Zip"
     382                    archName = i->second; // name (and location) of archive
     383
     384                    Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
     385                        (Core::getMediaPath() / archName).string(), typeName, secName);
     386                }
     387            }
     388            catch (Ogre::Exception& ex)
     389            {
     390                COUT(1) << ex.getFullDescription() << std::endl;
     391            }
     392        }
     393    }
     394
     395    void GSGraphics::loadRenderer()
     396    {
     397        CCOUT(4) << "Configuring Renderer" << std::endl;
     398
     399        if (!ogreRoot_->restoreConfig())
     400            if (!ogreRoot_->showConfigDialog())
     401                ThrowException(InitialisationFailed, "Could not show Ogre configuration dialogue.");
     402
     403        CCOUT(4) << "Creating render window" << std::endl;
     404
     405        this->renderWindow_ = ogreRoot_->initialise(true, "Orxonox");
     406
     407        Ogre::WindowEventUtilities::addWindowEventListener(this->renderWindow_, this);
     408
     409        Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(0);
     410
     411        // create a full screen default viewport
     412        this->viewport_ = this->renderWindow_->addViewport(0, 0);
     413
     414        if (this->graphicsEngine_)
     415            this->graphicsEngine_->setViewport(this->viewport_);
     416    }
     417
     418    void GSGraphics::initialiseResources()
     419    {
     420        CCOUT(4) << "Initialising resources" << std::endl;
     421        //TODO: Do NOT load all the groups, why are we doing that? And do we really do that? initialise != load...
     422        //try
     423        //{
     424            Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
     425            /*Ogre::StringVector str = Ogre::ResourceGroupManager::getSingleton().getResourceGroups();
     426            for (unsigned int i = 0; i < str.size(); i++)
     427            {
     428            Ogre::ResourceGroupManager::getSingleton().loadResourceGroup(str[i]);
     429            }*/
     430        //}
     431        //catch (...)
     432        //{
     433        //    CCOUT(2) << "Error: There was a serious error when initialising the resources." << std::endl;
     434        //    throw;
     435        //}
     436    }
     437
     438    /**
     439    @brief
     440        Method called by the LogListener interface from Ogre.
     441        We use it to capture Ogre log messages and handle it ourselves.
     442    @param message
     443        The message to be logged
     444    @param lml
     445        The message level the log is using
     446    @param maskDebug
     447        If we are printing to the console or not
     448    @param logName
     449        The name of this log (so you can have several listeners
     450        for different logs, and identify them)
     451    */
     452    void GSGraphics::messageLogged(const std::string& message,
     453        Ogre::LogMessageLevel lml, bool maskDebug, const std::string& logName)
     454    {
     455        int orxonoxLevel;
     456        switch (lml)
     457        {
     458        case Ogre::LML_TRIVIAL:
     459            orxonoxLevel = this->ogreLogLevelTrivial_;
     460            break;
     461        case Ogre::LML_NORMAL:
     462            orxonoxLevel = this->ogreLogLevelNormal_;
     463            break;
     464        case Ogre::LML_CRITICAL:
     465            orxonoxLevel = this->ogreLogLevelCritical_;
     466            break;
     467        default:
     468            orxonoxLevel = 0;
     469        }
     470        OutputHandler::getOutStream().setOutputLevel(orxonoxLevel)
     471            << "Ogre: " << message << std::endl;
     472    }
     473
     474    /**
     475    @brief
     476        Window has moved.
     477    @param rw
     478        The render window it occured in
     479    */
     480    void GSGraphics::windowMoved(Ogre::RenderWindow *rw)
     481    {
     482        for (ObjectList<orxonox::WindowEventListener>::iterator it = ObjectList<orxonox::WindowEventListener>::begin(); it; ++it)
     483            it->windowMoved();
    225484    }
    226485
     
    231490        The render window it occured in
    232491    @note
    233         GraphicsManager has a render window stored itself. This is the same
     492        GraphicsEngine has a render window stored itself. This is the same
    234493        as rw. But we have to be careful when using multiple render windows!
    235494    */
    236     void GSGraphics::windowResized(unsigned int newWidth, unsigned int newHeight)
    237     {
     495    void GSGraphics::windowResized(Ogre::RenderWindow *rw)
     496    {
     497        for (ObjectList<orxonox::WindowEventListener>::iterator it = ObjectList<orxonox::WindowEventListener>::begin(); it; ++it)
     498            it->windowResized(this->renderWindow_->getWidth(), this->renderWindow_->getHeight());
     499
    238500        // OIS needs this under linux even if we only use relative input measurement.
    239501        if (this->inputManager_)
    240             this->inputManager_->setWindowExtents(newWidth, newHeight);
     502            this->inputManager_->setWindowExtents(renderWindow_->getWidth(), renderWindow_->getHeight());
    241503    }
    242504
     
    247509        The render window it occured in
    248510    */
    249     void GSGraphics::windowFocusChanged()
    250     {
     511    void GSGraphics::windowFocusChange(Ogre::RenderWindow *rw)
     512    {
     513        for (ObjectList<orxonox::WindowEventListener>::iterator it = ObjectList<orxonox::WindowEventListener>::begin(); it; ++it)
     514            it->windowFocusChanged();
     515
    251516        // instruct InputManager to clear the buffers (core library so we cannot use the interface)
    252517        if (this->inputManager_)
     
    254519    }
    255520
     521    /**
     522    @brief
     523        Window was closed.
     524    @param rw
     525        The render window it occured in
     526    */
     527    void GSGraphics::windowClosed(Ogre::RenderWindow *rw)
     528    {
     529        this->requestState("root");
     530    }
     531
     532    void GSGraphics::printScreen()
     533    {
     534        if (this->renderWindow_)
     535        {
     536            this->renderWindow_->writeContentsToTimestampedFile("shot_", ".jpg");
     537        }
     538    }
    256539}
Note: See TracChangeset for help on using the changeset viewer.