From 32edaa25fe6324cb63b5bf11b86997d5763b6ff7 Mon Sep 17 00:00:00 2001
From: Marianne Gagnon <auria.mg@gmail.com>
Date: Tue, 9 Jun 2015 20:24:17 -0400
Subject: [PATCH] Adjust load and cleanup sequence for scripts, enabling
 scripts in library objects

---
 src/modes/world.cpp                      |  5 +++
 src/scriptengine/script_engine.cpp       | 57 ++++++++++--------------
 src/scriptengine/script_engine.hpp       |  5 ++-
 src/tracks/track_object_presentation.cpp |  9 ++++
 4 files changed, 40 insertions(+), 36 deletions(-)

diff --git a/src/modes/world.cpp b/src/modes/world.cpp
index d7d71b0f4..5310bdf80 100644
--- a/src/modes/world.cpp
+++ b/src/modes/world.cpp
@@ -163,6 +163,9 @@ void World::init()
         throw std::runtime_error(msg.str());
     }
 
+    std::string script_path = World::getWorld()->getTrack()->getTrackFile("scripting.as");
+    m_script_engine->loadScript(script_path, true);
+
     // Create the physics
     m_physics = new Physics();
 
@@ -207,6 +210,8 @@ void World::init()
         m_weather = new Weather(m_track->getWeatherLightning(),
                           m_track->getWeatherSound());
     }
+
+    m_script_engine->compileLoadedScripts();
 }   // init
 
 //-----------------------------------------------------------------------------
diff --git a/src/scriptengine/script_engine.cpp b/src/scriptengine/script_engine.cpp
index 7c03d35f4..3b1d387e4 100644
--- a/src/scriptengine/script_engine.cpp
+++ b/src/scriptengine/script_engine.cpp
@@ -85,14 +85,14 @@ namespace Scripting
     *  \param string scriptname = name of script to get
     *  \return      The corresponding script
     */
-    std::string getScript(std::string fileName)
+    std::string getScript(std::string script_path)
     {
-        std::string script_path = World::getWorld()->getTrack()->getTrackFile(fileName);
+        //std::string script_path = World::getWorld()->getTrack()->getTrackFile(fileName);
 
         FILE *f = fopen(script_path.c_str(), "rb");
         if (f == NULL)
         {
-            Log::debug("Scripting", "File does not exist : {0}.as", fileName.c_str());
+            Log::debug("Scripting", "File does not exist : {0}", script_path.c_str());
             return "";
         }
 
@@ -205,29 +205,7 @@ namespace Scripting
 
         // TODO: allow splitting in multiple files
         std::string script_filename = "scripting.as";
-        auto cached_script = m_loaded_files.find(script_filename);
         auto cached_function = m_functions_cache.find(function_name);
-
-        if (cached_script == m_loaded_files.end())
-        {
-            // Compile the script code
-            Log::info("Scripting", "Checking for script file '%s'", script_filename.c_str());
-            r = compileScript(m_engine, script_filename);
-            if (r < 0)
-            {
-                Log::info("Scripting", "Script '%s' is not available", script_filename.c_str());
-                m_loaded_files[script_filename] = false;
-                m_functions_cache[function_name] = NULL; // remember that this script is unavailable
-                return;
-            }
-
-            m_loaded_files[script_filename] = true;
-        }
-        else if (cached_script->second == false)
-        {
-            return; // script file unavailable
-        }
-
         if (cached_function == m_functions_cache.end())
         {
             // Find the function for the function we want to execute.
@@ -239,7 +217,7 @@ namespace Scripting
             if (func == NULL)
             {
                 Log::debug("Scripting", "Scripting function was not found : %s", function_name.c_str());
-                m_loaded_files[function_name] = NULL; // remember that this script is unavailable
+                m_functions_cache[function_name] = NULL; // remember that this function is unavailable
                 return;
             }
 
@@ -337,7 +315,7 @@ namespace Scripting
                 curr.second->Release();
         }
         m_functions_cache.clear();
-        m_loaded_files.clear();
+        m_engine->DiscardModule(MODULE_ID_MAIN_SCRIPT_FILE);
     }
 
     //-----------------------------------------------------------------------------
@@ -369,15 +347,15 @@ namespace Scripting
 
     //-----------------------------------------------------------------------------
 
-    int ScriptEngine::compileScript(asIScriptEngine *engine, std::string scriptName)
+    bool ScriptEngine::loadScript(std::string script_path, bool clear_previous)
     {
         int r;
 
-        std::string script = getScript(scriptName);
+        std::string script = getScript(script_path);
         if (script.size() == 0)
         {
             // No such file
-            return -1;
+            return false;
         }
 
         // Add the script sections that will be compiled into executable code.
@@ -385,14 +363,25 @@ namespace Scripting
         // we can call AddScriptSection() several times for the same module and
         // the script engine will treat them all as if they were one. The script
         // section name, will allow us to localize any errors in the script code.
-        asIScriptModule *mod = engine->GetModule(MODULE_ID_MAIN_SCRIPT_FILE, asGM_ALWAYS_CREATE);
+        asIScriptModule *mod = m_engine->GetModule(MODULE_ID_MAIN_SCRIPT_FILE,
+            clear_previous ? asGM_ALWAYS_CREATE : asGM_ONLY_IF_EXISTS);
         r = mod->AddScriptSection("script", &script[0], script.size());
         if (r < 0)
         {
             Log::error("Scripting", "AddScriptSection() failed");
-            return -1;
+            return false;
         }
     
+        return true;
+    }
+
+    //-----------------------------------------------------------------------------
+
+    bool ScriptEngine::compileLoadedScripts()
+    {
+        int r;
+        asIScriptModule *mod = m_engine->GetModule(MODULE_ID_MAIN_SCRIPT_FILE, asGM_ONLY_IF_EXISTS);
+
         // Compile the script. If there are any compiler messages they will
         // be written to the message stream that we set right after creating the 
         // script engine. If there are no errors, and no warnings, nothing will
@@ -401,7 +390,7 @@ namespace Scripting
         if (r < 0)
         {
             Log::error("Scripting", "Build() failed");
-            return -1;
+            return false;
         }
 
         // The engine doesn't keep a copy of the script sections after Build() has
@@ -414,6 +403,6 @@ namespace Scripting
         // scope, so function names, and global variables will not conflict with
         // each other.
 
-        return 0;
+        return true;
     }
 }
diff --git a/src/scriptengine/script_engine.hpp b/src/scriptengine/script_engine.hpp
index 961d16ecb..1d6aa956d 100644
--- a/src/scriptengine/script_engine.hpp
+++ b/src/scriptengine/script_engine.hpp
@@ -43,13 +43,14 @@ namespace Scripting
         void evalScript(std::string script_fragment);
         void cleanupCache();
 
+        bool loadScript(std::string script_path, bool clear_previous);
+        bool compileLoadedScripts();
+
     private:
         asIScriptEngine *m_engine;
-        std::map<std::string, bool> m_loaded_files;
         std::map<std::string, asIScriptFunction*> m_functions_cache;
 
         void configureEngine(asIScriptEngine *engine);
-        int  compileScript(asIScriptEngine *engine,std::string scriptName);
     };   // class ScriptEngine
 
 }
diff --git a/src/tracks/track_object_presentation.cpp b/src/tracks/track_object_presentation.cpp
index d5faeb0b7..6f97b2636 100644
--- a/src/tracks/track_object_presentation.cpp
+++ b/src/tracks/track_object_presentation.cpp
@@ -183,18 +183,27 @@ TrackObjectPresentationLibraryNode::TrackObjectPresentationLibraryNode(
         if (world != NULL)
             track = world->getTrack();
         std::string local_lib_node_path;
+        std::string local_script_file_path;
         if (track != NULL)
+        {
             local_lib_node_path = track->getTrackFile("library/" + name + "/node.xml");
+            local_script_file_path = track->getTrackFile("library/" + name + "/scripting.as");
+        }
         std::string lib_node_path = lib_path + "node.xml";
+        std::string lib_script_file_path = lib_path + "scripting.as";
 
         if (local_lib_node_path.size() > 0 && file_manager->fileExists(local_lib_node_path))
         {
             lib_path = track->getTrackFile("library/" + name);
             libroot = file_manager->createXMLTree(local_lib_node_path);
+            if (track != NULL)
+                World::getWorld()->getScriptEngine()->loadScript(lib_script_file_path, false);
         }
         else if (file_manager->fileExists(lib_node_path))
         {
             libroot = file_manager->createXMLTree(lib_node_path);
+            if (track != NULL)
+                World::getWorld()->getScriptEngine()->loadScript(lib_script_file_path, false);
         }
         else
         {