Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Jul 20, 2008, 7:49:26 PM (16 years ago)
Author:
rgrieder
Message:

merged input branch into gui test branch (was about time)
svn save (it's still a mess and CMLs haven't been updated)
I'll have to create a special project to create the tolua_bind files for tolua itself anyway..

Location:
code/branches/gui
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • code/branches/gui

  • code/branches/gui/src/orxonox/Orxonox.cc

    r1625 r1638  
    2222 *   Author:
    2323 *      Reto Grieder
     24 *      Benjamin Knecht <beni_at_orxonox.net>, (C) 2007
    2425 *   Co-authors:
    25  *      Benjamin Knecht <beni_at_orxonox.net>, (C) 2007
     26 *      ...
    2627 *
    2728 */
     
    3839//****** STD *******
    3940#include <deque>
     41#include <cassert>
    4042
    4143//****** OGRE ******
     
    5052// util
    5153//#include "util/Sleep.h"
    52 #include "util/ArgReader.h"
    5354
    5455// core
    5556#include "core/ConfigFileManager.h"
     57#include "core/ConfigValueIncludes.h"
    5658#include "core/ConsoleCommand.h"
    5759#include "core/Debug.h"
    5860#include "core/Loader.h"
     61#include "core/Exception.h"
    5962#include "core/input/InputManager.h"
     63#include "core/input/SimpleInputState.h"
     64#include "core/input/KeyBinder.h"
    6065#include "core/TclBind.h"
    6166#include "core/Core.h"
     
    6974
    7075// objects and tools
    71 #include "overlays/OverlayGroup.h"
    7276#include "overlays/console/InGameConsole.h"
    7377#include "objects/Tickable.h"
    7478#include "objects/Backlight.h"
    7579#include "tools/ParticleInterface.h"
     80#include "gui/GUIManager.h"
    7681
    7782#include "GraphicsEngine.h"
     
    8590namespace orxonox
    8691{
    87   SetConsoleCommandShortcut(Orxonox, exit).setKeybindMode(KeybindMode::OnPress);
    88   SetConsoleCommandShortcut(Orxonox, slomo).setAccessLevel(AccessLevel::Offline).setDefaultValue(0, 1.0).setAxisParamIndex(0).setIsAxisRelative(false);
    89   SetConsoleCommandShortcut(Orxonox, setTimeFactor).setAccessLevel(AccessLevel::Offline).setDefaultValue(0, 1.0);
     92  SetConsoleCommand(Orxonox, exit, true).setKeybindMode(KeybindMode::OnPress);
     93  SetConsoleCommand(Orxonox, slomo, true).setAccessLevel(AccessLevel::Offline).setDefaultValue(0, 1.0).setAxisParamIndex(0).setIsAxisRelative(false);
     94  SetConsoleCommand(Orxonox, setTimeFactor, true).setAccessLevel(AccessLevel::Offline).setDefaultValue(0, 1.0);
     95  SetConsoleCommand(Orxonox, loadGame, true).setAccessLevel(AccessLevel::User).setDefaultValue(0, "standalone");
    9096
    9197  /**
     
    106112    , bAbort_(false)
    107113    , timefactor_(1.0f)
    108     , mode_(STANDALONE)
    109     , serverIp_("")
    110     , serverPort_(NETWORK_PORT)
    111   {
     114    , mode_(GameMode::GM_Unspecified)
     115    , debugRefreshTime_(0.0f)
     116  {
     117    RegisterRootObject(Orxonox);
     118
     119    assert(singletonRef_s == 0);
     120    singletonRef_s = this;
    112121  }
    113122
     
    118127  {
    119128    // keep in mind: the order of deletion is very important!
    120     Loader::unload(startLevel_);
     129    Loader::unload();
    121130    if (this->startLevel_)
    122131      delete this->startLevel_;
     
    136145      delete this->timer_;
    137146    InputManager::destroy();
    138     GraphicsEngine::getSingleton().destroy();
     147
     148    if (this->ogre_)
     149      delete ogre_;
    139150
    140151    if (network::Client::getSingleton())
     
    142153    if (server_g)
    143154      delete network::Server::getSingleton();
     155
     156    singletonRef_s = 0;
     157  }
     158
     159  void Orxonox::setConfigValues()
     160  {
     161    SetConfigValue(debugRefreshTime_, 0.2).description("Sets the time interval at which average fps, etc. get updated.");
    144162  }
    145163
     
    157175   * @return singleton reference
    158176   */
    159   Orxonox* Orxonox::getSingleton()
    160   {
    161     if (!singletonRef_s)
    162       singletonRef_s = new Orxonox();
    163     return singletonRef_s;
    164   }
    165 
    166   /**
    167     @brief Destroys the Orxonox singleton.
    168   */
    169   void Orxonox::destroySingleton()
    170   {
    171     if (singletonRef_s)
    172       delete singletonRef_s;
    173     singletonRef_s = 0;
     177  Orxonox& Orxonox::getSingleton()
     178  {
     179    assert(singletonRef_s);
     180    return *singletonRef_s;
    174181  }
    175182
     
    179186  void Orxonox::setTimeFactor(float factor)
    180187  {
    181     float change = factor / Orxonox::getSingleton()->getTimeFactor();
    182     Orxonox::getSingleton()->timefactor_ = factor;
     188    float change = factor / Orxonox::getSingleton().getTimeFactor();
     189    Orxonox::getSingleton().timefactor_ = factor;
    183190    for (Iterator<ParticleInterface> it = ObjectList<ParticleInterface>::begin(); it; ++it)
    184191        it->setSpeedFactor(it->getSpeedFactor() * change);
    185192
    186193    for (Iterator<Backlight> it = ObjectList<Backlight>::begin(); it; ++it)
    187         it->setTimeFactor(Orxonox::getSingleton()->getTimeFactor());
    188   }
    189 
    190   /**
    191    * initialization of Orxonox object
    192    * @param argc argument counter
    193    * @param argv list of argumenst
     194        it->setTimeFactor(Orxonox::getSingleton().getTimeFactor());
     195  }
     196
     197
     198  /**
     199   * Starts the whole Game.
    194200   * @param path path to config (in home dir or something)
    195201   */
    196   bool Orxonox::init(int argc, char **argv)
     202  void Orxonox::start()
    197203  {
    198204#ifdef _DEBUG
     
    203209    Factory::createClassHierarchy();
    204210
    205     std::string mode;
    206     std::string tempDataPath;
    207 
    208     ArgReader ar(argc, argv);
    209     ar.checkArgument("mode", &mode, false);
    210     ar.checkArgument("data", &tempDataPath, false);
    211     ar.checkArgument("ip",   &serverIp_, false);
    212     ar.checkArgument("port", &serverPort_, false);
    213     if(ar.errorHandling())
    214     {
    215       COUT(1) << "Error while parsing command line arguments" << std::endl;
    216       COUT(1) << ar.getErrorString();
    217       COUT(0) << "Usage:" << std::endl << "orxonox [mode client|server|dedicated|standalone] "
    218         << "[--data PATH] [--ip IP] [--port PORT]" << std::endl;
    219       return false;
    220     }
    221 
    222     if (mode == "client")
    223       mode_ = CLIENT;
    224     else if (mode == "server")
    225       mode_ = SERVER;
    226     else if (mode == "dedicated")
    227       mode_ = DEDICATED;
    228     else
    229     {
    230       if (mode == "")
    231         mode = "standalone";
    232       if (mode != "standalone")
     211    setConfigValues();
     212
     213    const Settings::CommandLineArgument* mode = Settings::getCommandLineArgument("mode");
     214    assert(mode);
     215    if (!mode->bHasDefaultValue_)
     216    {
     217      Settings::setGameMode(mode->value_);
     218      this->mode_ = Settings::getGameMode();
     219    }
     220    COUT(3) << "Orxonox: Game mode is " << mode_.name << "." << std::endl;
     221
     222    const Settings::CommandLineArgument* dataPath = Settings::getCommandLineArgument("dataPath");
     223    assert(dataPath);
     224    if (!dataPath->bHasDefaultValue_)
     225    {
     226      if (*dataPath->value_.getString().end() != '/' && *dataPath->value_.getString().end() != '\\')
     227        Settings::tsetDataPath(dataPath->value_.getString() + "/");
     228      else
     229        Settings::tsetDataPath(dataPath->value_.getString());
     230    }
     231
     232    try
     233    {
     234        // initialise TCL
     235        TclBind::getInstance().setDataPath(Settings::getDataPath());
     236
     237        ogre_ = new GraphicsEngine();
     238        ogre_->setup();       // creates ogre root and other essentials
     239
     240        if (mode_.showsGraphics)
     241        {
     242          ogre_->loadRenderer();    // creates the render window
     243
     244          // TODO: Spread this so that this call only initialises things needed for the Console and GUI
     245          ogre_->initialiseResources();
     246
     247          // Calls the InputManager which sets up the input devices.
     248          // The render window width and height are used to set up the mouse movement.
     249          InputManager::initialise(ogre_->getWindowHandle(),
     250                ogre_->getWindowWidth(), ogre_->getWindowHeight(), true, true, true);
     251          KeyBinder* keyBinder = new KeyBinder();
     252          InputManager::createSimpleInputState("game", 20)->setHandler(keyBinder);
     253
     254          // Load the InGameConsole
     255          InGameConsole::getInstance().initialise();
     256
     257          // load the CEGUI interface
     258          GUIManager::getInstance().initialise();
     259        }
     260
     261        bool showGUI = true;
     262        if (mode_.mode != GameMode::Unspecified)
     263        {
     264          showGUI = false;
     265          // a game mode was specified with the command line
     266          // we therefore load the game and level directly
     267
     268          if (!loadLevel(this->mode_))
     269          {
     270            COUT(1) << "Loading with predefined mode failed. Showing main menu." << std::endl;
     271            showGUI = true;
     272            mode_ = GameMode::GM_Unspecified;
     273          }
     274        }
     275       
     276        if (showGUI)
     277        {
     278          // show main menu
     279          //GraphicsEngine::getSingleton().createNewScene();
     280          GUIManager::getInstance().showGUI("MainMenu", true);
     281        }
     282    }
     283    catch (std::exception& ex)
     284    {
     285      COUT(1) << ex.what() << std::endl;
     286      COUT(1) << "Loading sequence aborted." << std::endl;
     287      return;
     288    }
     289
     290    modeRequest_ = mode_;
     291    // here happens the game
     292    startRenderLoop();
     293
     294    if (mode_.mode == GameMode::Client)
     295      network::Client::getSingleton()->closeConnection();
     296
     297    if (mode_.hasServer)
     298      server_g->close();
     299  }
     300
     301  void Orxonox::loadGame(const std::string& name)
     302  {
     303      const GameMode& mode = Settings::getGameMode(name);
     304      if (mode.mode == GameMode::None)
     305          return;
     306
     307      getSingleton().modeRequest_ = mode;
     308  }
     309
     310  bool Orxonox::loadLevel(const GameMode& mode)
     311  {
     312      bool success = true;
     313
     314      if (mode.showsGraphics)
    233315      {
    234         COUT(2) << "Warning: mode \"" << mode << "\" doesn't exist. "
    235           << "Defaulting to standalone" << std::endl;
    236         mode = "standalone";
     316        // create Ogre SceneManager for the level
     317        ogre_->createNewScene();
     318
     319        if (!loadPlayground())
     320            return false;
    237321      }
    238       mode_ = STANDALONE;
    239     }
    240     COUT(3) << "Orxonox: Mode is " << mode << "." << std::endl;
    241 
    242     if (tempDataPath != "")
    243     {
    244       if (tempDataPath[tempDataPath.size() - 1] != '/')
    245         tempDataPath += "/";
    246       Settings::tsetDataPath(tempDataPath);
    247     }
    248 
    249     // initialise TCL
    250     TclBind::getInstance().setDataPath(Settings::getDataPath());
    251 
    252     //if (mode_ == DEDICATED)
    253       // TODO: decide what to do here
    254     //else
    255 
    256     // for playable server, client and standalone, the startup
    257     // procedure until the GUI is identical
    258 
    259     ogre_ = &GraphicsEngine::getSingleton();
    260     if (!ogre_->setup())       // creates ogre root and other essentials
    261       return false;
    262 
    263     return true;
    264   }
    265 
    266   /**
    267    * start modules
    268    */
    269   bool Orxonox::start()
    270   {
    271     if (mode_ == DEDICATED)
    272     {
    273       // do something else
    274     }
    275     else
    276     { // not dedicated server
    277       if (!ogre_->loadRenderer())    // creates the render window
    278         return false;
    279 
    280       // TODO: Spread this so that this call only initialises things needed for the Console
    281       if (!ogre_->initialiseResources())
    282         return false;
    283 
    284       // Load the InGameConsole
    285       InGameConsole::getInstance().initialise();
    286 
    287       // Calls the InputManager which sets up the input devices.
    288       // The render window width and height are used to set up the mouse movement.
    289       if (!InputManager::initialise(ogre_->getWindowHandle(),
    290             ogre_->getWindowWidth(), ogre_->getWindowHeight(), true, true, true))
    291         return false;
    292 
    293       // TOOD: load the GUI here
    294       // set InputManager to GUI mode
    295       InputManager::setInputState(InputManager::IS_GUI);
    296       // TODO: run GUI here
    297 
    298       // The following lines depend very much on the GUI output, so they're probably misplaced here..
    299 
    300       InputManager::setInputState(InputManager::IS_NONE);
    301 
    302       // create Ogre SceneManager
    303       ogre_->createNewScene();
    304 
    305       if (!loadPlayground())
    306         return false;
    307     }
    308 
    309     switch (mode_)
    310     {
    311     case SERVER:
    312       if (!serverLoad())
    313         return false;
    314       break;
    315     case CLIENT:
    316       if (!clientLoad())
    317         return false;
    318       break;
    319     case DEDICATED:
    320       if (!serverLoad())
    321         return false;
    322       break;
    323     default:
    324       if (!standaloneLoad())
    325         return false;
    326     }
    327 
    328     InputManager::setInputState(InputManager::IS_NORMAL);
    329 
    330     return startRenderLoop();
     322
     323      switch (mode.mode)
     324      {
     325      case GameMode::Server:
     326        success &= serverLoad();
     327        break;
     328      case GameMode::Client:
     329        success &= clientLoad();
     330        break;
     331      case GameMode::Dedicated:
     332        success &= serverLoad();
     333        break;
     334      case GameMode::Standalone:
     335        success &= standaloneLoad();
     336        break;
     337      default: // never happens
     338          assert(false);
     339      }
     340     
     341      if (success)
     342        InputManager::requestEnterState("game");
     343
     344      return success;
    331345  }
    332346
     
    337351  bool Orxonox::loadPlayground()
    338352  {
    339     // Init audio
    340     //auMan_ = new audio::AudioManager();
    341     //auMan_->ambientAdd("a1");
    342     //auMan_->ambientAdd("a2");
    343     //auMan_->ambientAdd("a3");
    344     //auMan->ambientAdd("ambient1");
    345     //auMan_->ambientStart();
     353    // Start the Radar
     354    this->radar_ = new Radar();
    346355
    347356    // Load the HUD
    348357    COUT(3) << "Orxonox: Loading HUD" << std::endl;
    349358    hud_ = new Level(Settings::getDataPath() + "overlay/hud.oxo");
    350     Loader::load(hud_);
    351 
    352     // Start the Radar
    353     this->radar_ = new Radar();
    354 
    355     return true;
     359    return Loader::load(hud_);
     360  }
     361
     362  /**
     363   * Helper method to load a level.
     364   */
     365  bool Orxonox::loadScene()
     366  {
     367    COUT(0) << "Loading level..." << std::endl;
     368    startLevel_ = new Level(Settings::getDataPath() + "levels/sample.oxw");
     369    return Loader::open(startLevel_);
    356370  }
    357371
     
    363377    COUT(0) << "Loading level in server mode" << std::endl;
    364378
     379    assert(Settings::getCommandLineArgument("port"));
     380    int serverPort = Settings::getCommandLineArgument("port")->value_;
    365381    //server_g = new network::Server(serverPort_);
    366     server_g = network::Server::createSingleton(serverPort_);
     382    server_g = network::Server::createSingleton(serverPort);
    367383
    368384    if (!loadScene())
     
    381397    COUT(0) << "Loading level in client mode" << std::endl;\
    382398
    383     if (serverIp_.compare("") == 0)
     399    assert(Settings::getCommandLineArgument("port"));
     400    assert(Settings::getCommandLineArgument("ip"));
     401    int serverPort = Settings::getCommandLineArgument("port")->value_;
     402    std::string serverIP = Settings::getCommandLineArgument("ip")->value_;
     403
     404    if (serverIP.compare("") == 0)
    384405      client_g = network::Client::createSingleton();
    385406    else
    386 
    387       client_g = network::Client::createSingleton(serverIp_, serverPort_);
     407      client_g = network::Client::createSingleton(serverIP, serverPort);
    388408
    389409    if(!client_g->establishConnection())
     
    408428
    409429  /**
    410    * Helper method to load a level.
    411    */
    412   bool Orxonox::loadScene()
    413   {
    414     startLevel_ = new Level("levels/sample.oxw");
    415     Loader::open(startLevel_);
    416 
    417     return true;
    418   }
    419 
    420 
    421   /**
    422430    Main loop of the orxonox game.
    423     About the loop: The design is almost exactly like the one in ogre, so that
    424     if any part of ogre registers a framelisteners, it will still behave
    425     correctly. Furthermore the time smoothing feature from ogre has been
    426     implemented too. If turned on (see orxonox constructor), it will calculate
    427     the dt_n by means of the recent most dt_n-1, dt_n-2, etc.
     431    We use the Ogre::Timer to measure time since it uses the most precise
     432    method an a platform (however the windows timer lacks time when under
     433    heavy kernel load!).
     434    There is a simple mechanism to measure the average time spent in our
     435    ticks as it may indicate performance issues.
     436    A note about the Ogre::FrameListener: Even though we don't use them,
     437    they still get called. However, the delta times are not correct (except
     438    for timeSinceLastFrame, which is the most important). A little research
     439    as shown that there is probably only one FrameListener that doesn't even
     440    need the time. So we shouldn't run into problems.
    428441  */
    429   bool Orxonox::startRenderLoop()
    430   {
    431     // first check whether ogre root object has been created
    432     if (Ogre::Root::getSingletonPtr() == 0)
    433     {
    434       COUT(2) << "Orxonox Error: Could not start rendering. No Ogre root object found" << std::endl;
    435       return false;
    436     }
     442  void Orxonox::startRenderLoop()
     443  {
    437444    Ogre::Root& ogreRoot = Ogre::Root::getSingleton();
    438 
    439445
    440446    // use the ogre timer class to measure time.
     
    444450    unsigned long frameCount = 0;
    445451   
    446     // TODO: this would very well fit into a configValue
    447     const unsigned long refreshTime = 200000;
     452    const unsigned long refreshTime = debugRefreshTime_ * 1000000.0f;
    448453    unsigned long refreshStartTime = 0;
    449454    unsigned long tickTime = 0;
     
    454459    unsigned long timeAfterTick = 0;
    455460
     461    int sleepTime = 0;
     462
     463    // TODO: Update time in seconds every 7 seconds to avoid any overflow (7 secs is very tight)
     464
    456465    COUT(3) << "Orxonox: Starting the main loop." << std::endl;
    457466
     467    try
     468    {
    458469    timer_->reset();
    459470    while (!bAbort_)
    460471    {
    461       // get current time
    462       timeBeforeTickOld = timeBeforeTick;
    463       timeBeforeTick    = timer_->getMicroseconds();
    464       float dt = (timeBeforeTick - timeBeforeTickOld) / 1000000.0;
    465 
    466 
    467       // tick the core (needs real time for input and tcl thread management)
    468       Core::tick(dt);
    469 
    470       // Call those objects that need the real time
    471       for (Iterator<TickableReal> it = ObjectList<TickableReal>::start(); it; ++it)
    472         it->tick(dt);
    473       // Call the scene objects
    474       for (Iterator<Tickable> it = ObjectList<Tickable>::start(); it; ++it)
    475         it->tick(dt * this->timefactor_);
    476 
    477       // call server/client with normal dt
    478       if (client_g)
    479         client_g->tick(dt * this->timefactor_);
    480       if (server_g)
    481         server_g->tick(dt * this->timefactor_);
    482 
    483 
    484       // get current time once again
    485       timeAfterTick = timer_->getMicroseconds();
    486 
    487       tickTime += timeAfterTick - timeBeforeTick;
    488       if (timeAfterTick > refreshStartTime + refreshTime)
    489       {
    490         GraphicsEngine::getSingleton().setAverageTickTime(
    491             (float)tickTime * 0.001 / (frameCount - oldFrameCount));
    492         GraphicsEngine::getSingleton().setAverageFramesPerSecond(
    493             (float)(frameCount - oldFrameCount) / (timeAfterTick - refreshStartTime) * 1000000.0);
    494         oldFrameCount = frameCount;
    495         tickTime = 0;
    496         refreshStartTime = timeAfterTick;
    497       }
    498 
    499 
    500       // don't forget to call _fireFrameStarted in ogre to make sure
    501       // everything goes smoothly
    502       Ogre::FrameEvent evt;
    503       evt.timeSinceLastFrame = dt;
    504       evt.timeSinceLastEvent = dt; // note: same time, but shouldn't matter anyway
    505       ogreRoot._fireFrameStarted(evt);
    506 
    507       if (mode_ != DEDICATED)
    508       {
    509         // Pump messages in all registered RenderWindows
    510         // This calls the WindowEventListener objects.
    511         Ogre::WindowEventUtilities::messagePump();
    512         // make sure the window stays active even when not focused
    513         // (probably only necessary on windows)
    514         GraphicsEngine::getSingleton().setWindowActivity(true);
    515 
    516         // render
    517         ogreRoot._updateAllRenderTargets();
    518       }
    519 
    520       // again, just to be sure ogre works fine
    521       ogreRoot._fireFrameEnded(evt); // note: uses the same time as _fireFrameStarted
    522 
    523       ++frameCount;
    524     }
    525 
    526     if (mode_ == CLIENT)
    527       network::Client::getSingleton()->closeConnection();
    528     else if (mode_ == SERVER)
    529       server_g->close();
    530 
    531     return true;
     472        // get current time
     473        timeBeforeTickOld = timeBeforeTick;
     474        timeBeforeTick    = timer_->getMicroseconds();
     475        float dt = (timeBeforeTick - timeBeforeTickOld) / 1000000.0;
     476
     477        // check whether we have to load a game
     478        if (mode_.mode != modeRequest_.mode && mode_.mode == GameMode::Unspecified)
     479        {
     480            this->loadLevel(modeRequest_);
     481            this->modeRequest_ = GameMode::GM_None;
     482        }
     483
     484
     485        // tick the core (needs real time for input and tcl thread management)
     486        Core::tick(dt);
     487
     488        // Call those objects that need the real time
     489        for (Iterator<TickableReal> it = ObjectList<TickableReal>::start(); it; ++it)
     490          it->tick(dt);
     491        // Call the scene objects
     492        for (Iterator<Tickable> it = ObjectList<Tickable>::start(); it; ++it)
     493          it->tick(dt * this->timefactor_);
     494
     495        // call server/client with normal dt
     496        if (client_g)
     497          client_g->tick(dt * this->timefactor_);
     498        if (server_g)
     499          server_g->tick(dt * this->timefactor_);
     500
     501
     502        // get current time once again
     503        timeAfterTick = timer_->getMicroseconds();
     504
     505        tickTime += timeAfterTick - timeBeforeTick;
     506        if (timeAfterTick > refreshStartTime + refreshTime)
     507        {
     508          GraphicsEngine::getSingleton().setAverageTickTime(
     509              (float)tickTime * 0.001 / (frameCount - oldFrameCount));
     510          float avgFPS = (float)(frameCount - oldFrameCount) / (timeAfterTick - refreshStartTime) * 1000000.0;
     511          GraphicsEngine::getSingleton().setAverageFramesPerSecond(avgFPS);
     512
     513          if (avgFPS > 60.0)
     514            sleepTime++;
     515          else
     516            sleepTime--;
     517          if (sleepTime < 0)
     518              sleepTime = 0;
     519
     520          oldFrameCount = frameCount;
     521          tickTime = 0;
     522          refreshStartTime = timeAfterTick;
     523        }
     524
     525        // do some sleeping when the frameRate is over 60
     526        if (sleepTime > 0)
     527          msleep(sleepTime);
     528
     529
     530        // don't forget to call _fireFrameStarted in ogre to make sure
     531        // everything goes smoothly
     532        Ogre::FrameEvent evt;
     533        evt.timeSinceLastFrame = dt;
     534        evt.timeSinceLastEvent = dt; // note: same time, but shouldn't matter anyway
     535        ogreRoot._fireFrameStarted(evt);
     536
     537        if (mode_.showsGraphics)
     538        {
     539          // Pump messages in all registered RenderWindows
     540          // This calls the WindowEventListener objects.
     541          Ogre::WindowEventUtilities::messagePump();
     542          // make sure the window stays active even when not focused
     543          // (probably only necessary on windows)
     544          GraphicsEngine::getSingleton().setWindowActivity(true);
     545
     546          // tick CEGUI
     547          GUIManager::getInstance().tick(dt);
     548
     549          // render
     550          ogreRoot._updateAllRenderTargets();
     551        }
     552
     553        // again, just to be sure ogre works fine
     554        ogreRoot._fireFrameEnded(evt); // note: uses the same time as _fireFrameStarted
     555
     556        ++frameCount;
     557    }
     558    }
     559    catch (std::exception& ex)
     560    {
     561      // something went wrong.
     562      COUT(1) << ex.what() << std::endl;
     563      COUT(1) << "Main loop was stopped by an unhandled exception. Shutting down." << std::endl;
     564    }
    532565  }
    533566}
Note: See TracChangeset for help on using the changeset viewer.