Index: code/trunk/src/libraries/core/Core.cc
===================================================================
--- code/trunk/src/libraries/core/Core.cc	(revision 9667)
+++ code/trunk/src/libraries/core/Core.cc	(revision 10624)
@@ -54,22 +54,18 @@
 #include "util/Output.h"
 #include "util/Exception.h"
+#include "util/SignalHandler.h"
 #include "util/output/LogWriter.h"
 #include "util/output/OutputManager.h"
-#include "util/Scope.h"
-#include "util/ScopedSingletonManager.h"
-#include "util/SignalHandler.h"
-#include "PathConfig.h"
-#include "config/CommandLineParser.h"
+#include "core/singleton/Scope.h"
+#include "ApplicationPaths.h"
+#include "ConfigurablePaths.h"
+#include "commandline/CommandLineIncludes.h"
 #include "config/ConfigFileManager.h"
-#include "config/ConfigValueIncludes.h"
-#include "CoreIncludes.h"
-#include "DynLibManager.h"
 #include "GameMode.h"
 #include "GraphicsManager.h"
 #include "GUIManager.h"
-#include "class/Identifier.h"
 #include "Language.h"
+#include "Loader.h"
 #include "LuaState.h"
-#include "command/ConsoleCommand.h"
 #include "command/IOConsole.h"
 #include "command/TclBind.h"
@@ -77,4 +73,10 @@
 #include "input/InputManager.h"
 #include "object/ObjectList.h"
+#include "module/DynLibManager.h"
+#include "module/ModuleInstance.h"
+#include "module/StaticInitializationManager.h"
+#include "module/PluginManager.h"
+#include "CoreStaticInitializationHandler.h"
+#include "UpdateListener.h"
 
 namespace orxonox
@@ -92,13 +94,12 @@
 #endif
 
-    // register Core as an abstract class to avoid problems if the class hierarchy is created within Core-constructor
-    RegisterAbstractClass(Core).inheritsFrom(Class(Configurable));
-
     Core::Core(const std::string& cmdLine)
-        : pathConfig_(NULL)
+        : applicationPaths_(NULL)
+        , configurablePaths_(NULL)
         , dynLibManager_(NULL)
         , signalHandler_(NULL)
         , configFileManager_(NULL)
         , languageInstance_(NULL)
+        , loaderInstance_(NULL)
         , ioConsole_(NULL)
         , tclBind_(NULL)
@@ -110,8 +111,8 @@
         , graphicsScope_(NULL)
         , bGraphicsLoaded_(false)
-        , bStartIOConsole_(true)
-        , lastLevelTimestamp_(0)
-        , ogreConfigTimestamp_(0)
-        , bDevMode_(false)
+        , staticInitHandler_(NULL)
+        , pluginManager_(NULL)
+        , rootModule_(NULL)
+        , config_(NULL)
         , destructionHelper_(this)
     {
@@ -119,23 +120,17 @@
 
         // Set the hard coded fixed paths
-        this->pathConfig_ = new PathConfig();
+        this->applicationPaths_ = new ApplicationPaths();
 
         // Create a new dynamic library manager
         this->dynLibManager_ = new DynLibManager();
 
-        // Load modules
-        orxout(internal_info) << "Loading modules:" << endl;
-        const std::vector<std::string>& modulePaths = this->pathConfig_->getModulePaths();
-        for (std::vector<std::string>::const_iterator it = modulePaths.begin(); it != modulePaths.end(); ++it)
-        {
-            try
-            {
-                this->dynLibManager_->load(*it);
-            }
-            catch (...)
-            {
-                orxout(user_error) << "Couldn't load module \"" << *it << "\": " << Exception::handleMessage() << endl;
-            }
-        }
+        // create handler for static initialization
+        new StaticInitializationManager(); // create singleton
+        this->staticInitHandler_ = new CoreStaticInitializationHandler();
+        StaticInitializationManager::getInstance().addHandler(this->staticInitHandler_);
+
+        // load root module (all libraries which are linked to the executable, including core, network, and orxonox)
+        this->rootModule_ = ModuleInstance::getCurrentModuleInstance();
+        StaticInitializationManager::getInstance().loadModule(this->rootModule_);
 
         // Parse command line arguments AFTER the modules have been loaded (static code!)
@@ -143,18 +138,21 @@
 
         // Set configurable paths like log, config and media
-        this->pathConfig_->setConfigurablePaths();
-
-        orxout(internal_info) << "Root path:       " << PathConfig::getRootPathString() << endl;
-        orxout(internal_info) << "Executable path: " << PathConfig::getExecutablePathString() << endl;
-        orxout(internal_info) << "Data path:       " << PathConfig::getDataPathString() << endl;
-        orxout(internal_info) << "Ext. data path:  " << PathConfig::getExternalDataPathString() << endl;
-        orxout(internal_info) << "Config path:     " << PathConfig::getConfigPathString() << endl;
-        orxout(internal_info) << "Log path:        " << PathConfig::getLogPathString() << endl;
-        orxout(internal_info) << "Modules path:    " << PathConfig::getModulePathString() << endl;
-
-        // create a signal handler (only active for Linux)
+        this->configurablePaths_ = new ConfigurablePaths();
+        this->configurablePaths_->setConfigurablePaths(ApplicationPaths::getInstance());
+
+        orxout(internal_info) << "Root path:       " << ApplicationPaths::getRootPathString() << endl;
+        orxout(internal_info) << "Executable path: " << ApplicationPaths::getExecutablePathString() << endl;
+        orxout(internal_info) << "Modules path:    " << ApplicationPaths::getModulePathString() << endl;
+        orxout(internal_info) << "Plugins path:    " << ApplicationPaths::getPluginPathString() << endl;
+
+        orxout(internal_info) << "Data path:       " << ConfigurablePaths::getDataPathString() << endl;
+        orxout(internal_info) << "Ext. data path:  " << ConfigurablePaths::getExternalDataPathString() << endl;
+        orxout(internal_info) << "Config path:     " << ConfigurablePaths::getConfigPathString() << endl;
+        orxout(internal_info) << "Log path:        " << ConfigurablePaths::getLogPathString() << endl;
+
+        // create a signal handler
         // This call is placed as soon as possible, but after the directories are set
         this->signalHandler_ = new SignalHandler();
-        this->signalHandler_->doCatch(PathConfig::getExecutablePathString(), PathConfig::getLogPathString() + "orxonox_crash.log");
+        this->signalHandler_->doCatch(ApplicationPaths::getExecutablePathString(), ConfigurablePaths::getLogPathString() + "orxonox_crash.log");
 
 #ifdef ORXONOX_PLATFORM_WINDOWS
@@ -177,20 +175,18 @@
         this->languageInstance_ = new Language();
 
+        // initialize root context
+        Context::setRootContext(new Context(NULL));
+
         // Do this soon after the ConfigFileManager has been created to open up the
         // possibility to configure everything below here
-        RegisterObject(Core);
         orxout(internal_info) << "configuring Core" << endl;
-        this->setConfigValues();
+        this->config_ = new CoreConfig();
 
         // Set the correct log path and rewrite the log file with the correct log levels
-        OutputManager::getInstance().getLogWriter()->setLogDirectory(PathConfig::getLogPathString());
+        OutputManager::getInstance().getLogWriter()->setLogDirectory(ConfigurablePaths::getLogPathString());
 
 #if !defined(ORXONOX_PLATFORM_APPLE) && !defined(ORXONOX_USE_WINMAIN)
         // Create persistent IO console
-        if (CommandLineParser::getValue("noIOConsole").get<bool>())
-        {
-            ModifyConfigValue(bStartIOConsole_, tset, false);
-        }
-        if (this->bStartIOConsole_)
+        if (CommandLineParser::getValue("noIOConsole").get<bool>() == false && this->config_->getStartIOConsole())
         {
             orxout(internal_info) << "creating IO console" << endl;
@@ -201,5 +197,13 @@
         // creates the class hierarchy for all classes with factories
         orxout(internal_info) << "creating class hierarchy" << endl;
-        IdentifierManager::getInstance().createClassHierarchy();
+        this->staticInitHandler_->initInstances(this->rootModule_);
+        this->staticInitHandler_->setInitInstances(true);
+
+        // Create plugin manager and search for plugins
+        this->pluginManager_ = new PluginManager();
+        this->pluginManager_->findPlugins();
+
+        // Loader
+        this->loaderInstance_ = new Loader();
 
         // Load OGRE excluding the renderer and the render window
@@ -208,10 +212,10 @@
 
         // initialise Tcl
-        this->tclBind_ = new TclBind(PathConfig::getDataPathString());
+        this->tclBind_ = new TclBind(ConfigurablePaths::getDataPathString());
         this->tclThreadManager_ = new TclThreadManager(tclBind_->getTclInterpreter());
 
         // Create singletons that always exist (in other libraries)
         orxout(internal_info) << "creating root scope:" << endl;
-        this->rootScope_ = new Scope<ScopeID::Root>();
+        this->rootScope_ = new Scope<ScopeID::ROOT>();
 
         // Generate documentation instead of normal run?
@@ -237,7 +241,4 @@
         orxout(internal_status) << "destroying Core object..." << endl;
 
-        // Remove us from the object lists again to avoid problems when destroying them
-        this->unregisterObject();
-
         safeObjectDelete(&graphicsScope_);
         safeObjectDelete(&guiManager_);
@@ -248,93 +249,82 @@
         safeObjectDelete(&tclBind_);
         safeObjectDelete(&ioConsole_);
+        safeObjectDelete(&loaderInstance_);
+        safeObjectDelete(&config_);
         safeObjectDelete(&languageInstance_);
         safeObjectDelete(&configFileManager_);
-        ConsoleCommand::destroyAll();
-        Context::setRootContext(NULL);
-        IdentifierManager::getInstance().destroyAllIdentifiers();
         safeObjectDelete(&signalHandler_);
+        safeObjectDelete(&pluginManager_);
+        Context::getRootContext()->unregisterObject(); // unregister context from object lists - otherwise the root context would be destroyed while unloading the root module
+        if (this->rootModule_)
+        {
+            StaticInitializationManager::getInstance().unloadModule(this->rootModule_);
+            this->rootModule_->deleteAllStaticallyInitializedInstances();
+        }
+        if (this->staticInitHandler_)
+            StaticInitializationManager::getInstance().removeHandler(this->staticInitHandler_);
+        Context::destroyRootContext();
+        safeObjectDelete(&rootModule_);
+        safeObjectDelete(&staticInitHandler_);
+        delete &StaticInitializationManager::getInstance();
         safeObjectDelete(&dynLibManager_);
-        safeObjectDelete(&pathConfig_);
+        safeObjectDelete(&configurablePaths_);
+        safeObjectDelete(&applicationPaths_);
 
         orxout(internal_status) << "finished destroying Core object" << endl;
     }
 
-    //! Function to collect the SetConfigValue-macro calls.
-    void Core::setConfigValues()
-    {
-        SetConfigValueExternal(OutputManager::getInstance().getLogWriter()->configurableMaxLevel_,
-                               OutputManager::getInstance().getLogWriter()->getConfigurableSectionName(),
-                               OutputManager::getInstance().getLogWriter()->getConfigurableMaxLevelName(),
-                               OutputManager::getInstance().getLogWriter()->configurableMaxLevel_)
-            .description("The maximum level of output shown in the log file")
-            .callback(static_cast<BaseWriter*>(OutputManager::getInstance().getLogWriter()), &BaseWriter::changedConfigurableLevel);
-        SetConfigValueExternal(OutputManager::getInstance().getLogWriter()->configurableAdditionalContextsMaxLevel_,
-                               OutputManager::getInstance().getLogWriter()->getConfigurableSectionName(),
-                               OutputManager::getInstance().getLogWriter()->getConfigurableAdditionalContextsMaxLevelName(),
-                               OutputManager::getInstance().getLogWriter()->configurableAdditionalContextsMaxLevel_)
-            .description("The maximum level of output shown in the log file for additional contexts")
-            .callback(static_cast<BaseWriter*>(OutputManager::getInstance().getLogWriter()), &BaseWriter::changedConfigurableAdditionalContextsLevel);
-        SetConfigValueExternal(OutputManager::getInstance().getLogWriter()->configurableAdditionalContexts_,
-                               OutputManager::getInstance().getLogWriter()->getConfigurableSectionName(),
-                               OutputManager::getInstance().getLogWriter()->getConfigurableAdditionalContextsName(),
-                               OutputManager::getInstance().getLogWriter()->configurableAdditionalContexts_)
-            .description("Additional output contexts shown in the log file")
-            .callback(static_cast<BaseWriter*>(OutputManager::getInstance().getLogWriter()), &BaseWriter::changedConfigurableAdditionalContexts);
-
-        SetConfigValue(bDevMode_, PathConfig::buildDirectoryRun())
-            .description("Developer mode. If not set, hides some things from the user to not confuse him.")
-            .callback(this, &Core::devModeChanged);
-        SetConfigValue(language_, Language::getInstance().defaultLanguage_)
-            .description("The language of the in game text")
-            .callback(this, &Core::languageChanged);
-        SetConfigValue(bInitRandomNumberGenerator_, true)
-            .description("If true, all random actions are different each time you start the game")
-            .callback(this, &Core::initRandomNumberGenerator);
-        SetConfigValue(bStartIOConsole_, true)
-            .description("Set to false if you don't want to use the IOConsole (for Lua debugging for instance)");
-        SetConfigValue(lastLevelTimestamp_, 0)
-            .description("Timestamp when the last level was started.");
-        SetConfigValue(ogreConfigTimestamp_, 0)
-            .description("Timestamp when the ogre config file was changed.");
-    }
-
-    /** Callback function for changes in the dev mode that affect debug levels.
-        The function behaves according to these rules:
-        - 'normal' mode is defined based on where the program was launched: if
-          the launch path was the build directory, development mode \c on is
-          normal, otherwise normal means development mode \c off.
-        - Debug levels should not be hard configured (\c config instead of
-          \c tconfig) in non 'normal' mode to avoid strange behaviour.
-        - Changing the development mode from 'normal' to the other state will
-          immediately change the debug levels to predefined values which can be
-          reconfigured with \c tconfig.
-    @note
-        The debug levels for the IOConsole and the InGameConsole can be found
-        in the Shell class. The same rules apply.
-    */
-    void Core::devModeChanged()
-    {
-        // Inform listeners
-        ObjectList<DevModeListener>::iterator it = ObjectList<DevModeListener>::begin();
-        for (; it != ObjectList<DevModeListener>::end(); ++it)
-            it->devModeChanged(bDevMode_);
-    }
-
-    //! Callback function if the language has changed.
-    void Core::languageChanged()
-    {
-        // Read the translation file after the language was configured
-        Language::getInstance().readTranslatedLanguageFile();
-    }
-
-    void Core::initRandomNumberGenerator()
-    {
-        static bool bInitialized = false;
-        if (!bInitialized && this->bInitRandomNumberGenerator_)
-        {
-            srand(static_cast<unsigned int>(time(0)));
-            rand();
-            bInitialized = true;
-        }
+    void Core::loadModules()
+    {
+        orxout(internal_info) << "Loading modules:" << endl;
+
+        const std::vector<std::string>& modulePaths = ApplicationPaths::getInstance().getModulePaths();
+        for (std::vector<std::string>::const_iterator it = modulePaths.begin(); it != modulePaths.end(); ++it)
+        {
+            ModuleInstance* module = new ModuleInstance(*it);
+            this->loadModule(module);
+            this->modules_.push_back(module);
+        }
+
+        orxout(internal_info) << "finished loading modules" << endl;
+    }
+
+    void Core::loadModule(ModuleInstance* module)
+    {
+        orxout(internal_info) << "Loading module " << module->getLibraryName() << "..." << endl;
+
+        try
+        {
+            ModuleInstance::setCurrentModuleInstance(module);
+            DynLib* dynLib = this->dynLibManager_->load(module->getLibraryName());
+            module->setDynLib(dynLib);
+
+            StaticInitializationManager::getInstance().loadModule(module);
+        }
+        catch (...)
+        {
+            orxout(user_error) << "Couldn't load module \"" << module->getLibraryName() << "\": " << Exception::handleMessage() << endl;
+        }
+    }
+
+    void Core::unloadModules()
+    {
+        for (std::list<ModuleInstance*>::iterator it = this->modules_.begin(); it != this->modules_.end(); ++it)
+        {
+            ModuleInstance* module = (*it);
+            this->unloadModule(module);
+            delete module;
+        }
+        this->modules_.clear();
+    }
+
+    void Core::unloadModule(ModuleInstance* module)
+    {
+        orxout(internal_info) << "Unloading module " << module->getLibraryName() << "..." << endl;
+
+        StaticInitializationManager::getInstance().unloadModule(module);
+
+        module->deleteAllStaticallyInitializedInstances();
+        this->dynLibManager_->unload(module->getDynLib());
+        module->setDynLib(NULL);
     }
 
@@ -344,5 +334,5 @@
 
         // Any exception should trigger this, even in upgradeToGraphics (see its remarks)
-        Loki::ScopeGuard unloader = Loki::MakeObjGuard(*this, &Core::unloadGraphics);
+        Loki::ScopeGuard unloader = Loki::MakeObjGuard(*this, &Core::unloadGraphics, true);
 
         // Upgrade OGRE to receive a render window
@@ -385,5 +375,5 @@
         // Create singletons associated with graphics (in other libraries)
         orxout(internal_info) << "creating graphics scope:" << endl;
-        graphicsScope_ = new Scope<ScopeID::Graphics>();
+        graphicsScope_ = new Scope<ScopeID::GRAPHICS>();
 
         unloader.Dismiss();
@@ -392,7 +382,10 @@
     }
 
-    void Core::unloadGraphics()
+    void Core::unloadGraphics(bool loadGraphicsManagerWithoutRenderer)
     {
         orxout(internal_info) << "unloading graphics in Core" << endl;
+
+        if (this->graphicsManager_)
+            this->graphicsManager_->unloadDebugOverlay();
 
         safeObjectDelete(&graphicsScope_);
@@ -403,5 +396,8 @@
         // Load Ogre::Root again, but without the render system
         try
-            { this->graphicsManager_ = new GraphicsManager(false); }
+        {
+            if (loadGraphicsManagerWithoutRenderer)
+                this->graphicsManager_ = new GraphicsManager(false);
+        }
         catch (...)
         {
@@ -414,10 +410,4 @@
         bGraphicsLoaded_ = false;
         GameMode::bShowsGraphics_s = false;
-    }
-
-    //! Sets the language in the config-file back to the default.
-    void Core::resetLanguage()
-    {
-        ResetConfigValue(language_);
     }
 
@@ -470,6 +460,7 @@
     void Core::preUpdate(const Clock& time)
     {
-        // Update singletons before general ticking
-        ScopedSingletonManager::preUpdate<ScopeID::Root>(time);
+        // Update UpdateListeners before general ticking
+        for (ObjectList<UpdateListener>::iterator it = ObjectList<UpdateListener>::begin(); it != ObjectList<UpdateListener>::end(); ++it)
+            it->preUpdate(time);
         if (this->bGraphicsLoaded_)
         {
@@ -478,6 +469,4 @@
             // Update GUI
             this->guiManager_->preUpdate(time);
-            // Update singletons before general ticking
-            ScopedSingletonManager::preUpdate<ScopeID::Graphics>(time);
         }
         // Process console events and status line
@@ -490,31 +479,12 @@
     void Core::postUpdate(const Clock& time)
     {
-        // Update singletons just before rendering
-        ScopedSingletonManager::postUpdate<ScopeID::Root>(time);
+        // Update UpdateListeners just before rendering
+        for (ObjectList<UpdateListener>::iterator it = ObjectList<UpdateListener>::begin(); it != ObjectList<UpdateListener>::end(); ++it)
+            it->postUpdate(time);
         if (this->bGraphicsLoaded_)
         {
-            // Update singletons just before rendering
-            ScopedSingletonManager::postUpdate<ScopeID::Graphics>(time);
             // Render (doesn't throw)
             this->graphicsManager_->postUpdate(time);
         }
     }
-
-    void Core::updateLastLevelTimestamp()
-    {
-        ModifyConfigValue(lastLevelTimestamp_, set, static_cast<long long>(time(NULL)));
-    }
-
-    void Core::updateOgreConfigTimestamp()
-    {
-        ModifyConfigValue(ogreConfigTimestamp_, set, static_cast<long long>(time(NULL)));
-    }
-
-
-    RegisterAbstractClass(DevModeListener).inheritsFrom(Class(Listable));
-
-    DevModeListener::DevModeListener()
-    {
-        RegisterObject(DevModeListener);
-    }
 }
