Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/resource/src/core/Core.cc @ 3356

Last change on this file since 3356 was 3356, checked in by rgrieder, 15 years ago

GameStates requiring graphics (Level is not one of them because it uses showsGraphics() to distinguish) are now only constructed when basic graphic support is given (GraphicsManager, InputManager and GUIManager loaded).

  • Property svn:eol-style set to native
File size: 26.0 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 *      Fabian 'x3n' Landau
24 *      Reto Grieder
25 *   Co-authors:
26 *      ...
27 *
28 */
29
30/**
31@file
32@brief
33    Implementation of the Core singleton with its global variables (avoids boost include)
34*/
35
36#include "Core.h"
37
38#include <cassert>
39#include <fstream>
40#include <cstdlib>
41#include <cstdio>
42#include <boost/filesystem.hpp>
43#include <OgreRenderWindow.h>
44
45#ifdef ORXONOX_PLATFORM_WINDOWS
46#  ifndef WIN32_LEAN_AND_MEAN
47#    define WIN32_LEAN_AND_MEAN
48#  endif
49#  include <windows.h>
50#  undef min
51#  undef max
52#elif defined(ORXONOX_PLATFORM_APPLE)
53#  include <sys/param.h>
54#  include <mach-o/dyld.h>
55#else /* Linux */
56#  include <sys/types.h>
57#  include <unistd.h>
58#endif
59
60#include "SpecialConfig.h"
61#include "util/Debug.h"
62#include "util/Exception.h"
63#include "util/SignalHandler.h"
64#include "Clock.h"
65#include "CommandExecutor.h"
66#include "CommandLine.h"
67#include "ConfigFileManager.h"
68#include "ConfigValueIncludes.h"
69#include "CoreIncludes.h"
70#include "Factory.h"
71#include "GameMode.h"
72#include "GraphicsManager.h"
73#include "GUIManager.h"
74#include "Identifier.h"
75#include "Language.h"
76#include "LuaBind.h"
77#include "Shell.h"
78#include "TclBind.h"
79#include "TclThreadManager.h"
80#include "input/InputManager.h"
81
82namespace orxonox
83{
84    //! Static pointer to the singleton
85    Core* Core::singletonRef_s  = 0;
86
87    SetCommandLineArgument(mediaPath, "").information("Path to the media/data files");
88    SetCommandLineOnlyArgument(writingPathSuffix, "").information("Additional subfolder for config and log files");
89    SetCommandLineArgument(settingsFile, "orxonox.ini").information("THE configuration file");
90#ifdef ORXONOX_PLATFORM_WINDOWS
91    SetCommandLineArgument(limitToCPU, 0).information("Limits the program to one cpu/core (1, 2, 3, etc.). 0 turns it off (default)");
92#endif
93
94    /**
95    @brief
96        Helper class for the Core singleton: we cannot derive
97        Core from OrxonoxClass because we need to handle the Identifier
98        destruction in the Core destructor.
99    */
100    class CoreConfiguration : public OrxonoxClass
101    {
102    public:
103        CoreConfiguration()
104        {
105        }
106
107        void initialise()
108        {
109            RegisterRootObject(CoreConfiguration);
110            this->setConfigValues();
111
112            // Possible media path override by the command line
113            if (!CommandLine::getArgument("mediaPath")->hasDefaultValue())
114                tsetMediaPath(CommandLine::getValue("mediaPath"));
115        }
116
117        /**
118            @brief Function to collect the SetConfigValue-macro calls.
119        */
120        void setConfigValues()
121        {
122#ifdef NDEBUG
123            const unsigned int defaultLevelConsole = 1;
124            const unsigned int defaultLevelLogfile = 3;
125            const unsigned int defaultLevelShell   = 1;
126#else
127            const unsigned int defaultLevelConsole = 3;
128            const unsigned int defaultLevelLogfile = 4;
129            const unsigned int defaultLevelShell   = 3;
130#endif
131            SetConfigValue(softDebugLevelConsole_, defaultLevelConsole)
132                .description("The maximal level of debug output shown in the console")
133                .callback(this, &CoreConfiguration::debugLevelChanged);
134            SetConfigValue(softDebugLevelLogfile_, defaultLevelLogfile)
135                .description("The maximal level of debug output shown in the logfile")
136                .callback(this, &CoreConfiguration::debugLevelChanged);
137            SetConfigValue(softDebugLevelShell_, defaultLevelShell)
138                .description("The maximal level of debug output shown in the ingame shell")
139                .callback(this, &CoreConfiguration::debugLevelChanged);
140
141            SetConfigValue(language_, Language::getLanguage().defaultLanguage_)
142                .description("The language of the ingame text")
143                .callback(this, &CoreConfiguration::languageChanged);
144            SetConfigValue(bInitializeRandomNumberGenerator_, true)
145                .description("If true, all random actions are different each time you start the game")
146                .callback(this, &CoreConfiguration::initializeRandomNumberGenerator);
147
148            // Only show this config value for development builds
149            if (Core::isDevelopmentRun())
150            {
151                SetConfigValue(mediaPathString_, mediaPath_.string())
152                    .description("Relative path to the game data.")
153                    .callback(this, &CoreConfiguration::mediaPathChanged);
154            }
155        }
156
157        /**
158            @brief Callback function if the debug level has changed.
159        */
160        void debugLevelChanged()
161        {
162            // softDebugLevel_ is the maximum of the 3 variables
163            this->softDebugLevel_ = this->softDebugLevelConsole_;
164            if (this->softDebugLevelLogfile_ > this->softDebugLevel_)
165                this->softDebugLevel_ = this->softDebugLevelLogfile_;
166            if (this->softDebugLevelShell_ > this->softDebugLevel_)
167                this->softDebugLevel_ = this->softDebugLevelShell_;
168
169            OutputHandler::setSoftDebugLevel(OutputHandler::LD_All,     this->softDebugLevel_);
170            OutputHandler::setSoftDebugLevel(OutputHandler::LD_Console, this->softDebugLevelConsole_);
171            OutputHandler::setSoftDebugLevel(OutputHandler::LD_Logfile, this->softDebugLevelLogfile_);
172            OutputHandler::setSoftDebugLevel(OutputHandler::LD_Shell,   this->softDebugLevelShell_);
173        }
174
175        /**
176            @brief Callback function if the language has changed.
177        */
178        void languageChanged()
179        {
180            // Read the translation file after the language was configured
181            Language::getLanguage().readTranslatedLanguageFile();
182        }
183
184        /**
185        @brief
186            Callback function if the media path has changed.
187        */
188        void mediaPathChanged()
189        {
190            mediaPath_ = boost::filesystem::path(this->mediaPathString_);
191        }
192
193        /**
194            @brief Sets the language in the config-file back to the default.
195        */
196        void resetLanguage()
197        {
198            ResetConfigValue(language_);
199        }
200
201        /**
202        @brief
203            Temporary sets the media path
204        @param path
205            The new media path
206        */
207        void tsetMediaPath(const std::string& path)
208        {
209            if (Core::isDevelopmentRun())
210            {
211                ModifyConfigValue(mediaPathString_, tset, path);
212            }
213            else
214            {
215                // Manual 'config' value without the file entry
216                mediaPathString_ = path;
217                this->mediaPathChanged();
218            }
219        }
220
221        void initializeRandomNumberGenerator()
222        {
223            static bool bInitialized = false;
224            if (!bInitialized && this->bInitializeRandomNumberGenerator_)
225            {
226                srand(static_cast<unsigned int>(time(0)));
227                rand();
228                bInitialized = true;
229            }
230        }
231
232        int softDebugLevel_;                            //!< The debug level
233        int softDebugLevelConsole_;                     //!< The debug level for the console
234        int softDebugLevelLogfile_;                     //!< The debug level for the logfile
235        int softDebugLevelShell_;                       //!< The debug level for the ingame shell
236        std::string language_;                          //!< The language
237        bool bInitializeRandomNumberGenerator_;         //!< If true, srand(time(0)) is called
238        std::string mediaPathString_;                   //!< Path to the data/media file folder as string
239
240        //! Path to the parent directory of the ones above if program was installed with relativ pahts
241        boost::filesystem::path rootPath_;
242        boost::filesystem::path executablePath_;        //!< Path to the executable
243        boost::filesystem::path mediaPath_;             //!< Path to the media file folder
244        boost::filesystem::path configPath_;            //!< Path to the config file folder
245        boost::filesystem::path logPath_;               //!< Path to the log file folder
246    };
247
248
249    Core::Core(const std::string& cmdLine)
250        : bDevRun_(false)
251        , bGraphicsLoaded_(false)
252    {
253        if (singletonRef_s != 0)
254        {
255            COUT(0) << "Error: The Core singleton cannot be recreated! Shutting down." << std::endl;
256            abort();
257        }
258        Core::singletonRef_s = this;
259
260        // We need the variables very soon. But don't configure them yet!
261        this->configuration_ = new CoreConfiguration();
262
263        // Parse command line arguments first
264        CommandLine::parseCommandLine(cmdLine);
265
266        // Determine and set the location of the executable
267        setExecutablePath();
268
269        // Determine whether we have an installed or a binary dir run
270        // The latter occurs when simply running from the build directory
271        checkDevBuild();
272
273        // Make sure the directories we write in exist or else make them
274        createDirectories();
275
276        // create a signal handler (only active for linux)
277        // This call is placed as soon as possible, but after the directories are set
278        this->signalHandler_ = new SignalHandler();
279        this->signalHandler_->doCatch(configuration_->executablePath_.string(), Core::getLogPathString() + "orxonox_crash.log");
280
281        // Set the correct log path. Before this call, /tmp (Unix) or %TEMP% was used
282        OutputHandler::getOutStream().setLogPath(Core::getLogPathString());
283
284        // Parse additional options file now that we know its path
285        CommandLine::parseFile();
286
287#ifdef ORXONOX_PLATFORM_WINDOWS
288        // limit the main thread to the first core so that QueryPerformanceCounter doesn't jump
289        // do this after ogre has initialised. Somehow Ogre changes the settings again (not through
290        // the timer though).
291        int limitToCPU = CommandLine::getValue("limitToCPU");
292        if (limitToCPU > 0)
293            setThreadAffinity(static_cast<unsigned int>(limitToCPU));
294#endif
295
296        // Manage ini files and set the default settings file (usually orxonox.ini)
297        this->configFileManager_ = new ConfigFileManager();
298        this->configFileManager_->setFilename(ConfigFileType::Settings,
299            CommandLine::getValue("settingsFile").getString());
300
301        // Required as well for the config values
302        this->languageInstance_ = new Language();
303
304        // Do this soon after the ConfigFileManager has been created to open up the
305        // possibility to configure everything below here
306        this->configuration_->initialise();
307
308        // Create the lua interface
309        this->luaBind_ = new LuaBind();
310
311        // initialise Tcl
312        this->tclBind_ = new TclBind(Core::getMediaPathString());
313        this->tclThreadManager_ = new TclThreadManager(tclBind_->getTclInterpreter());
314
315        // create a shell
316        this->shell_ = new Shell();
317
318        // creates the class hierarchy for all classes with factories
319        Factory::createClassHierarchy();
320    }
321
322    /**
323        @brief Sets the bool to true to avoid static functions accessing a deleted object.
324    */
325    Core::~Core()
326    {
327        delete this->shell_;
328        delete this->tclThreadManager_;
329        delete this->tclBind_;
330        delete this->luaBind_;
331        delete this->configuration_;
332        delete this->languageInstance_;
333        delete this->configFileManager_;
334
335        // Destroy command line arguments
336        CommandLine::destroyAllArguments();
337        // Also delete external console commands that don't belong to an Identifier
338        CommandExecutor::destroyExternalCommands();
339        // Clean up class hierarchy stuff (identifiers, XMLPort, configValues, consoleCommand)
340        Identifier::destroyAllIdentifiers();
341
342        delete this->signalHandler_;
343
344        // Don't assign singletonRef_s with NULL! Recreation is not supported
345    }
346
347    void Core::loadGraphics()
348    {
349        if (bGraphicsLoaded_)
350            return;
351
352        // Load OGRE including the render window
353        this->graphicsManager_ = new GraphicsManager();
354
355        // The render window width and height are used to set up the mouse movement.
356        size_t windowHnd = 0;
357        Ogre::RenderWindow* renderWindow = GraphicsManager::getInstance().getRenderWindow();
358        renderWindow->getCustomAttribute("WINDOW", &windowHnd);
359
360        // Calls the InputManager which sets up the input devices.
361        inputManager_ = new InputManager(windowHnd);
362
363        // load the CEGUI interface
364        guiManager_ = new GUIManager(renderWindow);
365
366        bGraphicsLoaded_ = true;
367    }
368
369    void Core::unloadGraphics()
370    {
371        if (!bGraphicsLoaded_)
372            return;
373
374        delete this->guiManager_;
375        delete this->inputManager_;
376        delete graphicsManager_;
377
378        bGraphicsLoaded_ = false;
379    }
380
381    /**
382        @brief Returns the softDebugLevel for the given device (returns a default-value if the class is right about to be created).
383        @param device The device
384        @return The softDebugLevel
385    */
386    /*static*/ int Core::getSoftDebugLevel(OutputHandler::OutputDevice device)
387    {
388        switch (device)
389        {
390        case OutputHandler::LD_All:
391            return Core::getInstance().configuration_->softDebugLevel_;
392        case OutputHandler::LD_Console:
393            return Core::getInstance().configuration_->softDebugLevelConsole_;
394        case OutputHandler::LD_Logfile:
395            return Core::getInstance().configuration_->softDebugLevelLogfile_;
396        case OutputHandler::LD_Shell:
397            return Core::getInstance().configuration_->softDebugLevelShell_;
398        default:
399            assert(0);
400            return 2;
401        }
402    }
403
404     /**
405        @brief Sets the softDebugLevel for the given device. Please use this only temporary and restore the value afterwards, as it overrides the configured value.
406        @param device The device
407        @param level The level
408    */
409    /*static*/ void Core::setSoftDebugLevel(OutputHandler::OutputDevice device, int level)
410    {
411        if (device == OutputHandler::LD_All)
412            Core::getInstance().configuration_->softDebugLevel_ = level;
413        else if (device == OutputHandler::LD_Console)
414            Core::getInstance().configuration_->softDebugLevelConsole_ = level;
415        else if (device == OutputHandler::LD_Logfile)
416            Core::getInstance().configuration_->softDebugLevelLogfile_ = level;
417        else if (device == OutputHandler::LD_Shell)
418            Core::getInstance().configuration_->softDebugLevelShell_ = level;
419
420        OutputHandler::setSoftDebugLevel(device, level);
421    }
422
423    /**
424        @brief Returns the configured language.
425    */
426    /*static*/ const std::string& Core::getLanguage()
427    {
428        return Core::getInstance().configuration_->language_;
429    }
430
431    /**
432        @brief Sets the language in the config-file back to the default.
433    */
434    /*static*/ void Core::resetLanguage()
435    {
436        Core::getInstance().configuration_->resetLanguage();
437    }
438
439    /*static*/ void Core::tsetMediaPath(const std::string& path)
440    {
441        getInstance().configuration_->tsetMediaPath(path);
442    }
443
444    /*static*/ const boost::filesystem::path& Core::getMediaPath()
445    {
446        return getInstance().configuration_->mediaPath_;
447    }
448    /*static*/ std::string Core::getMediaPathString()
449    {
450        return getInstance().configuration_->mediaPath_.string() + '/';
451    }
452
453    /*static*/ const boost::filesystem::path& Core::getConfigPath()
454    {
455        return getInstance().configuration_->configPath_;
456    }
457    /*static*/ std::string Core::getConfigPathString()
458    {
459        return getInstance().configuration_->configPath_.string() + '/';
460    }
461
462    /*static*/ const boost::filesystem::path& Core::getLogPath()
463    {
464        return getInstance().configuration_->logPath_;
465    }
466    /*static*/ std::string Core::getLogPathString()
467    {
468        return getInstance().configuration_->logPath_.string() + '/';
469    }
470
471    /*static*/ const boost::filesystem::path& Core::getRootPath()
472    {
473        return getInstance().configuration_->rootPath_;
474    }
475    /*static*/ std::string Core::getRootPathString()
476    {
477        return getInstance().configuration_->rootPath_.string() + '/';
478    }
479
480    /**
481    @note
482        The code of this function has been copied and adjusted from OGRE, an open source graphics engine.
483            (Object-oriented Graphics Rendering Engine)
484        For the latest info, see http://www.ogre3d.org/
485
486        Copyright (c) 2000-2008 Torus Knot Software Ltd
487
488        OGRE is licensed under the LGPL. For more info, see OGRE license.
489    */
490    void Core::setThreadAffinity(int limitToCPU)
491    {
492#ifdef ORXONOX_PLATFORM_WINDOWS
493
494        if (limitToCPU <= 0)
495            return;
496
497        unsigned int coreNr = limitToCPU - 1;
498        // Get the current process core mask
499        DWORD procMask;
500        DWORD sysMask;
501#  if _MSC_VER >= 1400 && defined (_M_X64)
502        GetProcessAffinityMask(GetCurrentProcess(), (PDWORD_PTR)&procMask, (PDWORD_PTR)&sysMask);
503#  else
504        GetProcessAffinityMask(GetCurrentProcess(), &procMask, &sysMask);
505#  endif
506
507        // If procMask is 0, consider there is only one core available
508        // (using 0 as procMask will cause an infinite loop below)
509        if (procMask == 0)
510            procMask = 1;
511
512        // if the core specified with coreNr is not available, take the lowest one
513        if (!(procMask & (1 << coreNr)))
514            coreNr = 0;
515
516        // Find the lowest core that this process uses and coreNr suggests
517        DWORD threadMask = 1;
518        while ((threadMask & procMask) == 0 || (threadMask < (1u << coreNr)))
519            threadMask <<= 1;
520
521        // Set affinity to the first core
522        SetThreadAffinityMask(GetCurrentThread(), threadMask);
523#endif
524    }
525
526    /**
527    @brief
528        Compares the executable path with the working directory
529    */
530    void Core::setExecutablePath()
531    {
532#ifdef ORXONOX_PLATFORM_WINDOWS
533        // get executable module
534        TCHAR buffer[1024];
535        if (GetModuleFileName(NULL, buffer, 1024) == 0)
536            ThrowException(General, "Could not retrieve executable path.");
537
538#elif defined(ORXONOX_PLATFORM_APPLE)
539        char buffer[1024];
540        unsigned long path_len = 1023;
541        if (_NSGetExecutablePath(buffer, &path_len))
542            ThrowException(General, "Could not retrieve executable path.");
543
544#else /* Linux */
545        /* written by Nicolai Haehnle <prefect_@gmx.net> */
546
547        /* Get our PID and build the name of the link in /proc */
548        char linkname[64]; /* /proc/<pid>/exe */
549        if (snprintf(linkname, sizeof(linkname), "/proc/%i/exe", getpid()) < 0)
550        {
551            /* This should only happen on large word systems. I'm not sure
552               what the proper response is here.
553               Since it really is an assert-like condition, aborting the
554               program seems to be in order. */
555            assert(false);
556        }
557
558        /* Now read the symbolic link */
559        char buffer[1024];
560        int ret;
561        ret = readlink(linkname, buffer, 1024);
562        /* In case of an error, leave the handling up to the caller */
563        if (ret == -1)
564            ThrowException(General, "Could not retrieve executable path.");
565
566        /* Ensure proper NUL termination */
567        buffer[ret] = 0;
568#endif
569
570        configuration_->executablePath_ = boost::filesystem::path(buffer);
571#ifndef ORXONOX_PLATFORM_APPLE
572        configuration_->executablePath_ = configuration_->executablePath_.branch_path(); // remove executable name
573#endif
574    }
575
576    /**
577    @brief
578        Checks for "orxonox_dev_build.keep_me" in the executable diretory.
579        If found it means that this is not an installed run, hence we
580        don't write the logs and config files to ~/.orxonox
581    @throws
582        GeneralException
583    */
584    void Core::checkDevBuild()
585    {
586        if (boost::filesystem::exists(configuration_->executablePath_ / "orxonox_dev_build.keep_me"))
587        {
588            COUT(1) << "Running from the build tree." << std::endl;
589            Core::bDevRun_ = true;
590            configuration_->mediaPath_  = ORXONOX_MEDIA_DEV_PATH;
591            configuration_->configPath_ = ORXONOX_CONFIG_DEV_PATH;
592            configuration_->logPath_    = ORXONOX_LOG_DEV_PATH;
593        }
594        else
595        {
596#ifdef INSTALL_COPYABLE // --> relative paths
597            // Also set the root path
598            boost::filesystem::path relativeExecutablePath(ORXONOX_RUNTIME_INSTALL_PATH);
599            configuration_->rootPath_ = configuration_->executablePath_;
600            while (!boost::filesystem::equivalent(configuration_->rootPath_ / relativeExecutablePath, configuration_->executablePath_)
601                   && !configuration_->rootPath_.empty())
602                configuration_->rootPath_ = configuration_->rootPath_.branch_path();
603            if (configuration_->rootPath_.empty())
604                ThrowException(General, "Could not derive a root directory. Might the binary installation directory contain '..' when taken relative to the installation prefix path?");
605
606            // Using paths relative to the install prefix, complete them
607            configuration_->mediaPath_  = configuration_->rootPath_ / ORXONOX_MEDIA_INSTALL_PATH;
608            configuration_->configPath_ = configuration_->rootPath_ / ORXONOX_CONFIG_INSTALL_PATH;
609            configuration_->logPath_    = configuration_->rootPath_ / ORXONOX_LOG_INSTALL_PATH;
610#else
611            // There is no root path, so don't set it at all
612
613            configuration_->mediaPath_  = ORXONOX_MEDIA_INSTALL_PATH;
614
615            // Get user directory
616#  ifdef ORXONOX_PLATFORM_UNIX /* Apple? */
617            char* userDataPathPtr(getenv("HOME"));
618#  else
619            char* userDataPathPtr(getenv("APPDATA"));
620#  endif
621            if (userDataPathPtr == NULL)
622                ThrowException(General, "Could not retrieve user data path.");
623            boost::filesystem::path userDataPath(userDataPathPtr);
624            userDataPath /= ".orxonox";
625
626            configuration_->configPath_ = userDataPath / ORXONOX_CONFIG_INSTALL_PATH;
627            configuration_->logPath_    = userDataPath / ORXONOX_LOG_INSTALL_PATH;
628#endif
629        }
630
631        // Option to put all the config and log files in a separate folder
632        if (!CommandLine::getArgument("writingPathSuffix")->hasDefaultValue())
633        {
634            std::string directory(CommandLine::getValue("writingPathSuffix").getString());
635            configuration_->configPath_ = configuration_->configPath_ / directory;
636            configuration_->logPath_    = configuration_->logPath_    / directory;
637        }
638    }
639
640    /*
641    @brief
642        Checks for the log and the config directory and creates them
643        if necessary. Otherwise me might have problems opening those files.
644    @throws
645        orxonox::GeneralException if the directory to be created is a file.
646    */
647    void Core::createDirectories()
648    {
649        std::vector<std::pair<boost::filesystem::path, std::string> > directories;
650        directories.push_back(std::make_pair(boost::filesystem::path(configuration_->configPath_), "config"));
651        directories.push_back(std::make_pair(boost::filesystem::path(configuration_->logPath_), "log"));
652
653        for (std::vector<std::pair<boost::filesystem::path, std::string> >::iterator it = directories.begin();
654            it != directories.end(); ++it)
655        {
656            if (boost::filesystem::exists(it->first) && !boost::filesystem::is_directory(it->first))
657            {
658                ThrowException(General, std::string("The ") + it->second + " directory has been preoccupied by a file! \
659                                         Please remove " + it->first.string());
660            }
661            if (boost::filesystem::create_directories(it->first)) // function may not return true at all (bug?)
662            {
663                COUT(4) << "Created " << it->second << " directory" << std::endl;
664            }
665        }
666    }
667
668    bool Core::preUpdate(const Clock& time) throw()
669    {
670        std::string exceptionMessage;
671        try
672        {
673            if (this->bGraphicsLoaded_)
674            {
675                // process input events
676                this->inputManager_->update(time);
677                // process gui events
678                this->guiManager_->update(time);
679            }
680            // process thread commands
681            this->tclThreadManager_->update(time);
682        }
683        catch (const std::exception& ex)
684        { exceptionMessage = ex.what(); }
685        catch (...)
686        { exceptionMessage = "Unknown exception"; }
687        if (!exceptionMessage.empty())
688        {
689            COUT(0) << "An exception occurred in the Core preUpdate: " << exceptionMessage << std::endl;
690            COUT(0) << "This should really never happen! Closing the program." << std::endl;
691            return false;
692        }
693        return true;
694    }
695
696    bool Core::postUpdate(const Clock& time) throw()
697    {
698        std::string exceptionMessage;
699        try
700        {
701            if (this->bGraphicsLoaded_)
702            {
703                // Render (doesn't throw)
704                this->graphicsManager_->update(time);
705            }
706        }
707        catch (const std::exception& ex)
708        { exceptionMessage = ex.what(); }
709        catch (...)
710        { exceptionMessage = "Unknown exception"; }
711        if (!exceptionMessage.empty())
712        {
713            COUT(0) << "An exception occurred in the Core postUpdate: " << exceptionMessage << std::endl;
714            COUT(0) << "This should really never happen! Closing the program." << std::endl;
715            return false;
716        }
717        return true;
718    }
719}
Note: See TracBrowser for help on using the repository browser.