| 
									
										
										
										
											2021-09-12 20:23:05 +02:00
										 |  |  | using System; | 
					
						
							|  |  |  | using System.Collections.Generic; | 
					
						
							|  |  |  | using System.IO; | 
					
						
							|  |  |  | using System.Reflection; | 
					
						
							|  |  |  | using System.Runtime.InteropServices; | 
					
						
							|  |  |  | using System.Runtime.Loader; | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  | using Godot.Bridge; | 
					
						
							| 
									
										
										
										
											2021-09-12 20:23:05 +02:00
										 |  |  | using Godot.NativeInterop; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace GodotPlugins | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     public static class Main | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         private static readonly List<AssemblyName> SharedAssemblies = new(); | 
					
						
							|  |  |  |         private static readonly Assembly CoreApiAssembly = typeof(Godot.Object).Assembly; | 
					
						
							|  |  |  |         private static Assembly? _editorApiAssembly; | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |         private static Assembly? _projectAssembly; | 
					
						
							| 
									
										
										
										
											2021-09-12 20:23:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         private static readonly AssemblyLoadContext MainLoadContext = | 
					
						
							|  |  |  |             AssemblyLoadContext.GetLoadContext(Assembly.GetExecutingAssembly()) ?? | 
					
						
							|  |  |  |             AssemblyLoadContext.Default; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-27 21:57:52 +01:00
										 |  |  |         private static DllImportResolver? _dllImportResolver; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-12 20:23:05 +02:00
										 |  |  |         // Right now we do it this way for simplicity as hot-reload is disabled. It will need to be changed later. | 
					
						
							|  |  |  |         [UnmanagedCallersOnly] | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |         // ReSharper disable once UnusedMember.Local | 
					
						
							| 
									
										
										
										
											2022-02-27 21:57:52 +01:00
										 |  |  |         private static unsafe godot_bool InitializeFromEngine(IntPtr godotDllHandle, godot_bool editorHint, | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |             PluginsCallbacks* pluginsCallbacks, ManagedCallbacks* managedCallbacks) | 
					
						
							| 
									
										
										
										
											2021-09-12 20:23:05 +02:00
										 |  |  |         { | 
					
						
							|  |  |  |             try | 
					
						
							|  |  |  |             { | 
					
						
							| 
									
										
										
										
											2022-02-27 21:57:52 +01:00
										 |  |  |                 _dllImportResolver = new GodotDllImportResolver(godotDllHandle).OnResolveDllImport; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-12 20:23:05 +02:00
										 |  |  |                 SharedAssemblies.Add(CoreApiAssembly.GetName()); | 
					
						
							| 
									
										
										
										
											2022-02-27 21:57:52 +01:00
										 |  |  |                 NativeLibrary.SetDllImportResolver(CoreApiAssembly, _dllImportResolver); | 
					
						
							| 
									
										
										
										
											2021-09-12 20:23:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 if (editorHint.ToBool()) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     _editorApiAssembly = Assembly.Load("GodotSharpEditor"); | 
					
						
							|  |  |  |                     SharedAssemblies.Add(_editorApiAssembly.GetName()); | 
					
						
							| 
									
										
										
										
											2022-02-27 21:57:52 +01:00
										 |  |  |                     NativeLibrary.SetDllImportResolver(_editorApiAssembly, _dllImportResolver); | 
					
						
							| 
									
										
										
										
											2021-09-12 20:23:05 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 *pluginsCallbacks = new() | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     LoadProjectAssemblyCallback = &LoadProjectAssembly, | 
					
						
							|  |  |  |                     LoadToolsAssemblyCallback = &LoadToolsAssembly, | 
					
						
							|  |  |  |                 }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |                 *managedCallbacks = ManagedCallbacks.Create(); | 
					
						
							| 
									
										
										
										
											2021-09-12 20:23:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 return godot_bool.True; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             catch (Exception e) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 Console.Error.WriteLine(e); | 
					
						
							|  |  |  |                 return false.ToGodotBool(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         [StructLayout(LayoutKind.Sequential)] | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |         private struct PluginsCallbacks | 
					
						
							| 
									
										
										
										
											2021-09-12 20:23:05 +02:00
										 |  |  |         { | 
					
						
							|  |  |  |             public unsafe delegate* unmanaged<char*, godot_bool> LoadProjectAssemblyCallback; | 
					
						
							|  |  |  |             public unsafe delegate* unmanaged<char*, IntPtr> LoadToolsAssemblyCallback; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         [UnmanagedCallersOnly] | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |         private static unsafe godot_bool LoadProjectAssembly(char* nAssemblyPath) | 
					
						
							| 
									
										
										
										
											2021-09-12 20:23:05 +02:00
										 |  |  |         { | 
					
						
							|  |  |  |             try | 
					
						
							|  |  |  |             { | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |                 if (_projectAssembly != null) | 
					
						
							|  |  |  |                     return godot_bool.True; // Already loaded | 
					
						
							| 
									
										
										
										
											2021-09-12 20:23:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |                 string assemblyPath = new(nAssemblyPath); | 
					
						
							| 
									
										
										
										
											2021-09-12 20:23:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |                 _projectAssembly = LoadPlugin(assemblyPath); | 
					
						
							| 
									
										
										
										
											2021-09-12 20:23:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |                 ScriptManagerBridge.LookupScriptsInAssembly(_projectAssembly); | 
					
						
							| 
									
										
										
										
											2021-09-12 20:23:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 return godot_bool.True; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             catch (Exception e) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 Console.Error.WriteLine(e); | 
					
						
							|  |  |  |                 return false.ToGodotBool(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         [UnmanagedCallersOnly] | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |         private static unsafe IntPtr LoadToolsAssembly(char* nAssemblyPath) | 
					
						
							| 
									
										
										
										
											2021-09-12 20:23:05 +02:00
										 |  |  |         { | 
					
						
							|  |  |  |             try | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 string assemblyPath = new(nAssemblyPath); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (_editorApiAssembly == null) | 
					
						
							|  |  |  |                     throw new InvalidOperationException("The Godot editor API assembly is not loaded"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 var assembly = LoadPlugin(assemblyPath); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-27 21:57:52 +01:00
										 |  |  |                 NativeLibrary.SetDllImportResolver(assembly, _dllImportResolver!); | 
					
						
							| 
									
										
										
										
											2021-09-12 20:23:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 var method = assembly.GetType("GodotTools.GodotSharpEditor")? | 
					
						
							|  |  |  |                     .GetMethod("InternalCreateInstance", | 
					
						
							|  |  |  |                         BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (method == null) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     throw new MissingMethodException("GodotTools.GodotSharpEditor", | 
					
						
							|  |  |  |                         "InternalCreateInstance"); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 return (IntPtr?)method.Invoke(null, null) ?? IntPtr.Zero; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             catch (Exception e) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 Console.Error.WriteLine(e); | 
					
						
							|  |  |  |                 return IntPtr.Zero; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         private static Assembly LoadPlugin(string assemblyPath) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             string assemblyName = Path.GetFileNameWithoutExtension(assemblyPath); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             var sharedAssemblies = new List<string>(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             foreach (var sharedAssembly in SharedAssemblies) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 string? sharedAssemblyName = sharedAssembly.Name; | 
					
						
							|  |  |  |                 if (sharedAssemblyName != null) | 
					
						
							|  |  |  |                     sharedAssemblies.Add(sharedAssemblyName); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             var loadContext = new PluginLoadContext(assemblyPath, sharedAssemblies, MainLoadContext); | 
					
						
							|  |  |  |             return loadContext.LoadFromAssemblyName(new AssemblyName(assemblyName)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |