Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Oct 13, 2009, 5:05:17 PM (15 years ago)
Author:
dafrick
Message:

Hopefully merged trunk successfully into pickup branch.

Location:
code/branches/pickup
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • code/branches/pickup

  • code/branches/pickup/src/libraries/core/Core.cc

    r5781 r5935  
    3737
    3838#include <cassert>
    39 #include <fstream>
    40 #include <cstdlib>
    41 #include <cstdio>
    42 #include <boost/version.hpp>
    43 #include <boost/filesystem.hpp>
     39#include <vector>
    4440
    4541#ifdef ORXONOX_PLATFORM_WINDOWS
     
    5046#  undef min
    5147#  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>
    5848#endif
    5949
    60 #include "SpecialConfig.h"
     50#include "util/Clock.h"
    6151#include "util/Debug.h"
    6252#include "util/Exception.h"
    6353#include "util/SignalHandler.h"
    64 #include "Clock.h"
     54#include "PathConfig.h"
    6555#include "CommandExecutor.h"
    6656#include "CommandLine.h"
     
    6959#include "CoreIncludes.h"
    7060#include "DynLibManager.h"
    71 #include "Factory.h"
    7261#include "GameMode.h"
    7362#include "GraphicsManager.h"
     
    7665#include "Language.h"
    7766#include "LuaState.h"
     67#include "ScopedSingletonManager.h"
    7868#include "Shell.h"
    7969#include "TclBind.h"
     
    8171#include "input/InputManager.h"
    8272
    83 // Boost 1.36 has some issues with deprecated functions that have been omitted
    84 #if (BOOST_VERSION == 103600)
    85 #  define BOOST_LEAF_FUNCTION filename
    86 #else
    87 #  define BOOST_LEAF_FUNCTION leaf
    88 #endif
    89 
    9073namespace orxonox
    9174{
     
    9376    Core* Core::singletonPtr_s  = 0;
    9477
    95     SetCommandLineArgument(externalDataPath, "").information("Path to the external data files");
    96     SetCommandLineOnlyArgument(writingPathSuffix, "").information("Additional subfolder for config and log files");
    9778    SetCommandLineArgument(settingsFile, "orxonox.ini").information("THE configuration file");
    9879#ifdef ORXONOX_PLATFORM_WINDOWS
     
    11798            RegisterRootObject(CoreConfiguration);
    11899            this->setConfigValues();
    119 
    120             // External data directory only exists for dev runs
    121             if (Core::isDevelopmentRun())
    122             {
    123                 // Possible data path override by the command line
    124                 if (!CommandLine::getArgument("externalDataPath")->hasDefaultValue())
    125                     tsetExternalDataPath(CommandLine::getValue("externalDataPath"));
    126             }
    127100        }
    128101
     
    194167        }
    195168
    196         /**
    197         @brief
    198             Temporary sets the external data path
    199         @param path
    200             The new data path
    201         */
    202         void tsetExternalDataPath(const std::string& path)
    203         {
    204             externalDataPath_ = boost::filesystem::path(path);
    205         }
    206 
    207169        void initializeRandomNumberGenerator()
    208170        {
     
    222184        std::string language_;                          //!< The language
    223185        bool bInitializeRandomNumberGenerator_;         //!< If true, srand(time(0)) is called
    224 
    225         //! Path to the parent directory of the ones above if program was installed with relativ pahts
    226         boost::filesystem::path rootPath_;
    227         boost::filesystem::path executablePath_;        //!< Path to the executable
    228         boost::filesystem::path modulePath_;            //!< Path to the modules
    229         boost::filesystem::path dataPath_;              //!< Path to the data file folder
    230         boost::filesystem::path externalDataPath_;      //!< Path to the external data file folder
    231         boost::filesystem::path configPath_;            //!< Path to the config file folder
    232         boost::filesystem::path logPath_;               //!< Path to the log file folder
    233186    };
    234187
     
    240193        , consoleCommandDestroyer_(CommandExecutor::destroyExternalCommands)
    241194        , configuration_(new CoreConfiguration()) // Don't yet create config values!
    242         , bDevRun_(false)
    243195        , bGraphicsLoaded_(false)
    244196    {
    245197        // Set the hard coded fixed paths
    246         this->setFixedPaths();
     198        this->pathConfig_.reset(new PathConfig());
    247199
    248200        // Create a new dynamic library manager
     
    250202
    251203        // Load modules
    252         try
    253         {
    254             // We search for helper files with the following extension
    255             std::string moduleextension = specialConfig::moduleExtension;
    256             size_t moduleextensionlength = moduleextension.size();
    257 
    258             // Search in the directory of our executable
    259             boost::filesystem::path searchpath = this->configuration_->modulePath_;
    260 
    261             // Add that path to the PATH variable in case a module depends on another one
    262             std::string pathVariable = getenv("PATH");
    263             putenv(const_cast<char*>(("PATH=" + pathVariable + ";" + configuration_->modulePath_.string()).c_str()));
    264 
    265             boost::filesystem::directory_iterator file(searchpath);
    266             boost::filesystem::directory_iterator end;
    267 
    268             // Iterate through all files
    269             while (file != end)
     204        const std::vector<std::string>& modulePaths = this->pathConfig_->getModulePaths();
     205        for (std::vector<std::string>::const_iterator it = modulePaths.begin(); it != modulePaths.end(); ++it)
     206        {
     207            try
    270208            {
    271                 std::string filename = file->BOOST_LEAF_FUNCTION();
    272 
    273                 // Check if the file ends with the exension in question
    274                 if (filename.size() > moduleextensionlength)
    275                 {
    276                     if (filename.substr(filename.size() - moduleextensionlength) == moduleextension)
    277                     {
    278                         // We've found a helper file - now load the library with the same name
    279                         std::string library = filename.substr(0, filename.size() - moduleextensionlength);
    280                         boost::filesystem::path librarypath = searchpath / library;
    281 
    282                         try
    283                         {
    284                             DynLibManager::getInstance().load(librarypath.string());
    285                         }
    286                         catch (...)
    287                         {
    288                             COUT(1) << "Couldn't load module \"" << librarypath.string() << "\": " << Exception::handleMessage() << std::endl;
    289                         }
    290                     }
    291                 }
    292 
    293                 ++file;
     209                this->dynLibManager_->load(*it);
    294210            }
    295         }
    296         catch (...)
    297         {
    298             COUT(1) << "An error occurred while loading modules: " << Exception::handleMessage() << std::endl;
     211            catch (...)
     212            {
     213                COUT(1) << "Couldn't load module \"" << *it << "\": " << Exception::handleMessage() << std::endl;
     214            }
    299215        }
    300216
     
    303219
    304220        // Set configurable paths like log, config and media
    305         this->setConfigurablePaths();
     221        this->pathConfig_->setConfigurablePaths();
    306222
    307223        // create a signal handler (only active for linux)
    308224        // This call is placed as soon as possible, but after the directories are set
    309225        this->signalHandler_.reset(new SignalHandler());
    310         this->signalHandler_->doCatch(configuration_->executablePath_.string(), Core::getLogPathString() + "orxonox_crash.log");
     226        this->signalHandler_->doCatch(PathConfig::getExecutablePathString(), PathConfig::getLogPathString() + "orxonox_crash.log");
    311227
    312228        // Set the correct log path. Before this call, /tmp (Unix) or %TEMP% was used
    313         OutputHandler::getOutStream().setLogPath(Core::getLogPathString());
     229        OutputHandler::getOutStream().setLogPath(PathConfig::getLogPathString());
    314230
    315231        // Parse additional options file now that we know its path
     
    334250
    335251        // creates the class hierarchy for all classes with factories
    336         Factory::createClassHierarchy();
     252        Identifier::createClassHierarchy();
    337253
    338254        // Do this soon after the ConfigFileManager has been created to open up the
     
    344260
    345261        // initialise Tcl
    346         this->tclBind_.reset(new TclBind(Core::getDataPathString()));
     262        this->tclBind_.reset(new TclBind(PathConfig::getDataPathString()));
    347263        this->tclThreadManager_.reset(new TclThreadManager(tclBind_->getTclInterpreter()));
    348264
    349265        // create a shell
    350266        this->shell_.reset(new Shell());
     267
     268        // Create singletons that always exist (in other libraries)
     269        this->rootScope_.reset(new Scope<ScopeID::Root>());
    351270    }
    352271
     
    370289        inputManager_.reset(new InputManager());
    371290
    372         // load the CEGUI interface
     291        // Load the CEGUI interface
    373292        guiManager_.reset(new GUIManager(graphicsManager_->getRenderWindow(),
    374293            inputManager_->getMousePosition(), graphicsManager_->isFullScreen()));
    375294
     295        bGraphicsLoaded_ = true;
     296        GameMode::bShowsGraphics_s = true;
     297
     298        // Load some sort of a debug overlay (only denoted by its name, "debug.oxo")
     299        graphicsManager_->loadDebugOverlay();
     300
     301        // Create singletons associated with graphics (in other libraries)
     302        graphicsScope_.reset(new Scope<ScopeID::Graphics>());
     303
    376304        unloader.Dismiss();
    377 
    378         bGraphicsLoaded_ = true;
    379305    }
    380306
    381307    void Core::unloadGraphics()
    382308    {
    383         this->guiManager_.reset();;
    384         this->inputManager_.reset();;
     309        this->graphicsScope_.reset();
     310        this->guiManager_.reset();
     311        this->inputManager_.reset();
    385312        this->graphicsManager_.reset();
    386313
     
    397324
    398325        bGraphicsLoaded_ = false;
     326        GameMode::bShowsGraphics_s = false;
    399327    }
    400328
     
    457385    }
    458386
    459     /*static*/ void Core::tsetExternalDataPath(const std::string& path)
    460     {
    461         getInstance().configuration_->tsetExternalDataPath(path);
    462     }
    463 
    464     /*static*/ const boost::filesystem::path& Core::getDataPath()
    465     {
    466         return getInstance().configuration_->dataPath_;
    467     }
    468     /*static*/ std::string Core::getDataPathString()
    469     {
    470         return getInstance().configuration_->dataPath_.string() + '/';
    471     }
    472 
    473     /*static*/ const boost::filesystem::path& Core::getExternalDataPath()
    474     {
    475         return getInstance().configuration_->externalDataPath_;
    476     }
    477     /*static*/ std::string Core::getExternalDataPathString()
    478     {
    479         return getInstance().configuration_->externalDataPath_.string() + '/';
    480     }
    481 
    482     /*static*/ const boost::filesystem::path& Core::getConfigPath()
    483     {
    484         return getInstance().configuration_->configPath_;
    485     }
    486     /*static*/ std::string Core::getConfigPathString()
    487     {
    488         return getInstance().configuration_->configPath_.string() + '/';
    489     }
    490 
    491     /*static*/ const boost::filesystem::path& Core::getLogPath()
    492     {
    493         return getInstance().configuration_->logPath_;
    494     }
    495     /*static*/ std::string Core::getLogPathString()
    496     {
    497         return getInstance().configuration_->logPath_.string() + '/';
    498     }
    499 
    500     /*static*/ const boost::filesystem::path& Core::getRootPath()
    501     {
    502         return getInstance().configuration_->rootPath_;
    503     }
    504     /*static*/ std::string Core::getRootPathString()
    505     {
    506         return getInstance().configuration_->rootPath_.string() + '/';
    507     }
    508 
    509387    /**
    510388    @note
     
    553431    }
    554432
    555     /**
    556     @brief
    557         Retrievs the executable path and sets all hard coded fixed path (currently only the module path)
    558         Also checks for "orxonox_dev_build.keep_me" in the executable diretory.
    559         If found it means that this is not an installed run, hence we
    560         don't write the logs and config files to ~/.orxonox
    561     @throw
    562         GeneralException
    563     */
    564     void Core::setFixedPaths()
    565     {
    566         //////////////////////////
    567         // FIND EXECUTABLE PATH //
    568         //////////////////////////
    569 
    570 #ifdef ORXONOX_PLATFORM_WINDOWS
    571         // get executable module
    572         TCHAR buffer[1024];
    573         if (GetModuleFileName(NULL, buffer, 1024) == 0)
    574             ThrowException(General, "Could not retrieve executable path.");
    575 
    576 #elif defined(ORXONOX_PLATFORM_APPLE)
    577         char buffer[1024];
    578         unsigned long path_len = 1023;
    579         if (_NSGetExecutablePath(buffer, &path_len))
    580             ThrowException(General, "Could not retrieve executable path.");
    581 
    582 #else /* Linux */
    583         /* written by Nicolai Haehnle <prefect_@gmx.net> */
    584 
    585         /* Get our PID and build the name of the link in /proc */
    586         char linkname[64]; /* /proc/<pid>/exe */
    587         if (snprintf(linkname, sizeof(linkname), "/proc/%i/exe", getpid()) < 0)
    588         {
    589             /* This should only happen on large word systems. I'm not sure
    590                what the proper response is here.
    591                Since it really is an assert-like condition, aborting the
    592                program seems to be in order. */
    593             assert(false);
    594         }
    595 
    596         /* Now read the symbolic link */
    597         char buffer[1024];
    598         int ret;
    599         ret = readlink(linkname, buffer, 1024);
    600         /* In case of an error, leave the handling up to the caller */
    601         if (ret == -1)
    602             ThrowException(General, "Could not retrieve executable path.");
    603 
    604         /* Ensure proper NUL termination */
    605         buffer[ret] = 0;
    606 #endif
    607 
    608         configuration_->executablePath_ = boost::filesystem::path(buffer);
    609 #ifndef ORXONOX_PLATFORM_APPLE
    610         configuration_->executablePath_ = configuration_->executablePath_.branch_path(); // remove executable name
    611 #endif
    612 
    613         /////////////////////
    614         // SET MODULE PATH //
    615         /////////////////////
    616 
    617         if (boost::filesystem::exists(configuration_->executablePath_ / "orxonox_dev_build.keep_me"))
    618         {
    619             COUT(1) << "Running from the build tree." << std::endl;
    620             Core::bDevRun_ = true;
    621             configuration_->modulePath_ = specialConfig::moduleDevDirectory;
    622         }
    623         else
    624         {
    625 
    626 #ifdef INSTALL_COPYABLE // --> relative paths
    627 
    628             // Also set the root path
    629             boost::filesystem::path relativeExecutablePath(specialConfig::defaultRuntimePath);
    630             configuration_->rootPath_ = configuration_->executablePath_;
    631             while (!boost::filesystem::equivalent(configuration_->rootPath_ / relativeExecutablePath, configuration_->executablePath_)
    632                    && !configuration_->rootPath_.empty())
    633                 configuration_->rootPath_ = configuration_->rootPath_.branch_path();
    634             if (configuration_->rootPath_.empty())
    635                 ThrowException(General, "Could not derive a root directory. Might the binary installation directory contain '..' when taken relative to the installation prefix path?");
    636 
    637             // Module path is fixed as well
    638             configuration_->modulePath_ = configuration_->rootPath_ / specialConfig::defaultModulePath;
    639 
    640 #else
    641 
    642             // There is no root path, so don't set it at all
    643             // Module path is fixed as well
    644             configuration_->modulePath_ = specialConfig::moduleInstallDirectory;
    645 
    646 #endif
    647         }
    648     }
    649 
    650     /**
    651     @brief
    652         Sets config, log and media path and creates folders if necessary.
    653     @throws
    654         GeneralException
    655     */
    656     void Core::setConfigurablePaths()
    657     {
    658         if (Core::isDevelopmentRun())
    659         {
    660             configuration_->dataPath_  = specialConfig::dataDevDirectory;
    661             configuration_->externalDataPath_ = specialConfig::externalDataDevDirectory;
    662             configuration_->configPath_ = specialConfig::configDevDirectory;
    663             configuration_->logPath_    = specialConfig::logDevDirectory;
    664         }
    665         else
    666         {
    667 
    668 #ifdef INSTALL_COPYABLE // --> relative paths
    669 
    670             // Using paths relative to the install prefix, complete them
    671             configuration_->dataPath_   = configuration_->rootPath_ / specialConfig::defaultDataPath;
    672             configuration_->configPath_ = configuration_->rootPath_ / specialConfig::defaultConfigPath;
    673             configuration_->logPath_    = configuration_->rootPath_ / specialConfig::defaultLogPath;
    674 
    675 #else
    676 
    677             configuration_->dataPath_  = specialConfig::dataInstallDirectory;
    678 
    679             // Get user directory
    680 #  ifdef ORXONOX_PLATFORM_UNIX /* Apple? */
    681             char* userDataPathPtr(getenv("HOME"));
    682 #  else
    683             char* userDataPathPtr(getenv("APPDATA"));
    684 #  endif
    685             if (userDataPathPtr == NULL)
    686                 ThrowException(General, "Could not retrieve user data path.");
    687             boost::filesystem::path userDataPath(userDataPathPtr);
    688             userDataPath /= ".orxonox";
    689 
    690             configuration_->configPath_ = userDataPath / specialConfig::defaultConfigPath;
    691             configuration_->logPath_    = userDataPath / specialConfig::defaultLogPath;
    692 
    693 #endif
    694 
    695         }
    696 
    697         // Option to put all the config and log files in a separate folder
    698         if (!CommandLine::getArgument("writingPathSuffix")->hasDefaultValue())
    699         {
    700             std::string directory(CommandLine::getValue("writingPathSuffix").getString());
    701             configuration_->configPath_ = configuration_->configPath_ / directory;
    702             configuration_->logPath_    = configuration_->logPath_    / directory;
    703         }
    704 
    705         // Create directories to avoid problems when opening files in non existent folders.
    706         std::vector<std::pair<boost::filesystem::path, std::string> > directories;
    707         directories.push_back(std::make_pair(boost::filesystem::path(configuration_->configPath_), "config"));
    708         directories.push_back(std::make_pair(boost::filesystem::path(configuration_->logPath_), "log"));
    709 
    710         for (std::vector<std::pair<boost::filesystem::path, std::string> >::iterator it = directories.begin();
    711             it != directories.end(); ++it)
    712         {
    713             if (boost::filesystem::exists(it->first) && !boost::filesystem::is_directory(it->first))
    714             {
    715                 ThrowException(General, std::string("The ") + it->second + " directory has been preoccupied by a file! \
    716                                          Please remove " + it->first.string());
    717             }
    718             if (boost::filesystem::create_directories(it->first)) // function may not return true at all (bug?)
    719             {
    720                 COUT(4) << "Created " << it->second << " directory" << std::endl;
    721             }
    722         }
    723     }
    724 
    725433    void Core::preUpdate(const Clock& time)
    726434    {
     435        // singletons from other libraries
     436        ScopedSingletonManager::update<ScopeID::Root>(time);
    727437        if (this->bGraphicsLoaded_)
    728438        {
     
    731441            // process gui events
    732442            this->guiManager_->update(time);
     443            // graphics singletons from other libraries
     444            ScopedSingletonManager::update<ScopeID::Graphics>(time);
    733445        }
    734446        // process thread commands
Note: See TracChangeset for help on using the changeset viewer.