Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Oct 4, 2015, 9:12:21 PM (9 years ago)
Author:
landauf
Message:

merged branch core7 back to trunk

Location:
code/trunk
Files:
9 deleted
64 edited
22 copied

Legend:

Unmodified
Added
Removed
  • code/trunk

  • code/trunk/src/libraries/core/BaseObject.cc

    r9667 r10624  
    6363        this->bActive_ = true;
    6464        this->bVisible_ = true;
    65         this->oldGametype_ = 0;
    6665        this->bRegisteredEventStates_ = false;
    6766
     
    7877        {
    7978            this->setFile(this->creator_->getFile());
    80             this->setNamespace(this->creator_->getNamespace());
    81             this->setScene(this->creator_->getScene(), this->creator_->getSceneID());
    82             this->setGametype(this->creator_->getGametype());
    83             this->setLevel(this->creator_->getLevel());
     79
     80            // store strong-pointers on all four base objects by default (can be overwritten with weak-ptr after the constructor if necessary)
     81            this->setNamespace(this->creator_->namespace_.createStrongPtr());
     82            this->setScene    (this->creator_->scene_    .createStrongPtr(), this->creator_->sceneID_);
     83            this->setGametype (this->creator_->gametype_ .createStrongPtr());
     84            this->setLevel    (this->creator_->level_    .createStrongPtr());
    8485        }
    8586        else
    8687        {
    8788            this->file_ = 0;
    88             this->namespace_ = 0;
    89             this->scene_ = 0;
    9089            this->sceneID_ = OBJECTID_UNKNOWN;
    91             this->gametype_ = 0;
    92             this->level_ = 0;
    9390        }
    9491    }
  • code/trunk/src/libraries/core/BaseObject.h

    r10298 r10624  
    5151#include "class/OrxonoxClass.h"
    5252#include "class/Super.h"
    53 #include "object/SmartPtr.h"
     53#include "object/StrongPtr.h"
    5454
    5555namespace orxonox
     
    6363    {
    6464        template <class T> friend class XMLPortClassParamContainer;
     65
     66        public:
     67            template <class T>
     68            class StrongOrWeakPtr
     69            {
     70                public:
     71                    inline StrongOrWeakPtr();
     72                    inline StrongOrWeakPtr(const StrongPtr<T>& ptr);
     73                    inline StrongOrWeakPtr(const WeakPtr<T>& ptr);
     74
     75                    inline T* get() const;
     76                    inline StrongPtr<T> createStrongPtr() const;
     77
     78                private:
     79                    StrongPtr<T> strongPtr_;
     80                    WeakPtr<T> weakPtr_;
     81            };
    6582
    6683        public:
     
    138155                { return this->templates_; }
    139156
    140             inline void setNamespace(const SmartPtr<Namespace>& ns) { this->namespace_ = ns; }
    141             inline const SmartPtr<Namespace>& getNamespace() const { return this->namespace_; }
     157            inline void setNamespace(const StrongOrWeakPtr<Namespace>& ns) { this->namespace_ = ns; }
     158            inline Namespace* getNamespace() const { return this->namespace_.get(); }
    142159
    143160            inline void setCreator(BaseObject* creator) { this->creator_ = creator; }
    144161            inline BaseObject* getCreator() const { return this->creator_; }
    145162
    146             inline void setScene(const SmartPtr<Scene>& scene, uint32_t sceneID) { this->scene_ = scene; this->sceneID_=sceneID; }
    147             inline const SmartPtr<Scene>& getScene() const { return this->scene_; }
     163            inline void setScene(const StrongOrWeakPtr<Scene>& scene, uint32_t sceneID) { this->scene_ = scene; this->sceneID_=sceneID; }
     164            inline Scene* getScene() const { return this->scene_.get(); }
    148165            inline virtual uint32_t getSceneID() const { return this->sceneID_; }
    149166
    150             inline void setGametype(const SmartPtr<Gametype>& gametype)
    151             {
    152                 if (gametype != this->gametype_)
    153                 {
    154                     this->oldGametype_ = this->gametype_;
    155                     this->gametype_ = gametype;
    156                     this->changedGametype();
    157                 }
    158             }
    159             inline const SmartPtr<Gametype>& getGametype() const { return this->gametype_; }
    160             inline Gametype* getOldGametype() const { return this->oldGametype_; }
    161             virtual void changedGametype() {}
    162 
    163             inline void setLevel(const SmartPtr<Level>& level)
    164             {
    165                 if (level != this->level_)
    166                 {
    167                     this->level_ = level;
    168                     this->changedLevel();
    169                 }
    170             }
    171             inline const SmartPtr<Level>& getLevel() const { return this->level_; }
    172             virtual void changedLevel() {}
     167            inline void setGametype(const StrongOrWeakPtr<Gametype>& gametype) { this->gametype_ = gametype; }
     168            inline Gametype* getGametype() const { return this->gametype_.get(); }
     169
     170            inline void setLevel(const StrongOrWeakPtr<Level>& level) { this->level_ = level; }
     171            inline Level* getLevel() const { return this->level_.get(); }
    173172
    174173            void addEventSource(BaseObject* source, const std::string& state);
     
    217216            void registerEventStates();
    218217
    219             bool                   bInitialized_;              //!< True if the object was initialized (passed the object registration)
    220             const XMLFile*         file_;                      //!< The XMLFile that loaded this object
    221             Element*               lastLoadedXMLElement_;      //!< Non 0 if the TinyXML attributes have already been copied to our own lowercase map
     218            bool                       bInitialized_;          //!< True if the object was initialized (passed the object registration)
     219            const XMLFile*             file_;                  //!< The XMLFile that loaded this object
     220            Element*                   lastLoadedXMLElement_;  //!< Non 0 if the TinyXML attributes have already been copied to our own lowercase map
    222221            std::map<std::string, std::string> xmlAttributes_; //!< Lowercase XML attributes
    223             std::string            loaderIndentation_;         //!< Indentation of the debug output in the Loader
    224             SmartPtr<Namespace>    namespace_;
    225             BaseObject*            creator_;
    226             SmartPtr<Scene>        scene_;
    227             uint32_t               sceneID_;
    228             SmartPtr<Gametype>     gametype_;
    229             Gametype*              oldGametype_;
    230             SmartPtr<Level>        level_;
    231             std::set<Template*>    templates_;
     222            std::string                loaderIndentation_;     //!< Indentation of the debug output in the Loader
     223            StrongOrWeakPtr<Namespace> namespace_;
     224            BaseObject*                creator_;
     225            StrongOrWeakPtr<Scene>     scene_;
     226            uint32_t                   sceneID_;
     227            StrongOrWeakPtr<Gametype>  gametype_;
     228            StrongOrWeakPtr<Level>     level_;
     229            std::set<Template*>        templates_;
    232230
    233231            std::map<BaseObject*, std::string>  eventSources_;           //!< List of objects which send events to this object, mapped to the state which they affect
     
    243241    SUPER_FUNCTION(4, BaseObject, XMLEventPort, false);
    244242    SUPER_FUNCTION(8, BaseObject, changedName, false);
    245     SUPER_FUNCTION(9, BaseObject, changedGametype, false);
     243
     244    template <class T>
     245    BaseObject::StrongOrWeakPtr<T>::StrongOrWeakPtr()
     246    {
     247    }
     248
     249    template <class T>
     250    BaseObject::StrongOrWeakPtr<T>::StrongOrWeakPtr(const StrongPtr<T>& ptr) : strongPtr_(ptr)
     251    {
     252    }
     253
     254    template <class T>
     255    BaseObject::StrongOrWeakPtr<T>::StrongOrWeakPtr(const WeakPtr<T>& ptr) : weakPtr_(ptr)
     256    {
     257    }
     258
     259    template <class T>
     260    T* BaseObject::StrongOrWeakPtr<T>::get() const
     261    {
     262        if (this->strongPtr_)
     263            return this->strongPtr_;
     264        else if (this->weakPtr_)
     265            return this->weakPtr_;
     266        else
     267            return NULL;
     268    }
     269
     270    template <class T>
     271    StrongPtr<T> BaseObject::StrongOrWeakPtr<T>::createStrongPtr() const
     272    {
     273        if (this->strongPtr_)
     274            return this->strongPtr_; // creates a copy
     275        else
     276            return this->weakPtr_; // converts automatically to StrongPtr
     277    }
    246278}
    247279
  • code/trunk/src/libraries/core/CMakeLists.txt

    r10268 r10624  
    2222#BUILD_UNIT CoreStableBuildUnit.cc
    2323  ClassTreeMask.cc
    24   DynLib.cc
    25   DynLibManager.cc
    2624  Event.cc
    2725  Game.cc
     26  GameConfig.cc
    2827  GameMode.cc
    2928  GameState.cc
     
    3433  NamespaceNode.cc
    3534  Template.cc
     35  UpdateListener.cc
    3636  ViewportEventListener.cc
    3737  WindowEventListener.cc
     
    4242  BaseObject.cc
    4343  Core.cc
     44  CoreConfig.cc
     45  CoreStaticInitializationHandler.cc
    4446
    4547BUILD_UNIT OgreBuildUnit.cc
     
    5254  command/ArgumentCompletionFunctions.cc
    5355  config/ConfigFile.cc
    54   PathConfig.cc
     56  ApplicationPaths.cc
     57  ConfigurablePaths.cc
    5558END_BUILD_UNIT
    5659
     
    6467ADD_SUBDIRECTORY(class)
    6568ADD_SUBDIRECTORY(command)
     69ADD_SUBDIRECTORY(commandline)
    6670ADD_SUBDIRECTORY(config)
    6771ADD_SUBDIRECTORY(input)
     72ADD_SUBDIRECTORY(module)
    6873ADD_SUBDIRECTORY(object)
     74ADD_SUBDIRECTORY(singleton)
    6975
    7076#Add the icon (for the renderwindow)
     
    7884    command/CommandExecutor.h
    7985    config/SettingsConfigFile.h
     86    ApplicationPaths.h
     87    ConfigurablePaths.h
    8088    Game.h
    8189    GameMode.h
     
    8492    Loader.h
    8593    LuaState.h
    86     PathConfig.h
    8794    input/InputManager.h
    8895    input/KeyBinder.h
  • code/trunk/src/libraries/core/ClassTreeMask.cc

    r9667 r10624  
    293293        {
    294294            // No it's not: Search for classes inheriting from the given class and add the rules for them
    295             for (std::set<const Identifier*>::const_iterator it = subclass->getDirectChildrenBegin(); it != subclass->getDirectChildrenEnd(); ++it)
     295            for (std::set<const Identifier*>::const_iterator it = subclass->getDirectChildren().begin(); it != subclass->getDirectChildren().end(); ++it)
    296296                if ((*it)->isA(this->root_->getClass()))
    297297                    if (overwrite || (!this->nodeExists(*it))) // If we don't want to overwrite, only add nodes that don't already exist
     
    392392        if (!subclass)
    393393            return;
    394         for (std::set<const Identifier*>::const_iterator it = subclass->getDirectChildrenBegin(); it != subclass->getDirectChildrenEnd(); ++it)
     394        for (std::set<const Identifier*>::const_iterator it = subclass->getDirectChildren().begin(); it != subclass->getDirectChildren().end(); ++it)
    395395            this->add(*it, this->isIncluded(*it), false, false);
    396396
     
    943943
    944944                                // Insert all directChildren of the directChild
    945                                 directChildren.insert((*it2)->getDirectChildrenBegin(), (*it2)->getDirectChildrenEnd());
     945                                directChildren.insert((*it2)->getDirectChildren().begin(), (*it2)->getDirectChildren().end());
    946946
    947947                                // Restart the scan with the expanded set of directChildren
  • code/trunk/src/libraries/core/Core.cc

    r9667 r10624  
    5454#include "util/Output.h"
    5555#include "util/Exception.h"
     56#include "util/SignalHandler.h"
    5657#include "util/output/LogWriter.h"
    5758#include "util/output/OutputManager.h"
    58 #include "util/Scope.h"
    59 #include "util/ScopedSingletonManager.h"
    60 #include "util/SignalHandler.h"
    61 #include "PathConfig.h"
    62 #include "config/CommandLineParser.h"
     59#include "core/singleton/Scope.h"
     60#include "ApplicationPaths.h"
     61#include "ConfigurablePaths.h"
     62#include "commandline/CommandLineIncludes.h"
    6363#include "config/ConfigFileManager.h"
    64 #include "config/ConfigValueIncludes.h"
    65 #include "CoreIncludes.h"
    66 #include "DynLibManager.h"
    6764#include "GameMode.h"
    6865#include "GraphicsManager.h"
    6966#include "GUIManager.h"
    70 #include "class/Identifier.h"
    7167#include "Language.h"
     68#include "Loader.h"
    7269#include "LuaState.h"
    73 #include "command/ConsoleCommand.h"
    7470#include "command/IOConsole.h"
    7571#include "command/TclBind.h"
     
    7773#include "input/InputManager.h"
    7874#include "object/ObjectList.h"
     75#include "module/DynLibManager.h"
     76#include "module/ModuleInstance.h"
     77#include "module/StaticInitializationManager.h"
     78#include "module/PluginManager.h"
     79#include "CoreStaticInitializationHandler.h"
     80#include "UpdateListener.h"
    7981
    8082namespace orxonox
     
    9294#endif
    9395
    94     // register Core as an abstract class to avoid problems if the class hierarchy is created within Core-constructor
    95     RegisterAbstractClass(Core).inheritsFrom(Class(Configurable));
    96 
    9796    Core::Core(const std::string& cmdLine)
    98         : pathConfig_(NULL)
     97        : applicationPaths_(NULL)
     98        , configurablePaths_(NULL)
    9999        , dynLibManager_(NULL)
    100100        , signalHandler_(NULL)
    101101        , configFileManager_(NULL)
    102102        , languageInstance_(NULL)
     103        , loaderInstance_(NULL)
    103104        , ioConsole_(NULL)
    104105        , tclBind_(NULL)
     
    110111        , graphicsScope_(NULL)
    111112        , bGraphicsLoaded_(false)
    112         , bStartIOConsole_(true)
    113         , lastLevelTimestamp_(0)
    114         , ogreConfigTimestamp_(0)
    115         , bDevMode_(false)
     113        , staticInitHandler_(NULL)
     114        , pluginManager_(NULL)
     115        , rootModule_(NULL)
     116        , config_(NULL)
    116117        , destructionHelper_(this)
    117118    {
     
    119120
    120121        // Set the hard coded fixed paths
    121         this->pathConfig_ = new PathConfig();
     122        this->applicationPaths_ = new ApplicationPaths();
    122123
    123124        // Create a new dynamic library manager
    124125        this->dynLibManager_ = new DynLibManager();
    125126
    126         // Load modules
    127         orxout(internal_info) << "Loading modules:" << endl;
    128         const std::vector<std::string>& modulePaths = this->pathConfig_->getModulePaths();
    129         for (std::vector<std::string>::const_iterator it = modulePaths.begin(); it != modulePaths.end(); ++it)
    130         {
    131             try
    132             {
    133                 this->dynLibManager_->load(*it);
    134             }
    135             catch (...)
    136             {
    137                 orxout(user_error) << "Couldn't load module \"" << *it << "\": " << Exception::handleMessage() << endl;
    138             }
    139         }
     127        // create handler for static initialization
     128        new StaticInitializationManager(); // create singleton
     129        this->staticInitHandler_ = new CoreStaticInitializationHandler();
     130        StaticInitializationManager::getInstance().addHandler(this->staticInitHandler_);
     131
     132        // load root module (all libraries which are linked to the executable, including core, network, and orxonox)
     133        this->rootModule_ = ModuleInstance::getCurrentModuleInstance();
     134        StaticInitializationManager::getInstance().loadModule(this->rootModule_);
    140135
    141136        // Parse command line arguments AFTER the modules have been loaded (static code!)
     
    143138
    144139        // Set configurable paths like log, config and media
    145         this->pathConfig_->setConfigurablePaths();
    146 
    147         orxout(internal_info) << "Root path:       " << PathConfig::getRootPathString() << endl;
    148         orxout(internal_info) << "Executable path: " << PathConfig::getExecutablePathString() << endl;
    149         orxout(internal_info) << "Data path:       " << PathConfig::getDataPathString() << endl;
    150         orxout(internal_info) << "Ext. data path:  " << PathConfig::getExternalDataPathString() << endl;
    151         orxout(internal_info) << "Config path:     " << PathConfig::getConfigPathString() << endl;
    152         orxout(internal_info) << "Log path:        " << PathConfig::getLogPathString() << endl;
    153         orxout(internal_info) << "Modules path:    " << PathConfig::getModulePathString() << endl;
    154 
    155         // create a signal handler (only active for Linux)
     140        this->configurablePaths_ = new ConfigurablePaths();
     141        this->configurablePaths_->setConfigurablePaths(ApplicationPaths::getInstance());
     142
     143        orxout(internal_info) << "Root path:       " << ApplicationPaths::getRootPathString() << endl;
     144        orxout(internal_info) << "Executable path: " << ApplicationPaths::getExecutablePathString() << endl;
     145        orxout(internal_info) << "Modules path:    " << ApplicationPaths::getModulePathString() << endl;
     146        orxout(internal_info) << "Plugins path:    " << ApplicationPaths::getPluginPathString() << endl;
     147
     148        orxout(internal_info) << "Data path:       " << ConfigurablePaths::getDataPathString() << endl;
     149        orxout(internal_info) << "Ext. data path:  " << ConfigurablePaths::getExternalDataPathString() << endl;
     150        orxout(internal_info) << "Config path:     " << ConfigurablePaths::getConfigPathString() << endl;
     151        orxout(internal_info) << "Log path:        " << ConfigurablePaths::getLogPathString() << endl;
     152
     153        // create a signal handler
    156154        // This call is placed as soon as possible, but after the directories are set
    157155        this->signalHandler_ = new SignalHandler();
    158         this->signalHandler_->doCatch(PathConfig::getExecutablePathString(), PathConfig::getLogPathString() + "orxonox_crash.log");
     156        this->signalHandler_->doCatch(ApplicationPaths::getExecutablePathString(), ConfigurablePaths::getLogPathString() + "orxonox_crash.log");
    159157
    160158#ifdef ORXONOX_PLATFORM_WINDOWS
     
    177175        this->languageInstance_ = new Language();
    178176
     177        // initialize root context
     178        Context::setRootContext(new Context(NULL));
     179
    179180        // Do this soon after the ConfigFileManager has been created to open up the
    180181        // possibility to configure everything below here
    181         RegisterObject(Core);
    182182        orxout(internal_info) << "configuring Core" << endl;
    183         this->setConfigValues();
     183        this->config_ = new CoreConfig();
    184184
    185185        // Set the correct log path and rewrite the log file with the correct log levels
    186         OutputManager::getInstance().getLogWriter()->setLogDirectory(PathConfig::getLogPathString());
     186        OutputManager::getInstance().getLogWriter()->setLogDirectory(ConfigurablePaths::getLogPathString());
    187187
    188188#if !defined(ORXONOX_PLATFORM_APPLE) && !defined(ORXONOX_USE_WINMAIN)
    189189        // Create persistent IO console
    190         if (CommandLineParser::getValue("noIOConsole").get<bool>())
    191         {
    192             ModifyConfigValue(bStartIOConsole_, tset, false);
    193         }
    194         if (this->bStartIOConsole_)
     190        if (CommandLineParser::getValue("noIOConsole").get<bool>() == false && this->config_->getStartIOConsole())
    195191        {
    196192            orxout(internal_info) << "creating IO console" << endl;
     
    201197        // creates the class hierarchy for all classes with factories
    202198        orxout(internal_info) << "creating class hierarchy" << endl;
    203         IdentifierManager::getInstance().createClassHierarchy();
     199        this->staticInitHandler_->initInstances(this->rootModule_);
     200        this->staticInitHandler_->setInitInstances(true);
     201
     202        // Create plugin manager and search for plugins
     203        this->pluginManager_ = new PluginManager();
     204        this->pluginManager_->findPlugins();
     205
     206        // Loader
     207        this->loaderInstance_ = new Loader();
    204208
    205209        // Load OGRE excluding the renderer and the render window
     
    208212
    209213        // initialise Tcl
    210         this->tclBind_ = new TclBind(PathConfig::getDataPathString());
     214        this->tclBind_ = new TclBind(ConfigurablePaths::getDataPathString());
    211215        this->tclThreadManager_ = new TclThreadManager(tclBind_->getTclInterpreter());
    212216
    213217        // Create singletons that always exist (in other libraries)
    214218        orxout(internal_info) << "creating root scope:" << endl;
    215         this->rootScope_ = new Scope<ScopeID::Root>();
     219        this->rootScope_ = new Scope<ScopeID::ROOT>();
    216220
    217221        // Generate documentation instead of normal run?
     
    237241        orxout(internal_status) << "destroying Core object..." << endl;
    238242
    239         // Remove us from the object lists again to avoid problems when destroying them
    240         this->unregisterObject();
    241 
    242243        safeObjectDelete(&graphicsScope_);
    243244        safeObjectDelete(&guiManager_);
     
    248249        safeObjectDelete(&tclBind_);
    249250        safeObjectDelete(&ioConsole_);
     251        safeObjectDelete(&loaderInstance_);
     252        safeObjectDelete(&config_);
    250253        safeObjectDelete(&languageInstance_);
    251254        safeObjectDelete(&configFileManager_);
    252         ConsoleCommand::destroyAll();
    253         Context::setRootContext(NULL);
    254         IdentifierManager::getInstance().destroyAllIdentifiers();
    255255        safeObjectDelete(&signalHandler_);
     256        safeObjectDelete(&pluginManager_);
     257        Context::getRootContext()->unregisterObject(); // unregister context from object lists - otherwise the root context would be destroyed while unloading the root module
     258        if (this->rootModule_)
     259        {
     260            StaticInitializationManager::getInstance().unloadModule(this->rootModule_);
     261            this->rootModule_->deleteAllStaticallyInitializedInstances();
     262        }
     263        if (this->staticInitHandler_)
     264            StaticInitializationManager::getInstance().removeHandler(this->staticInitHandler_);
     265        Context::destroyRootContext();
     266        safeObjectDelete(&rootModule_);
     267        safeObjectDelete(&staticInitHandler_);
     268        delete &StaticInitializationManager::getInstance();
    256269        safeObjectDelete(&dynLibManager_);
    257         safeObjectDelete(&pathConfig_);
     270        safeObjectDelete(&configurablePaths_);
     271        safeObjectDelete(&applicationPaths_);
    258272
    259273        orxout(internal_status) << "finished destroying Core object" << endl;
    260274    }
    261275
    262     //! Function to collect the SetConfigValue-macro calls.
    263     void Core::setConfigValues()
    264     {
    265         SetConfigValueExternal(OutputManager::getInstance().getLogWriter()->configurableMaxLevel_,
    266                                OutputManager::getInstance().getLogWriter()->getConfigurableSectionName(),
    267                                OutputManager::getInstance().getLogWriter()->getConfigurableMaxLevelName(),
    268                                OutputManager::getInstance().getLogWriter()->configurableMaxLevel_)
    269             .description("The maximum level of output shown in the log file")
    270             .callback(static_cast<BaseWriter*>(OutputManager::getInstance().getLogWriter()), &BaseWriter::changedConfigurableLevel);
    271         SetConfigValueExternal(OutputManager::getInstance().getLogWriter()->configurableAdditionalContextsMaxLevel_,
    272                                OutputManager::getInstance().getLogWriter()->getConfigurableSectionName(),
    273                                OutputManager::getInstance().getLogWriter()->getConfigurableAdditionalContextsMaxLevelName(),
    274                                OutputManager::getInstance().getLogWriter()->configurableAdditionalContextsMaxLevel_)
    275             .description("The maximum level of output shown in the log file for additional contexts")
    276             .callback(static_cast<BaseWriter*>(OutputManager::getInstance().getLogWriter()), &BaseWriter::changedConfigurableAdditionalContextsLevel);
    277         SetConfigValueExternal(OutputManager::getInstance().getLogWriter()->configurableAdditionalContexts_,
    278                                OutputManager::getInstance().getLogWriter()->getConfigurableSectionName(),
    279                                OutputManager::getInstance().getLogWriter()->getConfigurableAdditionalContextsName(),
    280                                OutputManager::getInstance().getLogWriter()->configurableAdditionalContexts_)
    281             .description("Additional output contexts shown in the log file")
    282             .callback(static_cast<BaseWriter*>(OutputManager::getInstance().getLogWriter()), &BaseWriter::changedConfigurableAdditionalContexts);
    283 
    284         SetConfigValue(bDevMode_, PathConfig::buildDirectoryRun())
    285             .description("Developer mode. If not set, hides some things from the user to not confuse him.")
    286             .callback(this, &Core::devModeChanged);
    287         SetConfigValue(language_, Language::getInstance().defaultLanguage_)
    288             .description("The language of the in game text")
    289             .callback(this, &Core::languageChanged);
    290         SetConfigValue(bInitRandomNumberGenerator_, true)
    291             .description("If true, all random actions are different each time you start the game")
    292             .callback(this, &Core::initRandomNumberGenerator);
    293         SetConfigValue(bStartIOConsole_, true)
    294             .description("Set to false if you don't want to use the IOConsole (for Lua debugging for instance)");
    295         SetConfigValue(lastLevelTimestamp_, 0)
    296             .description("Timestamp when the last level was started.");
    297         SetConfigValue(ogreConfigTimestamp_, 0)
    298             .description("Timestamp when the ogre config file was changed.");
    299     }
    300 
    301     /** Callback function for changes in the dev mode that affect debug levels.
    302         The function behaves according to these rules:
    303         - 'normal' mode is defined based on where the program was launched: if
    304           the launch path was the build directory, development mode \c on is
    305           normal, otherwise normal means development mode \c off.
    306         - Debug levels should not be hard configured (\c config instead of
    307           \c tconfig) in non 'normal' mode to avoid strange behaviour.
    308         - Changing the development mode from 'normal' to the other state will
    309           immediately change the debug levels to predefined values which can be
    310           reconfigured with \c tconfig.
    311     @note
    312         The debug levels for the IOConsole and the InGameConsole can be found
    313         in the Shell class. The same rules apply.
    314     */
    315     void Core::devModeChanged()
    316     {
    317         // Inform listeners
    318         ObjectList<DevModeListener>::iterator it = ObjectList<DevModeListener>::begin();
    319         for (; it != ObjectList<DevModeListener>::end(); ++it)
    320             it->devModeChanged(bDevMode_);
    321     }
    322 
    323     //! Callback function if the language has changed.
    324     void Core::languageChanged()
    325     {
    326         // Read the translation file after the language was configured
    327         Language::getInstance().readTranslatedLanguageFile();
    328     }
    329 
    330     void Core::initRandomNumberGenerator()
    331     {
    332         static bool bInitialized = false;
    333         if (!bInitialized && this->bInitRandomNumberGenerator_)
    334         {
    335             srand(static_cast<unsigned int>(time(0)));
    336             rand();
    337             bInitialized = true;
    338         }
     276    void Core::loadModules()
     277    {
     278        orxout(internal_info) << "Loading modules:" << endl;
     279
     280        const std::vector<std::string>& modulePaths = ApplicationPaths::getInstance().getModulePaths();
     281        for (std::vector<std::string>::const_iterator it = modulePaths.begin(); it != modulePaths.end(); ++it)
     282        {
     283            ModuleInstance* module = new ModuleInstance(*it);
     284            this->loadModule(module);
     285            this->modules_.push_back(module);
     286        }
     287
     288        orxout(internal_info) << "finished loading modules" << endl;
     289    }
     290
     291    void Core::loadModule(ModuleInstance* module)
     292    {
     293        orxout(internal_info) << "Loading module " << module->getLibraryName() << "..." << endl;
     294
     295        try
     296        {
     297            ModuleInstance::setCurrentModuleInstance(module);
     298            DynLib* dynLib = this->dynLibManager_->load(module->getLibraryName());
     299            module->setDynLib(dynLib);
     300
     301            StaticInitializationManager::getInstance().loadModule(module);
     302        }
     303        catch (...)
     304        {
     305            orxout(user_error) << "Couldn't load module \"" << module->getLibraryName() << "\": " << Exception::handleMessage() << endl;
     306        }
     307    }
     308
     309    void Core::unloadModules()
     310    {
     311        for (std::list<ModuleInstance*>::iterator it = this->modules_.begin(); it != this->modules_.end(); ++it)
     312        {
     313            ModuleInstance* module = (*it);
     314            this->unloadModule(module);
     315            delete module;
     316        }
     317        this->modules_.clear();
     318    }
     319
     320    void Core::unloadModule(ModuleInstance* module)
     321    {
     322        orxout(internal_info) << "Unloading module " << module->getLibraryName() << "..." << endl;
     323
     324        StaticInitializationManager::getInstance().unloadModule(module);
     325
     326        module->deleteAllStaticallyInitializedInstances();
     327        this->dynLibManager_->unload(module->getDynLib());
     328        module->setDynLib(NULL);
    339329    }
    340330
     
    344334
    345335        // Any exception should trigger this, even in upgradeToGraphics (see its remarks)
    346         Loki::ScopeGuard unloader = Loki::MakeObjGuard(*this, &Core::unloadGraphics);
     336        Loki::ScopeGuard unloader = Loki::MakeObjGuard(*this, &Core::unloadGraphics, true);
    347337
    348338        // Upgrade OGRE to receive a render window
     
    385375        // Create singletons associated with graphics (in other libraries)
    386376        orxout(internal_info) << "creating graphics scope:" << endl;
    387         graphicsScope_ = new Scope<ScopeID::Graphics>();
     377        graphicsScope_ = new Scope<ScopeID::GRAPHICS>();
    388378
    389379        unloader.Dismiss();
     
    392382    }
    393383
    394     void Core::unloadGraphics()
     384    void Core::unloadGraphics(bool loadGraphicsManagerWithoutRenderer)
    395385    {
    396386        orxout(internal_info) << "unloading graphics in Core" << endl;
     387
     388        if (this->graphicsManager_)
     389            this->graphicsManager_->unloadDebugOverlay();
    397390
    398391        safeObjectDelete(&graphicsScope_);
     
    403396        // Load Ogre::Root again, but without the render system
    404397        try
    405             { this->graphicsManager_ = new GraphicsManager(false); }
     398        {
     399            if (loadGraphicsManagerWithoutRenderer)
     400                this->graphicsManager_ = new GraphicsManager(false);
     401        }
    406402        catch (...)
    407403        {
     
    414410        bGraphicsLoaded_ = false;
    415411        GameMode::bShowsGraphics_s = false;
    416     }
    417 
    418     //! Sets the language in the config-file back to the default.
    419     void Core::resetLanguage()
    420     {
    421         ResetConfigValue(language_);
    422412    }
    423413
     
    470460    void Core::preUpdate(const Clock& time)
    471461    {
    472         // Update singletons before general ticking
    473         ScopedSingletonManager::preUpdate<ScopeID::Root>(time);
     462        // Update UpdateListeners before general ticking
     463        for (ObjectList<UpdateListener>::iterator it = ObjectList<UpdateListener>::begin(); it != ObjectList<UpdateListener>::end(); ++it)
     464            it->preUpdate(time);
    474465        if (this->bGraphicsLoaded_)
    475466        {
     
    478469            // Update GUI
    479470            this->guiManager_->preUpdate(time);
    480             // Update singletons before general ticking
    481             ScopedSingletonManager::preUpdate<ScopeID::Graphics>(time);
    482471        }
    483472        // Process console events and status line
     
    490479    void Core::postUpdate(const Clock& time)
    491480    {
    492         // Update singletons just before rendering
    493         ScopedSingletonManager::postUpdate<ScopeID::Root>(time);
     481        // Update UpdateListeners just before rendering
     482        for (ObjectList<UpdateListener>::iterator it = ObjectList<UpdateListener>::begin(); it != ObjectList<UpdateListener>::end(); ++it)
     483            it->postUpdate(time);
    494484        if (this->bGraphicsLoaded_)
    495485        {
    496             // Update singletons just before rendering
    497             ScopedSingletonManager::postUpdate<ScopeID::Graphics>(time);
    498486            // Render (doesn't throw)
    499487            this->graphicsManager_->postUpdate(time);
    500488        }
    501489    }
    502 
    503     void Core::updateLastLevelTimestamp()
    504     {
    505         ModifyConfigValue(lastLevelTimestamp_, set, static_cast<long long>(time(NULL)));
    506     }
    507 
    508     void Core::updateOgreConfigTimestamp()
    509     {
    510         ModifyConfigValue(ogreConfigTimestamp_, set, static_cast<long long>(time(NULL)));
    511     }
    512 
    513 
    514     RegisterAbstractClass(DevModeListener).inheritsFrom(Class(Listable));
    515 
    516     DevModeListener::DevModeListener()
    517     {
    518         RegisterObject(DevModeListener);
    519     }
    520490}
  • code/trunk/src/libraries/core/Core.h

    r9667 r10624  
    4747#include "util/DestructionHelper.h"
    4848#include "util/Singleton.h"
    49 #include "config/Configurable.h"
     49#include "CoreConfig.h"
    5050
    5151namespace orxonox
    5252{
    53     //! Informs about changes in the Development Mode.
    54     class DevModeListener : virtual public Listable
    55     {
    56     public:
    57         DevModeListener();
    58         virtual ~DevModeListener() {}
    59         virtual void devModeChanged(bool value) = 0;
    60     };
    61 
    6253    /**
    6354    @brief
     
    6657        You should only create this singleton once because it destroys the identifiers!
    6758    */
    68     class _CoreExport Core : public Singleton<Core>, public Configurable
     59    class _CoreExport Core : public Singleton<Core>
    6960    {
    7061        friend class Singleton<Core>;
    71         friend class Game;
    7262
    7363        public:
     
    8676            void destroy();
    8777
    88             void setConfigValues();
     78            void preUpdate(const Clock& time);
     79            void postUpdate(const Clock& time);
    8980
    90             //! Returns the configured language.
    91             const std::string& getLanguage()
    92                 { return this->language_; }
    93             void resetLanguage();
     81            void loadGraphics();
     82            void unloadGraphics(bool loadGraphicsManagerWithoutRenderer = true);
    9483
    95             void updateLastLevelTimestamp();
    96             inline long long getLastLevelTimestamp() const
    97                 { return this->lastLevelTimestamp_; }
     84            void loadModules();
     85            void unloadModules();
     86            void loadModule(ModuleInstance* module);
     87            void unloadModule(ModuleInstance* module);
    9888
    99             void updateOgreConfigTimestamp();
    100             inline long long getOgreConfigTimestamp() const
    101                 { return this->ogreConfigTimestamp_; }
    102 
    103             //! Developers bit. If returns false, some options are not available as to not confuse the normal user.
    104             inline bool inDevMode(void) const
    105                 { return this->bDevMode_; }
     89            inline CoreConfig* getConfig() const
     90                { return this->config_; }
    10691
    10792        private:
    10893            Core(const Core&); //!< Don't use (undefined symbol)
    10994
    110             void devModeChanged();
    111             void languageChanged();
    112             void initRandomNumberGenerator();
    113 
    114             void preUpdate(const Clock& time);
    115             void postUpdate(const Clock& time);
    116 
    117             void loadGraphics();
    118             void unloadGraphics();
    119 
    12095            void setThreadAffinity(int limitToCPU);
    12196
    122             PathConfig*               pathConfig_;
    123             DynLibManager*            dynLibManager_;
    124             SignalHandler*            signalHandler_;
    125             ConfigFileManager*        configFileManager_;
    126             Language*                 languageInstance_;
    127             IOConsole*                ioConsole_;
    128             TclBind*                  tclBind_;
    129             TclThreadManager*         tclThreadManager_;
    130             Scope<ScopeID::Root>*     rootScope_;
     97            ApplicationPaths*                applicationPaths_;
     98            ConfigurablePaths*               configurablePaths_;
     99            DynLibManager*                   dynLibManager_;
     100            SignalHandler*                   signalHandler_;
     101            ConfigFileManager*               configFileManager_;
     102            Language*                        languageInstance_;
     103            Loader*                          loaderInstance_;
     104            IOConsole*                       ioConsole_;
     105            TclBind*                         tclBind_;
     106            TclThreadManager*                tclThreadManager_;
     107            Scope<ScopeID::ROOT>*            rootScope_;
    131108            // graphical
    132             GraphicsManager*          graphicsManager_;            //!< Interface to OGRE
    133             InputManager*             inputManager_;               //!< Interface to OIS
    134             GUIManager*               guiManager_;                 //!< Interface to GUI
    135             Scope<ScopeID::Graphics>* graphicsScope_;
     109            GraphicsManager*                 graphicsManager_;            //!< Interface to OGRE
     110            InputManager*                    inputManager_;               //!< Interface to OIS
     111            GUIManager*                      guiManager_;                 //!< Interface to GUI
     112            Scope<ScopeID::GRAPHICS>*        graphicsScope_;
     113            bool                             bGraphicsLoaded_;
    136114
    137             bool                      bGraphicsLoaded_;
    138             std::string               language_;                   //!< The language
    139             bool                      bInitRandomNumberGenerator_; //!< If true, srand(time(0)) is called
    140             bool                      bStartIOConsole_;            //!< Set to false if you don't want to use the IOConsole
    141             long long                 lastLevelTimestamp_;         ///< Timestamp when the last level was started
    142             long long                 ogreConfigTimestamp_;        ///< Timestamp wehen the ogre config level was modified
    143             bool                      bDevMode_;                   //!< Developers bit. If set to false, some options are not available as to not confuse the normal user.
     115            CoreStaticInitializationHandler* staticInitHandler_;
     116            PluginManager*                   pluginManager_;
     117            ModuleInstance*                  rootModule_;
     118            std::list<ModuleInstance*>       modules_;
     119
     120            /// Helper object that stores the config values
     121            CoreConfig*                      config_;
    144122
    145123            /// Helper object that executes the surrogate destructor destroy()
    146             DestructionHelper<Core>   destructionHelper_;
     124            DestructionHelper<Core>          destructionHelper_;
    147125
    148             static Core*              singletonPtr_s;
     126            static Core*                     singletonPtr_s;
    149127    };
    150128}
  • code/trunk/src/libraries/core/CoreIncludes.h

    r10208 r10624  
    8484#include "object/ClassFactory.h"
    8585#include "object/ObjectList.h"
     86#include "module/StaticallyInitializedInstance.h"
    8687
    8788// resolve macro conflict on windows
     
    126127*/
    127128#define RegisterClassWithFactory(ClassName, FactoryInstance, bLoadable) \
    128     Identifier& _##ClassName##Identifier = orxonox::registerClass<ClassName>(#ClassName, FactoryInstance, bLoadable)
     129    orxonox::SI_I& _##ClassName##Identifier = (*new orxonox::SI_I(orxonox::registerClass<ClassName>(#ClassName, FactoryInstance, bLoadable)))
    129130
    130131/**
     
    133134*/
    134135#define RegisterObject(ClassName) \
    135     if (ClassIdentifier<ClassName>::getIdentifier(#ClassName)->initializeObject(this)) \
     136    if (ClassIdentifier<ClassName>::getIdentifier()->initializeObject(this)) \
    136137        return; \
    137138    else \
     
    152153     */
    153154    template <class T>
    154     inline Identifier& registerClass(const std::string& name, ClassFactory<T>* factory, bool bLoadable = true)
     155    inline Identifier* registerClass(const std::string& name, ClassFactory<T>* factory, bool bLoadable = true)
    155156    {
    156157        return registerClass<T>(name, static_cast<Factory*>(factory), bLoadable);
     
    164165     */
    165166    template <class T>
    166     inline Identifier& registerClass(const std::string& name, Factory* factory, bool bLoadable = true)
    167     {
    168         orxout(verbose, context::misc::factory) << "Create entry for " << name << " in Factory." << endl;
    169         Identifier* identifier = ClassIdentifier<T>::getIdentifier(name);
    170         identifier->setFactory(factory);
    171         identifier->setLoadable(bLoadable);
    172         return *identifier;
     167    inline Identifier* registerClass(const std::string& name, Factory* factory, bool bLoadable = true)
     168    {
     169        return new ClassIdentifier<T>(name, factory, bLoadable);
    173170    }
    174171
     
    211208        return ClassIdentifier<T>::getIdentifier();
    212209    }
     210
     211
     212
     213
     214    /**
     215     * The static initializer stores the parent classes of this identifier. The corresponding identifiers are later loaded. This prevents identifiers from
     216     * being used before they are completely initialized.
     217     */
     218    class _CoreExport StaticallyInitializedIdentifier : public StaticallyInitializedInstance
     219    {
     220        template <class T>
     221        struct InheritsFromClass : public Identifier::InheritsFrom
     222        {
     223            virtual Identifier* getParent() const { return Class(T); }
     224        };
     225
     226        public:
     227            StaticallyInitializedIdentifier(Identifier* identifier)
     228                : StaticallyInitializedInstance(StaticInitialization::IDENTIFIER)
     229                , identifier_(identifier)
     230            {}
     231            ~StaticallyInitializedIdentifier() { delete identifier_; }
     232
     233            virtual void load()
     234            {
     235                IdentifierManager::getInstance().addIdentifier(this->identifier_);
     236            }
     237
     238            virtual void unload()
     239            {
     240                IdentifierManager::getInstance().removeIdentifier(this->identifier_);
     241            }
     242
     243            inline Identifier& getIdentifier()
     244                { return *this->identifier_; }
     245
     246            template <class T>
     247            inline StaticallyInitializedIdentifier& inheritsFrom()
     248                { this->identifier_->inheritsFrom(new InheritsFromClass<T>()); return *this; }
     249
     250            inline StaticallyInitializedIdentifier& virtualBase()
     251                { this->identifier_->setVirtualBase(true); return *this; }
     252
     253        private:
     254            Identifier* identifier_;
     255    };
     256
     257    typedef StaticallyInitializedIdentifier SI_I;
    213258}
    214259
  • code/trunk/src/libraries/core/CorePrereqs.h

    r9978 r10624  
    7777namespace orxonox
    7878{
     79    namespace ScopeID
     80    {
     81        typedef int Value;
     82
     83        //!A list of available scopes for the Scope template.
     84        static const Value ROOT = 1;
     85        static const Value GRAPHICS = 2;
     86    }
     87
     88    namespace StaticInitialization
     89    {
     90        typedef int Type;
     91
     92        static const Type STATIC_INITIALIZATION_HANDLER = 1;
     93        static const Type IDENTIFIER = 2;
     94        static const Type SCOPED_SINGLETON_WRAPPER = 3;
     95        static const Type COMMAND_LINE_ARGUMENT = 4;
     96        static const Type CONSOLE_COMMAND = 5;
     97    }
     98
    7999    namespace XMLPort
    80100    {
     
    123143    T orxonox_cast(U*);
    124144
     145    class ApplicationPaths;
    125146    class BaseObject;
    126147    template <class T>
     
    143164    class ConfigFileSection;
    144165    class Configurable;
     166    class ConfigurablePaths;
    145167    class ConfigValueContainer;
    146168    class Context;
    147169    class Core;
     170    class CoreConfig;
     171    class CoreStaticInitializationHandler;
    148172    class Destroyable;
     173    class DestroyLaterManager;
    149174    class DestructionListener;
    150175    class DynLib;
     
    154179    class Factory;
    155180    class Game;
     181    class GameConfig;
    156182    class GameState;
    157183    struct GameStateInfo;
     
    165191    class Language;
    166192    class Listable;
     193    class Loader;
    167194    class LuaFunctor;
    168195    class LuaState;
    169196    class MemoryArchive;
    170197    class MemoryArchiveFactory;
     198    class ModuleInstance;
    171199    class Namespace;
    172200    class NamespaceNode;
     
    182210    class OrxonoxClass;
    183211    class OrxonoxInterface;
    184     class PathConfig;
     212    class Plugin;
     213    class PluginManager;
     214    class PluginReference;
    185215    struct ResourceInfo;
     216    template <ScopeID::Value>
     217    class Scope;
     218    class ScopeManager;
     219    class ScopedSingletonWrapper;
    186220    class SettingsConfigFile;
    187     template <class T>
    188     class SmartPtr;
     221    class StaticallyInitializedInstance;
     222    class StaticInitializationHandler;
     223    class StaticInitializationManager;
     224    template <class T>
     225    class StrongPtr;
    189226    template <class T>
    190227    class SubclassIdentifier;
     
    192229    class Thread;
    193230    class ThreadPool;
     231    class UpdateListener;
    194232    class ViewportEventListener;
    195233    template <class T>
     
    210248    class CommandEvaluation;
    211249    class ConsoleCommand;
     250    class ConsoleCommandManager;
    212251    class Executor;
    213252    template <class T>
  • code/trunk/src/libraries/core/GUIManager.cc

    r10279 r10624  
    106106#include "GraphicsManager.h"
    107107#include "LuaState.h"
    108 #include "PathConfig.h"
     108#include "ConfigurablePaths.h"
    109109#include "Resource.h"
    110 #include "command/ConsoleCommand.h"
     110#include "command/ConsoleCommandIncludes.h"
    111111#include "input/InputManager.h"
    112112#include "input/InputState.h"
     
    255255    SetConsoleCommand("toggleGUI", &GUIManager::toggleGUI).defaultValue(1, false).defaultValue(2, false);
    256256
     257    RegisterAbstractClass(GUIManager).inheritsFrom<WindowEventListener>();
     258
    257259    /**
    258260    @brief
     
    329331        // Create our own logger to specify the filepath
    330332        std::auto_ptr<CEGUILogger> ceguiLogger(new CEGUILogger());
    331         ceguiLogger->setLogFilename(PathConfig::getLogPathString() + "cegui.log");
     333        ceguiLogger->setLogFilename(ConfigurablePaths::getLogPathString() + "cegui.log");
    332334        ceguiLogger->setLoggingLevel(static_cast<CEGUI::LoggingLevel>(this->outputLevelCeguiLog_));
    333335        this->ceguiLogger_ = ceguiLogger.release();
     
    833835    /*static*/ bool GUIManager::inDevMode()
    834836    {
    835          return Core::getInstance().inDevMode();
     837         return Core::getInstance().getConfig()->inDevMode();
    836838    }
    837839
  • code/trunk/src/libraries/core/Game.cc

    r9667 r10624  
    4545#include "util/SubString.h"
    4646#include "Core.h"
    47 #include "CoreIncludes.h"
    48 #include "config/CommandLineParser.h"
    49 #include "config/ConfigValueIncludes.h"
     47#include "commandline/CommandLineParser.h"
     48#include "GameConfig.h"
    5049#include "GameMode.h"
    5150#include "GameState.h"
    5251#include "GraphicsManager.h"
    5352#include "GUIManager.h"
    54 #include "command/ConsoleCommand.h"
     53#include "command/ConsoleCommandIncludes.h"
    5554
    5655namespace orxonox
     
    8281        , bChangingState_(false)
    8382        , bAbort_(false)
     83        , config_(NULL)
    8484        , destructionHelper_(this)
    8585    {
     
    110110        orxout(internal_info) << "creating Core object:" << endl;
    111111        this->core_ = new Core(cmdLine);
     112        this->core_->loadModules();
    112113
    113114        // Do this after the Core creation!
    114         RegisterObject(Game);
    115         this->setConfigValues();
     115        this->config_ = new GameConfig();
    116116
    117117        // After the core has been created, we can safely instantiate the GameStates that don't require graphics
     
    136136        orxout(internal_status) << "destroying Game object..." << endl;
    137137
    138         // Remove us from the object lists again to avoid problems when destroying them
    139         this->unregisterObject();
    140 
    141138        assert(loadedStates_.size() <= 1); // Just empty root GameState
    142139        // Destroy all GameStates (shared_ptrs take care of actual destruction)
     
    144141
    145142        GameStateFactory::getFactories().clear();
     143        safeObjectDelete(&config_);
     144        if (this->core_)
     145            this->core_->unloadModules();
    146146        safeObjectDelete(&core_);
    147147        safeObjectDelete(&gameClock_);
    148148
    149149        orxout(internal_status) << "finished destroying Game object..." << endl;
    150     }
    151 
    152     void Game::setConfigValues()
    153     {
    154         SetConfigValue(statisticsRefreshCycle_, 250000)
    155             .description("Sets the time in microseconds interval at which average fps, etc. get updated.");
    156         SetConfigValue(statisticsAvgLength_, 1000000)
    157             .description("Sets the time in microseconds interval at which average fps, etc. gets calculated.");
    158 
    159         SetConfigValueExternal(fpsLimit_, "GraphicsSettings", "fpsLimit", 50)
    160             .description("Sets the desired frame rate (0 for no limit).");
    161150    }
    162151
     
    229218            // Limit frame rate
    230219            static bool hasVSync = GameMode::showsGraphics() && GraphicsManager::getInstance().hasVSyncEnabled(); // can be static since changes of VSync currently require a restart
    231             if (this->fpsLimit_ > 0 && !hasVSync)
     220            if (this->config_->getFpsLimit() > 0 && !hasVSync)
    232221                this->updateFPSLimiter();
    233222        }
     
    311300        this->statisticsTickTimes_.back().tickLength += (uint32_t)(currentRealTime - currentTime);
    312301        this->periodTickTime_ += (uint32_t)(currentRealTime - currentTime);
    313         if (this->periodTime_ > this->statisticsRefreshCycle_)
     302        if (this->periodTime_ > this->config_->getStatisticsRefreshCycle())
    314303        {
    315304            std::list<StatisticsTickInfo>::iterator it = this->statisticsTickTimes_.begin();
    316305            assert(it != this->statisticsTickTimes_.end());
    317             int64_t lastTime = currentTime - this->statisticsAvgLength_;
     306            int64_t lastTime = currentTime - this->config_->getStatisticsAvgLength();
    318307            if (static_cast<int64_t>(it->tickTime) < lastTime)
    319308            {
     
    333322            this->avgTickTime_ = static_cast<float>(this->periodTickTime_) / framesPerPeriod / 1000.0f;
    334323
    335             this->periodTime_ -= this->statisticsRefreshCycle_;
     324            this->periodTime_ -= this->config_->getStatisticsRefreshCycle();
    336325        }
    337326    }
     
    339328    void Game::updateFPSLimiter()
    340329    {
    341         uint64_t nextTime = gameClock_->getMicroseconds() - excessSleepTime_ + static_cast<uint32_t>(1000000.0f / fpsLimit_);
     330        uint64_t nextTime = gameClock_->getMicroseconds() - excessSleepTime_ + static_cast<uint32_t>(1000000.0f / this->config_->getFpsLimit());
    342331        uint64_t currentRealTime = gameClock_->getRealMicroseconds();
    343332        while (currentRealTime < nextTime - minimumSleepTime_)
     
    529518
    530519            core_->loadGraphics();
    531             Loki::ScopeGuard graphicsUnloader = Loki::MakeObjGuard(*this, &Game::unloadGraphics);
     520            Loki::ScopeGuard graphicsUnloader = Loki::MakeObjGuard(*this, &Game::unloadGraphics, true);
    532521
    533522            // Construct all the GameStates that require graphics
     
    550539    }
    551540
    552     void Game::unloadGraphics()
     541    void Game::unloadGraphics(bool loadGraphicsManagerWithoutRenderer)
    553542    {
    554543        if (GameMode::showsGraphics())
     
    566555            }
    567556
    568             core_->unloadGraphics();
     557            core_->unloadGraphics(loadGraphicsManagerWithoutRenderer);
    569558        }
    570559    }
     
    587576
    588577        // If state requires graphics, load it
    589         Loki::ScopeGuard graphicsUnloader = Loki::MakeObjGuard(*this, &Game::unloadGraphics);
     578        Loki::ScopeGuard graphicsUnloader = Loki::MakeObjGuard(*this, &Game::unloadGraphics, true);
    590579        if (gameStateDeclarations_s[name].bGraphicsMode && !GameMode::showsGraphics())
    591580            this->loadGraphics();
     
    623612        }
    624613        // Check if graphics is still required
    625         if (!bAbort_)
    626         {
    627             bool graphicsRequired = false;
    628             for (unsigned i = 0; i < loadedStates_.size(); ++i)
    629                 graphicsRequired |= loadedStates_[i]->getInfo().bGraphicsMode;
    630             if (!graphicsRequired)
    631                 this->unloadGraphics();
    632         }
     614        bool graphicsRequired = false;
     615        for (unsigned i = 0; i < loadedStates_.size(); ++i)
     616            graphicsRequired |= loadedStates_[i]->getInfo().bGraphicsMode;
     617        if (!graphicsRequired)
     618            this->unloadGraphics(!this->bAbort_); // if abort is false, that means the game is still running while unloading graphics. in this case we load a graphics manager without renderer (to keep all necessary ogre instances alive)
    633619        this->bChangingState_ = false;
    634620    }
  • code/trunk/src/libraries/core/Game.h

    r9667 r10624  
    5050#include "util/DestructionHelper.h"
    5151#include "util/Singleton.h"
    52 #include "config/Configurable.h"
    5352
    5453/**
     
    8281    class _CoreExport Game
    8382// tolua_end
    84         : public Singleton<Game>, public Configurable
     83        : public Singleton<Game>
    8584    { // tolua_export
    8685        friend class Singleton<Game>;
     
    9695        /// Destructor that also executes when object fails to construct
    9796        void destroy();
    98 
    99         void setConfigValues();
    10097
    10198        void setStateHierarchy(const std::string& str);
     
    151148
    152149        void loadGraphics();
    153         void unloadGraphics();
     150        void unloadGraphics(bool loadGraphicsManagerWithoutRenderer = true);
    154151
    155152        void parseStates(std::vector<std::pair<std::string, int> >::const_iterator& it, shared_ptr<GameStateTreeNode> currentNode);
     
    189186        unsigned int                       minimumSleepTime_;
    190187
    191         // config values
    192         unsigned int                       statisticsRefreshCycle_;
    193         unsigned int                       statisticsAvgLength_;
    194         unsigned int                       fpsLimit_;
     188        /// Helper object that stores the config values
     189        GameConfig*                        config_;
    195190
    196191        /// Helper object that executes the surrogate destructor destroy()
  • code/trunk/src/libraries/core/GraphicsManager.cc

    r10295 r10624  
    5959#include "GUIManager.h"
    6060#include "Loader.h"
    61 #include "PathConfig.h"
     61#include "ApplicationPaths.h"
     62#include "ConfigurablePaths.h"
    6263#include "ViewportEventListener.h"
    6364#include "WindowEventListener.h"
    6465#include "XMLFile.h"
    65 #include "command/ConsoleCommand.h"
     66#include "command/ConsoleCommandIncludes.h"
    6667#include "input/InputManager.h"
    6768
     
    9495    GraphicsManager* GraphicsManager::singletonPtr_s = 0;
    9596
     97    RegisterAbstractClass(GraphicsManager).inheritsFrom<Configurable>();
     98
    9699    GraphicsManager::GraphicsManager(bool bLoadRenderer)
    97100        : ogreWindowEventListener_(new OgreWindowEventListener())
     
    111114
    112115        // At first, add the root paths of the data directories as resource locations
    113         Ogre::ResourceGroupManager::getSingleton().addResourceLocation(PathConfig::getDataPathString(), "FileSystem");
     116        Ogre::ResourceGroupManager::getSingleton().addResourceLocation(ConfigurablePaths::getDataPathString(), "FileSystem");
    114117        // Load resources
    115118        resources_.reset(new XMLFile("DefaultResources.oxr"));
    116119        resources_->setLuaSupport(false);
    117         Loader::open(resources_.get(), ClassTreeMask(), false);
     120        Loader::getInstance().load(resources_.get(), ClassTreeMask(), false);
    118121
    119122        // Only for runs in the build directory (not installed)
    120         if (PathConfig::buildDirectoryRun())
    121             Ogre::ResourceGroupManager::getSingleton().addResourceLocation(PathConfig::getExternalDataPathString(), "FileSystem");
     123        if (ApplicationPaths::buildDirectoryRun())
     124            Ogre::ResourceGroupManager::getSingleton().addResourceLocation(ConfigurablePaths::getExternalDataPathString(), "FileSystem");
    122125
    123126        extResources_.reset(new XMLFile("resources.oxr"));
    124127        extResources_->setLuaSupport(false);
    125         Loader::open(extResources_.get(), ClassTreeMask(), false);
     128        Loader::getInstance().load(extResources_.get(), ClassTreeMask(), false);
    126129
    127130        if (bLoadRenderer)
     
    137140    {
    138141        orxout(internal_status) << "destroying GraphicsManager..." << endl;
    139 
    140         Loader::unload(debugOverlay_.get());
    141142
    142143        Ogre::WindowEventUtilities::removeWindowEventListener(renderWindow_, ogreWindowEventListener_);
     
    147148
    148149        // Undeclare the resources
    149         Loader::unload(resources_.get());
    150         Loader::unload(extResources_.get());
     150        Loader::getInstance().unload(resources_.get());
     151        Loader::getInstance().unload(extResources_.get());
    151152
    152153        safeObjectDelete(&ogreRoot_);
     
    218219        }
    219220
    220         boost::filesystem::path ogreConfigFilepath(PathConfig::getConfigPath() / this->ogreConfigFile_);
    221         boost::filesystem::path ogreLogFilepath(PathConfig::getLogPath() / this->ogreLogFile_);
     221        boost::filesystem::path ogreConfigFilepath(ConfigurablePaths::getConfigPath() / this->ogreConfigFile_);
     222        boost::filesystem::path ogreLogFilepath(ConfigurablePaths::getLogPath() / this->ogreLogFile_);
    222223
    223224        // create a new logManager
     
    258259        std::string pluginPath = specialConfig::ogrePluginsDirectory;
    259260#ifdef DEPENDENCY_PACKAGE_ENABLE
    260         if (!PathConfig::buildDirectoryRun())
     261        if (!ApplicationPaths::buildDirectoryRun())
    261262        {
    262263#  if defined(ORXONOX_PLATFORM_WINDOWS)
    263             pluginPath = PathConfig::getExecutablePathString();
     264            pluginPath = ApplicationPaths::getExecutablePathString();
    264265#  elif defined(ORXONOX_PLATFORM_APPLE)
    265266            // TODO: Where are the plugins being installed to?
    266             pluginPath = PathConfig::getExecutablePathString();
     267            pluginPath = ApplicationPaths::getExecutablePathString();
    267268#  endif
    268269        }
     
    279280        orxout(internal_info) << "GraphicsManager: Configuring Renderer" << endl;
    280281
    281         bool updatedConfig = Core::getInstance().getOgreConfigTimestamp() > Core::getInstance().getLastLevelTimestamp();
     282        bool updatedConfig = Core::getInstance().getConfig()->getOgreConfigTimestamp() > Core::getInstance().getConfig()->getLastLevelTimestamp();
    282283        if (updatedConfig)
    283284            orxout(user_info)<< "Ogre config file has changed, but no level was started since then. Displaying config dialogue again to verify the changes." << endl;
     
    288289                ThrowException(InitialisationFailed, "OGRE graphics configuration dialogue canceled.");
    289290            else
    290                 Core::getInstance().updateOgreConfigTimestamp();
     291                Core::getInstance().getConfig()->updateOgreConfigTimestamp();
    291292        }
    292293
     
    328329        orxout(internal_info) << "Loading Debug Overlay..." << endl;
    329330        debugOverlay_.reset(new XMLFile("debug.oxo"));
    330         Loader::open(debugOverlay_.get(), ClassTreeMask(), false);
     331        Loader::getInstance().load(debugOverlay_.get(), ClassTreeMask(), false);
     332    }
     333
     334    void GraphicsManager::unloadDebugOverlay()
     335    {
     336        Loader::getInstance().unload(debugOverlay_.get());
    331337    }
    332338
     
    514520            GraphicsManager::getInstance().getRenderWindow()->setFullscreen(fullscreen, width, height);
    515521            this->ogreRoot_->saveConfig();
    516             Core::getInstance().updateOgreConfigTimestamp();
     522            Core::getInstance().getConfig()->updateOgreConfigTimestamp();
    517523            // Also reload the input devices
    518524            InputManager::getInstance().reload();
     
    532538            //this->ogreRoot_->getRenderSystem()->reinitialise(); // can't use this that easily, because it recreates the render window, invalidating renderWindow_
    533539            this->ogreRoot_->saveConfig();
    534             Core::getInstance().updateOgreConfigTimestamp();
     540            Core::getInstance().getConfig()->updateOgreConfigTimestamp();
    535541        }
    536542
     
    548554            //this->ogreRoot_->getRenderSystem()->reinitialise(); // can't use this that easily, because it recreates the render window, invalidating renderWindow_
    549555            this->ogreRoot_->saveConfig();
    550             Core::getInstance().updateOgreConfigTimestamp();
     556            Core::getInstance().getConfig()->updateOgreConfigTimestamp();
    551557        }
    552558
     
    557563    {
    558564        assert(this->renderWindow_);
    559         this->renderWindow_->writeContentsToTimestampedFile(PathConfig::getLogPathString() + "screenShot_", ".png");
     565        this->renderWindow_->writeContentsToTimestampedFile(ConfigurablePaths::getLogPathString() + "screenShot_", ".png");
    560566    }
    561567}
  • code/trunk/src/libraries/core/GraphicsManager.h

    r9675 r10624  
    9595        void upgradeToGraphics();
    9696        void loadDebugOverlay();
     97        void unloadDebugOverlay();
    9798        bool rendererLoaded() const { return renderWindow_ != NULL; }
    9899
  • code/trunk/src/libraries/core/Language.cc

    r8858 r10624  
    3737#include "util/Output.h"
    3838#include "util/StringUtils.h"
    39 #include "Core.h"
    40 #include "PathConfig.h"
     39#include "ConfigurablePaths.h"
    4140
    4241namespace orxonox
     
    203202        orxout(internal_info, context::language) << "Read default language file." << endl;
    204203
    205         const std::string& filepath = PathConfig::getConfigPathString() + getFilename(this->defaultLanguage_);
     204        const std::string& filepath = ConfigurablePaths::getConfigPathString() + getFilename(this->defaultLanguage_);
    206205
    207206        // This creates the file if it's not existing
     
    247246    /**
    248247        @brief Reads the language file of the configured language and assigns the localisation to the corresponding LanguageEntry object.
    249     */
    250     void Language::readTranslatedLanguageFile()
    251     {
    252         orxout(internal_info, context::language) << "Read translated language file (" << Core::getInstance().getLanguage() << ")." << endl;
    253 
    254         const std::string& filepath = PathConfig::getConfigPathString() + getFilename(Core::getInstance().getLanguage());
     248        @return Returns false if the language file couldn't be found.
     249    */
     250    bool Language::readTranslatedLanguageFile(const std::string& language)
     251    {
     252        orxout(internal_info, context::language) << "Read translated language file (" << language << ")." << endl;
     253
     254        const std::string& filepath = ConfigurablePaths::getConfigPathString() + getFilename(language);
    255255
    256256        // Open the file
     
    261261        {
    262262            orxout(internal_error, context::language) << "An error occurred in Language.cc:" << endl;
    263             orxout(internal_error, context::language) << "Couldn't open file " << getFilename(Core::getInstance().getLanguage()) << " to read the translated language entries!" << endl;
    264             Core::getInstance().resetLanguage();
    265             orxout(internal_info, context::language) << "Reset language to " << this->defaultLanguage_ << '.' << endl;
    266             return;
     263            orxout(internal_error, context::language) << "Couldn't open file " << getFilename(language) << " to read the translated language entries!" << endl;
     264            return false;
    267265        }
    268266
     
    291289                else
    292290                {
    293                     orxout(internal_warning, context::language) << "Invalid language entry \"" << lineString << "\" in " << getFilename(Core::getInstance().getLanguage()) << endl;
     291                    orxout(internal_warning, context::language) << "Invalid language entry \"" << lineString << "\" in " << getFilename(language) << endl;
    294292                }
    295293            }
     
    297295
    298296        file.close();
     297        return true;
    299298    }
    300299
     
    306305        orxout(verbose, context::language) << "Write default language file." << endl;
    307306
    308         const std::string& filepath = PathConfig::getConfigPathString() + getFilename(this->defaultLanguage_);
     307        const std::string& filepath = ConfigurablePaths::getConfigPathString() + getFilename(this->defaultLanguage_);
    309308
    310309        // Open the file
  • code/trunk/src/libraries/core/Language.h

    r8858 r10624  
    161161    {
    162162        friend class Singleton<Language>;
    163         friend class Core;
     163        friend class CoreConfig;
    164164
    165165        public:
     
    174174
    175175            void readDefaultLanguageFile();
    176             void readTranslatedLanguageFile();
     176            bool readTranslatedLanguageFile(const std::string& language);
    177177            void writeDefaultLanguageFile() const;
    178178            static std::string getFilename(const std::string& language);
  • code/trunk/src/libraries/core/Loader.cc

    r10278 r10624  
    4848namespace orxonox
    4949{
    50     std::vector<std::pair<const XMLFile*, ClassTreeMask> > Loader::files_s;
    51     ClassTreeMask Loader::currentMask_s;
    52 
    53     bool Loader::open(const XMLFile* file, const ClassTreeMask& mask, bool bVerbose)
    54     {
    55         Loader::add(file, mask);
    56         return Loader::load(file, mask, bVerbose);
    57     }
    58 
    59     void Loader::close()
    60     {
    61         Loader::unload();
    62         Loader::files_s.clear();
    63     }
    64 
    65     void Loader::close(const XMLFile* file)
    66     {
    67         Loader::unload(file);
    68         Loader::remove(file);
    69     }
    70 
    71     void Loader::add(const XMLFile* file, const ClassTreeMask& mask)
    72     {
    73         if (!file)
    74             return;
    75         Loader::files_s.insert(Loader::files_s.end(), std::pair<const XMLFile*, ClassTreeMask>(file, mask));
    76     }
    77 
    78     void Loader::remove(const XMLFile* file)
    79     {
    80         if (!file)
    81             return;
    82         for (std::vector<std::pair<const XMLFile*, ClassTreeMask> >::iterator it = Loader::files_s.begin(); it != Loader::files_s.end(); ++it)
    83         {
    84             if (it->first == file)
    85             {
    86                 Loader::files_s.erase(it);
    87                 break;
    88             }
    89         }
    90     }
    91 
    92     /**
    93     @brief
    94         Loads all opened files, while conforming to the restrictions given by the input ClassTreeMask.
    95     @param mask
    96         A ClassTreeMask, which defines which types of classes are loaded and which aren't.
    97     @param bVerbose
    98         Whether the loader is verbose (prints its progress in a low output level) or not.
    99     @return
    100         Returns true if successful.
    101     */
    102     bool Loader::load(const ClassTreeMask& mask, bool bVerbose)
    103     {
    104         bool success = true;
    105         for (std::vector<std::pair<const XMLFile*, ClassTreeMask> >::iterator it = Loader::files_s.begin(); it != Loader::files_s.end(); ++it)
    106             if (!Loader::load(it->first, it->second * mask, bVerbose))
    107                 success = false;
    108 
    109         return success;
    110     }
    111 
    112     void Loader::unload(const ClassTreeMask& mask)
    113     {
    114         for (ObjectList<BaseObject>::iterator it = ObjectList<BaseObject>::begin(); it != ObjectList<BaseObject>::end(); )
    115         {
    116             if (mask.isIncluded(it->getIdentifier()))
    117                 (it++)->destroy();
    118             else
    119                 ++it;
    120         }
    121     }
    122 
    123     /**
    124     @brief
    125         Reloads all opened files, while conforming to the restrictions given by the input ClassTreeMask.
    126     @param mask
    127         A ClassTreeMask, which defines which types of classes are reloaded and which aren't.
    128     @param bVerbose
    129         Whether the loader is verbose (prints its progress in a low output level) or not.
    130     @return
    131         Returns true if successful.
    132     */
    133     bool Loader::reload(const ClassTreeMask& mask, bool bVerbose)
    134     {
    135         Loader::unload(mask);
    136         return Loader::load(mask, bVerbose);
    137     }
     50    Loader* Loader::singletonPtr_s = 0;
    13851
    13952    /**
     
    15669            return false;
    15770
    158         Loader::currentMask_s = file->getMask() * mask;
     71        this->currentMask_ = file->getMask() * mask;
    15972
    16073        std::string xmlInput;
     
    189102                // start of the program.
    190103                // Assumption: the LevelInfo tag does not use Lua scripting
    191                 xmlInput = removeLuaTags(xmlInput);
     104                xmlInput = Loader::removeLuaTags(xmlInput);
    192105            }
    193106        }
     
    198111            {
    199112                orxout(user_info) << "Start loading " << file->getFilename() << "..." << endl;
    200                 orxout(internal_info, context::loader) << "Mask: " << Loader::currentMask_s << endl;
     113                orxout(internal_info, context::loader) << "Mask: " << this->currentMask_ << endl;
    201114            }
    202115            else
    203116            {
    204117                orxout(verbose, context::loader) << "Start loading " << file->getFilename() << "..." << endl;
    205                 orxout(verbose_more, context::loader) << "Mask: " << Loader::currentMask_s << endl;
     118                orxout(verbose_more, context::loader) << "Mask: " << this->currentMask_ << endl;
    206119            }
    207120
     
    220133            rootNamespace->setLoaderIndentation("    ");
    221134            rootNamespace->setFile(file);
    222             rootNamespace->setNamespace(rootNamespace);
    223135            rootNamespace->setRoot(true);
    224136            rootNamespace->XMLPort(rootElement, XMLPort::LoadObject);
     
    303215                ++it;
    304216        }
    305     }
    306 
    307     /**
    308     @brief
    309         Reloads the input file, while conforming to the restrictions given by the input ClassTreeMask.
    310     @param file
    311         The file to be reloaded.
    312     @param mask
    313         A ClassTreeMask, which defines which types of classes are reloaded and which aren't.
    314     @param bVerbose
    315         Whether the loader is verbose (prints its progress in a low output level) or not.
    316     @return
    317         Returns true if successful.
    318     */
    319     bool Loader::reload(const XMLFile* file, const ClassTreeMask& mask, bool bVerbose)
    320     {
    321         Loader::unload(file, mask);
    322         return Loader::load(file, mask, bVerbose);
    323217    }
    324218
  • code/trunk/src/libraries/core/Loader.h

    r8858 r10624  
    4444#include <map>
    4545#include <vector>
     46
     47#include "util/Singleton.h"
    4648#include "ClassTreeMask.h"
    4749
    4850namespace orxonox
    4951{
    50     class _CoreExport Loader
     52    class _CoreExport Loader : public Singleton<Loader>
    5153    {
     54        friend class Singleton<Loader>;
     55
    5256        public:
    53             static bool open(const XMLFile* file, const ClassTreeMask& mask = ClassTreeMask(), bool bVerbose = true);
    54             static void close();
    55             static void close(const XMLFile* file);
    56 
    57             static void add(const XMLFile* file, const ClassTreeMask& mask = ClassTreeMask());
    58             static void remove(const XMLFile* file);
    59 
    60             static bool load(const ClassTreeMask& mask = ClassTreeMask(), bool bVerbose = true);
    61             static void unload(const ClassTreeMask& mask = ClassTreeMask());
    62             static bool reload(const ClassTreeMask& mask = ClassTreeMask(), bool bVerbose = true);
    63 
    64             static bool load(const XMLFile* file, const ClassTreeMask& mask = ClassTreeMask(),
    65                              bool bVerbose = true, bool bRemoveLuaTags = false);
    66             static void unload(const XMLFile* file, const ClassTreeMask& mask = ClassTreeMask());
    67             static bool reload(const XMLFile* file, const ClassTreeMask& mask = ClassTreeMask(), bool bVerbose = true);
     57            bool load(const XMLFile* file, const ClassTreeMask& mask = ClassTreeMask(),
     58                      bool bVerbose = true, bool bRemoveLuaTags = false);
     59            void unload(const XMLFile* file, const ClassTreeMask& mask = ClassTreeMask());
    6860
    6961            static std::string replaceLuaTags(const std::string& text);
    7062            static std::string removeLuaTags(const std::string& text);
    7163
    72             static ClassTreeMask currentMask_s;
     64            ClassTreeMask currentMask_;
    7365
    7466        private:
    7567            static bool getLuaTags(const std::string& text, std::map<size_t, bool>& luaTags);
    7668
    77             static std::vector<std::pair<const XMLFile*, ClassTreeMask> > files_s;
     69            std::vector<std::pair<const XMLFile*, ClassTreeMask> > files_;
     70
     71            static Loader* singletonPtr_s;
    7872    };
    7973}
  • code/trunk/src/libraries/core/Namespace.cc

    r10298 r10624  
    4747        RegisterObject(Namespace);
    4848
    49         this->setNamespace(SmartPtr<Namespace>(this, false));
     49        this->setNamespace(WeakPtr<Namespace>(this)); // store a weak-pointer to itself (a strong-pointer would create a recursive dependency)
    5050    }
    5151
     
    105105    void Namespace::loadObjects(BaseObject* object)
    106106    {
    107         object->setNamespace(this);
    108107    }
    109108
  • code/trunk/src/libraries/core/ViewportEventListener.cc

    r9667 r10624  
    3232namespace orxonox
    3333{
    34     RegisterAbstractClass(ViewportEventListener).inheritsFrom(Class(Listable));
     34    RegisterAbstractClass(ViewportEventListener).inheritsFrom<Listable>();
    3535
    3636    ViewportEventListener::ViewportEventListener()
  • code/trunk/src/libraries/core/WindowEventListener.cc

    r9667 r10624  
    3535    unsigned int WindowEventListener::windowHeight_s = 0;
    3636
    37     RegisterAbstractClass(WindowEventListener).inheritsFrom(Class(Listable));
     37    RegisterAbstractClass(WindowEventListener).inheritsFrom<Listable>();
    3838
    3939    WindowEventListener::WindowEventListener()
  • code/trunk/src/libraries/core/XMLNameListener.cc

    r9667 r10624  
    3232namespace orxonox
    3333{
    34     RegisterAbstractClass(XMLNameListener).inheritsFrom(Class(Listable));
     34    RegisterAbstractClass(XMLNameListener).inheritsFrom<Listable>();
    3535
    3636    XMLNameListener::XMLNameListener()
  • code/trunk/src/libraries/core/XMLPort.cc

    r9667 r10624  
    4040    bool XMLPortObjectContainer::identifierIsIncludedInLoaderMask(const Identifier* identifier)
    4141    {
    42         return ((!this->bApplyLoaderMask_) || identifier->isA(ClassIdentifier<Namespace>::getIdentifier()) || Loader::currentMask_s.isIncluded(identifier));
     42        return ((!this->bApplyLoaderMask_) || identifier->isA(ClassIdentifier<Namespace>::getIdentifier()) || Loader::getInstance().currentMask_.isIncluded(identifier));
    4343    }
    4444
  • code/trunk/src/libraries/core/class/Identifiable.cc

    r9667 r10624  
    4141namespace orxonox
    4242{
    43     RegisterClassNoArgs(Identifiable);
     43    RegisterClassNoArgs(Identifiable).virtualBase();
    4444
    4545    /**
  • code/trunk/src/libraries/core/class/Identifier.cc

    r9667 r10624  
    4444namespace orxonox
    4545{
     46    bool Identifier::initConfigValues_s = true;
     47
    4648    // ###############################
    4749    // ###       Identifier        ###
     
    5052        @brief Constructor: No factory, no object created, new ObjectList and a unique networkID.
    5153    */
    52     Identifier::Identifier()
    53         : classID_(IdentifierManager::getInstance().getUniqueClassId())
    54     {
    55         this->factory_ = 0;
     54    Identifier::Identifier(const std::string& name, Factory* factory, bool bLoadable)
     55    {
     56        orxout(verbose, context::identifier) << "Create identifier for " << name << endl;
     57
     58        static unsigned int classIDCounter = 0;
     59
     60        this->classID_ = classIDCounter++;
     61        this->name_ = name;
     62        this->factory_ = factory;
     63        this->bLoadable_ = bLoadable;
    5664        this->bInitialized_ = false;
    57         this->bLoadable_ = false;
     65        this->bIsVirtualBase_ = false;
    5866
    5967        this->bHasConfigValues_ = false;
     
    7179            delete this->factory_;
    7280
     81        for (std::list<const InheritsFrom*>::const_iterator it = this->manualDirectParents_.begin(); it != this->manualDirectParents_.end(); ++it)
     82            delete (*it);
     83
     84        // erase this Identifier from all related identifiers
     85        for (std::list<const Identifier*>::const_iterator it = this->parents_.begin(); it != this->parents_.end(); ++it)
     86            const_cast<Identifier*>(*it)->children_.erase(this);
     87        for (std::list<const Identifier*>::const_iterator it = this->directParents_.begin(); it != this->directParents_.end(); ++it)
     88            const_cast<Identifier*>(*it)->directChildren_.erase(this);
     89        for (std::set<const Identifier*>::const_iterator it = this->children_.begin(); it != this->children_.end(); ++it)
     90            const_cast<Identifier*>(*it)->parents_.remove(this);
     91        for (std::set<const Identifier*>::const_iterator it = this->directChildren_.begin(); it != this->directChildren_.end(); ++it)
     92            const_cast<Identifier*>(*it)->directParents_.remove(this);
     93
    7394        for (std::map<std::string, ConfigValueContainer*>::iterator it = this->configValues_.begin(); it != this->configValues_.end(); ++it)
    7495            delete (it->second);
     
    7798        for (std::map<std::string, XMLPortObjectContainer*>::iterator it = this->xmlportObjectContainers_.begin(); it != this->xmlportObjectContainers_.end(); ++it)
    7899            delete (it->second);
    79     }
    80 
    81     /**
    82         @brief Sets the name of the class.
    83     */
    84     void Identifier::setName(const std::string& name)
    85     {
    86         if (name != this->name_)
    87         {
    88             this->name_ = name;
    89             IdentifierManager::getInstance().addIdentifierToLookupMaps(this);
    90         }
    91     }
    92 
    93     void Identifier::setFactory(Factory* factory)
    94     {
    95         if (this->factory_)
    96             delete this->factory_;
    97 
    98         this->factory_ = factory;
    99100    }
    100101
     
    126127    {
    127128        this->networkID_ = id;
    128         IdentifierManager::getInstance().addIdentifierToLookupMaps(this);
     129        IdentifierManager::getInstance().addIdentifier(this);    // add with new id
    129130    }
    130131
     
    132133     * @brief Used to define the direct parents of an Identifier of an abstract class.
    133134     */
    134     Identifier& Identifier::inheritsFrom(Identifier* directParent)
    135     {
    136         if (this->parents_.empty())
    137             this->directParents_.insert(directParent);
    138         else
    139             orxout(internal_error) << "Trying to add " << directParent->getName() << " as a direct parent of " << this->getName() << " after the latter was already initialized" << endl;
     135    Identifier& Identifier::inheritsFrom(InheritsFrom* directParent)
     136    {
     137        if (this->directParents_.empty())
     138            this->manualDirectParents_.push_back(directParent);
     139        else
     140            orxout(internal_error) << "Trying to manually add direct parent of " << this->getName() << " after the latter was already initialized" << endl;
    140141
    141142        return *this;
     
    144145    /**
    145146     * @brief Initializes the parents of this Identifier while creating the class hierarchy.
    146      * @param identifiers All identifiers that were used to create an instance of this class (including this identifier itself)
    147      */
    148     void Identifier::initializeParents(const std::set<const Identifier*>& identifiers)
     147     * @param initializationTrace All identifiers that were recorded while creating an instance of this class (including nested classes and this identifier itself)
     148     */
     149    void Identifier::initializeParents(const std::list<const Identifier*>& initializationTrace)
    149150    {
    150151        if (!IdentifierManager::getInstance().isCreatingHierarchy())
     
    154155        }
    155156
    156         for (std::set<const Identifier*>::const_iterator it = identifiers.begin(); it != identifiers.end(); ++it)
    157             if (*it != this)
    158                 this->parents_.insert(*it);
    159     }
    160 
    161     /**
    162      * @brief Initializes the direct parents of this Identifier while creating the class hierarchy. This is only intended for abstract classes.
    163      */
    164     void Identifier::initializeDirectParentsOfAbstractClass()
     157        if (this->directParents_.empty())
     158        {
     159            for (std::list<const Identifier*>::const_iterator it = initializationTrace.begin(); it != initializationTrace.end(); ++it)
     160                if (*it != this)
     161                    this->parents_.push_back(*it);
     162        }
     163        else
     164            orxout(internal_error) << "Trying to add parents to " << this->getName() << " after it was already initialized with manual calls to inheritsFrom<Class>()." << endl;
     165    }
     166
     167    /**
     168     * @brief Finishes the initialization of this Identifier after creating the class hierarchy by wiring the (direct) parent/child references correctly.
     169     */
     170    void Identifier::finishInitialization()
    165171    {
    166172        if (!IdentifierManager::getInstance().isCreatingHierarchy())
    167173        {
    168             orxout(internal_warning) << "Identifier::initializeDirectParentsOfAbstractClass() created outside of class hierarchy creation" << endl;
     174            orxout(internal_warning) << "Identifier::finishInitialization() created outside of class hierarchy creation" << endl;
    169175            return;
    170176        }
    171177
    172         // only Identifiable is allowed to have no parents (even tough it's currently not abstract)
    173         if (this->directParents_.empty() && !this->isExactlyA(Class(Identifiable)))
    174         {
    175             orxout(internal_error) << "Identifier " << this->getName() << " / " << this->getTypeidName() << " is marked as abstract but has no direct parents defined" << endl;
     178        if (this->isInitialized())
     179            return;
     180
     181        if (!this->parents_.empty())
     182        {
     183            // parents defined -> this class was initialized by creating a sample instance and recording the trace of identifiers
     184
     185            // initialize all parents
     186            for (std::list<const Identifier*>::const_iterator it = this->parents_.begin(); it != this->parents_.end(); ++it)
     187                const_cast<Identifier*>(*it)->finishInitialization(); // initialize parent
     188
     189            // parents of parents are no direct parents of this identifier
     190            this->directParents_ = this->parents_;
     191            for (std::list<const Identifier*>::const_iterator it_parent = this->parents_.begin(); it_parent != this->parents_.end(); ++it_parent)
     192                for (std::list<const Identifier*>::const_iterator it_parent_parent = const_cast<Identifier*>(*it_parent)->parents_.begin(); it_parent_parent != const_cast<Identifier*>(*it_parent)->parents_.end(); ++it_parent_parent)
     193                    this->directParents_.remove(*it_parent_parent);
     194
     195            this->verifyIdentifierTrace();
     196        }
     197        else if (!this->manualDirectParents_.empty())
     198        {
     199            // no parents defined -> this class was manually initialized by calling inheritsFrom<Class>()
     200
     201            // initialize all direct parents
     202            for (std::list<const InheritsFrom*>::const_iterator it = this->manualDirectParents_.begin(); it != this->manualDirectParents_.end(); ++it)
     203            {
     204                Identifier* directParent = (*it)->getParent();
     205                this->directParents_.push_back(directParent);
     206                directParent->finishInitialization(); // initialize parent
     207            }
     208
     209            // direct parents and their parents are also parents of this identifier (but only add them once)
     210            for (std::list<const Identifier*>::const_iterator it_parent = this->directParents_.begin(); it_parent != this->directParents_.end(); ++it_parent)
     211            {
     212                for (std::list<const Identifier*>::const_iterator it_parent_parent = const_cast<Identifier*>(*it_parent)->parents_.begin(); it_parent_parent != const_cast<Identifier*>(*it_parent)->parents_.end(); ++it_parent_parent)
     213                    this->addIfNotExists(this->parents_, *it_parent_parent);
     214                this->addIfNotExists(this->parents_, *it_parent);
     215            }
     216        }
     217        else if (!this->isExactlyA(Class(Identifiable)))
     218        {
     219            // only Identifiable is allowed to have no parents (even tough it's currently not abstract)
     220            orxout(internal_error) << "Identifier " << this->getName() << " / " << this->getTypeInfo().name() << " is marked as abstract but has no direct parents defined" << endl;
    176221            orxout(internal_error) << "  If this class is not abstract, use RegisterClass(ThisClass);" << endl;
    177222            orxout(internal_error) << "  If this class is abstract, use RegisterAbstractClass(ThisClass).inheritsFrom(Class(BaseClass));" << endl;
    178223        }
    179     }
    180 
    181     /**
    182      * @brief Finishes the initialization of this Identifier after creating the class hierarchy by wiring the (direct) parent/child references correctly.
    183      */
    184     void Identifier::finishInitialization()
    185     {
    186         if (!IdentifierManager::getInstance().isCreatingHierarchy())
    187         {
    188             orxout(internal_warning) << "Identifier::finishInitialization() created outside of class hierarchy creation" << endl;
    189             return;
    190         }
    191 
    192         if (this->isInitialized())
    193             return;
    194 
    195         // if no direct parents were defined, initialize them with the set of all parents
    196         if (this->directParents_.empty())
    197             this->directParents_ = this->parents_;
    198 
    199         // initialize all parents before continuing to initialize this identifier
    200         for (std::set<const Identifier*>::const_iterator it = this->directParents_.begin(); it != this->directParents_.end(); ++it)
    201         {
    202             Identifier* directParent = const_cast<Identifier*>(*it);
    203             directParent->finishInitialization(); // initialize parent
    204             this->parents_.insert(directParent);  // direct parent is also a parent
    205             this->parents_.insert(directParent->parents_.begin(), directParent->parents_.end()); // parents of direct parent are also parents
    206         }
    207 
    208         // parents of parents are no direct parents of this identifier
    209         for (std::set<const Identifier*>::const_iterator it_parent = this->parents_.begin(); it_parent != this->parents_.end(); ++it_parent)
    210             for (std::set<const Identifier*>::const_iterator it_parent_parent = const_cast<Identifier*>(*it_parent)->parents_.begin(); it_parent_parent != const_cast<Identifier*>(*it_parent)->parents_.end(); ++it_parent_parent)
    211                 this->directParents_.erase(*it_parent_parent);
    212224
    213225        // tell all parents that this identifier is a child
    214         for (std::set<const Identifier*>::const_iterator it = this->parents_.begin(); it != this->parents_.end(); ++it)
     226        for (std::list<const Identifier*>::const_iterator it = this->parents_.begin(); it != this->parents_.end(); ++it)
    215227            const_cast<Identifier*>(*it)->children_.insert(this);
    216228
    217229        // tell all direct parents that this identifier is a direct child
    218         for (std::set<const Identifier*>::const_iterator it = this->directParents_.begin(); it != this->directParents_.end(); ++it)
     230        for (std::list<const Identifier*>::const_iterator it = this->directParents_.begin(); it != this->directParents_.end(); ++it)
    219231        {
    220232            const_cast<Identifier*>(*it)->directChildren_.insert(this);
     
    228240
    229241    /**
     242     * Resets all information about the class hierarchy. The identifier is considered uninitialized afterwards.
     243     */
     244    void Identifier::reset()
     245    {
     246        this->directParents_.clear();
     247        this->parents_.clear();
     248        this->directChildren_.clear();
     249        this->children_.clear();
     250        this->bInitialized_ = false;
     251    }
     252
     253    /**
     254     * Verifies if the recorded trace of parent identifiers matches the expected trace according to the class hierarchy. If it doesn't match, the class
     255     * hierarchy is likely wrong, e.g. due to wrong inheritsFrom<>() definitions in abstract classes.
     256     */
     257    void Identifier::verifyIdentifierTrace() const
     258    {
     259
     260        std::list<const Identifier*> expectedIdentifierTrace;
     261
     262        // if any parent class is virtual, it will be instantiated first, so we need to add them first.
     263        for (std::list<const Identifier*>::const_iterator it_parent = this->parents_.begin(); it_parent != this->parents_.end(); ++it_parent)
     264        {
     265            if ((*it_parent)->isVirtualBase())
     266            {
     267                for (std::list<const Identifier*>::const_iterator it_parent_parent = const_cast<Identifier*>(*it_parent)->parents_.begin(); it_parent_parent != const_cast<Identifier*>(*it_parent)->parents_.end(); ++it_parent_parent)
     268                    this->addIfNotExists(expectedIdentifierTrace, *it_parent_parent);
     269                this->addIfNotExists(expectedIdentifierTrace, *it_parent);
     270            }
     271        }
     272
     273        // now all direct parents get created recursively. already added identifiers (e.g. virtual base classes) are not added again.
     274        for (std::list<const Identifier*>::const_iterator it_parent = this->directParents_.begin(); it_parent != this->directParents_.end(); ++it_parent)
     275        {
     276            for (std::list<const Identifier*>::const_iterator it_parent_parent = const_cast<Identifier*>(*it_parent)->parents_.begin(); it_parent_parent != const_cast<Identifier*>(*it_parent)->parents_.end(); ++it_parent_parent)
     277                this->addIfNotExists(expectedIdentifierTrace, *it_parent_parent);
     278            this->addIfNotExists(expectedIdentifierTrace, *it_parent);
     279        }
     280
     281        // check if the expected trace matches the actual trace (which was defined by creating a sample instance)
     282        if (expectedIdentifierTrace != this->parents_)
     283        {
     284            orxout(internal_warning) << this->getName() << " has an unexpected initialization trace:" << endl;
     285
     286            orxout(internal_warning) << "  Actual trace (after creating a sample instance):" << endl << "    ";
     287            for (std::list<const Identifier*>::const_iterator it_parent = this->parents_.begin(); it_parent != this->parents_.end(); ++it_parent)
     288                orxout(internal_warning) << " " << (*it_parent)->getName();
     289            orxout(internal_warning) << endl;
     290
     291            orxout(internal_warning) << "  Expected trace (according to class hierarchy definitions):" << endl << "    ";
     292            for (std::list<const Identifier*>::const_iterator it_parent = expectedIdentifierTrace.begin(); it_parent != expectedIdentifierTrace.end(); ++it_parent)
     293                orxout(internal_warning) << " " << (*it_parent)->getName();
     294            orxout(internal_warning) << endl;
     295
     296            orxout(internal_warning) << "  Direct parents (according to class hierarchy definitions):" << endl << "    ";
     297            for (std::list<const Identifier*>::const_iterator it_parent = this->directParents_.begin(); it_parent != this->directParents_.end(); ++it_parent)
     298                orxout(internal_warning) << " " << (*it_parent)->getName();
     299            orxout(internal_warning) << endl;
     300        }
     301    }
     302
     303    /**
     304     * Adds @param identifierToAdd to @param list if this identifier is not already contained in the list.
     305     */
     306    void Identifier::addIfNotExists(std::list<const Identifier*>& list, const Identifier* identifierToAdd) const
     307    {
     308        if (std::find(list.begin(), list.end(), identifierToAdd) == list.end())
     309            list.push_back(identifierToAdd);
     310    }
     311
     312    /**
    230313        @brief Returns true, if the Identifier is at least of the given type.
    231314        @param identifier The identifier to compare with
     
    233316    bool Identifier::isA(const Identifier* identifier) const
    234317    {
    235         return (identifier == this || (this->parents_.find(identifier) != this->parents_.end()));
     318        return (identifier == this || (this->isChildOf(identifier)));
    236319    }
    237320
     
    251334    bool Identifier::isChildOf(const Identifier* identifier) const
    252335    {
    253         return (this->parents_.find(identifier) != this->parents_.end());
     336        return (std::find(this->parents_.begin(), this->parents_.end(),  identifier) != this->parents_.end());
    254337    }
    255338
     
    260343    bool Identifier::isDirectChildOf(const Identifier* identifier) const
    261344    {
    262         return (this->directParents_.find(identifier) != this->directParents_.end());
     345        return (std::find(this->directParents_.begin(), this->directParents_.end(), identifier) != this->directParents_.end());
    263346    }
    264347
  • code/trunk/src/libraries/core/class/Identifier.h

    r9667 r10624  
    8080#include <typeinfo>
    8181#include <loki/TypeTraits.h>
     82#include <boost/static_assert.hpp>
     83#include <boost/type_traits/is_base_of.hpp>
    8284
    8385#include "util/Output.h"
     86#include "util/OrxAssert.h"
    8487#include "core/object/ObjectList.h"
    8588#include "core/object/Listable.h"
     
    109112    {
    110113        public:
    111             Identifier();
     114            struct InheritsFrom //! helper class to manually define inheritance
     115            {
     116                virtual ~InheritsFrom() {}
     117                virtual Identifier* getParent() const = 0;
     118            };
     119
     120        public:
     121            Identifier(const std::string& name, Factory* factory, bool bLoadable);
    112122            Identifier(const Identifier& identifier); // don't copy
    113123            virtual ~Identifier();
     
    115125            /// Returns the name of the class the Identifier belongs to.
    116126            inline const std::string& getName() const { return this->name_; }
    117             void setName(const std::string& name);
    118 
    119             /// Returns the name of the class as it is returned by typeid(T).name()
    120             virtual const std::string& getTypeidName() = 0;
     127
     128            /// Returns the type_info of the class as it is returned by typeid(T)
     129            virtual const std::type_info& getTypeInfo() = 0;
    121130
    122131            /// Returns the network ID to identify a class through the network.
     
    127136            ORX_FORCEINLINE unsigned int getClassID() const { return this->classID_; }
    128137
    129             /// Sets the Factory.
    130             void setFactory(Factory* factory);
    131138            /// Returns true if the Identifier has a Factory.
    132139            inline bool hasFactory() const { return (this->factory_ != 0); }
     
    136143            /// Returns true if the class can be loaded through XML.
    137144            inline bool isLoadable() const { return this->bLoadable_; }
    138             /// Set the class to be loadable through XML or not.
    139             inline void setLoadable(bool bLoadable) { this->bLoadable_ = bLoadable; }
     145
     146            /// Returns true if child classes should inherit virtually from this class.
     147            inline bool isVirtualBase() const { return this->bIsVirtualBase_; }
     148            /// Defines if child classes should inherit virtually from this class.
     149            inline void setVirtualBase(bool bIsVirtualBase) { this->bIsVirtualBase_ = bIsVirtualBase; }
    140150
    141151            /// Returns true if the Identifier was completely initialized.
    142152            inline bool isInitialized() const { return this->bInitialized_; }
     153
     154            virtual void destroyObjects() = 0;
     155
     156            virtual bool canDynamicCastObjectToIdentifierClass(Identifiable* object) const = 0;
     157
     158            static bool initConfigValues_s; // TODO: this is a hack - remove it as soon as possible
    143159
    144160
     
    146162            ////// Class Hierarchy //////
    147163            /////////////////////////////
    148             Identifier& inheritsFrom(Identifier* directParent);
    149 
    150             void initializeParents(const std::set<const Identifier*>& identifiers);
    151             void initializeDirectParentsOfAbstractClass();
     164            Identifier& inheritsFrom(InheritsFrom* directParent);
     165
     166            void initializeParents(const std::list<const Identifier*>& initializationTrace);
    152167            void finishInitialization();
     168            void reset();
    153169
    154170            bool isA(const Identifier* identifier) const;
     
    159175            bool isDirectParentOf(const Identifier* identifier) const;
    160176
     177            /// Returns the direct parents of the class the Identifier belongs to.
     178            inline const std::list<const Identifier*>& getDirectParents() const { return this->directParents_; }
    161179            /// Returns the parents of the class the Identifier belongs to.
    162             inline const std::set<const Identifier*>& getParents() const { return this->parents_; }
    163             /// Returns the begin-iterator of the parents-list.
    164             inline std::set<const Identifier*>::const_iterator getParentsBegin() const { return this->parents_.begin(); }
    165             /// Returns the end-iterator of the parents-list.
    166             inline std::set<const Identifier*>::const_iterator getParentsEnd() const { return this->parents_.end(); }
    167 
     180            inline const std::list<const Identifier*>& getParents() const { return this->parents_; }
     181
     182            /// Returns the direct children the class the Identifier belongs to.
     183            inline const std::set<const Identifier*>& getDirectChildren() const { return this->directChildren_; }
    168184            /// Returns the children of the class the Identifier belongs to.
    169185            inline const std::set<const Identifier*>& getChildren() const { return this->children_; }
    170             /// Returns the begin-iterator of the children-list.
    171             inline std::set<const Identifier*>::const_iterator getChildrenBegin() const { return this->children_.begin(); }
    172             /// Returns the end-iterator of the children-list.
    173             inline std::set<const Identifier*>::const_iterator getChildrenEnd() const { return this->children_.end(); }
    174 
    175             /// Returns the direct parents of the class the Identifier belongs to.
    176             inline const std::set<const Identifier*>& getDirectParents() const { return this->directParents_; }
    177             /// Returns the begin-iterator of the direct-parents-list.
    178             inline std::set<const Identifier*>::const_iterator getDirectParentsBegin() const { return this->directParents_.begin(); }
    179             /// Returns the end-iterator of the direct-parents-list.
    180             inline std::set<const Identifier*>::const_iterator getDirectParentsEnd() const { return this->directParents_.end(); }
    181 
    182             /// Returns the direct children the class the Identifier belongs to.
    183             inline const std::set<const Identifier*>& getDirectChildren() const { return this->directChildren_; }
    184             /// Returns the begin-iterator of the direct-children-list.
    185             inline std::set<const Identifier*>::const_iterator getDirectChildrenBegin() const { return this->directChildren_.begin(); }
    186             /// Returns the end-iterator of the direct-children-list.
    187             inline std::set<const Identifier*>::const_iterator getDirectChildrenEnd() const { return this->directChildren_.end(); }
    188186
    189187
     
    223221            XMLPortObjectContainer* getXMLPortObjectContainer(const std::string& sectionname);
    224222
    225 
    226223        protected:
    227224            virtual void createSuperFunctionCaller() const = 0;
    228225
    229226        private:
    230             std::set<const Identifier*> parents_;                          //!< The parents of the class the Identifier belongs to
     227            void verifyIdentifierTrace() const;
     228            void addIfNotExists(std::list<const Identifier*>& list, const Identifier* identifierToAdd) const;
     229
     230            std::list<const InheritsFrom*> manualDirectParents_;            //!< Manually defined direct parents
     231            std::list<const Identifier*> directParents_;                    //!< The direct parents of the class the Identifier belongs to (sorted by their order of initialization)
     232            std::list<const Identifier*> parents_;                          //!< The parents of the class the Identifier belongs to (sorted by their order of initialization)
     233
     234            std::set<const Identifier*> directChildren_;                   //!< The direct children of the class the Identifier belongs to
    231235            std::set<const Identifier*> children_;                         //!< The children of the class the Identifier belongs to
    232 
    233             std::set<const Identifier*> directParents_;                    //!< The direct parents of the class the Identifier belongs to
    234             std::set<const Identifier*> directChildren_;                   //!< The direct children of the class the Identifier belongs to
    235236
    236237            bool bInitialized_;                                            //!< Is true if the Identifier was completely initialized
    237238            bool bLoadable_;                                               //!< False = it's not permitted to load the object through XML
     239            bool bIsVirtualBase_;                                          //!< If true, it is recommended to inherit virtually from this class. This changes the order of initialization of child classes, thus this information is necessary to check the class hierarchy.
    238240            std::string name_;                                             //!< The name of the class the Identifier belongs to
    239241            Factory* factory_;                                             //!< The Factory, able to create new objects of the given class (if available)
    240242            uint32_t networkID_;                                           //!< The network ID to identify a class through the network
    241             const unsigned int classID_;                                   //!< Uniquely identifies a class (might not be the same as the networkID_)
     243            unsigned int classID_;                                         //!< Uniquely identifies a class (might not be the same as the networkID_)
    242244
    243245            bool bHasConfigValues_;                                        //!< True if this class has at least one assigned config value
     
    267269    class ClassIdentifier : public Identifier
    268270    {
     271        BOOST_STATIC_ASSERT((boost::is_base_of<Identifiable, T>::value));
     272
    269273        #ifndef DOXYGEN_SHOULD_SKIP_THIS
    270274          #define SUPER_INTRUSIVE_DECLARATION_INCLUDE
     
    273277
    274278        public:
    275             static ClassIdentifier<T>* getIdentifier();
    276             static ClassIdentifier<T>* getIdentifier(const std::string& name);
    277 
    278             bool initializeObject(T* object);
    279 
    280             void setConfigValues(T* object, Configurable*) const;
    281             void setConfigValues(T* object, Identifiable*) const;
    282 
    283             void addObjectToList(T* object, Listable*);
    284             void addObjectToList(T* object, Identifiable*);
    285 
    286             virtual void updateConfigValues(bool updateChildren = true) const;
    287 
    288             virtual const std::string& getTypeidName()
    289                 { return this->typeidName_; }
    290 
    291         private:
    292             static void initializeIdentifier();
    293 
    294             ClassIdentifier(const ClassIdentifier<T>& identifier) {}    // don't copy
    295             ClassIdentifier()
     279            ClassIdentifier(const std::string& name, Factory* factory, bool bLoadable) : Identifier(name, factory, bLoadable)
    296280            {
    297                 this->typeidName_ = typeid(T).name();
     281                OrxVerify(ClassIdentifier<T>::classIdentifier_s == NULL, "Assertion failed in ClassIdentifier of type " << typeid(T).name());
     282                ClassIdentifier<T>::classIdentifier_s = this;
     283
    298284                SuperFunctionInitialization<0, T>::initialize(this);
    299285            }
     
    303289            }
    304290
     291            bool initializeObject(T* object);
     292
     293            virtual void updateConfigValues(bool updateChildren = true) const;
     294
     295            virtual const std::type_info& getTypeInfo()
     296                { return typeid(T); }
     297
     298            virtual bool canDynamicCastObjectToIdentifierClass(Identifiable* object) const
     299                { return dynamic_cast<T*>(object) != 0; }
     300
     301            virtual void destroyObjects();
     302
     303            static ClassIdentifier<T>* getIdentifier();
     304
     305        private:
     306            ClassIdentifier(const ClassIdentifier<T>& identifier) {}    // don't copy
     307
     308            void setConfigValues(T* object, Configurable*) const;
     309            void setConfigValues(T* object, Identifiable*) const;
     310
     311            void addObjectToList(T* object, Listable*);
     312            void addObjectToList(T* object, Identifiable*);
     313
     314            void destroyObjects(Listable*);
     315            void destroyObjects(void*);
     316
     317            void destroyObject(Destroyable* object);
     318            void destroyObject(void* object);
     319
    305320            void updateConfigValues(bool updateChildren, Listable*) const;
    306321            void updateConfigValues(bool updateChildren, Identifiable*) const;
    307322
    308             std::string typeidName_;
    309323            static WeakPtr<ClassIdentifier<T> > classIdentifier_s;
    310324    };
     
    318332    */
    319333    template <class T>
    320     inline ClassIdentifier<T>* ClassIdentifier<T>::getIdentifier()
    321     {
    322         // check if the Identifier already exists
    323         if (!ClassIdentifier<T>::classIdentifier_s)
    324             ClassIdentifier<T>::initializeIdentifier();
    325 
     334    /*static*/ inline ClassIdentifier<T>* ClassIdentifier<T>::getIdentifier()
     335    {
     336        if (ClassIdentifier<T>::classIdentifier_s == NULL)
     337            ClassIdentifier<T>::classIdentifier_s = (ClassIdentifier<T>*) IdentifierManager::getInstance().getIdentifierByTypeInfo(typeid(T));
     338
     339        OrxVerify(ClassIdentifier<T>::classIdentifier_s != NULL, "Did you forget to register the class of type " << typeid(T).name() << "?");
    326340        return ClassIdentifier<T>::classIdentifier_s;
    327     }
    328 
    329     /**
    330         @brief Does the same as getIdentifier() but sets the name if this wasn't done yet.
    331         @param name The name of this Identifier
    332         @return The Identifier
    333     */
    334     template <class T>
    335     inline ClassIdentifier<T>* ClassIdentifier<T>::getIdentifier(const std::string& name)
    336     {
    337         ClassIdentifier<T>* identifier = ClassIdentifier<T>::getIdentifier();
    338         identifier->setName(name);
    339         return identifier;
    340     }
    341 
    342     /**
    343         @brief Assigns the static field for the identifier singleton.
    344     */
    345     template <class T>
    346     /*static */ void ClassIdentifier<T>::initializeIdentifier()
    347     {
    348         // create a new identifier anyway. Will be deleted if not used.
    349         ClassIdentifier<T>* proposal = new ClassIdentifier<T>();
    350 
    351         // Get the entry from the map
    352         ClassIdentifier<T>::classIdentifier_s = (ClassIdentifier<T>*)IdentifierManager::getInstance().getGloballyUniqueIdentifier(proposal);
    353 
    354         if (ClassIdentifier<T>::classIdentifier_s == proposal)
    355             orxout(verbose, context::identifier) << "Requested Identifier for " << proposal->getTypeidName() << " was not yet existing and got created." << endl;
    356         else
    357         {
    358             orxout(verbose, context::identifier) << "Requested Identifier for " << proposal->getTypeidName() << " was already existing and got assigned." << endl;
    359             delete proposal; // delete proposal (it is not used anymore)
    360         }
    361341    }
    362342
     
    375355            IdentifierManager::getInstance().createdObject(object);
    376356
    377             this->setConfigValues(object, object);
     357            if (Identifier::initConfigValues_s)
     358                this->setConfigValues(object, object);
     359
    378360            return true;
    379361        }
     
    420402
    421403    /**
     404     * @brief Destroy all objects of this class (must be Listable).
     405     * Destroyables are destroyed with destroy(), all other classes with delete.
     406     */
     407    template <class T>
     408    void ClassIdentifier<T>::destroyObjects()
     409    {
     410        this->destroyObjects((T*)0);
     411    }
     412
     413    /**
     414     * @brief Only searches and destroys objects if is a @ref Listable
     415     */
     416    template <class T>
     417    void ClassIdentifier<T>::destroyObjects(Listable*)
     418    {
     419        ObjectListBase* objectList = Context::getRootContext()->getObjectList(this);
     420        ObjectListElement<T>* begin = static_cast<ObjectListElement<T>*>(objectList->begin());
     421        ObjectListElement<T>* end = static_cast<ObjectListElement<T>*>(objectList->end());
     422        for (typename ObjectList<T>::iterator it = begin; it != end; )
     423            this->destroyObject(*(it++));
     424    }
     425
     426    template <class T>
     427    void ClassIdentifier<T>::destroyObjects(void*)
     428    {
     429        // no action
     430    }
     431
     432    /**
     433     * @brief Call 'object->destroy()' for Destroyables and 'delete object' for all other types.
     434     */
     435    template <class T>
     436    void ClassIdentifier<T>::destroyObject(Destroyable* object)
     437    {
     438        object->destroy();
     439    }
     440
     441    template <class T>
     442    void ClassIdentifier<T>::destroyObject(void* object)
     443    {
     444        delete static_cast<Identifiable*>(object);
     445    }
     446
     447    /**
    422448        @brief Updates the config-values of all existing objects of this class by calling their setConfigValues() function.
    423449    */
     
    438464
    439465        if (updateChildren)
    440             for (std::set<const Identifier*>::const_iterator it = this->getChildrenBegin(); it != this->getChildrenEnd(); ++it)
     466            for (std::set<const Identifier*>::const_iterator it = this->getChildren().begin(); it != this->getChildren().end(); ++it)
    441467                (*it)->updateConfigValues(false);
    442468    }
  • code/trunk/src/libraries/core/class/IdentifierManager.cc

    r9667 r10624  
    3737
    3838#include "util/StringUtils.h"
    39 #include "core/CoreIncludes.h"
     39#include "core/Core.h"
    4040#include "core/config/ConfigValueContainer.h"
    4141#include "core/XMLPort.h"
     
    4444namespace orxonox
    4545{
    46     /* static */ IdentifierManager& IdentifierManager::getInstance()
    47     {
    48         static IdentifierManager instance;
    49         return instance;
    50     }
     46    IdentifierManager* IdentifierManager::singletonPtr_s = 0;
    5147
    5248    IdentifierManager::IdentifierManager()
    5349    {
    5450        this->hierarchyCreatingCounter_s = 0;
    55         this->classIDCounter_s = 0;
    56     }
    57 
    58     /**
    59         @brief Returns an identifier by name and adds it if not available
    60         @param proposal A pointer to a newly created identifier for the case of non existence in the map
    61         @return The identifier (unique instance)
    62     */
    63     Identifier* IdentifierManager::getGloballyUniqueIdentifier(Identifier* proposal)
    64     {
    65         const std::string& typeidName = proposal->getTypeidName();
    66         std::map<std::string, Identifier*>::const_iterator it = this->identifierByTypeidName_.find(typeidName);
    67 
    68         if (it != this->identifierByTypeidName_.end())
    69         {
    70             // There is already an entry: return it
    71             return it->second;
    72         }
    73         else
    74         {
    75             // There is no entry: put the proposal into the map and return it
    76             this->identifierByTypeidName_[typeidName] = proposal;
    77             return proposal;
    78         }
     51        this->recordTraceForIdentifier_ = NULL;
    7952    }
    8053
     
    8255     * Registers the identifier in all maps of the IdentifierManager.
    8356     */
    84     void IdentifierManager::addIdentifierToLookupMaps(Identifier* identifier)
    85     {
    86         const std::string& typeidName = identifier->getTypeidName();
    87         if (this->identifierByTypeidName_.find(typeidName) != this->identifierByTypeidName_.end())
    88         {
    89             this->identifierByString_[identifier->getName()] = identifier;
    90             this->identifierByLowercaseString_[getLowercase(identifier->getName())] = identifier;
    91             this->identifierByNetworkId_[identifier->getNetworkID()] = identifier;
    92         }
    93         else
    94             orxout(internal_warning) << "Trying to add an identifier to lookup maps which is not known to IdentifierManager" << endl;
     57    void IdentifierManager::addIdentifier(Identifier* identifier)
     58    {
     59        orxout(verbose, context::identifier) << "Adding identifier for " << identifier->getName() << " / " << identifier->getTypeInfo().name() << endl;
     60
     61        this->identifiers_.insert(identifier);
     62        this->identifierByString_[identifier->getName()] = identifier;
     63        this->identifierByLowercaseString_[getLowercase(identifier->getName())] = identifier;
     64        this->identifierByNetworkId_[identifier->getNetworkID()] = identifier;
     65    }
     66
     67    /**
     68     * Unregisters the identifier from all maps of the IdentifierManager.
     69     */
     70    void IdentifierManager::removeIdentifier(Identifier* identifier)
     71    {
     72        this->identifiers_.erase(identifier);
     73        this->identifierByString_.erase(identifier->getName());
     74        this->identifierByLowercaseString_.erase(getLowercase(identifier->getName()));
     75        this->identifierByNetworkId_.erase(identifier->getNetworkID());
    9576    }
    9677
     
    11293        {
    11394            Context temporaryContext(NULL);
    114             for (std::map<std::string, Identifier*>::const_iterator it = this->identifierByTypeidName_.begin(); it != this->identifierByTypeidName_.end(); ++it)
     95            for (std::set<Identifier*>::const_iterator it = this->identifiers_.begin(); it != this->identifiers_.end(); ++it)
    11596            {
    116                 orxout(verbose, context::identifier) << "Initialize ClassIdentifier<" << it->second->getName() << ">-Singleton." << endl;
     97                Identifier* identifier = (*it);
     98                if (identifier->isInitialized())
     99                    continue;
     100
     101                orxout(verbose, context::identifier) << "Initialize ClassIdentifier<" << identifier->getName() << ">-Singleton." << endl;
    117102                // To initialize the identifier, we create a new object and delete it afterwards.
    118                 if (it->second->hasFactory())
     103                if (identifier->hasFactory())
    119104                {
    120                     this->identifiersOfNewObject_.clear();
    121                     Identifiable* temp = it->second->fabricate(&temporaryContext);
    122                     if (temp->getIdentifier() != it->second)
    123                         orxout(internal_error) << "Newly created object of type " << it->second->getName() << " has unexpected identifier. Did you forget to use RegisterObject(classname)?" << endl;
     105                    this->identifierTraceOfNewObject_.clear();
     106                    this->recordTraceForIdentifier_ = identifier;
     107
     108                    Identifiable* temp = identifier->fabricate(&temporaryContext);
     109
     110                    this->recordTraceForIdentifier_ = NULL;
     111
     112                    if (temp->getIdentifier() != identifier)
     113                        orxout(internal_error) << "Newly created object of type " << identifier->getName() << " has unexpected identifier. Did you forget to use RegisterObject(classname)?" << endl;
     114
     115                    identifier->initializeParents(this->identifierTraceOfNewObject_[temp]);
     116
    124117                    delete temp;
    125 
    126                     it->second->initializeParents(this->identifiersOfNewObject_);
    127118                }
    128                 else
    129                     it->second->initializeDirectParentsOfAbstractClass();
    130 
    131                 initializedIdentifiers.insert(it->second);
     119
     120                initializedIdentifiers.insert(identifier);
    132121            }
    133122
     
    138127
    139128        // finish the initialization of all identifiers
    140         for (std::map<std::string, Identifier*>::const_iterator it = this->identifierByTypeidName_.begin(); it != this->identifierByTypeidName_.end(); ++it)
    141         {
    142             if (initializedIdentifiers.find(it->second) != initializedIdentifiers.end())
    143                 it->second->finishInitialization();
    144             else
    145                 orxout(internal_error) << "Identifier was registered late and is not initialized: " << it->second->getName() << " / " << it->second->getTypeidName() << endl;
    146         }
     129        for (std::set<Identifier*>::const_iterator it = initializedIdentifiers.begin(); it != initializedIdentifiers.end(); ++it)
     130            (*it)->finishInitialization();
     131
     132        // only check class hierarchy in dev mode because it's an expensive operation and it requires a developer to fix detected problems anyway.
     133        if (!Core::exists() || Core::getInstance().getConfig()->inDevMode())
     134            this->verifyClassHierarchy(initializedIdentifiers);
    147135
    148136        this->stopCreatingHierarchy();
     
    151139
    152140    /**
    153         @brief Destroys all Identifiers. Called when exiting the program.
    154     */
    155     void IdentifierManager::destroyAllIdentifiers()
    156     {
    157         for (std::map<std::string, Identifier*>::iterator it = this->identifierByTypeidName_.begin(); it != this->identifierByTypeidName_.end(); ++it)
    158             delete (it->second);
    159 
    160         this->identifierByTypeidName_.clear();
    161         this->identifierByString_.clear();
    162         this->identifierByLowercaseString_.clear();
    163         this->identifierByNetworkId_.clear();
     141     * Verifies if the class hierarchy is consistent with the RTTI.
     142     */
     143    void IdentifierManager::verifyClassHierarchy(const std::set<Identifier*>& initializedIdentifiers)
     144    {
     145        // check if there are any uninitialized identifiers remaining
     146        for (std::set<Identifier*>::const_iterator it = this->identifiers_.begin(); it != this->identifiers_.end(); ++it)
     147            if (!(*it)->isInitialized())
     148                orxout(internal_error) << "Identifier was registered late and is not initialized: " << (*it)->getName() << " / " << (*it)->getTypeInfo().name() << endl;
     149
     150        // for all initialized identifiers, check if a sample instance behaves as expected according to the class hierarchy
     151        Context temporaryContext(NULL);
     152        for (std::set<Identifier*>::const_iterator it1 = initializedIdentifiers.begin(); it1 != initializedIdentifiers.end(); ++it1)
     153        {
     154            if (!(*it1)->hasFactory())
     155                continue;
     156
     157            Identifiable* temp = (*it1)->fabricate(&temporaryContext);
     158
     159            for (std::set<Identifier*>::const_iterator it2 = this->identifiers_.begin(); it2 != this->identifiers_.end(); ++it2)
     160            {
     161                bool isA_AccordingToRtti = (*it2)->canDynamicCastObjectToIdentifierClass(temp);
     162                bool isA_AccordingToClassHierarchy = temp->isA((*it2));
     163
     164                if (isA_AccordingToRtti != isA_AccordingToClassHierarchy)
     165                {
     166                    orxout(internal_error) << "Class hierarchy does not match RTTI: Class hierarchy claims that " << (*it1)->getName() <<
     167                        (isA_AccordingToClassHierarchy ? " is a " : " is not a ") << (*it2)->getName() << " but RTTI says the opposite." << endl;
     168                }
     169            }
     170
     171            delete temp;
     172        }
     173        orxout(internal_info) << "Class hierarchy matches RTTI" << endl;
     174
     175        size_t numberOfObjects = temporaryContext.getObjectList<Listable>()->size();
     176        if (numberOfObjects > 0)
     177            orxout(internal_warning) << "There are still " << numberOfObjects << " listables left after creating the class hierarchy" << endl;
     178    }
     179
     180    /**
     181     * @brief Resets all Identifiers.
     182     */
     183    void IdentifierManager::destroyClassHierarchy()
     184    {
     185        orxout(internal_status) << "Destroy class-hierarchy" << endl;
     186        for (std::set<Identifier*>::const_iterator it = this->identifiers_.begin(); it != this->identifiers_.end(); ++it)
     187            (*it)->reset();
    164188    }
    165189
     
    170194    {
    171195        if (this->isCreatingHierarchy())
    172             this->identifiersOfNewObject_.insert(identifiable->getIdentifier());
     196        {
     197            if (this->recordTraceForIdentifier_)
     198            {
     199                std::list<const Identifier*>& traceForObject = this->identifierTraceOfNewObject_[identifiable];
     200                if (std::find(traceForObject.begin(), traceForObject.end(), identifiable->getIdentifier()) != traceForObject.end())
     201                {
     202                    orxout(internal_warning) << this->recordTraceForIdentifier_->getName() << " inherits two times from " <<
     203                        identifiable->getIdentifier()->getName() << ". Did you forget to use virtual inheritance?" << endl;
     204                }
     205                traceForObject.push_back(identifiable->getIdentifier());
     206            }
     207        }
    173208        else
    174209            orxout(internal_warning) << "createdObject() called outside of class hierarchy creation" << endl;
     
    218253
    219254    /**
     255        @brief Returns the Identifier with a given typeid-name.
     256        @param name The typeid-name of the wanted Identifier
     257        @return The Identifier
     258    */
     259    Identifier* IdentifierManager::getIdentifierByTypeInfo(const std::type_info& typeInfo)
     260    {
     261        // TODO: use std::type_index and a map to find identifiers by type_info (only with c++11)
     262        for (std::set<Identifier*>::iterator it = this->identifiers_.begin(); it != this->identifiers_.end(); ++it)
     263            if ((*it)->getTypeInfo() == typeInfo)
     264                return (*it);
     265        return 0;
     266    }
     267
     268    /**
    220269        @brief Cleans the NetworkID map (needed on clients for correct initialization)
    221270    */
  • code/trunk/src/libraries/core/class/IdentifierManager.h

    r9667 r10624  
    3939#include <map>
    4040#include <set>
     41#include <list>
    4142#include <string>
     43
     44#include "util/Singleton.h"
    4245
    4346namespace orxonox
    4447{
    45     class _CoreExport IdentifierManager
     48    class _CoreExport IdentifierManager : public Singleton<IdentifierManager>
    4649    {
     50        friend class Singleton<IdentifierManager>;
     51
    4752        public:
    48             static IdentifierManager& getInstance();
     53            IdentifierManager();
     54            ~IdentifierManager() {}
    4955
    50             Identifier* getGloballyUniqueIdentifier(Identifier* proposal);
    51             void addIdentifierToLookupMaps(Identifier* identifier);
    52 
    53             unsigned int getUniqueClassId()
    54                 { return this->classIDCounter_s++; }
     56            void addIdentifier(Identifier* identifier);
     57            void removeIdentifier(Identifier* identifier);
    5558
    5659
     
    5962            /////////////////////////////
    6063            void createClassHierarchy();
    61             void destroyAllIdentifiers();
     64            void verifyClassHierarchy(const std::set<Identifier*>& initializedIdentifiers);
     65            void destroyClassHierarchy();
    6266
    6367            void createdObject(Identifiable* identifiable);
     
    7478            Identifier* getIdentifierByLowercaseString(const std::string& name);
    7579            Identifier* getIdentifierByID(uint32_t id);
     80            Identifier* getIdentifierByTypeInfo(const std::type_info& typeInfo);
    7681
    7782            void clearNetworkIDs();
     
    8893
    8994        private:
    90             IdentifierManager();
    91             IdentifierManager(const IdentifierManager&);
    92             ~IdentifierManager() {}
     95            IdentifierManager(const IdentifierManager&); // not implemented
    9396
    9497            /// Increases the hierarchyCreatingCounter_s variable, causing all new objects to store their parents.
     
    99102                { hierarchyCreatingCounter_s--; }
    100103
    101             std::map<std::string, Identifier*> identifierByTypeidName_;      //!< Map with the names as received by typeid(). This is only used internally.
    102 
     104            std::set<Identifier*> identifiers_;                              //!< All identifiers. This is only used internally.
    103105            std::map<std::string, Identifier*> identifierByString_;          //!< Map that stores all Identifiers with their names.
    104106            std::map<std::string, Identifier*> identifierByLowercaseString_; //!< Map that stores all Identifiers with their names in lowercase.
     
    106108
    107109            int hierarchyCreatingCounter_s;                         //!< Bigger than zero if at least one Identifier stores its parents (its an int instead of a bool to avoid conflicts with multithreading)
    108             std::set<const Identifier*> identifiersOfNewObject_;    //!< Used while creating the object hierarchy to keep track of the identifiers of a newly created object
    109             unsigned int classIDCounter_s;                          //!< counter for the unique classIDs
     110
     111            /// Used while creating the object hierarchy to keep track of the identifiers of a newly created object (and all other objects that get created as
     112            /// a consequence of this, e.g. nested member objects).
     113            std::map<Identifiable*, std::list<const Identifier*> > identifierTraceOfNewObject_;
     114            Identifier* recordTraceForIdentifier_; //!< The identifier for which we want to record the trace of identifiers during object creation. If null, no trace is recorded.
     115
     116            static IdentifierManager* singletonPtr_s;
    110117    };
    111118}
  • code/trunk/src/libraries/core/class/OrxonoxInterface.cc

    r9667 r10624  
    3232namespace orxonox
    3333{
    34     RegisterClassNoArgs(OrxonoxInterface);
     34    RegisterClassNoArgs(OrxonoxInterface).virtualBase();
    3535
    3636    OrxonoxInterface::OrxonoxInterface()
  • code/trunk/src/libraries/core/class/Super.h

    r9667 r10624  
    274274        SUPER_NOARGS(classname, functionname)
    275275
    276     #define SUPER_changedGametype(classname, functionname, ...) \
    277         SUPER_NOARGS(classname, functionname)
    278 
    279276    #define SUPER_changedUsed(classname, functionname, ...) \
    280277        SUPER_NOARGS(classname, functionname)
     
    555552        SUPER_FUNCTION_GLOBAL_DECLARATION_PART2;
    556553
    557         SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(9, changedGametype, false)
    558             ()
    559         SUPER_FUNCTION_GLOBAL_DECLARATION_PART2;
    560 
    561         SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(10, changedUsed, false)
    562             ()
    563         SUPER_FUNCTION_GLOBAL_DECLARATION_PART2;
    564 
    565         SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(11, changedCarrier, false)
    566             ()
    567         SUPER_FUNCTION_GLOBAL_DECLARATION_PART2;
    568 
    569         SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(12, changedPickedUp, false)
     554        SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(9, changedUsed, false)
     555            ()
     556        SUPER_FUNCTION_GLOBAL_DECLARATION_PART2;
     557
     558        SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(10, changedCarrier, false)
     559            ()
     560        SUPER_FUNCTION_GLOBAL_DECLARATION_PART2;
     561
     562        SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(11, changedPickedUp, false)
    570563            ()
    571564        SUPER_FUNCTION_GLOBAL_DECLARATION_PART2;
     
    623616    SUPER_INTRUSIVE_DECLARATION(changedOverlayGroup);
    624617    SUPER_INTRUSIVE_DECLARATION(changedName);
    625     SUPER_INTRUSIVE_DECLARATION(changedGametype);
    626618    SUPER_INTRUSIVE_DECLARATION(changedUsed);
    627619    SUPER_INTRUSIVE_DECLARATION(changedCarrier);
  • code/trunk/src/libraries/core/command/ArgumentCompletionFunctions.cc

    r9667 r10624  
    4444#include "CommandExecutor.h"
    4545#include "ConsoleCommand.h"
     46#include "ConsoleCommandManager.h"
    4647#include "TclThreadManager.h"
    4748
     
    9899
    99100                // get all the groups that are visible (except the shortcut group "")
    100                 const std::map<std::string, std::map<std::string, ConsoleCommand*> >& commands = ConsoleCommand::getCommands();
     101                const std::map<std::string, std::map<std::string, ConsoleCommand*> >& commands = ConsoleCommandManager::getInstance().getCommands();
    101102                for (std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = commands.begin(); it_group != commands.end(); ++it_group)
    102103                    if (groupIsVisible(it_group->second, bOnlyShowHidden) && it_group->first != "" && (fragmentLC == "" || getLowercase(it_group->first).find(fragmentLC) == 0))
     
    137138
    138139                // find the iterator of the given group
    139                 std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = ConsoleCommand::getCommands().begin();
    140                 for ( ; it_group != ConsoleCommand::getCommands().end(); ++it_group)
     140                std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = ConsoleCommandManager::getInstance().getCommands().begin();
     141                for ( ; it_group != ConsoleCommandManager::getInstance().getCommands().end(); ++it_group)
    141142                    if (getLowercase(it_group->first) == groupLC)
    142143                        break;
    143144
    144145                // add all commands in the group to the list
    145                 if (it_group != ConsoleCommand::getCommands().end())
     146                if (it_group != ConsoleCommandManager::getInstance().getCommands().end())
    146147                {
    147148                    for (std::map<std::string, ConsoleCommand*>::const_iterator it_command = it_group->second.begin(); it_command != it_group->second.end(); ++it_command)
     
    206207                return detail::_groupsandcommands(fragment, true);
    207208
    208             if (ConsoleCommand::getCommandLC(getLowercase(tokens[0])))
     209            if (ConsoleCommandManager::getInstance().getCommandLC(getLowercase(tokens[0])))
    209210                return ARGUMENT_COMPLETION_FUNCTION_CALL(command)(fragment);
    210211
    211212            if (tokens.size() == 1)
    212213            {
    213                 std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = ConsoleCommand::getCommands().find(tokens[0]);
    214                 if (it_group != ConsoleCommand::getCommands().end())
     214                std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = ConsoleCommandManager::getInstance().getCommands().find(tokens[0]);
     215                if (it_group != ConsoleCommandManager::getInstance().getCommands().end())
    215216                    return detail::_subcommands(fragment, tokens[0], true);
    216217                else
     
    218219            }
    219220
    220             if (ConsoleCommand::getCommandLC(getLowercase(tokens[0]), getLowercase(tokens[1])))
     221            if (ConsoleCommandManager::getInstance().getCommandLC(getLowercase(tokens[0]), getLowercase(tokens[1])))
    221222                return ARGUMENT_COMPLETION_FUNCTION_CALL(command)(fragment);
    222223
  • code/trunk/src/libraries/core/command/CMakeLists.txt

    r7284 r10624  
    44  ConsoleCommand.cc
    55  ConsoleCommandCompilation.cc
     6  ConsoleCommandIncludes.cc
     7  ConsoleCommandManager.cc
    68  Executor.cc
    79  IOConsole.cc
  • code/trunk/src/libraries/core/command/CommandEvaluation.cc

    r9550 r10624  
    3737#include "CommandExecutor.h"
    3838#include "ConsoleCommand.h"
     39#include "ConsoleCommandManager.h"
    3940
    4041namespace orxonox
     
    305306                // the user typed 1-2 arguments, check what he tried to type and print a suitable error
    306307                std::string groupLC = getLowercase(this->getToken(0));
    307                 for (std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = ConsoleCommand::getCommandsLC().begin(); it_group != ConsoleCommand::getCommandsLC().end(); ++it_group)
     308                for (std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = ConsoleCommandManager::getInstance().getCommandsLC().begin(); it_group != ConsoleCommandManager::getInstance().getCommandsLC().end(); ++it_group)
    308309                    if (it_group->first == groupLC)
    309310                        return std::string("Error: There is no command in group \"") + this->getToken(0) + "\" starting with \"" + this->getToken(1) + "\".";
     
    327328
    328329        // iterate through all groups and their commands and calculate the distance to the current command. keep the best.
    329         for (std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = ConsoleCommand::getCommandsLC().begin(); it_group != ConsoleCommand::getCommandsLC().end(); ++it_group)
     330        for (std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = ConsoleCommandManager::getInstance().getCommandsLC().begin(); it_group != ConsoleCommandManager::getInstance().getCommandsLC().end(); ++it_group)
    330331        {
    331332            if (it_group->first != "")
     
    345346
    346347        // now also iterate through all shortcuts and keep the best if it's better than the one found above.
    347         std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = ConsoleCommand::getCommandsLC().find("");
    348         if (it_group !=  ConsoleCommand::getCommandsLC().end())
     348        std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = ConsoleCommandManager::getInstance().getCommandsLC().find("");
     349        if (it_group !=  ConsoleCommandManager::getInstance().getCommandsLC().end())
    349350        {
    350351            for (std::map<std::string, ConsoleCommand*>::const_iterator it_name = it_group->second.begin(); it_name != it_group->second.end(); ++it_name)
  • code/trunk/src/libraries/core/command/CommandExecutor.cc

    r9550 r10624  
    3434#include "CommandExecutor.h"
    3535
    36 #include "ConsoleCommand.h"
     36#include "ConsoleCommandIncludes.h"
    3737#include "TclBind.h"
    3838#include "Shell.h"
     
    155155
    156156        // assign the fallback-command to get hints about the possible commands and groups
    157         evaluation.hintCommand_ = ConsoleCommand::getCommand(__CC_CommandExecutor_name, __CC_autocomplete_name);
     157        evaluation.hintCommand_ = ConsoleCommandManager::getInstance().getCommand(__CC_CommandExecutor_name, __CC_autocomplete_name);
    158158
    159159        // check if there's at least one argument
     
    161161        {
    162162            // try to get a command from the first token
    163             evaluation.execCommand_ = ConsoleCommand::getCommandLC(evaluation.getToken(0));
     163            evaluation.execCommand_ = ConsoleCommandManager::getInstance().getCommandLC(evaluation.getToken(0));
    164164            if (evaluation.execCommand_)
    165165                evaluation.execArgumentsOffset_ = 1;
     
    167167            {
    168168                // try to get a command from the first two tokens
    169                 evaluation.execCommand_ = ConsoleCommand::getCommandLC(evaluation.getToken(0), evaluation.getToken(1));
     169                evaluation.execCommand_ = ConsoleCommandManager::getInstance().getCommandLC(evaluation.getToken(0), evaluation.getToken(1));
    170170                if (evaluation.execCommand_)
    171171                    evaluation.execArgumentsOffset_ = 2;
     
    288288
    289289            // check if the alias already exists - print an error and return if it does
    290             if ((tokens.size() == 1 && ConsoleCommand::getCommand(tokens[0])) || (tokens.size() == 2 && ConsoleCommand::getCommand(tokens[0], tokens[1])))
     290            if ((tokens.size() == 1 && ConsoleCommandManager::getInstance().getCommand(tokens[0])) || (tokens.size() == 2 && ConsoleCommandManager::getInstance().getCommand(tokens[0], tokens[1])))
    291291            {
    292292                orxout(user_error) << "A command with name \"" << alias << "\" already exists." << endl;
     
    296296            // create a new console command with the given alias as its name
    297297            if (tokens.size() == 1)
    298                 createConsoleCommand(tokens[0], executor);
     298                ConsoleCommandManager::getInstance().registerCommand(new ConsoleCommand(tokens[0], executor));
    299299            else if (tokens.size() == 2)
    300                 createConsoleCommand(tokens[0], tokens[1], executor);
     300                ConsoleCommandManager::getInstance().registerCommand(new ConsoleCommand(tokens[0], tokens[1], executor));
    301301            else
    302302                orxout(user_error) << "\"" << alias << "\" is not a valid alias name (must have one or two words)." << endl;
  • code/trunk/src/libraries/core/command/ConsoleCommand.cc

    r9348 r10624  
    3535
    3636#include "util/Convert.h"
    37 #include "util/StringUtils.h"
    3837#include "core/Language.h"
    3938#include "core/GameMode.h"
    4039#include "core/input/KeyBinder.h"
    4140#include "core/input/KeyBinderManager.h"
     41#include "ConsoleCommandManager.h"
    4242
    4343namespace orxonox
    4444{
    4545    /**
    46         @brief Constructor: Initializes all values and registers the command.
     46        @brief Constructor: Initializes all values and registers the command (without a group).
     47        @param name The name of the command
     48        @param executor The executor of the command
     49        @param bInitialized If true, the executor is used for both, the definition of the function-header AND to executute the command. If false, the command is inactive and needs to be assigned a function before it can be used.
     50    */
     51    ConsoleCommand::ConsoleCommand(const std::string& name, const ExecutorPtr& executor, bool bInitialized)
     52    {
     53        this->init("", name, executor, bInitialized);
     54    }
     55
     56    /**
     57        @brief Constructor: Initializes all values and registers the command (with a group).
    4758        @param group The group of the command
    4859        @param name The name of the command
     
    5263    ConsoleCommand::ConsoleCommand(const std::string& group, const std::string& name, const ExecutorPtr& executor, bool bInitialized)
    5364    {
     65        this->init(group, name, executor, bInitialized);
     66    }
     67
     68    void ConsoleCommand::init(const std::string& group, const std::string& name, const ExecutorPtr& executor, bool bInitialized)
     69    {
    5470        this->bActive_ = true;
    5571        this->bHidden_ = false;
     
    6884            this->executor_ = executor;
    6985
    70         ConsoleCommand::registerCommand(group, name, this);
     86        this->names_.push_back(CommandName(group, name));
    7187    }
    7288
     
    7692    ConsoleCommand::~ConsoleCommand()
    7793    {
    78         ConsoleCommand::unregisterCommand(this);
    7994    }
    8095
     
    8499    ConsoleCommand& ConsoleCommand::addShortcut()
    85100    {
    86         ConsoleCommand::registerCommand("", this->baseName_, this);
     101        this->names_.push_back(CommandName("", this->baseName_));
    87102        return *this;
    88103    }
     
    93108    ConsoleCommand& ConsoleCommand::addShortcut(const std::string&  name)
    94109    {
    95         ConsoleCommand::registerCommand("", name, this);
     110        this->names_.push_back(CommandName("", name));
    96111        return *this;
    97112    }
     
    102117    ConsoleCommand& ConsoleCommand::addGroup(const std::string& group)
    103118    {
    104         ConsoleCommand::registerCommand(group, this->baseName_, this);
     119        this->names_.push_back(CommandName(group, this->baseName_));
    105120        return *this;
    106121    }
     
    111126    ConsoleCommand& ConsoleCommand::addGroup(const std::string& group, const std::string&  name)
    112127    {
    113         ConsoleCommand::registerCommand(group, name, this);
     128        this->names_.push_back(CommandName(group, name));
    114129        return *this;
    115130    }
     
    587602        return *this;
    588603    }
    589 
    590     /**
    591         @brief Returns the command with given group an name.
    592         @param group The group of the requested command
    593         @param name The group of the requested command
    594         @param bPrintError If true, an error is printed if the command doesn't exist
    595     */
    596     /* static */ ConsoleCommand* ConsoleCommand::getCommand(const std::string& group, const std::string& name, bool bPrintError)
    597     {
    598         // find the group
    599         std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = ConsoleCommand::getCommandMap().find(group);
    600         if (it_group != ConsoleCommand::getCommandMap().end())
    601         {
    602             // find the name
    603             std::map<std::string, ConsoleCommand*>::const_iterator it_name = it_group->second.find(name);
    604             if (it_name != it_group->second.end())
    605             {
    606                 // return the pointer
    607                 return it_name->second;
    608             }
    609         }
    610         if (bPrintError)
    611         {
    612             if (group == "")
    613                 orxout(internal_error, context::commands) << "Couldn't find console command with shortcut \"" << name << "\"" << endl;
    614             else
    615                 orxout(internal_error, context::commands) << "Couldn't find console command with group \"" << group << "\" and name \"" << name << "\"" << endl;
    616         }
    617         return 0;
    618     }
    619 
    620     /**
    621         @brief Returns the command with given group an name in lowercase.
    622         @param group The group of the requested command in lowercase
    623         @param name The group of the requested command in lowercase
    624         @param bPrintError If true, an error is printed if the command doesn't exist
    625     */
    626     /* static */ ConsoleCommand* ConsoleCommand::getCommandLC(const std::string& group, const std::string& name, bool bPrintError)
    627     {
    628         std::string groupLC = getLowercase(group);
    629         std::string nameLC = getLowercase(name);
    630 
    631         // find the group
    632         std::map<std::string, std::map<std::string, ConsoleCommand*> >::const_iterator it_group = ConsoleCommand::getCommandMapLC().find(groupLC);
    633         if (it_group != ConsoleCommand::getCommandMapLC().end())
    634         {
    635             // find the name
    636             std::map<std::string, ConsoleCommand*>::const_iterator it_name = it_group->second.find(nameLC);
    637             if (it_name != it_group->second.end())
    638             {
    639                 // return the pointer
    640                 return it_name->second;
    641             }
    642         }
    643         if (bPrintError)
    644         {
    645             if (group == "")
    646                 orxout(internal_error, context::commands) << "Couldn't find console command with shortcut \"" << name << "\"" << endl;
    647             else
    648                 orxout(internal_error, context::commands) << "Couldn't find console command with group \"" << group << "\" and name \"" << name << "\"" << endl;
    649         }
    650         return 0;
    651     }
    652 
    653     /**
    654         @brief Returns the static map that stores all console commands.
    655     */
    656     /* static */ std::map<std::string, std::map<std::string, ConsoleCommand*> >& ConsoleCommand::getCommandMap()
    657     {
    658         static std::map<std::string, std::map<std::string, ConsoleCommand*> > commandMap;
    659         return commandMap;
    660     }
    661 
    662     /**
    663         @brief Returns the static map that stores all console commands in lowercase.
    664     */
    665     /* static */ std::map<std::string, std::map<std::string, ConsoleCommand*> >& ConsoleCommand::getCommandMapLC()
    666     {
    667         static std::map<std::string, std::map<std::string, ConsoleCommand*> > commandMapLC;
    668         return commandMapLC;
    669     }
    670 
    671     /**
    672         @brief Registers a new command with given group an name by adding it to the command map.
    673     */
    674     /* static */ void ConsoleCommand::registerCommand(const std::string& group, const std::string& name, ConsoleCommand* command)
    675     {
    676         if (name == "")
    677             return;
    678 
    679         // check if a command with this name already exists
    680         if (ConsoleCommand::getCommand(group, name) != 0)
    681         {
    682             if (group == "")
    683                 orxout(internal_warning, context::commands) << "A console command with shortcut \"" << name << "\" already exists." << endl;
    684             else
    685                 orxout(internal_warning, context::commands) << "A console command with name \"" << name << "\" already exists in group \"" << group << "\"." << endl;
    686         }
    687         else
    688         {
    689             // add the command to the map
    690             ConsoleCommand::getCommandMap()[group][name] = command;
    691             ConsoleCommand::getCommandMapLC()[getLowercase(group)][getLowercase(name)] = command;
    692         }
    693     }
    694 
    695     /**
    696         @brief Removes the command from the command map.
    697     */
    698     /* static */ void ConsoleCommand::unregisterCommand(ConsoleCommand* command)
    699     {
    700         // iterate through all groups
    701         for (std::map<std::string, std::map<std::string, ConsoleCommand*> >::iterator it_group = ConsoleCommand::getCommandMap().begin(); it_group != ConsoleCommand::getCommandMap().end(); )
    702         {
    703             // iterate through all commands of each group
    704             for (std::map<std::string, ConsoleCommand*>::iterator it_name = it_group->second.begin(); it_name != it_group->second.end(); )
    705             {
    706                 // erase the command
    707                 if (it_name->second == command)
    708                     it_group->second.erase(it_name++);
    709                 else
    710                     ++it_name;
    711             }
    712 
    713             // erase the group if it is empty now
    714             if (it_group->second.empty())
    715                 ConsoleCommand::getCommandMap().erase(it_group++);
    716             else
    717                 ++it_group;
    718         }
    719 
    720         // now the same for the lowercase-map:
    721 
    722         // iterate through all groups
    723         for (std::map<std::string, std::map<std::string, ConsoleCommand*> >::iterator it_group = ConsoleCommand::getCommandMapLC().begin(); it_group != ConsoleCommand::getCommandMapLC().end(); )
    724         {
    725             // iterate through all commands of each group
    726             for (std::map<std::string, ConsoleCommand*>::iterator it_name = it_group->second.begin(); it_name != it_group->second.end(); )
    727             {
    728                 // erase the command
    729                 if (it_name->second == command)
    730                     it_group->second.erase(it_name++);
    731                 else
    732                     ++it_name;
    733             }
    734 
    735             // erase the group if it is empty now
    736             if (it_group->second.empty())
    737                 ConsoleCommand::getCommandMapLC().erase(it_group++);
    738             else
    739                 ++it_group;
    740         }
    741     }
    742 
    743     /**
    744         @brief Deletes all commands
    745     */
    746     /* static */ void ConsoleCommand::destroyAll()
    747     {
    748         // delete entries until the map is empty
    749         while (!ConsoleCommand::getCommandMap().empty() && !ConsoleCommand::getCommandMap().begin()->second.empty())
    750             delete ConsoleCommand::getCommandMap().begin()->second.begin()->second;
    751     }
    752604}
  • code/trunk/src/libraries/core/command/ConsoleCommand.h

    r9983 r10624  
    2828
    2929/**
    30     @defgroup ConsoleCommand Console commands
    31     @ingroup Command
    32 */
    33 
    34 /**
    3530    @file
    3631    @ingroup Command ConsoleCommand
    37     @brief Declaration of the orxonox::ConsoleCommand class and the SetConsoleCommand() macro.
    38 
    39     @anchor ConsoleCommandExample
    40 
    41     Console commands can be used to write scripts, use key-bindings or simply to be
    42     entered into the shell by the user. Instances of orxonox::ConsoleCommand define
    43     the function of a command, and also more information like, for example, if it is
    44     active, default values, and possible arguments.
    45 
    46     Commands need to be registered to the system statically on startup by using the
    47     SetConsoleCommand() or DeclareConsoleCommand() macros outside of a function.
    48     This ensures that commands are known to the system at any time, so they can be
    49     evaluated (see orxonox::CommandExecutor::evaluate()), for example for key-bindings.
    50 
    51     Example:
    52     @code
    53     void myCoutFunction(const std::string& text)        // Define a static function
    54     {
    55         orxout() << "Text: " << text << endl;           // Print the text to the console
    56     }
    57 
    58     SetConsoleCommand("cout", &myCoutFunction);         // Register the function as command with name "cout"
    59     @endcode
    60 
    61     Now you can open the shell and execute the command:
    62     @code
    63     $ cout Hello World
    64     @endcode
    65 
    66     Internally this command is now passed to orxonox::CommandExecutor::execute():
    67     @code
    68     CommandExecutor::execute("cout HelloWorld");
    69     @endcode
    70 
    71     CommandExecutor searches for a command with name "cout" and passes the arguments
    72     "Hello World" to it. Because we registered myCoutFunction() with this command,
    73     as a result the following text will be printed to the console:
    74     @code
    75     Text: Hello World
    76     @endcode
    77 
    78     You can add more attributes to the ConsoleCommand, by using the command-chain feature
    79     of SetConsoleCommand(). For example like this:
    80     @code
    81     SetConsoleCommand("cout", &myCoutFunction)
    82         .addGroup("output", "text")
    83         .accessLevel(AccessLevel::Offline)
    84         .defaultValues("no text");
    85     @endcode
    86 
    87     Open the shell again and try it:
    88     @code
    89     $ cout Hello World
    90     Text: Hello World
    91     $ output text Hello World
    92     Text: Hello World
    93     $ cout
    94     Text: no text
    95     @endcode
    96 
    97     If you execute it online (note: the access level is "Offline"), you will see the
    98     following (or something similar):
    99     @code
    100     $ cout Hello World
    101     Error: Can't execute command "cout", access denied.
    102     @endcode
    103 
    104     If a command is executed, the arguments are passed to an underlying function,
    105     whitch is wrapped by an orxonox::Functor which again is wrapped by an orxonox::Executor.
    106     The Functor contains the function-pointer, as well as the object-pointer in
    107     case of a non-static member-function. The executor stores possible default-values
    108     for each argument of the function.
    109 
    110     The function of a command can be changed at any time. It's possible to just exchange
    111     the function-pointer of the underlying Functor if the headers of the functions are
    112     exactly the same. But you can also exchange the Functor itself or even completely
    113     replace the Executor. Also the other attributes of a ConsoleCommand can be modified
    114     during the game, for example it can be activated or deactivated.
    115 
    116     To do so, the function ModifyConsoleCommand() has to be used. It returns an instance
    117     of orxonox::ConsoleCommand::ConsoleCommandManipulator which has an interface similar to
    118     orxonox::ConsoleCommand, but with slight differences. You can use it the same way like
    119     SetConsoleCommand(), meaning you can use command-chains to change different attributes at
    120     the same time. ModifyConsoleCommand() must not be executed statically, but rather in a
    121     function at some point of the execution of the program.
    122 
    123     Example:
    124     @code
    125     void myOtherCoutFunction(const std::string& text)                       // Define a new static function
    126     {
    127         orxout() << "Uppercase: " << getUppercase(text) << endl;            // Print the text in uppercase to the console
    128     }
    129 
    130     {
    131         // ...                                                              // somewhere in the code
    132 
    133         ModifyConsoleCommand("cout").setFunction(&myOtherCoutFunction);     // Modify the underlying function of the command
    134 
    135         // ...
    136     }
    137     @endcode
    138 
    139     If you now enter the command into the shell, you'll see a different behavior:
    140     @code
    141     $ cout Hello World
    142     Uppercase: HELLO WORLD
    143     $ cout
    144     Uppercase: NO TEXT
    145     @endcode
    146 
    147     A few important notes about changing functions:
    148 
    149     Instead of changing the function with setFunction(), you can also create a command-stack
    150     by using pushFunction() and popFunction(). It's important to note a few things about that,
    151     because the underlying structure of Executor and Functor has a few pitfalls:
    152      - If you push a new function-pointer, the same executor as before will be used (and, if
    153        the headers match, even the same functor can be used, which is very fast)
    154      - If you push a new Functor, the same executor as before will be used
    155      - If you push a new Executor, everything is changed
    156 
    157     Note that the executor contains the @b default @b values, so if you just exchange the
    158     Functor, the default values remain the same. However if you decide to change the default
    159     values at any point of the stack, <b>this will also change the default values on all
    160     other stack-levels</b> that share the same executor. If you don't like this behavior,
    161     you have to explicitly push a new executor before changing the default values, either by
    162     calling pushFunction(executor) or by calling pushFunction(void) which pushes a copy of
    163     the current executor to the stack.
    164 
    165     Another important point are object pointers in case of non-static member-functions.
    166     Whenever you set or push a new function, <b>you must add the object pointer again</b>
    167     because objects are stored in the Functor which is usually exchanged if you change
    168     the function.
    169 
    170     You can also use a stack for objects, but note that this <b>object-stack is different for each
    171     function</b> - so if you set a new function, the object-stack will be cleared. If you push
    172     a new function, the old object-stack is stored in the stack, so it can be restored if
    173     you pop the function.
    174 
    175     %DeclareConsoleCommand():
    176 
    177     Appart from SetConsoleCommand() you can also call DeclareConsoleCommand(). In contrast
    178     to SetConsoleCommand(), this doesn't assign a function to the command. Indeed you have
    179     to pass a function-pointer to DeclareConsoleCommand(), but it is only used to determine
    180     the header of the future command-function. This allows to declare a command statically,
    181     thus it's possible to evaluate key-bindings of this command, but the actual function
    182     can be assigned at a later point.
    183 
    184     Example:
    185     @code
    186     DeclareConsoleCommand("cout", &prototype::void__string);
    187     @endcode
    188 
    189     If you try to execute the command now, you see the following (or something similar):
    190     @code
    191     $ cout Hello World
    192     Error: Can't execute command "cout", command is not active.
    193     @endcode
    194 
    195     You first have to assign a function to use the command:
    196     @code
    197     {
    198         // ...
    199 
    200         ModifyConsoleCommand("cout").setFunction(&myCoutFunction);
    201 
    202         // ...
    203     }
    204     @endcode
    205 
    206     Now you can use it:
    207     @code
    208     $ cout Hello World
    209     Text: Hello World
    210     @endcode
    211 
    212     Note that the initial function prototype::void__string is defined in the namespace
    213     orxonox::prototype. If there's no function with the desired header, you can extend
    214     the collection of functions or simply use another function that has the same header.
     32    @brief Declaration of the orxonox::ConsoleCommand class.
    21533*/
    21634
     
    22341#include <vector>
    22442
    225 #include "util/VA_NARGS.h"
    22643#include "ArgumentCompletionFunctions.h"
    22744#include "Executor.h"
    228 
    229 
    230 /**
    231     @brief Defines a console command. The macro is overloaded for 2-4 parameters.
    232 
    233     This is an overloaded macro. Depending on the number of arguments a different
    234     overloaded implementation of the macro will be chosen.
    235 
    236     Console commands created with SetConsoleCommand() become active immediately and
    237     the given function-pointer (and optionally the object) will be used to execute
    238     the command.
    239 */
    240 #define SetConsoleCommand(...) \
    241     BOOST_PP_EXPAND(BOOST_PP_CAT(SetConsoleCommand, ORXONOX_VA_NARGS(__VA_ARGS__))(__VA_ARGS__))
    242 /**
    243     @brief This macro is executed if you call SetConsoleCommand() with 2 arguments.
    244     @param name The name (string) of the console command
    245     @param functionpointer The function-pointer of the corresponding command-function
    246 */
    247 #define SetConsoleCommand2(name, functionpointer) \
    248     SetConsoleCommandGeneric("", name, orxonox::createFunctor(functionpointer))
    249 /**
    250     @brief This macro is executed if you call SetConsoleCommand() with 3 arguments.
    251     @param group The group (string) of the console command
    252     @param name The name (string) of the console command
    253     @param functionpointer The function-pointer of the corresponding command-function
    254 */
    255 #define SetConsoleCommand3(group, name, functionpointer) \
    256     SetConsoleCommandGeneric(group, name, orxonox::createFunctor(functionpointer))
    257 /**
    258     @brief This macro is executed if you call SetConsoleCommand() with 4 arguments.
    259     @param group The group (string) of the console command
    260     @param name The name (string) of the console command
    261     @param functionpointer The function-pointer of the corresponding command-function
    262     @param object The object that will be assigned to the command. Used for member-functions.
    263 */
    264 #define SetConsoleCommand4(group, name, functionpointer, object) \
    265     SetConsoleCommandGeneric(group, name, orxonox::createFunctor(functionpointer, object))
    266 
    267 /// Internal macro
    268 #define SetConsoleCommandGeneric(group, name, functor) \
    269     static orxonox::ConsoleCommand& BOOST_PP_CAT(__consolecommand_, __UNIQUE_NUMBER__) = (*orxonox::createConsoleCommand(group, name, orxonox::createExecutor(functor)))
    270 
    271 
    272 /**
    273     @brief Declares a console command. The macro is overloaded for 2-3 parameters.
    274 
    275     This is an overloaded macro. Depending on the number of arguments a different
    276     overloaded implementation of the macro will be chosen.
    277 
    278     Console commands created with DeclareConsoleCommand() don't use the the given
    279     function-pointer to execute the command, it is only used to define the header
    280     of the future command-function. The command is inactive until you manually
    281     set a function with orxonox::ModifyConsoleCommand(). You can use a different
    282     function-pointer than in the final command, as long as it has the same header.
    283 */
    284 #define DeclareConsoleCommand(...) \
    285     BOOST_PP_EXPAND(BOOST_PP_CAT(DeclareConsoleCommand, ORXONOX_VA_NARGS(__VA_ARGS__))(__VA_ARGS__))
    286 /**
    287     @brief This macro is executed if you call DeclareConsoleCommand() with 2 arguments.
    288     @param name The name (string) of the console command
    289     @param functionpointer The function-pointer of an arbitrary function that has the same header as the final function
    290 */
    291 #define DeclareConsoleCommand2(name, functionpointer) \
    292     DeclareConsoleCommandGeneric("", name, orxonox::createFunctor(functionpointer))
    293 /**
    294     @brief This macro is executed if you call DeclareConsoleCommand() with 3 arguments.
    295     @param group The group (string) of the console command
    296     @param name The name (string) of the console command
    297     @param functionpointer The function-pointer of an arbitrary function that has the same header as the final function
    298 */
    299 #define DeclareConsoleCommand3(group, name, functionpointer) \
    300     DeclareConsoleCommandGeneric(group, name, orxonox::createFunctor(functionpointer))
    301 
    302 /// Internal macro
    303 #define DeclareConsoleCommandGeneric(group, name, functor) \
    304     static orxonox::ConsoleCommand& BOOST_PP_CAT(__consolecommand_, __UNIQUE_NUMBER__) = (*orxonox::createConsoleCommand(group, name, orxonox::createExecutor(functor), false))
    305 
    30645
    30746namespace orxonox
     
    365104
    366105        public:
     106            /**
     107             * @brief Defines the name of a command, consisting of an optional group ("" means no group) and the name itself.
     108             */
     109            struct CommandName
     110            {
     111                CommandName(const std::string& group, const std::string& name) : group_(group), name_(name) {}
     112                std::string group_;
     113                std::string name_;
     114            };
     115
    367116            /**
    368117                @brief Helper class that is used to manipulate console commands.
     
    522271
    523272        public:
     273            ConsoleCommand(const std::string& name, const ExecutorPtr& executor, bool bInitialized = true);
    524274            ConsoleCommand(const std::string& group, const std::string& name, const ExecutorPtr& executor, bool bInitialized = true);
    525275            ~ConsoleCommand();
     
    620370                { return this; }
    621371
     372            inline const std::vector<CommandName>& getNames()
     373                { return this->names_; }
     374
    622375        private:
     376            void init(const std::string& group, const std::string& name, const ExecutorPtr& executor, bool bInitialized);
     377
    623378            bool headersMatch(const FunctorPtr& functor);
    624379            bool headersMatch(const ExecutorPtr& executor);
     
    641396            AccessLevel::Enum accessLevel_;                                 ///< The access level (the state of the game in which you can access the command)
    642397            std::string baseName_;                                          ///< The name that was first assigned to the command
     398            std::vector<CommandName> names_;                                ///< All names and aliases of this command
    643399            FunctorPtr baseFunctor_;                                        ///< The functor that defines the header of the command-function
    644400
     
    655411            LanguageEntryLabel descriptionReturnvalue_;                     ///< A description of the return-value
    656412            LanguageEntryLabel descriptionParam_[MAX_FUNCTOR_ARGUMENTS];    ///< A description for each argument
    657 
    658         public:
    659             /// Returns the map with all groups and commands.
    660             static inline const std::map<std::string, std::map<std::string, ConsoleCommand*> >& getCommands()
    661                 { return ConsoleCommand::getCommandMap(); }
    662             /// Returns the map with all groups and commands in lowercase.
    663             static inline const std::map<std::string, std::map<std::string, ConsoleCommand*> >& getCommandsLC()
    664                 { return ConsoleCommand::getCommandMapLC(); }
    665 
    666             /// Returns a command (shortcut) with given name. @param name The name of the command shortcut @param bPrintError If true, an error is printed if the command doesn't exist
    667             static inline ConsoleCommand* getCommand(const std::string& name, bool bPrintError = false)
    668                 { return ConsoleCommand::getCommand("", name, bPrintError); }
    669             /// Returns a command (shortcut) with given name in lowercase. @param name The lowercase name of the command shortcut @param bPrintError If true, an error is printed if the command doesn't exist
    670             static inline ConsoleCommand* getCommandLC(const std::string& name, bool bPrintError = false)
    671                 { return ConsoleCommand::getCommandLC("", name, bPrintError); }
    672 
    673             static ConsoleCommand* getCommand(const std::string& group, const std::string& name, bool bPrintError = false);
    674             static ConsoleCommand* getCommandLC(const std::string& group, const std::string& name, bool bPrintError = false);
    675 
    676             static void destroyAll();
    677 
    678         private:
    679             static std::map<std::string, std::map<std::string, ConsoleCommand*> >& getCommandMap();
    680             static std::map<std::string, std::map<std::string, ConsoleCommand*> >& getCommandMapLC();
    681 
    682             static void registerCommand(const std::string& group, const std::string& name, ConsoleCommand* command);
    683             static void unregisterCommand(ConsoleCommand* command);
    684413    };
    685 
    686     /**
    687         @brief Creates a new ConsoleCommand.
    688         @param name The name of the command
    689         @param executor The executor of the command
    690         @param bInitialized If true, the command is ready to be executed, otherwise it has to be activated first.
    691     */
    692     inline ConsoleCommand* createConsoleCommand(const std::string& name, const ExecutorPtr& executor, bool bInitialized = true)
    693         { return new ConsoleCommand("", name, executor, bInitialized); }
    694     /**
    695         @brief Creates a new ConsoleCommand.
    696         @param group The group of the command
    697         @param name The name of the command
    698         @param executor The executor of the command
    699         @param bInitialized If true, the command is ready to be executed, otherwise it has to be activated first.
    700     */
    701     inline ConsoleCommand* createConsoleCommand(const std::string& group, const std::string& name, const ExecutorPtr& executor, bool bInitialized = true)
    702         { return new ConsoleCommand(group, name, executor, bInitialized); }
    703 
    704 
    705     /**
    706         @brief Returns a manipulator for a command with the given name.
    707 
    708         @note If the command doesn't exist, the manipulator contains a NULL pointer to the command,
    709         but it can still be used without checks, because all functions of ConsoleCommandManipulator
    710         check internally if the command exists.
    711     */
    712     inline ConsoleCommand::ConsoleCommandManipulator ModifyConsoleCommand(const std::string& name)
    713         { return ConsoleCommand::getCommand(name, true); }
    714     /**
    715         @brief Returns a manipulator for a command with the given group and name.
    716 
    717         @note If the command doesn't exist, the manipulator contains a NULL pointer to the command,
    718         but it can still be used without checks, because all functions of ConsoleCommandManipulator
    719         check internally if the command exists.
    720     */
    721     inline ConsoleCommand::ConsoleCommandManipulator ModifyConsoleCommand(const std::string& group, const std::string& name)
    722         { return ConsoleCommand::getCommand(group, name, true); }
    723414}
    724415
  • code/trunk/src/libraries/core/command/ConsoleCommandCompilation.cc

    r8858 r10624  
    4141#include "util/ExprParser.h"
    4242#include "util/StringUtils.h"
    43 #include "ConsoleCommand.h"
     43#include "ConsoleCommandIncludes.h"
    4444#include "CommandExecutor.h"
    4545
  • code/trunk/src/libraries/core/command/IRC.cc

    r8858 r10624  
    3939#include "util/Exception.h"
    4040#include "util/StringUtils.h"
    41 #include "ConsoleCommand.h"
     41#include "ConsoleCommandIncludes.h"
    4242#include "TclThreadManager.h"
    4343
  • code/trunk/src/libraries/core/command/Shell.cc

    r9667 r10624  
    4242#include "core/config/ConfigFileManager.h"
    4343#include "core/config/ConfigValueIncludes.h"
    44 #include "core/PathConfig.h"
     44#include "core/ApplicationPaths.h"
    4545#include "core/input/InputBuffer.h"
    4646#include "CommandExecutor.h"
     
    8484
    8585        // Choose the default level according to the path Orxonox was started (build directory or not)
    86         OutputLevel defaultDebugLevel = (PathConfig::buildDirectoryRun() ? DefaultLogLevel::Dev : DefaultLogLevel::User);
     86        OutputLevel defaultDebugLevel = (ApplicationPaths::buildDirectoryRun() ? DefaultLogLevel::Dev : DefaultLogLevel::User);
    8787        this->setLevelMax(defaultDebugLevel);
    8888
     
    164164    void Shell::devModeChanged(bool value)
    165165    {
    166         bool isNormal = (value == PathConfig::buildDirectoryRun());
     166        bool isNormal = (value == ApplicationPaths::buildDirectoryRun());
    167167        if (isNormal)
    168168        {
  • code/trunk/src/libraries/core/command/Shell.h

    r9667 r10624  
    4949
    5050#include "util/output/BaseWriter.h"
    51 #include "core/Core.h"
     51#include "core/CoreConfig.h"
    5252
    5353namespace orxonox
  • code/trunk/src/libraries/core/command/TclBind.cc

    r9550 r10624  
    3737#include "util/Exception.h"
    3838#include "util/StringUtils.h"
    39 #include "core/PathConfig.h"
     39#include "core/ApplicationPaths.h"
    4040#include "CommandExecutor.h"
    41 #include "ConsoleCommand.h"
     41#include "ConsoleCommandIncludes.h"
    4242#include "TclThreadManager.h"
    4343
     
    143143    {
    144144#ifdef DEPENDENCY_PACKAGE_ENABLE
    145         if (PathConfig::buildDirectoryRun())
     145        if (ApplicationPaths::buildDirectoryRun())
    146146            return (std::string(specialConfig::dependencyLibraryDirectory) + "/tcl");
    147147        else
    148             return (PathConfig::getRootPathString() + specialConfig::defaultLibraryPath + "/tcl");
     148            return (ApplicationPaths::getRootPathString() + specialConfig::defaultLibraryPath + "/tcl");
    149149#else
    150150        return "";
  • code/trunk/src/libraries/core/command/TclThreadManager.cc

    r8858 r10624  
    4747#include "core/CoreIncludes.h"
    4848#include "CommandExecutor.h"
    49 #include "ConsoleCommand.h"
     49#include "ConsoleCommandIncludes.h"
    5050#include "TclBind.h"
    5151#include "TclThreadList.h"
  • code/trunk/src/libraries/core/config/CMakeLists.txt

    r9667 r10624  
    11ADD_SOURCE_FILES(CORE_SRC_FILES
    2   CommandLineParser.cc
    32#  ConfigFile.cc is already included in FilesystemBuildUnit.cc
    43  ConfigFileEntryValue.cc
  • code/trunk/src/libraries/core/config/ConfigFile.cc

    r9559 r10624  
    3838#include "util/Convert.h"
    3939#include "util/StringUtils.h"
    40 #include "core/PathConfig.h"
     40#include "core/ConfigurablePaths.h"
    4141#include "ConfigFileEntryComment.h"
    4242#include "ConfigFileEntryValue.h"
     
    8181        if (!filepath.is_complete())
    8282        {
    83             filepath = PathConfig::getConfigPath() / filepath;
     83            filepath = ConfigurablePaths::getConfigPath() / filepath;
    8484            if (this->bCopyFallbackFile_)
    8585            {
     
    8787                if (!boost::filesystem::exists(filepath))
    8888                {
    89                     boost::filesystem::path defaultFilepath(PathConfig::getDataPath() / DEFAULT_CONFIG_FOLDER / this->filename_);
     89                    boost::filesystem::path defaultFilepath(ConfigurablePaths::getDataPath() / DEFAULT_CONFIG_FOLDER / this->filename_);
    9090                    if (boost::filesystem::exists(defaultFilepath))
    9191                    {
     
    216216        boost::filesystem::path filepath(filename);
    217217        if (!filepath.is_complete())
    218             filepath = PathConfig::getConfigPath() / filename;
     218            filepath = ConfigurablePaths::getConfigPath() / filename;
    219219        std::ofstream file;
    220220        file.open(filepath.string().c_str(), std::fstream::out);
  • code/trunk/src/libraries/core/config/Configurable.cc

    r9667 r10624  
    3232namespace orxonox
    3333{
    34     RegisterClassNoArgs(Configurable);
     34    RegisterClassNoArgs(Configurable).virtualBase();
    3535
    3636    Configurable::Configurable()
  • code/trunk/src/libraries/core/config/SettingsConfigFile.cc

    r9569 r10624  
    3535
    3636#include "util/StringUtils.h"
    37 #include "core/command/ConsoleCommand.h"
     37#include "core/command/ConsoleCommandIncludes.h"
    3838#include "ConfigFileManager.h"
    3939#include "ConfigValueContainer.h"
  • code/trunk/src/libraries/core/input/InputManager.cc

    r9667 r10624  
    4848#include "core/GraphicsManager.h"
    4949#include "core/config/ConfigValueIncludes.h"
    50 #include "core/config/CommandLineParser.h"
    51 #include "core/command/ConsoleCommand.h"
     50#include "core/commandline/CommandLineIncludes.h"
     51#include "core/command/ConsoleCommandIncludes.h"
    5252#include "core/command/Functor.h"
    5353
     
    8585        return (lval = (InputManager::State)(lval & rval));
    8686    }
     87
     88    RegisterAbstractClass(InputManager).inheritsFrom<WindowEventListener>();
    8789
    8890    // ############################################################
  • code/trunk/src/libraries/core/input/JoyStick.cc

    r9667 r10624  
    4747
    4848    std::vector<std::string> JoyStick::deviceNames_s;
     49
     50    RegisterAbstractClass(JoyStick).inheritsFrom<Configurable>();
    4951
    5052    JoyStick::JoyStick(unsigned int id, OIS::InputManager* oisInputManager)
  • code/trunk/src/libraries/core/input/JoyStickQuantityListener.cc

    r9667 r10624  
    3636    std::vector<JoyStick*> JoyStickQuantityListener::joyStickList_s;
    3737
     38    RegisterAbstractClass(JoyStickQuantityListener).inheritsFrom<Listable>();
     39
    3840    JoyStickQuantityListener::JoyStickQuantityListener()
    3941    {
  • code/trunk/src/libraries/core/input/KeyBinder.cc

    r9667 r10624  
    3737#include "core/config/ConfigValueIncludes.h"
    3838#include "core/config/ConfigFile.h"
    39 #include "core/PathConfig.h"
     39#include "core/ApplicationPaths.h"
     40#include "core/ConfigurablePaths.h"
    4041#include "InputCommands.h"
    4142#include "JoyStick.h"
     
    4344namespace orxonox
    4445{
     46    RegisterAbstractClass(KeyBinder).inheritsFrom<JoyStickQuantityListener>();
     47
    4548    /**
    4649    @brief
     
    253256        orxout(internal_info, context::input) << "KeyBinder: Loading key bindings..." << endl;
    254257
    255         this->configFile_ = new ConfigFile(this->filename_, !PathConfig::buildDirectoryRun());
     258        this->configFile_ = new ConfigFile(this->filename_, !ApplicationPaths::buildDirectoryRun());
    256259        this->configFile_->load();
    257260
    258         if (PathConfig::buildDirectoryRun())
     261        if (ApplicationPaths::buildDirectoryRun())
    259262        {
    260263            // Dev users should have combined key bindings files
    261             std::string defaultFilepath(PathConfig::getDataPathString() + ConfigFile::DEFAULT_CONFIG_FOLDER + '/' + this->filename_);
     264            std::string defaultFilepath(ConfigurablePaths::getDataPathString() + ConfigFile::DEFAULT_CONFIG_FOLDER + '/' + this->filename_);
    262265            std::ifstream file(defaultFilepath.c_str());
    263266            if (file.is_open())
     
    287290            addButtonToCommand(binding, it->second);
    288291            std::string str = binding;
    289             if (PathConfig::buildDirectoryRun() && binding.empty())
     292            if (ApplicationPaths::buildDirectoryRun() && binding.empty())
    290293                str = "NoBinding";
    291294            it->second->setBinding(this->configFile_, this->fallbackConfigFile_, binding, bTemporary);
  • code/trunk/src/libraries/core/input/KeyBinderManager.cc

    r9667 r10624  
    3131#include "util/Output.h"
    3232#include "util/Exception.h"
    33 #include "util/ScopedSingletonManager.h"
     33#include "core/singleton/ScopedSingletonIncludes.h"
    3434#include "core/config/ConfigValueIncludes.h"
    3535#include "core/CoreIncludes.h"
    3636#include "core/LuaState.h"
    37 #include "core/command/ConsoleCommand.h"
     37#include "core/command/ConsoleCommandIncludes.h"
    3838#include "InputManager.h"
    3939#include "KeyDetector.h"
     
    4141namespace orxonox
    4242{
    43     ManageScopedSingleton(KeyBinderManager, ScopeID::Graphics, false);
     43    ManageScopedSingleton(KeyBinderManager, ScopeID::GRAPHICS, false);
    4444
    4545    static const std::string __CC_keybind_name = "keybind";
     
    5252    SetConsoleCommand(__CC_unbind_name,   &KeyBinderManager::unbind).defaultValues("");
    5353    SetConsoleCommand(__CC_tunbind_name,  &KeyBinderManager::tunbind).defaultValues("");
     54
     55    RegisterAbstractClass(KeyBinderManager).inheritsFrom<Configurable>();
    5456
    5557    KeyBinderManager::KeyBinderManager()
  • code/trunk/src/libraries/core/input/KeyDetector.cc

    r7284 r10624  
    2929#include "KeyDetector.h"
    3030
    31 #include "util/ScopedSingletonManager.h"
    3231#include "core/CoreIncludes.h"
    33 #include "core/command/ConsoleCommand.h"
     32#include "core/singleton/ScopedSingletonIncludes.h"
     33#include "core/command/ConsoleCommandIncludes.h"
    3434#include "Button.h"
    3535#include "InputManager.h"
     
    3838namespace orxonox
    3939{
    40     ManageScopedSingleton(KeyDetector, ScopeID::Graphics, false);
     40    ManageScopedSingleton(KeyDetector, ScopeID::GRAPHICS, false);
    4141
    4242    static const std::string __CC_KeyDetector_callback_name = "KeyDetectorKeyPressed";
    4343    DeclareConsoleCommand(__CC_KeyDetector_callback_name, &prototype::void__string).hide();
     44
     45    RegisterAbstractClass(KeyDetector).inheritsFrom<KeyBinder>();
    4446
    4547    KeyDetector::KeyDetector()
  • code/trunk/src/libraries/core/input/Mouse.cc

    r9667 r10624  
    3131#include <ois/OISMouse.h>
    3232#include "core/CoreIncludes.h"
    33 #include "core/command/ConsoleCommand.h"
     33#include "core/command/ConsoleCommandIncludes.h"
    3434#include "InputState.h"
    3535
     
    5050    SetConsoleCommand(__CC_Mouse_name, __CC_ungrab_name, &Mouse::ungrab);
    5151#endif
     52
     53    RegisterAbstractClass(Mouse).inheritsFrom<WindowEventListener>();
    5254
    5355    Mouse::Mouse(unsigned int id, OIS::InputManager* oisInputManager)
  • code/trunk/src/libraries/core/object/CMakeLists.txt

    r9667 r10624  
    22  Context.cc
    33  Destroyable.cc
     4  DestroyLaterManager.cc
    45  Listable.cc
    56  ObjectListBase.cc
  • code/trunk/src/libraries/core/object/Context.cc

    r9667 r10624  
    7676    /*static*/ void Context::setRootContext(Context* context)
    7777    {
    78         if (Context::rootContext_s)
    79             delete Context::rootContext_s;
    8078        Context::rootContext_s = context;
     79    }
     80
     81    /*static*/ void Context::destroyRootContext()
     82    {
     83        delete Context::rootContext_s;
     84        Context::rootContext_s = NULL;
    8185    }
    8286
    8387    /*static*/ Context* Context::getRootContext()
    8488    {
    85         if (!Context::rootContext_s)
    86             Context::rootContext_s = new Context(NULL);
     89        OrxVerify(Context::rootContext_s != NULL, "Root Context is undefined");
    8790        return Context::rootContext_s;
    8891    }
     
    97100        return this->objectLists_[classID];
    98101    }
     102
     103    void Context::destroyObjectList(const Identifier* identifier)
     104    {
     105        ObjectListBase* objectList = this->getObjectList(identifier);
     106        delete objectList;
     107        this->objectLists_[identifier->getClassID()] = NULL;
     108    }
    99109}
  • code/trunk/src/libraries/core/object/Context.h

    r9667 r10624  
    4747        public:
    4848            static void setRootContext(Context* context);
     49            static void destroyRootContext();
    4950            static Context* getRootContext();
    5051
     
    7172            }
    7273
     74            void destroyObjectList(const Identifier* identifier);
     75
    7376        private:
    7477            Context* parentContext_;
  • code/trunk/src/libraries/core/object/Destroyable.cc

    r9944 r10624  
    3333
    3434#include "Destroyable.h"
     35#include "DestroyLaterManager.h"
    3536
    3637#include <cassert>
     
    6061
    6162    /**
    62         @brief Deletes the object if no @ref orxonox::SmartPtr "smart pointers" point to this object. Otherwise schedules the object to be deleted as soon as possible.
    63         Always call destroy() instead of using 'delete' directly, otherwise smart pointers won't work.
     63        @brief Deletes the object if no @ref orxonox::StrongPtr "strong pointers" point to this object. Otherwise schedules the object to be deleted as soon as possible.
     64        Always call destroy() instead of using 'delete' directly, otherwise strong pointers won't work.
    6465    */
    6566    void Destroyable::destroy()
     
    7475        }
    7576    }
     77
     78    /**
     79     * Works like @ref destroy() but doesn't destroy the object until the current tick has ended.
     80     */
     81    void Destroyable::destroyLater()
     82    {
     83        // register in DestroyLaterManager - this ensures that a strongPtr points to this object and keeps it alive for a while
     84        DestroyLaterManager::getInstance().retain(this);
     85
     86        // request destruction -> object will be deleted after all strongPtrs (including the one in DestroyLaterManager) were destroyed.
     87        this->destroy();
     88    }
    7689}
  • code/trunk/src/libraries/core/object/Destroyable.h

    r9944 r10624  
    3030    @file
    3131    @ingroup Object
    32     @brief Declaration of Destroyable, the base class of all objects which can be used with SmartPtr and WeakPtr.
     32    @brief Declaration of Destroyable, the base class of all objects which can be used with StrongPtr and WeakPtr.
    3333*/
    3434
     
    4343{
    4444    /**
    45         @brief Classes must inherit from this class if they should be used with SmartPtr or WeakPtr.
     45        @brief Classes must inherit from this class if they should be used with StrongPtr or WeakPtr.
    4646    */
    4747    class _CoreExport Destroyable
    4848    {
    4949        template <class T>
    50         friend class SmartPtr;
     50        friend class StrongPtr;
    5151
    5252        friend class DestructionListener;
     
    5757
    5858            void destroy();
     59            void destroyLater();
    5960
    60             /// Returns the number of @ref orxonox::SmartPtr "smart pointers" that point to this object.
     61            /// Returns the number of @ref orxonox::StrongPtr "strong pointers" that point to this object.
    6162            inline unsigned int getReferenceCount() const
    6263                { return this->referenceCount_; }
    6364
    6465        protected:
    65             /// This virtual function is called if destroy() is called and no SmartPtr points to this object. Used in some cases to create a new SmartPtr to
     66            /// This virtual function is called if destroy() is called and no StrongPtr points to this object. Used in some cases to create a new StrongPtr to
    6667            /// prevent destruction. Don't call this function directly - use destroy() instead.
    6768            virtual void preDestroy() {}
    6869
    6970        private:
    70             /// Increments the reference counter (for smart pointers).
     71            /// Increments the reference counter (for strong pointers).
    7172            inline void incrementReferenceCount()
    7273                { ++this->referenceCount_; }
    73             /// Decrements the reference counter (for smart pointers).
     74            /// Decrements the reference counter (for strong pointers).
    7475            inline void decrementReferenceCount()
    7576            {
     
    8687                { this->destructionListeners_.erase(pointer); }
    8788
    88             int referenceCount_;                                    //!< Counts the references from smart pointers to this object
     89            int referenceCount_;                                    //!< Counts the references from strong pointers to this object
    8990            bool requestedDestruction_;                             //!< Becomes true after someone called delete on this object
    9091            std::set<DestructionListener*> destructionListeners_;   //!< All destruction listeners (for example weak pointers which point to this object and like to get notified if it dies)
  • code/trunk/src/libraries/core/object/Iterator.h

    r9667 r10624  
    7676                @brief Constructor: Sets the element, whereon the iterator points, to zero.
    7777            */
    78             inline Iterator() : IteratorBase<T, Iterator<T> >(NULL) {}
     78            inline Iterator() : IteratorBase<T, Iterator<T> >() {}
    7979
    8080            /**
     
    8888                @param other The other Iterator
    8989            */
    90             inline Iterator(const Iterator<T>& other) : IteratorBase<T, Iterator<T> >(other) {}
     90            inline Iterator(const IteratorBase<T, Iterator<T> >& other) : IteratorBase<T, Iterator<T> >(other) {}
    9191
    9292            /**
  • code/trunk/src/libraries/core/object/IteratorBase.h

    r9667 r10624  
    3737
    3838#include "core/CorePrereqs.h"
     39
     40#include <boost/static_assert.hpp>
     41#include <boost/type_traits/is_base_of.hpp>
    3942
    4043#include "ObjectListBase.h"
     
    4952    class IteratorBase : public ObjectListElementRemovalListener
    5053    {
     54        BOOST_STATIC_ASSERT((boost::is_base_of<Listable, T>::value));
     55
     56        protected:
     57            /**
     58                @brief Constructor: Sets the element, whereon the iterator points, to the given element.
     59                This constructor is protected and only for internal usage (don't mess with the BaseElements directly).
     60            */
     61            inline IteratorBase(ObjectListBaseElement* element = NULL)
     62            {
     63                this->element_ = element;
     64                this->registerIterator();
     65            }
     66
     67
    5168        public:
    5269            /**
    53                 @brief Constructor: Sets the element, whereon the iterator points, to zero.
    54             */
    55             inline IteratorBase(ObjectListBaseElement* element)
    56             {
     70                @brief Constructor: Sets the element, whereon the iterator points, to the given element.
     71            */
     72            inline IteratorBase(ObjectListElement<T>* element)
     73            {
     74                this->element_ = element;
     75                this->registerIterator();
     76            }
     77
     78            /**
     79                @brief Constructor: Sets the element, whereon the iterator points, to the given element of another type.
     80                The element's type O must be a derivative of the Iterator's type T.
     81            */
     82            template <class O>
     83            inline IteratorBase(ObjectListElement<O>* element)
     84            {
     85                (void)static_cast<T*>((O*)NULL); // Check type: The element's type O must be a derivative of the Iterator's type T.
    5786                this->element_ = element;
    5887                this->registerIterator();
  • code/trunk/src/libraries/core/object/Listable.cc

    r9667 r10624  
    3939namespace orxonox
    4040{
    41     RegisterClass(Listable);
     41    RegisterClass(Listable).virtualBase();
    4242
    4343    /**
  • code/trunk/src/libraries/core/object/ObjectList.h

    r9667 r10624  
    4747#include "core/CorePrereqs.h"
    4848
     49#include <boost/static_assert.hpp>
     50#include <boost/type_traits/is_base_of.hpp>
     51
    4952#include "ObjectListBase.h"
    5053#include "ObjectListIterator.h"
     
    6669    class ObjectList
    6770    {
     71        BOOST_STATIC_ASSERT((boost::is_base_of<Listable, T>::value));
     72
    6873        public:
    6974            typedef ObjectListIterator<T> iterator;
    7075
     76            /// Returns the size of the list (for the root context)
     77            inline static size_t size()
     78            {   return size(Context::getRootContext());   }
    7179            /// Returns the size of the list
    72             inline static size_t size()
     80            inline static size_t size(Context* context)
    7381            {
    74                 return Context::getRootContext()->getObjectList<T>()->size();
     82                return context->getObjectList<T>()->size();
    7583            }
    7684
     85            /// Returns an Iterator to the first element in the list (for the root context).
     86            inline static ObjectListElement<T>* begin()
     87            {   return begin(Context::getRootContext());   }
    7788            /// Returns an Iterator to the first element in the list.
    78             inline static ObjectListElement<T>* begin()
     89            inline static ObjectListElement<T>* begin(Context* context)
    7990            {
    80                 ObjectListBase* list = Context::getRootContext()->getObjectList<T>();
     91                ObjectListBase* list = context->getObjectList<T>();
    8192                return static_cast<ObjectListElement<T>*>(list->begin());
    8293            }
    8394
     95            /// Returns an Iterator to the element after the last element in the list (for the root context).
     96            inline static ObjectListElement<T>* end()
     97            {   return end(Context::getRootContext());   }
    8498            /// Returns an Iterator to the element after the last element in the list.
    85             inline static ObjectListElement<T>* end()
     99            inline static ObjectListElement<T>* end(Context* context)
    86100            {
    87                 ObjectListBase* list = Context::getRootContext()->getObjectList<T>();
     101                ObjectListBase* list = context->getObjectList<T>();
    88102                return static_cast<ObjectListElement<T>*>(list->end());
    89103            }
    90104
     105            /// Returns an Iterator to the last element in the list (for the root context).
     106            inline static ObjectListElement<T>* rbegin()
     107            {   return rbegin(Context::getRootContext());   }
    91108            /// Returns an Iterator to the last element in the list.
    92             inline static ObjectListElement<T>* rbegin()
     109            inline static ObjectListElement<T>* rbegin(Context* context)
    93110            {
    94                 ObjectListBase* list = Context::getRootContext()->getObjectList<T>();
     111                ObjectListBase* list = context->getObjectList<T>();
    95112                return static_cast<ObjectListElement<T>*>(list->rbegin());
    96113            }
    97114
     115            /// Returns an Iterator to the element before the first element in the list (for the root context).
     116            inline static ObjectListElement<T>* rend()
     117            {   return rend(Context::getRootContext());   }
    98118            /// Returns an Iterator to the element before the first element in the list.
    99             inline static ObjectListElement<T>* rend()
     119            inline static ObjectListElement<T>* rend(Context* context)
    100120            {
    101                 ObjectListBase* list = Context::getRootContext()->getObjectList<T>();
     121                ObjectListBase* list = context->getObjectList<T>();
    102122                return static_cast<ObjectListElement<T>*>(list->rend());
    103123            }
  • code/trunk/src/libraries/core/object/ObjectListIterator.h

    r9667 r10624  
    7474                @brief Constructor: Sets the element, whereon the ObjectListIterator points, to zero.
    7575            */
    76             inline ObjectListIterator() : IteratorBase<T, ObjectListIterator<T> >(NULL) {}
     76            inline ObjectListIterator() : IteratorBase<T, ObjectListIterator<T> >() {}
    7777
    7878            /**
  • code/trunk/src/libraries/core/object/WeakPtr.h

    r9571 r10624  
    104104            }
    105105
    106             /// Constructor: Used to explicitly initialize the weak pointer with a null pointer
    107             inline WeakPtr(int) : pointer_(0), base_(0), callback_(0)
    108             {
    109             }
    110 
    111106            /// Constructor: Initializes the weak pointer with a pointer to an object.
    112107            inline WeakPtr(T* pointer) : pointer_(pointer), base_(pointer), callback_(0)
     
    132127            {
    133128                this->unregisterAsDestructionListener(this->base_);
    134             }
    135 
    136             /// Used to assign a null pointer.
    137             inline WeakPtr& operator=(int)
    138             {
    139                 WeakPtr(0).swap(*this);
    140                 return *this;
    141129            }
    142130
Note: See TracChangeset for help on using the changeset viewer.