Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/resource2/src/core/Core.cc @ 5641

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

Prepared build system for an external media directory.
This revision only runs in console mode! (tcl files working again)

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