diff --git a/src/MoonSharp.Interpreter/Loaders/UnityAssetsScriptLoader.cs b/src/MoonSharp.Interpreter/Loaders/UnityAssetsScriptLoader.cs index 8bf52a18..7e2ad145 100644 --- a/src/MoonSharp.Interpreter/Loaders/UnityAssetsScriptLoader.cs +++ b/src/MoonSharp.Interpreter/Loaders/UnityAssetsScriptLoader.cs @@ -5,140 +5,153 @@ namespace MoonSharp.Interpreter.Loaders { - /// - /// A script loader which can load scripts from assets in Unity3D. - /// Scripts should be saved as .txt files in a subdirectory of Assets/Resources. - /// - /// When MoonSharp is activated on Unity3D and the default script loader is used, - /// scripts should be saved as .txt files in Assets/Resources/MoonSharp/Scripts. - /// - public class UnityAssetsScriptLoader : ScriptLoaderBase - { - Dictionary m_Resources = new Dictionary(); - - /// - /// The default path where scripts are meant to be stored (if not changed) - /// - public const string DEFAULT_PATH = "MoonSharp/Scripts"; - - /// - /// Initializes a new instance of the class. - /// - /// The path, relative to Assets/Resources. For example - /// if your scripts are stored under Assets/Resources/Scripts, you should - /// pass the value "Scripts". If null, "MoonSharp/Scripts" is used. - public UnityAssetsScriptLoader(string assetsPath = null) - { - assetsPath = assetsPath ?? DEFAULT_PATH; - LoadResourcesWithReflection(assetsPath); - } - - - /// - /// Initializes a new instance of the class. - /// - /// A dictionary mapping filenames to the proper Lua script code. - public UnityAssetsScriptLoader(Dictionary scriptToCodeMap) - { - m_Resources = scriptToCodeMap; - } - - - void LoadResourcesWithReflection(string assetsPath) - { - try - { - Type resourcesType = Type.GetType("UnityEngine.Resources, UnityEngine"); - Type textAssetType = Type.GetType("UnityEngine.TextAsset, UnityEngine"); - - MethodInfo textAssetNameGet = textAssetType.GetProperty("name").GetGetMethod(); - MethodInfo textAssetTextGet = textAssetType.GetProperty("text").GetGetMethod(); - - MethodInfo loadAll = resourcesType.GetMethod("LoadAll", - new Type[] { typeof(string), typeof(Type) }); - - Array array = (Array)loadAll.Invoke(null, new object[] { assetsPath, textAssetType }); - - for (int i = 0; i < array.Length; i++) - { - object o = array.GetValue(i); - - string name = textAssetNameGet.Invoke(o, null) as string; - string text = textAssetTextGet.Invoke(o, null) as string; - - m_Resources.Add(name, text); - } - } - catch (Exception ex) - { + /// + /// A script loader which can load scripts from assets in Unity3D. + /// Scripts should be saved as .txt files in a subdirectory of Assets/Resources. + /// + /// When MoonSharp is activated on Unity3D and the default script loader is used, + /// scripts should be saved as .txt files in Assets/Resources/MoonSharp/Scripts. + /// + public class UnityAssetsScriptLoader : ScriptLoaderBase + { + Dictionary m_Resources = new Dictionary(); + + /// + /// The default path where scripts are meant to be stored (if not changed) + /// + public const string DEFAULT_PATH = "MoonSharp/Scripts"; + + /// + /// Initializes a new instance of the class. + /// + /// The path, relative to Assets/Resources. For example + /// if your scripts are stored under Assets/Resources/Scripts, you should + /// pass the value "Scripts". If null, "MoonSharp/Scripts" is used. + public UnityAssetsScriptLoader(string assetsPath = null) + { + assetsPath = assetsPath ?? DEFAULT_PATH; + LoadResources(assetsPath); + } + + + /// + /// Initializes a new instance of the class. + /// + /// A dictionary mapping filenames to the proper Lua script code. + public UnityAssetsScriptLoader(Dictionary scriptToCodeMap) + { + m_Resources = scriptToCodeMap; + } + + void LoadResources(string assetsPath) + { +#if UNITY_WEBGL + UnityEngine.TextAsset[] array = UnityEngine.Resources.LoadAll(assetsPath); + for (int i = 0; i < array.Length; i++) + { + UnityEngine.TextAsset text = array[i]; + m_Resources.Add(text.name, text.text); + } +#else + LoadResourcesWithReflection(assetsPath); +#endif + } + + void LoadResourcesWithReflection(string assetsPath) + { + try + { + Type resourcesType = Type.GetType("UnityEngine.Resources, UnityEngine"); + Type textAssetType = Type.GetType("UnityEngine.TextAsset, UnityEngine"); + + MethodInfo textAssetNameGet = textAssetType.GetProperty("name").GetGetMethod(); + MethodInfo textAssetTextGet = textAssetType.GetProperty("text").GetGetMethod(); + + MethodInfo loadAll = resourcesType.GetMethod("LoadAll", + new Type[] { typeof(string), typeof(Type) }); + + Array array = (Array)loadAll.Invoke(null, new object[] { assetsPath, textAssetType }); //Unity5.4 + WebGL, it will crash in web browser + + for (int i = 0; i < array.Length; i++) + { + object o = array.GetValue(i); + + string name = textAssetNameGet.Invoke(o, null) as string; + string text = textAssetTextGet.Invoke(o, null) as string; + + m_Resources.Add(name, text); + } + } + catch (Exception ex) + { #if !PCL - Console.WriteLine("Error initializing UnityScriptLoader : {0}", ex); + Console.WriteLine("Error initializing UnityScriptLoader : {0}", ex); #endif - } - } - - private string GetFileName(string filename) - { - int b = Math.Max(filename.LastIndexOf('\\'), filename.LastIndexOf('/')); - - if (b > 0) - filename = filename.Substring(b + 1); - - return filename; - } - - /// - /// Opens a file for reading the script code. - /// It can return either a string, a byte[] or a Stream. - /// If a byte[] is returned, the content is assumed to be a serialized (dumped) bytecode. If it's a string, it's - /// assumed to be either a script or the output of a string.dump call. If a Stream, autodetection takes place. - /// - /// The file. - /// The global context. - /// - /// A string, a byte[] or a Stream. - /// - /// UnityAssetsScriptLoader.LoadFile : Cannot load + file - public override object LoadFile(string file, Table globalContext) - { - file = GetFileName(file); - - if (m_Resources.ContainsKey(file)) - return m_Resources[file]; - else - { - var error = string.Format( + } + } + + private string GetFileName(string filename) + { + int b = Math.Max(filename.LastIndexOf('\\'), filename.LastIndexOf('/')); + + if (b > 0) + filename = filename.Substring(b + 1); + + return filename; + } + + /// + /// Opens a file for reading the script code. + /// It can return either a string, a byte[] or a Stream. + /// If a byte[] is returned, the content is assumed to be a serialized (dumped) bytecode. If it's a string, it's + /// assumed to be either a script or the output of a string.dump call. If a Stream, autodetection takes place. + /// + /// The file. + /// The global context. + /// + /// A string, a byte[] or a Stream. + /// + /// UnityAssetsScriptLoader.LoadFile : Cannot load + file + public override object LoadFile(string file, Table globalContext) + { + file = GetFileName(file); + + if (m_Resources.ContainsKey(file)) + return m_Resources[file]; + else + { + var error = string.Format( @"Cannot load script '{0}'. By default, scripts should be .txt files placed under a Assets/Resources/{1} directory. If you want scripts to be put in another directory or another way, use a custom instance of UnityAssetsScriptLoader or implement your own IScriptLoader (possibly extending ScriptLoaderBase).", file, DEFAULT_PATH); - throw new Exception(error); - } - } + throw new Exception(error); + } + } - /// - /// Checks if a given file exists - /// - /// The file. - /// - public override bool ScriptFileExists(string file) - { - file = GetFileName(file); - return m_Resources.ContainsKey(file); - } + /// + /// Checks if a given file exists + /// + /// The file. + /// + public override bool ScriptFileExists(string file) + { + file = GetFileName(file); + return m_Resources.ContainsKey(file); + } - /// - /// Gets the list of loaded scripts filenames (useful for debugging purposes). - /// - /// - public string[] GetLoadedScripts() - { - return m_Resources.Keys.ToArray(); - } + /// + /// Gets the list of loaded scripts filenames (useful for debugging purposes). + /// + /// + public string[] GetLoadedScripts() + { + return m_Resources.Keys.ToArray(); + } - } + } }