Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Mar 25, 2009, 7:37:00 PM (15 years ago)
Author:
rgrieder
Message:

Exported showsGraphics, etc. to a new class named GameMode in the core.

File:
1 copied

Legend:

Unmodified
Added
Removed
  • code/branches/gui/src/core/GameMode.cc

    r2843 r2848  
    2121 *
    2222 *   Author:
    23  *      Fabian 'x3n' Landau
    2423 *      Reto Grieder
    2524 *   Co-authors:
     
    3029/**
    3130    @file
    32     @brief Implementation of the Core class.
     31    @brief Implementation of the GameMode class.
    3332*/
    3433
    35 #include "Core.h"
    36 
    37 #include <cassert>
    38 #include <fstream>
    39 #include <cstdlib>
    40 #include <cstdio>
    41 #include <boost/filesystem.hpp>
    42 
    43 #ifdef ORXONOX_PLATFORM_WINDOWS
    44 #  ifndef WIN32_LEAN_AND_MEAN
    45 #    define WIN32_LEAN_AND_MEAN
    46 #  endif
    47 #  include <windows.h>
    48 #elif defined(ORXONOX_PLATFORM_APPLE)
    49 #  include <sys/param.h>
    50 #  include <mach-o/dyld.h>
    51 #else /* Linux */
    52 #  include <sys/types.h>
    53 #  include <unistd.h>
    54 #endif
    55 
    56 #include "SpecialConfig.h"
    57 #include "util/Debug.h"
    58 #include "util/Exception.h"
    59 #include "util/SignalHandler.h"
    60 #include "Clock.h"
    61 #include "CommandExecutor.h"
    62 #include "CommandLine.h"
    63 #include "ConfigFileManager.h"
    64 #include "ConfigValueIncludes.h"
    65 #include "CoreIncludes.h"
    66 #include "Factory.h"
    67 #include "Identifier.h"
    68 #include "Language.h"
    69 #include "LuaBind.h"
    70 #include "Shell.h"
    71 #include "TclBind.h"
    72 #include "TclThreadManager.h"
     34#include "GameMode.h"
    7335
    7436namespace orxonox
    7537{
    76     //! Path to the parent directory of the ones above if program was installed with relativ pahts
    77     static boost::filesystem::path rootPath_g;
    78     static boost::filesystem::path executablePath_g;            //!< Path to the executable
    79     static boost::filesystem::path mediaPath_g;                 //!< Path to the media file folder
    80     static boost::filesystem::path configPath_g;                //!< Path to the config file folder
    81     static boost::filesystem::path logPath_g;                   //!< Path to the log file folder
    82 
    83     bool Core::bShowsGraphics_s = false;
    84     bool Core::bHasServer_s     = false;
    85     bool Core::bIsClient_s      = false;
    86     bool Core::bIsStandalone_s  = false;
    87     bool Core::bIsMaster_s      = false;
    88 
    89     Core* Core::singletonRef_s  = 0;
    90 
    91     SetCommandLineArgument(mediaPath, "").information("PATH");
    92     SetCommandLineArgument(writingPathSuffix, "").information("DIR");
    93     SetCommandLineArgument(settingsFile, "orxonox.ini");
    94     SetCommandLineArgument(limitToCPU, 0).information("0: off | #cpu");
    95 
    96     Core::Core()
    97     {
    98         RegisterRootObject(Core);
    99 
    100         assert(Core::singletonRef_s == 0);
    101         Core::singletonRef_s = this;
    102     }
    103 
    104     Clock* Core::initialise(int argc, char** argv)
    105     {
    106         // Set up a basic clock to keep time
    107         this->gameClock_ = new Clock();
    108 
    109         // Parse command line arguments fist
    110         try
    111         {
    112             CommandLine::parseAll(argc, argv);
    113         }
    114         catch (ArgumentException& ex)
    115         {
    116             COUT(1) << ex.what() << std::endl;
    117             COUT(0) << "Usage:" << std::endl << "orxonox " << CommandLine::getUsageInformation() << std::endl;
    118         }
    119 
    120         // limit the main thread to the first core so that QueryPerformanceCounter doesn't jump
    121         // do this after ogre has initialised. Somehow Ogre changes the settings again (not through
    122         // the timer though).
    123         int limitToCPU = CommandLine::getValue("limitToCPU");
    124         if (limitToCPU > 0)
    125             setThreadAffinity((unsigned int)limitToCPU);
    126 
    127         // Determine and set the location of the executable
    128         setExecutablePath();
    129 
    130         // Determine whether we have an installed or a binary dir run
    131         // The latter occurs when simply running from the build directory
    132         checkDevBuild();
    133 
    134         // Make sure the directories we write in exist or else make them
    135         createDirectories();
    136 
    137         // create a signal handler (only active for linux)
    138         // This call is placed as soon as possible, but after the directories are set
    139         this->signalHandler_ = new SignalHandler();
    140         this->signalHandler_->doCatch(executablePath_g.string(), Core::getLogPathString() + "orxonox_crash.log");
    141 
    142         // Set the correct log path. Before this call, /tmp (Unix) or %TEMP% was used
    143         OutputHandler::getOutStream().setLogPath(Core::getLogPathString());
    144 
    145         // Manage ini files and set the default settings file (usually orxonox.ini)
    146         this->configFileManager_ = new ConfigFileManager();
    147         this->configFileManager_->setFilename(ConfigFileType::Settings,
    148             CommandLine::getValue("settingsFile").getString());
    149 
    150         this->languageInstance_ = new Language();
    151 
    152         // Do this soon after the ConfigFileManager has been created to open up the
    153         // possibility to configure everything below here
    154         this->setConfigValues();
    155 
    156         // Possible media path override by the command line
    157         if (!CommandLine::getArgument("mediaPath")->hasDefaultValue())
    158         {
    159             //std::string mediaPath = CommandLine::getValue("mediaPath");
    160             Core::tsetMediaPath(CommandLine::getValue("mediaPath"));
    161         }
    162 
    163         // Create the lua interface
    164         this->luaBind_ = new LuaBind();
    165 
    166         // initialise Tcl
    167         this->tclBind_ = new TclBind(Core::getMediaPathString());
    168         this->tclThreadManager_ = new TclThreadManager(tclBind_->getTclInterpreter());
    169 
    170         // create a shell
    171         this->shell_ = new Shell();
    172 
    173         // creates the class hierarchy for all classes with factories
    174         Factory::createClassHierarchy();
    175        
    176         this->loaded_ = true;
    177 
    178         // Return non const pointer to the game's clock for the main loop
    179         return this->gameClock_;
    180     }
    181 
    182     /**
    183         @brief Sets the bool to true to avoid static functions accessing a deleted object.
    184     */
    185     Core::~Core()
    186     {
    187         this->loaded_ = false;
    188 
    189         delete this->shell_;
    190         delete this->tclThreadManager_;
    191         delete this->tclBind_;
    192         delete this->luaBind_;
    193         delete this->languageInstance_;
    194         delete this->configFileManager_;
    195         delete this->signalHandler_;
    196 
    197         // Destroy command line arguments
    198         CommandLine::destroyAllArguments();
    199         // Also delete external console command that don't belong to an Identifier
    200         CommandExecutor::destroyExternalCommands();
    201 
    202         delete this->gameClock_;
    203 
    204         assert(Core::singletonRef_s);
    205         Core::singletonRef_s = 0;
    206     }
    207 
    208     /**
    209         @brief Function to collect the SetConfigValue-macro calls.
    210     */
    211     void Core::setConfigValues()
    212     {
    213 #ifdef NDEBUG
    214         const unsigned int defaultLevelConsole = 1;
    215         const unsigned int defaultLevelLogfile = 3;
    216         const unsigned int defaultLevelShell   = 1;
    217 #else
    218         const unsigned int defaultLevelConsole = 3;
    219         const unsigned int defaultLevelLogfile = 4;
    220         const unsigned int defaultLevelShell   = 3;
    221 #endif
    222         SetConfigValue(softDebugLevelConsole_, defaultLevelConsole)
    223             .description("The maximal level of debug output shown in the console").callback(this, &Core::debugLevelChanged);
    224         SetConfigValue(softDebugLevelLogfile_, defaultLevelLogfile)
    225             .description("The maximal level of debug output shown in the logfile").callback(this, &Core::debugLevelChanged);
    226         SetConfigValue(softDebugLevelShell_, defaultLevelShell)
    227             .description("The maximal level of debug output shown in the ingame shell").callback(this, &Core::debugLevelChanged);
    228 
    229         SetConfigValue(language_, Language::getLanguage().defaultLanguage_).description("The language of the ingame text").callback(this, &Core::languageChanged);
    230         SetConfigValue(bInitializeRandomNumberGenerator_, true).description("If true, all random actions are different each time you start the game").callback(this, &Core::initializeRandomNumberGenerator);
    231 
    232         SetConfigValue(mediaPathString_, mediaPath_g.string())
    233             .description("Relative path to the game data.").callback(this, &Core::mediaPathChanged);
    234     }
    235 
    236     /**
    237         @brief Callback function if the debug level has changed.
    238     */
    239     void Core::debugLevelChanged()
    240     {
    241         // softDebugLevel_ is the maximum of the 3 variables
    242         this->softDebugLevel_ = this->softDebugLevelConsole_;
    243         if (this->softDebugLevelLogfile_ > this->softDebugLevel_)
    244             this->softDebugLevel_ = this->softDebugLevelLogfile_;
    245         if (this->softDebugLevelShell_ > this->softDebugLevel_)
    246             this->softDebugLevel_ = this->softDebugLevelShell_;
    247 
    248         OutputHandler::setSoftDebugLevel(OutputHandler::LD_All,     this->softDebugLevel_);
    249         OutputHandler::setSoftDebugLevel(OutputHandler::LD_Console, this->softDebugLevelConsole_);
    250         OutputHandler::setSoftDebugLevel(OutputHandler::LD_Logfile, this->softDebugLevelLogfile_);
    251         OutputHandler::setSoftDebugLevel(OutputHandler::LD_Shell,   this->softDebugLevelShell_);
    252     }
    253 
    254     /**
    255         @brief Callback function if the language has changed.
    256     */
    257     void Core::languageChanged()
    258     {
    259         // Read the translation file after the language was configured
    260         Language::getLanguage().readTranslatedLanguageFile();
    261     }
    262 
    263     /**
    264     @brief
    265         Callback function if the media path has changed.
    266     */
    267     void Core::mediaPathChanged()
    268     {
    269         mediaPath_g = boost::filesystem::path(this->mediaPathString_);
    270     }
    271 
    272     /**
    273         @brief Returns the softDebugLevel for the given device (returns a default-value if the class ist right about to be created).
    274         @param device The device
    275         @return The softDebugLevel
    276     */
    277     int Core::getSoftDebugLevel(OutputHandler::OutputDevice device)
    278     {
    279         switch (device)
    280         {
    281         case OutputHandler::LD_All:
    282             return Core::getInstance().softDebugLevel_;
    283         case OutputHandler::LD_Console:
    284             return Core::getInstance().softDebugLevelConsole_;
    285         case OutputHandler::LD_Logfile:
    286             return Core::getInstance().softDebugLevelLogfile_;
    287         case OutputHandler::LD_Shell:
    288             return Core::getInstance().softDebugLevelShell_;
    289         default:
    290             assert(0);
    291             return 2;
    292         }
    293     }
    294 
    295      /**
    296         @brief Sets the softDebugLevel for the given device. Please use this only temporary and restore the value afterwards, as it overrides the configured value.
    297         @param device The device
    298         @param level The level
    299     */
    300      void Core::setSoftDebugLevel(OutputHandler::OutputDevice device, int level)
    301      {
    302         if (device == OutputHandler::LD_All)
    303             Core::getInstance().softDebugLevel_ = level;
    304         else if (device == OutputHandler::LD_Console)
    305             Core::getInstance().softDebugLevelConsole_ = level;
    306         else if (device == OutputHandler::LD_Logfile)
    307             Core::getInstance().softDebugLevelLogfile_ = level;
    308         else if (device == OutputHandler::LD_Shell)
    309             Core::getInstance().softDebugLevelShell_ = level;
    310 
    311         OutputHandler::setSoftDebugLevel(device, level);
    312      }
    313 
    314     /**
    315         @brief Returns the configured language.
    316     */
    317     const std::string& Core::getLanguage()
    318     {
    319         return Core::getInstance().language_;
    320     }
    321 
    322     /**
    323         @brief Sets the language in the config-file back to the default.
    324     */
    325     void Core::resetLanguage()
    326     {
    327         Core::getInstance().resetLanguageIntern();
    328     }
    329 
    330     /**
    331         @brief Sets the language in the config-file back to the default.
    332     */
    333     void Core::resetLanguageIntern()
    334     {
    335         ResetConfigValue(language_);
    336     }
    337 
    338     /**
    339     @brief
    340         Temporary sets the media path
    341     @param path
    342         The new media path
    343     */
    344     void Core::_tsetMediaPath(const std::string& path)
    345     {
    346         ModifyConfigValue(mediaPathString_, tset, path);
    347     }
    348 
    349     /*static*/ const boost::filesystem::path& Core::getMediaPath()
    350     {
    351         return mediaPath_g;
    352     }
    353     /*static*/ std::string Core::getMediaPathString()
    354     {
    355         return mediaPath_g.string() + '/';
    356     }
    357 
    358     /*static*/ const boost::filesystem::path& Core::getConfigPath()
    359     {
    360         return configPath_g;
    361     }
    362     /*static*/ std::string Core::getConfigPathString()
    363     {
    364         return configPath_g.string() + '/';
    365     }
    366 
    367     /*static*/ const boost::filesystem::path& Core::getLogPath()
    368     {
    369         return logPath_g;
    370     }
    371     /*static*/ std::string Core::getLogPathString()
    372     {
    373         return logPath_g.string() + '/';
    374     }
    375 
    376     void Core::initializeRandomNumberGenerator()
    377     {
    378         static bool bInitialized = false;
    379         if (!bInitialized && this->bInitializeRandomNumberGenerator_)
    380         {
    381             srand(time(0));
    382             rand();
    383             bInitialized = true;
    384         }
    385     }
    386 
    387 
    388     /**
    389     @note
    390         The code of this function has been copied and adjusted from OGRE, an open source graphics engine.
    391             (Object-oriented Graphics Rendering Engine)
    392         For the latest info, see http://www.ogre3d.org/
    393 
    394         Copyright (c) 2000-2008 Torus Knot Software Ltd
    395 
    396         OGRE is licensed under the LGPL. For more info, see OGRE license.
    397     */
    398     void Core::setThreadAffinity(int limitToCPU)
    399     {
    400         if (limitToCPU <= 0)
    401             return;
    402 
    403 #ifdef ORXONOX_PLATFORM_WINDOWS
    404         unsigned int coreNr = limitToCPU - 1;
    405         // Get the current process core mask
    406         DWORD procMask;
    407         DWORD sysMask;
    408 #  if _MSC_VER >= 1400 && defined (_M_X64)
    409         GetProcessAffinityMask(GetCurrentProcess(), (PDWORD_PTR)&procMask, (PDWORD_PTR)&sysMask);
    410 #  else
    411         GetProcessAffinityMask(GetCurrentProcess(), &procMask, &sysMask);
    412 #  endif
    413 
    414         // If procMask is 0, consider there is only one core available
    415         // (using 0 as procMask will cause an infinite loop below)
    416         if (procMask == 0)
    417             procMask = 1;
    418 
    419         // if the core specified with coreNr is not available, take the lowest one
    420         if (!(procMask & (1 << coreNr)))
    421             coreNr = 0;
    422 
    423         // Find the lowest core that this process uses and coreNr suggests
    424         DWORD threadMask = 1;
    425         while ((threadMask & procMask) == 0 || (threadMask < (1u << coreNr)))
    426             threadMask <<= 1;
    427 
    428         // Set affinity to the first core
    429         SetThreadAffinityMask(GetCurrentThread(), threadMask);
    430 #endif
    431     }
    432 
    433     /**
    434     @brief
    435         Compares the executable path with the working directory
    436     */
    437     void Core::setExecutablePath()
    438     {
    439 #ifdef ORXONOX_PLATFORM_WINDOWS
    440         // get executable module
    441         TCHAR buffer[1024];
    442         if (GetModuleFileName(NULL, buffer, 1024) == 0)
    443             ThrowException(General, "Could not retrieve executable path.");
    444 
    445 #elif defined(ORXONOX_PLATFORM_APPLE)
    446         char buffer[1024];
    447         unsigned long path_len = 1023;
    448         if (_NSGetExecutablePath(buffer, &path_len))
    449             ThrowException(General, "Could not retrieve executable path.");
    450 
    451 #else /* Linux */
    452         /* written by Nicolai Haehnle <prefect_@gmx.net> */
    453 
    454         /* Get our PID and build the name of the link in /proc */
    455         char linkname[64]; /* /proc/<pid>/exe */
    456         if (snprintf(linkname, sizeof(linkname), "/proc/%i/exe", getpid()) < 0)
    457         {
    458             /* This should only happen on large word systems. I'm not sure
    459                what the proper response is here.
    460                Since it really is an assert-like condition, aborting the
    461                program seems to be in order. */
    462             assert(false);
    463         }
    464 
    465         /* Now read the symbolic link */
    466         char buffer[1024];
    467         int ret;
    468         ret = readlink(linkname, buffer, 1024);
    469         /* In case of an error, leave the handling up to the caller */
    470         if (ret == -1)
    471             ThrowException(General, "Could not retrieve executable path.");
    472 
    473         /* Ensure proper NUL termination */
    474         buffer[ret] = 0;
    475 #endif
    476 
    477         executablePath_g = boost::filesystem::path(buffer);
    478 #ifndef ORXONOX_PLATFORM_APPLE
    479         executablePath_g = executablePath_g.branch_path(); // remove executable name
    480 #endif
    481     }
    482 
    483     /**
    484     @brief
    485         Checks for "orxonox_dev_build.keep_me" in the executable diretory.
    486         If found it means that this is not an installed run, hence we
    487         don't write the logs and config files to ~/.orxonox
    488     */
    489     void Core::checkDevBuild()
    490     {
    491         if (boost::filesystem::exists(executablePath_g / "orxonox_dev_build.keep_me"))
    492         {
    493             COUT(1) << "Running from the build tree." << std::endl;
    494             Core::isDevBuild_ = true;
    495             mediaPath_g  = ORXONOX_MEDIA_DEV_PATH;
    496             configPath_g = ORXONOX_CONFIG_DEV_PATH;
    497             logPath_g    = ORXONOX_LOG_DEV_PATH;
    498         }
    499         else
    500         {
    501 #ifdef INSTALL_COPYABLE // --> relative paths
    502             // Also set the root path
    503             boost::filesystem::path relativeExecutablePath(ORXONOX_RUNTIME_INSTALL_PATH);
    504             rootPath_g = executablePath_g;
    505             while (!boost::filesystem::equivalent(rootPath_g / relativeExecutablePath, executablePath_g) || rootPath_g.empty())
    506                 rootPath_g = rootPath_g.branch_path();
    507             if (rootPath_g.empty())
    508                 ThrowException(General, "Could not derive a root directory. Might the binary installation directory contain '..' when taken relative to the installation prefix path?");
    509 
    510             // Using paths relative to the install prefix, complete them
    511             mediaPath_g  = rootPath_g / ORXONOX_MEDIA_INSTALL_PATH;
    512             configPath_g = rootPath_g / ORXONOX_CONFIG_INSTALL_PATH;
    513             logPath_g    = rootPath_g / ORXONOX_LOG_INSTALL_PATH;
    514 #else
    515             // There is no root path, so don't set it at all
    516 
    517             mediaPath_g  = ORXONOX_MEDIA_INSTALL_PATH;
    518 
    519             // Get user directory
    520 #  ifdef ORXONOX_PLATFORM_UNIX /* Apple? */
    521             char* userDataPathPtr(getenv("HOME"));
    522 #  else
    523             char* userDataPathPtr(getenv("APPDATA"));
    524 #  endif
    525             if (userDataPathPtr == NULL)
    526                 ThrowException(General, "Could not retrieve user data path.");
    527             boost::filesystem::path userDataPath(userDataPathPtr);
    528             userDataPath /= ".orxonox";
    529 
    530             configPath_g = userDataPath / ORXONOX_CONFIG_INSTALL_PATH;
    531             logPath_g    = userDataPath / ORXONOX_LOG_INSTALL_PATH;
    532 #endif
    533         }
    534 
    535         // Option to put all the config and log files in a separate folder
    536         if (!CommandLine::getArgument("writingPathSuffix")->hasDefaultValue())
    537         {
    538             std::string directory(CommandLine::getValue("writingPathSuffix").getString());
    539             configPath_g = configPath_g / directory;
    540             logPath_g    = logPath_g    / directory;
    541         }
    542     }
    543 
    544     /*
    545     @brief
    546         Checks for the log and the config directory and creates them
    547         if necessary. Otherwise me might have problems opening those files.
    548     */
    549     void Core::createDirectories()
    550     {
    551         std::vector<std::pair<boost::filesystem::path, std::string> > directories;
    552         directories.push_back(std::pair<boost::filesystem::path, std::string>
    553             (boost::filesystem::path(configPath_g), "config"));
    554         directories.push_back(std::pair<boost::filesystem::path, std::string>
    555             (boost::filesystem::path(logPath_g),    "log"));
    556 
    557         for (std::vector<std::pair<boost::filesystem::path, std::string> >::iterator it = directories.begin();
    558             it != directories.end(); ++it)
    559         {
    560             if (boost::filesystem::exists(it->first) && !boost::filesystem::is_directory(it->first))
    561             {
    562                 ThrowException(General, std::string("The ") + it->second + " directory has been preoccupied by a file! \
    563                                          Please remove " + it->first.string());
    564             }
    565             if (boost::filesystem::create_directories(it->first)) // function may not return true at all (bug?)
    566             {
    567                 COUT(4) << "Created " << it->second << " directory" << std::endl;
    568             }
    569         }
    570     }
    571 
    572     void Core::update(const Clock& time)
    573     {
    574         this->tclThreadManager_->update(time);
    575     }
     38    bool GameMode::bShowsGraphics_s = false;
     39    bool GameMode::bHasServer_s     = false;
     40    bool GameMode::bIsClient_s      = false;
     41    bool GameMode::bIsStandalone_s  = false;
     42    bool GameMode::bIsMaster_s      = false;
    57643}
Note: See TracChangeset for help on using the changeset viewer.