Changeset 5929 for code/trunk/src/libraries/core/Core.cc
- Timestamp:
- Oct 12, 2009, 8:20:07 PM (16 years ago)
- Location:
- code/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
code/trunk
- Property svn:mergeinfo changed
/code/branches/core5 (added) merged: 5768-5769,5772,5775-5780,5783-5785,5791-5792,5795-5807,5809-5814,5816-5832,5836-5839,5842-5853,5855-5899,5904-5922,5924-5928
- Property svn:mergeinfo changed
-
code/trunk/src/libraries/core/Core.cc
r5781 r5929 37 37 38 38 #include <cassert> 39 #include <fstream> 40 #include <cstdlib> 41 #include <cstdio> 42 #include <boost/version.hpp> 43 #include <boost/filesystem.hpp> 39 #include <vector> 44 40 45 41 #ifdef ORXONOX_PLATFORM_WINDOWS … … 50 46 # undef min 51 47 # 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 48 #endif 59 49 60 #include " SpecialConfig.h"50 #include "util/Clock.h" 61 51 #include "util/Debug.h" 62 52 #include "util/Exception.h" 63 53 #include "util/SignalHandler.h" 64 #include " Clock.h"54 #include "PathConfig.h" 65 55 #include "CommandExecutor.h" 66 56 #include "CommandLine.h" … … 69 59 #include "CoreIncludes.h" 70 60 #include "DynLibManager.h" 71 #include "Factory.h"72 61 #include "GameMode.h" 73 62 #include "GraphicsManager.h" … … 76 65 #include "Language.h" 77 66 #include "LuaState.h" 67 #include "ScopedSingletonManager.h" 78 68 #include "Shell.h" 79 69 #include "TclBind.h" … … 81 71 #include "input/InputManager.h" 82 72 83 // Boost 1.36 has some issues with deprecated functions that have been omitted84 #if (BOOST_VERSION == 103600)85 # define BOOST_LEAF_FUNCTION filename86 #else87 # define BOOST_LEAF_FUNCTION leaf88 #endif89 90 73 namespace orxonox 91 74 { … … 93 76 Core* Core::singletonPtr_s = 0; 94 77 95 SetCommandLineArgument(externalDataPath, "").information("Path to the external data files");96 SetCommandLineOnlyArgument(writingPathSuffix, "").information("Additional subfolder for config and log files");97 78 SetCommandLineArgument(settingsFile, "orxonox.ini").information("THE configuration file"); 98 79 #ifdef ORXONOX_PLATFORM_WINDOWS … … 117 98 RegisterRootObject(CoreConfiguration); 118 99 this->setConfigValues(); 119 120 // External data directory only exists for dev runs121 if (Core::isDevelopmentRun())122 {123 // Possible data path override by the command line124 if (!CommandLine::getArgument("externalDataPath")->hasDefaultValue())125 tsetExternalDataPath(CommandLine::getValue("externalDataPath"));126 }127 100 } 128 101 … … 194 167 } 195 168 196 /**197 @brief198 Temporary sets the external data path199 @param path200 The new data path201 */202 void tsetExternalDataPath(const std::string& path)203 {204 externalDataPath_ = boost::filesystem::path(path);205 }206 207 169 void initializeRandomNumberGenerator() 208 170 { … … 222 184 std::string language_; //!< The language 223 185 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 pahts226 boost::filesystem::path rootPath_;227 boost::filesystem::path executablePath_; //!< Path to the executable228 boost::filesystem::path modulePath_; //!< Path to the modules229 boost::filesystem::path dataPath_; //!< Path to the data file folder230 boost::filesystem::path externalDataPath_; //!< Path to the external data file folder231 boost::filesystem::path configPath_; //!< Path to the config file folder232 boost::filesystem::path logPath_; //!< Path to the log file folder233 186 }; 234 187 … … 240 193 , consoleCommandDestroyer_(CommandExecutor::destroyExternalCommands) 241 194 , configuration_(new CoreConfiguration()) // Don't yet create config values! 242 , bDevRun_(false)243 195 , bGraphicsLoaded_(false) 244 196 { 245 197 // Set the hard coded fixed paths 246 this-> setFixedPaths();198 this->pathConfig_.reset(new PathConfig()); 247 199 248 200 // Create a new dynamic library manager … … 250 202 251 203 // 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 270 208 { 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); 294 210 } 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 } 299 215 } 300 216 … … 303 219 304 220 // Set configurable paths like log, config and media 305 this-> setConfigurablePaths();221 this->pathConfig_->setConfigurablePaths(); 306 222 307 223 // create a signal handler (only active for linux) 308 224 // This call is placed as soon as possible, but after the directories are set 309 225 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"); 311 227 312 228 // 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()); 314 230 315 231 // Parse additional options file now that we know its path … … 334 250 335 251 // creates the class hierarchy for all classes with factories 336 Factory::createClassHierarchy();252 Identifier::createClassHierarchy(); 337 253 338 254 // Do this soon after the ConfigFileManager has been created to open up the … … 344 260 345 261 // initialise Tcl 346 this->tclBind_.reset(new TclBind( Core::getDataPathString()));262 this->tclBind_.reset(new TclBind(PathConfig::getDataPathString())); 347 263 this->tclThreadManager_.reset(new TclThreadManager(tclBind_->getTclInterpreter())); 348 264 349 265 // create a shell 350 266 this->shell_.reset(new Shell()); 267 268 // Create singletons that always exist (in other libraries) 269 this->rootScope_.reset(new Scope<ScopeID::Root>()); 351 270 } 352 271 … … 370 289 inputManager_.reset(new InputManager()); 371 290 372 // load the CEGUI interface291 // Load the CEGUI interface 373 292 guiManager_.reset(new GUIManager(graphicsManager_->getRenderWindow(), 374 293 inputManager_->getMousePosition(), graphicsManager_->isFullScreen())); 375 294 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 376 304 unloader.Dismiss(); 377 378 bGraphicsLoaded_ = true;379 305 } 380 306 381 307 void Core::unloadGraphics() 382 308 { 383 this->guiManager_.reset();; 384 this->inputManager_.reset();; 309 this->graphicsScope_.reset(); 310 this->guiManager_.reset(); 311 this->inputManager_.reset(); 385 312 this->graphicsManager_.reset(); 386 313 … … 397 324 398 325 bGraphicsLoaded_ = false; 326 GameMode::bShowsGraphics_s = false; 399 327 } 400 328 … … 457 385 } 458 386 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 509 387 /** 510 388 @note … … 553 431 } 554 432 555 /**556 @brief557 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 we560 don't write the logs and config files to ~/.orxonox561 @throw562 GeneralException563 */564 void Core::setFixedPaths()565 {566 //////////////////////////567 // FIND EXECUTABLE PATH //568 //////////////////////////569 570 #ifdef ORXONOX_PLATFORM_WINDOWS571 // get executable module572 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 sure590 what the proper response is here.591 Since it really is an assert-like condition, aborting the592 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 #endif607 608 configuration_->executablePath_ = boost::filesystem::path(buffer);609 #ifndef ORXONOX_PLATFORM_APPLE610 configuration_->executablePath_ = configuration_->executablePath_.branch_path(); // remove executable name611 #endif612 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 else624 {625 626 #ifdef INSTALL_COPYABLE // --> relative paths627 628 // Also set the root path629 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 well638 configuration_->modulePath_ = configuration_->rootPath_ / specialConfig::defaultModulePath;639 640 #else641 642 // There is no root path, so don't set it at all643 // Module path is fixed as well644 configuration_->modulePath_ = specialConfig::moduleInstallDirectory;645 646 #endif647 }648 }649 650 /**651 @brief652 Sets config, log and media path and creates folders if necessary.653 @throws654 GeneralException655 */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 else666 {667 668 #ifdef INSTALL_COPYABLE // --> relative paths669 670 // Using paths relative to the install prefix, complete them671 configuration_->dataPath_ = configuration_->rootPath_ / specialConfig::defaultDataPath;672 configuration_->configPath_ = configuration_->rootPath_ / specialConfig::defaultConfigPath;673 configuration_->logPath_ = configuration_->rootPath_ / specialConfig::defaultLogPath;674 675 #else676 677 configuration_->dataPath_ = specialConfig::dataInstallDirectory;678 679 // Get user directory680 # ifdef ORXONOX_PLATFORM_UNIX /* Apple? */681 char* userDataPathPtr(getenv("HOME"));682 # else683 char* userDataPathPtr(getenv("APPDATA"));684 # endif685 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 #endif694 695 }696 697 // Option to put all the config and log files in a separate folder698 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 725 433 void Core::preUpdate(const Clock& time) 726 434 { 435 // singletons from other libraries 436 ScopedSingletonManager::update<ScopeID::Root>(time); 727 437 if (this->bGraphicsLoaded_) 728 438 { … … 731 441 // process gui events 732 442 this->guiManager_->update(time); 443 // graphics singletons from other libraries 444 ScopedSingletonManager::update<ScopeID::Graphics>(time); 733 445 } 734 446 // process thread commands
Note: See TracChangeset
for help on using the changeset viewer.