Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/resource3/src/core/Core.cc @ 5677

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

Merged most of revision 5614 and its fixes from revisions 5628, 5658, 5662 and 5670:

  • Creating Ogre::Root in non graphics mode as well. This allows to always make use of the ResourceGroupManager.
  • Switched to smart pointers for the destruction code in GraphicsManager
  • Property svn:eol-style set to native
File size: 26.1 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(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::getInstance().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::getInstance().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        // Cleanup guard for identifier destruction (incl. XMLPort, configValues, consoleCommands)
251        : identifierDestroyer_(Identifier::destroyAllIdentifiers)
252        // Cleanup guard for external console commands that don't belong to an Identifier
253        , consoleCommandDestroyer_(CommandExecutor::destroyExternalCommands)
254        , configuration_(new CoreConfiguration()) // Don't yet create config values!
255        , bDevRun_(false)
256        , bGraphicsLoaded_(false)
257    {
258        // Parse command line arguments first
259        CommandLine::parseCommandLine(cmdLine);
260
261        // Determine and set the location of the executable
262        setExecutablePath();
263
264        // Determine whether we have an installed or a binary dir run
265        // The latter occurs when simply running from the build directory
266        checkDevBuild();
267
268        // Make sure the directories we write in exist or else make them
269        createDirectories();
270
271        // create a signal handler (only active for linux)
272        // This call is placed as soon as possible, but after the directories are set
273        this->signalHandler_.reset(new SignalHandler());
274        this->signalHandler_->doCatch(configuration_->executablePath_.string(), Core::getLogPathString() + "orxonox_crash.log");
275
276        // Set the correct log path. Before this call, /tmp (Unix) or %TEMP% was used
277        OutputHandler::getOutStream().setLogPath(Core::getLogPathString());
278
279        // Parse additional options file now that we know its path
280        CommandLine::parseFile();
281
282#ifdef ORXONOX_PLATFORM_WINDOWS
283        // limit the main thread to the first core so that QueryPerformanceCounter doesn't jump
284        // do this after ogre has initialised. Somehow Ogre changes the settings again (not through
285        // the timer though).
286        int limitToCPU = CommandLine::getValue("limitToCPU");
287        if (limitToCPU > 0)
288            setThreadAffinity(static_cast<unsigned int>(limitToCPU));
289#endif
290
291        // Manage ini files and set the default settings file (usually orxonox.ini)
292        this->configFileManager_.reset(new ConfigFileManager());
293        this->configFileManager_->setFilename(ConfigFileType::Settings,
294            CommandLine::getValue("settingsFile").getString());
295
296        // Required as well for the config values
297        this->languageInstance_.reset(new Language());
298
299        // Do this soon after the ConfigFileManager has been created to open up the
300        // possibility to configure everything below here
301        this->configuration_->initialise();
302
303        // Create the lua interface
304        this->luaBind_.reset(new LuaBind());
305
306        // initialise Tcl
307        this->tclBind_.reset(new TclBind(Core::getMediaPathString()));
308        this->tclThreadManager_.reset(new TclThreadManager(tclBind_->getTclInterpreter()));
309
310        // create a shell
311        this->shell_.reset(new Shell());
312
313        // creates the class hierarchy for all classes with factories
314        Factory::createClassHierarchy();
315
316        // Load OGRE excluding the renderer and the render window
317        this->graphicsManager_.reset(new GraphicsManager(false));
318    }
319
320    /**
321    @brief
322        All destruction code is handled by scoped_ptrs and SimpleScopeGuards.
323    */
324    Core::~Core()
325    {
326    }
327
328    void Core::loadGraphics()
329    {
330        // Any exception should trigger this, even in upgradeToGraphics (see its remarks)
331        Loki::ScopeGuard unloader = Loki::MakeObjGuard(*this, &Core::unloadGraphics);
332
333        // Upgrade OGRE to receive a render window
334        graphicsManager_->upgradeToGraphics();
335
336        // The render window width and height are used to set up the mouse movement.
337        size_t windowHnd = 0;
338        graphicsManager_->getRenderWindow()->getCustomAttribute("WINDOW", &windowHnd);
339
340        // Calls the InputManager which sets up the input devices.
341        inputManager_.reset(new InputManager(windowHnd));
342
343        // load the CEGUI interface
344        guiManager_.reset(new GUIManager(graphicsManager_->getRenderWindow()));
345
346        unloader.Dismiss();
347
348        bGraphicsLoaded_ = true;
349    }
350
351    void Core::unloadGraphics()
352    {
353        this->guiManager_.reset();;
354        this->inputManager_.reset();;
355        this->graphicsManager_.reset();
356
357        // Load Ogre::Root again, but without the render system
358        try
359            { this->graphicsManager_.reset(new GraphicsManager(false)); }
360        catch (...)
361        {
362            COUT(0) << "An exception occurred during 'new GraphicsManager' while "
363                    << "another exception was being handled. This will lead to undefined behaviour!" << std::endl
364                    << "Terminating the program." << std::endl;
365            abort();
366        }
367
368        bGraphicsLoaded_ = false;
369    }
370
371    /**
372        @brief Returns the softDebugLevel for the given device (returns a default-value if the class is right about to be created).
373        @param device The device
374        @return The softDebugLevel
375    */
376    /*static*/ int Core::getSoftDebugLevel(OutputHandler::OutputDevice device)
377    {
378        switch (device)
379        {
380        case OutputHandler::LD_All:
381            return Core::getInstance().configuration_->softDebugLevel_;
382        case OutputHandler::LD_Console:
383            return Core::getInstance().configuration_->softDebugLevelConsole_;
384        case OutputHandler::LD_Logfile:
385            return Core::getInstance().configuration_->softDebugLevelLogfile_;
386        case OutputHandler::LD_Shell:
387            return Core::getInstance().configuration_->softDebugLevelShell_;
388        default:
389            assert(0);
390            return 2;
391        }
392    }
393
394     /**
395        @brief Sets the softDebugLevel for the given device. Please use this only temporary and restore the value afterwards, as it overrides the configured value.
396        @param device The device
397        @param level The level
398    */
399    /*static*/ void Core::setSoftDebugLevel(OutputHandler::OutputDevice device, int level)
400    {
401        if (device == OutputHandler::LD_All)
402            Core::getInstance().configuration_->softDebugLevel_ = level;
403        else if (device == OutputHandler::LD_Console)
404            Core::getInstance().configuration_->softDebugLevelConsole_ = level;
405        else if (device == OutputHandler::LD_Logfile)
406            Core::getInstance().configuration_->softDebugLevelLogfile_ = level;
407        else if (device == OutputHandler::LD_Shell)
408            Core::getInstance().configuration_->softDebugLevelShell_ = level;
409
410        OutputHandler::setSoftDebugLevel(device, level);
411    }
412
413    /**
414        @brief Returns the configured language.
415    */
416    /*static*/ const std::string& Core::getLanguage()
417    {
418        return Core::getInstance().configuration_->language_;
419    }
420
421    /**
422        @brief Sets the language in the config-file back to the default.
423    */
424    /*static*/ void Core::resetLanguage()
425    {
426        Core::getInstance().configuration_->resetLanguage();
427    }
428
429    /*static*/ void Core::tsetMediaPath(const std::string& path)
430    {
431        getInstance().configuration_->tsetMediaPath(path);
432    }
433
434    /*static*/ const boost::filesystem::path& Core::getMediaPath()
435    {
436        return getInstance().configuration_->mediaPath_;
437    }
438    /*static*/ std::string Core::getMediaPathString()
439    {
440        return getInstance().configuration_->mediaPath_.string() + '/';
441    }
442
443    /*static*/ const boost::filesystem::path& Core::getConfigPath()
444    {
445        return getInstance().configuration_->configPath_;
446    }
447    /*static*/ std::string Core::getConfigPathString()
448    {
449        return getInstance().configuration_->configPath_.string() + '/';
450    }
451
452    /*static*/ const boost::filesystem::path& Core::getLogPath()
453    {
454        return getInstance().configuration_->logPath_;
455    }
456    /*static*/ std::string Core::getLogPathString()
457    {
458        return getInstance().configuration_->logPath_.string() + '/';
459    }
460
461    /*static*/ const boost::filesystem::path& Core::getRootPath()
462    {
463        return getInstance().configuration_->rootPath_;
464    }
465    /*static*/ std::string Core::getRootPathString()
466    {
467        return getInstance().configuration_->rootPath_.string() + '/';
468    }
469
470    /**
471    @note
472        The code of this function has been copied and adjusted from OGRE, an open source graphics engine.
473            (Object-oriented Graphics Rendering Engine)
474        For the latest info, see http://www.ogre3d.org/
475
476        Copyright (c) 2000-2008 Torus Knot Software Ltd
477
478        OGRE is licensed under the LGPL. For more info, see OGRE license.
479    */
480    void Core::setThreadAffinity(int limitToCPU)
481    {
482#ifdef ORXONOX_PLATFORM_WINDOWS
483
484        if (limitToCPU <= 0)
485            return;
486
487        unsigned int coreNr = limitToCPU - 1;
488        // Get the current process core mask
489        DWORD procMask;
490        DWORD sysMask;
491#  if _MSC_VER >= 1400 && defined (_M_X64)
492        GetProcessAffinityMask(GetCurrentProcess(), (PDWORD_PTR)&procMask, (PDWORD_PTR)&sysMask);
493#  else
494        GetProcessAffinityMask(GetCurrentProcess(), &procMask, &sysMask);
495#  endif
496
497        // If procMask is 0, consider there is only one core available
498        // (using 0 as procMask will cause an infinite loop below)
499        if (procMask == 0)
500            procMask = 1;
501
502        // if the core specified with coreNr is not available, take the lowest one
503        if (!(procMask & (1 << coreNr)))
504            coreNr = 0;
505
506        // Find the lowest core that this process uses and coreNr suggests
507        DWORD threadMask = 1;
508        while ((threadMask & procMask) == 0 || (threadMask < (1u << coreNr)))
509            threadMask <<= 1;
510
511        // Set affinity to the first core
512        SetThreadAffinityMask(GetCurrentThread(), threadMask);
513#endif
514    }
515
516    /**
517    @brief
518        Compares the executable path with the working directory
519    */
520    void Core::setExecutablePath()
521    {
522#ifdef ORXONOX_PLATFORM_WINDOWS
523        // get executable module
524        TCHAR buffer[1024];
525        if (GetModuleFileName(NULL, buffer, 1024) == 0)
526            ThrowException(General, "Could not retrieve executable path.");
527
528#elif defined(ORXONOX_PLATFORM_APPLE)
529        char buffer[1024];
530        unsigned long path_len = 1023;
531        if (_NSGetExecutablePath(buffer, &path_len))
532            ThrowException(General, "Could not retrieve executable path.");
533
534#else /* Linux */
535        /* written by Nicolai Haehnle <prefect_@gmx.net> */
536
537        /* Get our PID and build the name of the link in /proc */
538        char linkname[64]; /* /proc/<pid>/exe */
539        if (snprintf(linkname, sizeof(linkname), "/proc/%i/exe", getpid()) < 0)
540        {
541            /* This should only happen on large word systems. I'm not sure
542               what the proper response is here.
543               Since it really is an assert-like condition, aborting the
544               program seems to be in order. */
545            assert(false);
546        }
547
548        /* Now read the symbolic link */
549        char buffer[1024];
550        int ret;
551        ret = readlink(linkname, buffer, 1024);
552        /* In case of an error, leave the handling up to the caller */
553        if (ret == -1)
554            ThrowException(General, "Could not retrieve executable path.");
555
556        /* Ensure proper NUL termination */
557        buffer[ret] = 0;
558#endif
559
560        configuration_->executablePath_ = boost::filesystem::path(buffer);
561#ifndef ORXONOX_PLATFORM_APPLE
562        configuration_->executablePath_ = configuration_->executablePath_.branch_path(); // remove executable name
563#endif
564    }
565
566    /**
567    @brief
568        Checks for "orxonox_dev_build.keep_me" in the executable diretory.
569        If found it means that this is not an installed run, hence we
570        don't write the logs and config files to ~/.orxonox
571    @throws
572        GeneralException
573    */
574    void Core::checkDevBuild()
575    {
576        if (boost::filesystem::exists(configuration_->executablePath_ / "orxonox_dev_build.keep_me"))
577        {
578            COUT(1) << "Running from the build tree." << std::endl;
579            Core::bDevRun_ = true;
580            configuration_->mediaPath_  = ORXONOX_MEDIA_DEV_PATH;
581            configuration_->configPath_ = ORXONOX_CONFIG_DEV_PATH;
582            configuration_->logPath_    = ORXONOX_LOG_DEV_PATH;
583        }
584        else
585        {
586#ifdef INSTALL_COPYABLE // --> relative paths
587            // Also set the root path
588            boost::filesystem::path relativeExecutablePath(ORXONOX_RUNTIME_INSTALL_PATH);
589            configuration_->rootPath_ = configuration_->executablePath_;
590            while (!boost::filesystem::equivalent(configuration_->rootPath_ / relativeExecutablePath, configuration_->executablePath_)
591                   && !configuration_->rootPath_.empty())
592                configuration_->rootPath_ = configuration_->rootPath_.branch_path();
593            if (configuration_->rootPath_.empty())
594                ThrowException(General, "Could not derive a root directory. Might the binary installation directory contain '..' when taken relative to the installation prefix path?");
595
596            // Using paths relative to the install prefix, complete them
597            configuration_->mediaPath_  = configuration_->rootPath_ / ORXONOX_MEDIA_INSTALL_PATH;
598            configuration_->configPath_ = configuration_->rootPath_ / ORXONOX_CONFIG_INSTALL_PATH;
599            configuration_->logPath_    = configuration_->rootPath_ / ORXONOX_LOG_INSTALL_PATH;
600#else
601            // There is no root path, so don't set it at all
602
603            configuration_->mediaPath_  = ORXONOX_MEDIA_INSTALL_PATH;
604
605            // Get user directory
606#  ifdef ORXONOX_PLATFORM_UNIX /* Apple? */
607            char* userDataPathPtr(getenv("HOME"));
608#  else
609            char* userDataPathPtr(getenv("APPDATA"));
610#  endif
611            if (userDataPathPtr == NULL)
612                ThrowException(General, "Could not retrieve user data path.");
613            boost::filesystem::path userDataPath(userDataPathPtr);
614            userDataPath /= ".orxonox";
615
616            configuration_->configPath_ = userDataPath / ORXONOX_CONFIG_INSTALL_PATH;
617            configuration_->logPath_    = userDataPath / ORXONOX_LOG_INSTALL_PATH;
618#endif
619        }
620
621        // Option to put all the config and log files in a separate folder
622        if (!CommandLine::getArgument("writingPathSuffix")->hasDefaultValue())
623        {
624            std::string directory(CommandLine::getValue("writingPathSuffix").getString());
625            configuration_->configPath_ = configuration_->configPath_ / directory;
626            configuration_->logPath_    = configuration_->logPath_    / directory;
627        }
628    }
629
630    /*
631    @brief
632        Checks for the log and the config directory and creates them
633        if necessary. Otherwise me might have problems opening those files.
634    @throws
635        orxonox::GeneralException if the directory to be created is a file.
636    */
637    void Core::createDirectories()
638    {
639        std::vector<std::pair<boost::filesystem::path, std::string> > directories;
640        directories.push_back(std::make_pair(boost::filesystem::path(configuration_->configPath_), "config"));
641        directories.push_back(std::make_pair(boost::filesystem::path(configuration_->logPath_), "log"));
642
643        for (std::vector<std::pair<boost::filesystem::path, std::string> >::iterator it = directories.begin();
644            it != directories.end(); ++it)
645        {
646            if (boost::filesystem::exists(it->first) && !boost::filesystem::is_directory(it->first))
647            {
648                ThrowException(General, std::string("The ") + it->second + " directory has been preoccupied by a file! \
649                                         Please remove " + it->first.string());
650            }
651            if (boost::filesystem::create_directories(it->first)) // function may not return true at all (bug?)
652            {
653                COUT(4) << "Created " << it->second << " directory" << std::endl;
654            }
655        }
656    }
657
658    bool Core::preUpdate(const Clock& time) throw()
659    {
660        std::string exceptionMessage;
661        try
662        {
663            if (this->bGraphicsLoaded_)
664            {
665                // process input events
666                this->inputManager_->update(time);
667                // process gui events
668                this->guiManager_->update(time);
669            }
670            // process thread commands
671            this->tclThreadManager_->update(time);
672        }
673        catch (const std::exception& ex)
674        { exceptionMessage = ex.what(); }
675        catch (...)
676        { exceptionMessage = "Unknown exception"; }
677        if (!exceptionMessage.empty())
678        {
679            COUT(0) << "An exception occurred in the Core preUpdate: " << exceptionMessage << std::endl;
680            COUT(0) << "This should really never happen! Closing the program." << std::endl;
681            return false;
682        }
683        return true;
684    }
685
686    bool Core::postUpdate(const Clock& time) throw()
687    {
688        std::string exceptionMessage;
689        try
690        {
691            if (this->bGraphicsLoaded_)
692            {
693                // Render (doesn't throw)
694                this->graphicsManager_->update(time);
695            }
696        }
697        catch (const std::exception& ex)
698        { exceptionMessage = ex.what(); }
699        catch (...)
700        { exceptionMessage = "Unknown exception"; }
701        if (!exceptionMessage.empty())
702        {
703            COUT(0) << "An exception occurred in the Core postUpdate: " << exceptionMessage << std::endl;
704            COUT(0) << "This should really never happen! Closing the program." << std::endl;
705            return false;
706        }
707        return true;
708    }
709}
Note: See TracBrowser for help on using the repository browser.