From fbaf14b6fa963eb3513b450cce63faf44fb961e2 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Sun, 22 Oct 2023 21:58:20 -0500 Subject: [PATCH 1/2] Add to be able to specify order of plugin initialization and deinitialization. --- .../Scripting/Attributes/PluginLoadOrder.cs | 21 + .../Scripting/Plugins/PluginManager.cpp | 480 +++++++++++++++++- 2 files changed, 473 insertions(+), 28 deletions(-) create mode 100644 Source/Engine/Scripting/Attributes/PluginLoadOrder.cs diff --git a/Source/Engine/Scripting/Attributes/PluginLoadOrder.cs b/Source/Engine/Scripting/Attributes/PluginLoadOrder.cs new file mode 100644 index 000000000..d1d02d024 --- /dev/null +++ b/Source/Engine/Scripting/Attributes/PluginLoadOrder.cs @@ -0,0 +1,21 @@ +using System; + +namespace FlaxEngine; + +/// +/// This attribute allows for specifying initialization and deinitialization order for plugins +/// +[Serializable] +[AttributeUsage(AttributeTargets.Class)] +public class PluginLoadOrderAttribute : Attribute +{ + /// + /// The plugin type to initialize this plugin after. + /// + public Type InitializeAfter; + + /// + /// The plugin type to deinitialize this plugin before. + /// + public Type DeinitializeBefore; +} diff --git a/Source/Engine/Scripting/Plugins/PluginManager.cpp b/Source/Engine/Scripting/Plugins/PluginManager.cpp index a8198474c..124e842eb 100644 --- a/Source/Engine/Scripting/Plugins/PluginManager.cpp +++ b/Source/Engine/Scripting/Plugins/PluginManager.cpp @@ -13,6 +13,7 @@ #include "Engine/Profiler/ProfilerCPU.h" #include "Engine/Engine/EngineService.h" #include "Engine/Core/Log.h" +#include "Engine/Scripting/ManagedCLR/MField.h" Plugin::Plugin(const SpawnParams& params) : ScriptingObject(params) @@ -145,19 +146,20 @@ void PluginManagerImpl::LoadPlugin(MClass* klass, bool isEditor) auto plugin = (Plugin*)Scripting::NewObject(klass); if (!plugin) return; - +/* + auto engineAssembly = ((NativeBinaryModule*)GetBinaryModuleFlaxEngine())->Assembly; + auto pluginLoadOrderAttribute = engineAssembly->GetClass("FlaxEngine.PluginLoadOrderAttribute"); + auto afterTypeField = pluginLoadOrderAttribute->GetField("InitializeAfter"); + ASSERT(afterTypeField); +*/ if (!isEditor) { GamePlugins.Add((GamePlugin*)plugin); -#if !USE_EDITOR - PluginManagerService::InvokeInitialize(plugin); -#endif } #if USE_EDITOR else { EditorPlugins.Add(plugin); - PluginManagerService::InvokeInitialize(plugin); } #endif PluginManager::PluginsChanged(); @@ -209,23 +211,104 @@ void PluginManagerImpl::OnAssemblyLoaded(MAssembly* assembly) void PluginManagerImpl::OnAssemblyUnloading(MAssembly* assembly) { bool changed = false; - for (int32 i = EditorPlugins.Count() - 1; i >= 0 && EditorPlugins.Count() > 0; i--) + + auto engineAssembly = ((NativeBinaryModule*)GetBinaryModuleFlaxEngine())->Assembly; + auto pluginLoadOrderAttribute = engineAssembly->GetClass("FlaxEngine.PluginLoadOrderAttribute"); + auto afterTypeField = pluginLoadOrderAttribute->GetField("DeinitializeBefore"); + ASSERT(afterTypeField); + + // Sort editor plugins + Array editorPlugins; + for(int i = 0; i < EditorPlugins.Count(); i++) { - auto plugin = EditorPlugins[i]; + Plugin* plugin = EditorPlugins[i]; + // Sort game plugin as needed + int insertIndex = -1; + for(int j = 0; j < editorPlugins.Count(); j++) + { + // Get first instance where a game plugin needs another one before it + auto attribute = editorPlugins[j]->GetClass()->GetAttribute(pluginLoadOrderAttribute); + if (attribute == nullptr || MCore::Object::GetClass(attribute) != pluginLoadOrderAttribute) + continue; + + // Check if attribute references a valid class + MTypeObject* refType = nullptr; + afterTypeField->GetValue(attribute, &refType); + if (refType == nullptr) + continue; + + MType* type = INTERNAL_TYPE_OBJECT_GET(refType); + if (type == nullptr) + continue; + MClass* typeClass = MCore::Type::GetClass(type); + + if (plugin->GetClass() == typeClass) + { + insertIndex = j; + break; + } + } + if (insertIndex == -1) + editorPlugins.Add(plugin); + else + editorPlugins.Insert(insertIndex, plugin); + } + + for (int32 i = editorPlugins.Count() - 1; i >= 0 && editorPlugins.Count() > 0; i--) + { + auto plugin = editorPlugins[i]; if (plugin->GetType().ManagedClass->GetAssembly() == assembly) { PluginManagerService::InvokeDeinitialize(plugin); - EditorPlugins.RemoveAtKeepOrder(i); + EditorPlugins.Remove(plugin); changed = true; } } - for (int32 i = GamePlugins.Count() - 1; i >= 0 && GamePlugins.Count() > 0; i--) + + // Sort game plugins + Array gamePlugins; + for(int i = 0; i < GamePlugins.Count(); i++) { - auto plugin = GamePlugins[i]; + GamePlugin* plugin = GamePlugins[i]; + // Sort game plugin as needed + int insertIndex = -1; + for(int j = 0; j < gamePlugins.Count(); j++) + { + // Get first instance where a game plugin needs another one before it + auto attribute = gamePlugins[j]->GetClass()->GetAttribute(pluginLoadOrderAttribute); + if (attribute == nullptr || MCore::Object::GetClass(attribute) != pluginLoadOrderAttribute) + continue; + + // Check if attribute references a valid class + MTypeObject* refType = nullptr; + afterTypeField->GetValue(attribute, &refType); + if (refType == nullptr) + continue; + + MType* type = INTERNAL_TYPE_OBJECT_GET(refType); + if (type == nullptr) + continue; + MClass* typeClass = MCore::Type::GetClass(type); + + if (plugin->GetClass() == typeClass) + { + insertIndex = j; + break; + } + } + if (insertIndex == -1) + gamePlugins.Add(plugin); + else + gamePlugins.Insert(insertIndex, plugin); + } + + for (int32 i = gamePlugins.Count() - 1; i >= 0 && gamePlugins.Count() > 0; i--) + { + auto plugin = gamePlugins[i]; if (plugin->GetType().ManagedClass->GetAssembly() == assembly) { PluginManagerService::InvokeDeinitialize(plugin); - GamePlugins.RemoveAtKeepOrder(i); + GamePlugins.Remove(plugin); changed = true; } } @@ -261,21 +344,102 @@ void PluginManagerImpl::OnScriptsReloading() { // When scripting is reloading (eg. for hot-reload in Editor) we have to deinitialize plugins (Scripting service destroys C# objects later on) bool changed = false; - for (int32 i = EditorPlugins.Count() - 1; i >= 0 && EditorPlugins.Count() > 0; i--) + + auto engineAssembly = ((NativeBinaryModule*)GetBinaryModuleFlaxEngine())->Assembly; + auto pluginLoadOrderAttribute = engineAssembly->GetClass("FlaxEngine.PluginLoadOrderAttribute"); + auto afterTypeField = pluginLoadOrderAttribute->GetField("DeinitializeBefore"); + ASSERT(afterTypeField); + + // Sort editor plugins + Array editorPlugins; + for(int i = 0; i < EditorPlugins.Count(); i++) { - auto plugin = EditorPlugins[i]; + Plugin* plugin = EditorPlugins[i]; + // Sort game plugin as needed + int insertIndex = -1; + for(int j = 0; j < editorPlugins.Count(); j++) + { + // Get first instance where a game plugin needs another one before it + auto attribute = editorPlugins[j]->GetClass()->GetAttribute(pluginLoadOrderAttribute); + if (attribute == nullptr || MCore::Object::GetClass(attribute) != pluginLoadOrderAttribute) + continue; + + // Check if attribute references a valid class + MTypeObject* refType = nullptr; + afterTypeField->GetValue(attribute, &refType); + if (refType == nullptr) + continue; + + MType* type = INTERNAL_TYPE_OBJECT_GET(refType); + if (type == nullptr) + continue; + MClass* typeClass = MCore::Type::GetClass(type); + + if (plugin->GetClass() == typeClass) + { + insertIndex = j; + break; + } + } + if (insertIndex == -1) + editorPlugins.Add(plugin); + else + editorPlugins.Insert(insertIndex, plugin); + } + + for (int32 i = editorPlugins.Count() - 1; i >= 0 && editorPlugins.Count() > 0; i--) + { + auto plugin = editorPlugins[i]; { PluginManagerService::InvokeDeinitialize(plugin); - EditorPlugins.RemoveAtKeepOrder(i); + EditorPlugins.Remove(plugin); changed = true; } } - for (int32 i = GamePlugins.Count() - 1; i >= 0 && GamePlugins.Count() > 0; i--) + + // Sort game plugins + Array gamePlugins; + for(int i = 0; i < GamePlugins.Count(); i++) { - auto plugin = GamePlugins[i]; + GamePlugin* plugin = GamePlugins[i]; + // Sort game plugin as needed + int insertIndex = -1; + for(int j = 0; j < gamePlugins.Count(); j++) + { + // Get first instance where a game plugin needs another one before it + auto attribute = gamePlugins[j]->GetClass()->GetAttribute(pluginLoadOrderAttribute); + if (attribute == nullptr || MCore::Object::GetClass(attribute) != pluginLoadOrderAttribute) + continue; + + // Check if attribute references a valid class + MTypeObject* refType = nullptr; + afterTypeField->GetValue(attribute, &refType); + if (refType == nullptr) + continue; + + MType* type = INTERNAL_TYPE_OBJECT_GET(refType); + if (type == nullptr) + continue; + MClass* typeClass = MCore::Type::GetClass(type); + + if (plugin->GetClass() == typeClass) + { + insertIndex = j; + break; + } + } + if (insertIndex == -1) + gamePlugins.Add(plugin); + else + gamePlugins.Insert(insertIndex, plugin); + } + + for (int32 i = gamePlugins.Count() - 1; i >= 0 && gamePlugins.Count() > 0; i--) + { + auto plugin = gamePlugins[i]; { PluginManagerService::InvokeDeinitialize(plugin); - GamePlugins.RemoveAtKeepOrder(i); + GamePlugins.Remove(plugin); changed = true; } } @@ -291,6 +455,102 @@ bool PluginManagerService::Init() OnBinaryModuleLoaded(module); } + // Initialize plugins + auto engineAssembly = ((NativeBinaryModule*)GetBinaryModuleFlaxEngine())->Assembly; + auto pluginLoadOrderAttribute = engineAssembly->GetClass("FlaxEngine.PluginLoadOrderAttribute"); + auto afterTypeField = pluginLoadOrderAttribute->GetField("InitializeAfter"); + ASSERT(afterTypeField); + +#if !USE_EDITOR + // Sort game plugins + Array gamePlugins; + for(int i = 0; i < GamePlugins.Count(); i++) + { + GamePlugin* plugin = GamePlugins[i]; + // Sort game plugin as needed + int insertIndex = -1; + for(int j = 0; j < gamePlugins.Count(); j++) + { + // Get first instance where a game plugin needs another one before it + auto attribute = gamePlugins[j]->GetClass()->GetAttribute(pluginLoadOrderAttribute); + if (attribute == nullptr || MCore::Object::GetClass(attribute) != pluginLoadOrderAttribute) + continue; + + // Check if attribute references a valid class + MTypeObject* refType = nullptr; + afterTypeField->GetValue(attribute, &refType); + if (refType == nullptr) + continue; + + MType* type = INTERNAL_TYPE_OBJECT_GET(refType); + if (type == nullptr) + continue; + MClass* typeClass = MCore::Type::GetClass(type); + + if (plugin->GetClass() == typeClass) + { + insertIndex = j; + break; + } + } + if (insertIndex == -1) + gamePlugins.Add(plugin); + else + gamePlugins.Insert(insertIndex, plugin); + } + + // Initalize game plugins + for (auto plugin : gamePlugins) + { + PluginManagerService::InvokeInitialize(plugin); + } +#endif + +#if USE_EDITOR + // Sort editor plugins + Array editorPlugins; + for(int i = 0; i < EditorPlugins.Count(); i++) + { + Plugin* plugin = EditorPlugins[i]; + // Sort game plugin as needed + int insertIndex = -1; + for(int j = 0; j < editorPlugins.Count(); j++) + { + // Get first instance where a game plugin needs another one before it + auto attribute = editorPlugins[j]->GetClass()->GetAttribute(pluginLoadOrderAttribute); + if (attribute == nullptr || MCore::Object::GetClass(attribute) != pluginLoadOrderAttribute) + continue; + + // Check if attribute references a valid class + MTypeObject* refType = nullptr; + afterTypeField->GetValue(attribute, &refType); + if (refType == nullptr) + continue; + + MType* type = INTERNAL_TYPE_OBJECT_GET(refType); + if (type == nullptr) + continue; + MClass* typeClass = MCore::Type::GetClass(type); + + if (plugin->GetClass() == typeClass) + { + insertIndex = j; + break; + } + } + if (insertIndex == -1) + editorPlugins.Add(plugin); + else + editorPlugins.Insert(insertIndex, plugin); + } + + // Initialize editor plugins + for (auto plugin : editorPlugins) + { + PluginManagerService::InvokeInitialize(plugin); + } +#endif + // Register for new binary modules load actions Scripting::BinaryModuleLoaded.Bind(&OnBinaryModuleLoaded); Scripting::ScriptsReloading.Bind(&OnScriptsReloading); @@ -309,17 +569,97 @@ void PluginManagerService::Dispose() if (pluginsCount == 0) return; LOG(Info, "Unloading {0} plugins", pluginsCount); - for (int32 i = EditorPlugins.Count() - 1; i >= 0 && EditorPlugins.Count() > 0; i--) + + auto engineAssembly = ((NativeBinaryModule*)GetBinaryModuleFlaxEngine())->Assembly; + auto pluginLoadOrderAttribute = engineAssembly->GetClass("FlaxEngine.PluginLoadOrderAttribute"); + auto afterTypeField = pluginLoadOrderAttribute->GetField("DeinitializeBefore"); + ASSERT(afterTypeField); + + // Sort editor plugins + Array editorPlugins; + for(int i = 0; i < EditorPlugins.Count(); i++) { - auto plugin = EditorPlugins[i]; - InvokeDeinitialize(plugin); - EditorPlugins.RemoveAtKeepOrder(i); + Plugin* plugin = EditorPlugins[i]; + // Sort game plugin as needed + int insertIndex = -1; + for(int j = 0; j < editorPlugins.Count(); j++) + { + // Get first instance where a game plugin needs another one before it + auto attribute = editorPlugins[j]->GetClass()->GetAttribute(pluginLoadOrderAttribute); + if (attribute == nullptr || MCore::Object::GetClass(attribute) != pluginLoadOrderAttribute) + continue; + + // Check if attribute references a valid class + MTypeObject* refType = nullptr; + afterTypeField->GetValue(attribute, &refType); + if (refType == nullptr) + continue; + + MType* type = INTERNAL_TYPE_OBJECT_GET(refType); + if (type == nullptr) + continue; + MClass* typeClass = MCore::Type::GetClass(type); + + if (plugin->GetClass() == typeClass) + { + insertIndex = j; + break; + } + } + if (insertIndex == -1) + editorPlugins.Add(plugin); + else + editorPlugins.Insert(insertIndex, plugin); } - for (int32 i = GamePlugins.Count() - 1; i >= 0 && GamePlugins.Count() > 0; i--) + + for (int32 i = editorPlugins.Count() - 1; i >= 0 && editorPlugins.Count() > 0; i--) { - auto plugin = GamePlugins[i]; + auto plugin = editorPlugins[i]; InvokeDeinitialize(plugin); - GamePlugins.RemoveAtKeepOrder(i); + EditorPlugins.Remove(plugin); + } + + // Sort game plugins + Array gamePlugins; + for(int i = 0; i < GamePlugins.Count(); i++) + { + GamePlugin* plugin = GamePlugins[i]; + // Sort game plugin as needed + int insertIndex = -1; + for(int j = 0; j < gamePlugins.Count(); j++) + { + // Get first instance where a game plugin needs another one before it + auto attribute = gamePlugins[j]->GetClass()->GetAttribute(pluginLoadOrderAttribute); + if (attribute == nullptr || MCore::Object::GetClass(attribute) != pluginLoadOrderAttribute) + continue; + + // Check if attribute references a valid class + MTypeObject* refType = nullptr; + afterTypeField->GetValue(attribute, &refType); + if (refType == nullptr) + continue; + + MType* type = INTERNAL_TYPE_OBJECT_GET(refType); + if (type == nullptr) + continue; + MClass* typeClass = MCore::Type::GetClass(type); + + if (plugin->GetClass() == typeClass) + { + insertIndex = j; + break; + } + } + if (insertIndex == -1) + gamePlugins.Add(plugin); + else + gamePlugins.Insert(insertIndex, plugin); + } + for (int32 i = gamePlugins.Count() - 1; i >= 0 && gamePlugins.Count() > 0; i--) + { + auto plugin = gamePlugins[i]; + InvokeDeinitialize(plugin); + GamePlugins.Remove(plugin); } PluginManager::PluginsChanged(); } @@ -386,18 +726,102 @@ Plugin* PluginManager::GetPlugin(const ScriptingTypeHandle& type) void PluginManager::InitializeGamePlugins() { PROFILE_CPU(); - for (int32 i = 0; i < GamePlugins.Count(); i++) + + auto engineAssembly = ((NativeBinaryModule*)GetBinaryModuleFlaxEngine())->Assembly; + auto pluginLoadOrderAttribute = engineAssembly->GetClass("FlaxEngine.PluginLoadOrderAttribute"); + auto afterTypeField = pluginLoadOrderAttribute->GetField("InitializeAfter"); + ASSERT(afterTypeField); + + // Sort game plugins + Array gamePlugins; + for(int i = 0; i < GamePlugins.Count(); i++) { - PluginManagerService::InvokeInitialize(GamePlugins[i]); + GamePlugin* plugin = GamePlugins[i]; + // Sort game plugin as needed + int insertIndex = -1; + for(int j = 0; j < gamePlugins.Count(); j++) + { + // Get first instance where a game plugin needs another one before it + auto attribute = gamePlugins[j]->GetClass()->GetAttribute(pluginLoadOrderAttribute); + if (attribute == nullptr || MCore::Object::GetClass(attribute) != pluginLoadOrderAttribute) + continue; + + // Check if attribute references a valid class + MTypeObject* refType = nullptr; + afterTypeField->GetValue(attribute, &refType); + if (refType == nullptr) + continue; + + MType* type = INTERNAL_TYPE_OBJECT_GET(refType); + if (type == nullptr) + continue; + MClass* typeClass = MCore::Type::GetClass(type); + + if (plugin->GetClass() == typeClass) + { + insertIndex = j; + break; + } + } + if (insertIndex == -1) + gamePlugins.Add(plugin); + else + gamePlugins.Insert(insertIndex, plugin); + } + for (int32 i = 0; i < gamePlugins.Count(); i++) + { + PluginManagerService::InvokeInitialize(gamePlugins[i]); } } void PluginManager::DeinitializeGamePlugins() { PROFILE_CPU(); - for (int32 i = GamePlugins.Count() - 1; i >= 0; i--) + + auto engineAssembly = ((NativeBinaryModule*)GetBinaryModuleFlaxEngine())->Assembly; + auto pluginLoadOrderAttribute = engineAssembly->GetClass("FlaxEngine.PluginLoadOrderAttribute"); + auto afterTypeField = pluginLoadOrderAttribute->GetField("DeinitializeBefore"); + ASSERT(afterTypeField); + + // Sort game plugins + Array gamePlugins; + for(int i = 0; i < GamePlugins.Count(); i++) { - PluginManagerService::InvokeDeinitialize(GamePlugins[i]); + GamePlugin* plugin = GamePlugins[i]; + // Sort game plugin as needed + int insertIndex = -1; + for(int j = 0; j < gamePlugins.Count(); j++) + { + // Get first instance where a game plugin needs another one before it + auto attribute = gamePlugins[j]->GetClass()->GetAttribute(pluginLoadOrderAttribute); + if (attribute == nullptr || MCore::Object::GetClass(attribute) != pluginLoadOrderAttribute) + continue; + + // Check if attribute references a valid class + MTypeObject* refType = nullptr; + afterTypeField->GetValue(attribute, &refType); + if (refType == nullptr) + continue; + + MType* type = INTERNAL_TYPE_OBJECT_GET(refType); + if (type == nullptr) + continue; + MClass* typeClass = MCore::Type::GetClass(type); + + if (plugin->GetClass() == typeClass) + { + insertIndex = j; + break; + } + } + if (insertIndex == -1) + gamePlugins.Add(plugin); + else + gamePlugins.Insert(insertIndex, plugin); + } + for (int32 i = gamePlugins.Count() - 1; i >= 0; i--) + { + PluginManagerService::InvokeDeinitialize(gamePlugins[i]); } } From 2e85ff0fb3c479af85120dd0e452ace02a5bd898 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Sun, 22 Oct 2023 22:19:51 -0500 Subject: [PATCH 2/2] Simplify code --- .../Scripting/Plugins/PluginManager.cpp | 479 ++++-------------- 1 file changed, 104 insertions(+), 375 deletions(-) diff --git a/Source/Engine/Scripting/Plugins/PluginManager.cpp b/Source/Engine/Scripting/Plugins/PluginManager.cpp index 124e842eb..77a3467fd 100644 --- a/Source/Engine/Scripting/Plugins/PluginManager.cpp +++ b/Source/Engine/Scripting/Plugins/PluginManager.cpp @@ -83,6 +83,8 @@ namespace PluginManagerImpl void OnAssemblyUnloading(MAssembly* assembly); void OnBinaryModuleLoaded(BinaryModule* module); void OnScriptsReloading(); + Array SortGamePlugins(Array& plugins, MClass* pluginLoadOrderAttribute, MField* typeField); + Array SortPlugins(Array plugins, MClass* pluginLoadOrderAttribute, MField* typeField); } using namespace PluginManagerImpl; @@ -146,12 +148,7 @@ void PluginManagerImpl::LoadPlugin(MClass* klass, bool isEditor) auto plugin = (Plugin*)Scripting::NewObject(klass); if (!plugin) return; -/* - auto engineAssembly = ((NativeBinaryModule*)GetBinaryModuleFlaxEngine())->Assembly; - auto pluginLoadOrderAttribute = engineAssembly->GetClass("FlaxEngine.PluginLoadOrderAttribute"); - auto afterTypeField = pluginLoadOrderAttribute->GetField("InitializeAfter"); - ASSERT(afterTypeField); -*/ + if (!isEditor) { GamePlugins.Add((GamePlugin*)plugin); @@ -214,45 +211,10 @@ void PluginManagerImpl::OnAssemblyUnloading(MAssembly* assembly) auto engineAssembly = ((NativeBinaryModule*)GetBinaryModuleFlaxEngine())->Assembly; auto pluginLoadOrderAttribute = engineAssembly->GetClass("FlaxEngine.PluginLoadOrderAttribute"); - auto afterTypeField = pluginLoadOrderAttribute->GetField("DeinitializeBefore"); - ASSERT(afterTypeField); + auto beforeTypeField = pluginLoadOrderAttribute->GetField("DeinitializeBefore"); + ASSERT(beforeTypeField); - // Sort editor plugins - Array editorPlugins; - for(int i = 0; i < EditorPlugins.Count(); i++) - { - Plugin* plugin = EditorPlugins[i]; - // Sort game plugin as needed - int insertIndex = -1; - for(int j = 0; j < editorPlugins.Count(); j++) - { - // Get first instance where a game plugin needs another one before it - auto attribute = editorPlugins[j]->GetClass()->GetAttribute(pluginLoadOrderAttribute); - if (attribute == nullptr || MCore::Object::GetClass(attribute) != pluginLoadOrderAttribute) - continue; - - // Check if attribute references a valid class - MTypeObject* refType = nullptr; - afterTypeField->GetValue(attribute, &refType); - if (refType == nullptr) - continue; - - MType* type = INTERNAL_TYPE_OBJECT_GET(refType); - if (type == nullptr) - continue; - MClass* typeClass = MCore::Type::GetClass(type); - - if (plugin->GetClass() == typeClass) - { - insertIndex = j; - break; - } - } - if (insertIndex == -1) - editorPlugins.Add(plugin); - else - editorPlugins.Insert(insertIndex, plugin); - } + auto editorPlugins = SortPlugins(EditorPlugins, pluginLoadOrderAttribute, beforeTypeField); for (int32 i = editorPlugins.Count() - 1; i >= 0 && editorPlugins.Count() > 0; i--) { @@ -265,42 +227,7 @@ void PluginManagerImpl::OnAssemblyUnloading(MAssembly* assembly) } } - // Sort game plugins - Array gamePlugins; - for(int i = 0; i < GamePlugins.Count(); i++) - { - GamePlugin* plugin = GamePlugins[i]; - // Sort game plugin as needed - int insertIndex = -1; - for(int j = 0; j < gamePlugins.Count(); j++) - { - // Get first instance where a game plugin needs another one before it - auto attribute = gamePlugins[j]->GetClass()->GetAttribute(pluginLoadOrderAttribute); - if (attribute == nullptr || MCore::Object::GetClass(attribute) != pluginLoadOrderAttribute) - continue; - - // Check if attribute references a valid class - MTypeObject* refType = nullptr; - afterTypeField->GetValue(attribute, &refType); - if (refType == nullptr) - continue; - - MType* type = INTERNAL_TYPE_OBJECT_GET(refType); - if (type == nullptr) - continue; - MClass* typeClass = MCore::Type::GetClass(type); - - if (plugin->GetClass() == typeClass) - { - insertIndex = j; - break; - } - } - if (insertIndex == -1) - gamePlugins.Add(plugin); - else - gamePlugins.Insert(insertIndex, plugin); - } + auto gamePlugins = SortGamePlugins(GamePlugins, pluginLoadOrderAttribute, beforeTypeField); for (int32 i = gamePlugins.Count() - 1; i >= 0 && gamePlugins.Count() > 0; i--) { @@ -347,45 +274,10 @@ void PluginManagerImpl::OnScriptsReloading() auto engineAssembly = ((NativeBinaryModule*)GetBinaryModuleFlaxEngine())->Assembly; auto pluginLoadOrderAttribute = engineAssembly->GetClass("FlaxEngine.PluginLoadOrderAttribute"); - auto afterTypeField = pluginLoadOrderAttribute->GetField("DeinitializeBefore"); - ASSERT(afterTypeField); + auto beforeTypeField = pluginLoadOrderAttribute->GetField("DeinitializeBefore"); + ASSERT(beforeTypeField); - // Sort editor plugins - Array editorPlugins; - for(int i = 0; i < EditorPlugins.Count(); i++) - { - Plugin* plugin = EditorPlugins[i]; - // Sort game plugin as needed - int insertIndex = -1; - for(int j = 0; j < editorPlugins.Count(); j++) - { - // Get first instance where a game plugin needs another one before it - auto attribute = editorPlugins[j]->GetClass()->GetAttribute(pluginLoadOrderAttribute); - if (attribute == nullptr || MCore::Object::GetClass(attribute) != pluginLoadOrderAttribute) - continue; - - // Check if attribute references a valid class - MTypeObject* refType = nullptr; - afterTypeField->GetValue(attribute, &refType); - if (refType == nullptr) - continue; - - MType* type = INTERNAL_TYPE_OBJECT_GET(refType); - if (type == nullptr) - continue; - MClass* typeClass = MCore::Type::GetClass(type); - - if (plugin->GetClass() == typeClass) - { - insertIndex = j; - break; - } - } - if (insertIndex == -1) - editorPlugins.Add(plugin); - else - editorPlugins.Insert(insertIndex, plugin); - } + auto editorPlugins = SortPlugins(EditorPlugins, pluginLoadOrderAttribute, beforeTypeField); for (int32 i = editorPlugins.Count() - 1; i >= 0 && editorPlugins.Count() > 0; i--) { @@ -397,42 +289,7 @@ void PluginManagerImpl::OnScriptsReloading() } } - // Sort game plugins - Array gamePlugins; - for(int i = 0; i < GamePlugins.Count(); i++) - { - GamePlugin* plugin = GamePlugins[i]; - // Sort game plugin as needed - int insertIndex = -1; - for(int j = 0; j < gamePlugins.Count(); j++) - { - // Get first instance where a game plugin needs another one before it - auto attribute = gamePlugins[j]->GetClass()->GetAttribute(pluginLoadOrderAttribute); - if (attribute == nullptr || MCore::Object::GetClass(attribute) != pluginLoadOrderAttribute) - continue; - - // Check if attribute references a valid class - MTypeObject* refType = nullptr; - afterTypeField->GetValue(attribute, &refType); - if (refType == nullptr) - continue; - - MType* type = INTERNAL_TYPE_OBJECT_GET(refType); - if (type == nullptr) - continue; - MClass* typeClass = MCore::Type::GetClass(type); - - if (plugin->GetClass() == typeClass) - { - insertIndex = j; - break; - } - } - if (insertIndex == -1) - gamePlugins.Add(plugin); - else - gamePlugins.Insert(insertIndex, plugin); - } + auto gamePlugins = SortGamePlugins(GamePlugins, pluginLoadOrderAttribute, beforeTypeField); for (int32 i = gamePlugins.Count() - 1; i >= 0 && gamePlugins.Count() > 0; i--) { @@ -447,6 +304,88 @@ void PluginManagerImpl::OnScriptsReloading() PluginManager::PluginsChanged(); } +Array PluginManagerImpl::SortGamePlugins(Array& plugins, MClass* pluginLoadOrderAttribute, MField* typeField) +{ + // Sort game plugins + Array newPlugins; + for(int i = 0; i < plugins.Count(); i++) + { + GamePlugin* plugin = plugins[i]; + // Sort game plugin as needed + int insertIndex = -1; + for(int j = 0; j < newPlugins.Count(); j++) + { + // Get first instance where a game plugin needs another one before it + auto attribute = newPlugins[j]->GetClass()->GetAttribute(pluginLoadOrderAttribute); + if (attribute == nullptr || MCore::Object::GetClass(attribute) != pluginLoadOrderAttribute) + continue; + + // Check if attribute references a valid class + MTypeObject* refType = nullptr; + typeField->GetValue(attribute, &refType); + if (refType == nullptr) + continue; + + MType* type = INTERNAL_TYPE_OBJECT_GET(refType); + if (type == nullptr) + continue; + MClass* typeClass = MCore::Type::GetClass(type); + + if (plugin->GetClass() == typeClass) + { + insertIndex = j; + break; + } + } + if (insertIndex == -1) + newPlugins.Add(plugin); + else + newPlugins.Insert(insertIndex, plugin); + } + return newPlugins; +} + +Array PluginManagerImpl::SortPlugins(Array plugins, MClass* pluginLoadOrderAttribute, MField* typeField) +{ + // Sort plugins + Array newPlugins; + for(int i = 0; i < plugins.Count(); i++) + { + Plugin* plugin = plugins[i]; + // Sort plugin as needed + int insertIndex = -1; + for(int j = 0; j < newPlugins.Count(); j++) + { + // Get first instance where a game plugin needs another one before it + auto attribute = newPlugins[j]->GetClass()->GetAttribute(pluginLoadOrderAttribute); + if (attribute == nullptr || MCore::Object::GetClass(attribute) != pluginLoadOrderAttribute) + continue; + + // Check if attribute references a valid class + MTypeObject* refType = nullptr; + typeField->GetValue(attribute, &refType); + if (refType == nullptr) + continue; + + MType* type = INTERNAL_TYPE_OBJECT_GET(refType); + if (type == nullptr) + continue; + MClass* typeClass = MCore::Type::GetClass(type); + + if (plugin->GetClass() == typeClass) + { + insertIndex = j; + break; + } + } + if (insertIndex == -1) + newPlugins.Add(plugin); + else + newPlugins.Insert(insertIndex, plugin); + } + return newPlugins; +} + bool PluginManagerService::Init() { // Process already loaded modules @@ -460,44 +399,9 @@ bool PluginManagerService::Init() auto pluginLoadOrderAttribute = engineAssembly->GetClass("FlaxEngine.PluginLoadOrderAttribute"); auto afterTypeField = pluginLoadOrderAttribute->GetField("InitializeAfter"); ASSERT(afterTypeField); - + #if !USE_EDITOR - // Sort game plugins - Array gamePlugins; - for(int i = 0; i < GamePlugins.Count(); i++) - { - GamePlugin* plugin = GamePlugins[i]; - // Sort game plugin as needed - int insertIndex = -1; - for(int j = 0; j < gamePlugins.Count(); j++) - { - // Get first instance where a game plugin needs another one before it - auto attribute = gamePlugins[j]->GetClass()->GetAttribute(pluginLoadOrderAttribute); - if (attribute == nullptr || MCore::Object::GetClass(attribute) != pluginLoadOrderAttribute) - continue; - - // Check if attribute references a valid class - MTypeObject* refType = nullptr; - afterTypeField->GetValue(attribute, &refType); - if (refType == nullptr) - continue; - - MType* type = INTERNAL_TYPE_OBJECT_GET(refType); - if (type == nullptr) - continue; - MClass* typeClass = MCore::Type::GetClass(type); - - if (plugin->GetClass() == typeClass) - { - insertIndex = j; - break; - } - } - if (insertIndex == -1) - gamePlugins.Add(plugin); - else - gamePlugins.Insert(insertIndex, plugin); - } + auto gamePlugins = SortGamePlugins(GamePlugins, pluginLoadOrderAttribute, afterTypeField); // Initalize game plugins for (auto plugin : gamePlugins) @@ -507,42 +411,7 @@ bool PluginManagerService::Init() #endif #if USE_EDITOR - // Sort editor plugins - Array editorPlugins; - for(int i = 0; i < EditorPlugins.Count(); i++) - { - Plugin* plugin = EditorPlugins[i]; - // Sort game plugin as needed - int insertIndex = -1; - for(int j = 0; j < editorPlugins.Count(); j++) - { - // Get first instance where a game plugin needs another one before it - auto attribute = editorPlugins[j]->GetClass()->GetAttribute(pluginLoadOrderAttribute); - if (attribute == nullptr || MCore::Object::GetClass(attribute) != pluginLoadOrderAttribute) - continue; - - // Check if attribute references a valid class - MTypeObject* refType = nullptr; - afterTypeField->GetValue(attribute, &refType); - if (refType == nullptr) - continue; - - MType* type = INTERNAL_TYPE_OBJECT_GET(refType); - if (type == nullptr) - continue; - MClass* typeClass = MCore::Type::GetClass(type); - - if (plugin->GetClass() == typeClass) - { - insertIndex = j; - break; - } - } - if (insertIndex == -1) - editorPlugins.Add(plugin); - else - editorPlugins.Insert(insertIndex, plugin); - } + auto editorPlugins = SortPlugins(EditorPlugins, pluginLoadOrderAttribute, afterTypeField); // Initialize editor plugins for (auto plugin : editorPlugins) @@ -572,45 +441,10 @@ void PluginManagerService::Dispose() auto engineAssembly = ((NativeBinaryModule*)GetBinaryModuleFlaxEngine())->Assembly; auto pluginLoadOrderAttribute = engineAssembly->GetClass("FlaxEngine.PluginLoadOrderAttribute"); - auto afterTypeField = pluginLoadOrderAttribute->GetField("DeinitializeBefore"); - ASSERT(afterTypeField); + auto beforeTypeField = pluginLoadOrderAttribute->GetField("DeinitializeBefore"); + ASSERT(beforeTypeField); - // Sort editor plugins - Array editorPlugins; - for(int i = 0; i < EditorPlugins.Count(); i++) - { - Plugin* plugin = EditorPlugins[i]; - // Sort game plugin as needed - int insertIndex = -1; - for(int j = 0; j < editorPlugins.Count(); j++) - { - // Get first instance where a game plugin needs another one before it - auto attribute = editorPlugins[j]->GetClass()->GetAttribute(pluginLoadOrderAttribute); - if (attribute == nullptr || MCore::Object::GetClass(attribute) != pluginLoadOrderAttribute) - continue; - - // Check if attribute references a valid class - MTypeObject* refType = nullptr; - afterTypeField->GetValue(attribute, &refType); - if (refType == nullptr) - continue; - - MType* type = INTERNAL_TYPE_OBJECT_GET(refType); - if (type == nullptr) - continue; - MClass* typeClass = MCore::Type::GetClass(type); - - if (plugin->GetClass() == typeClass) - { - insertIndex = j; - break; - } - } - if (insertIndex == -1) - editorPlugins.Add(plugin); - else - editorPlugins.Insert(insertIndex, plugin); - } + auto editorPlugins = SortPlugins(EditorPlugins, pluginLoadOrderAttribute, beforeTypeField); for (int32 i = editorPlugins.Count() - 1; i >= 0 && editorPlugins.Count() > 0; i--) { @@ -619,42 +453,7 @@ void PluginManagerService::Dispose() EditorPlugins.Remove(plugin); } - // Sort game plugins - Array gamePlugins; - for(int i = 0; i < GamePlugins.Count(); i++) - { - GamePlugin* plugin = GamePlugins[i]; - // Sort game plugin as needed - int insertIndex = -1; - for(int j = 0; j < gamePlugins.Count(); j++) - { - // Get first instance where a game plugin needs another one before it - auto attribute = gamePlugins[j]->GetClass()->GetAttribute(pluginLoadOrderAttribute); - if (attribute == nullptr || MCore::Object::GetClass(attribute) != pluginLoadOrderAttribute) - continue; - - // Check if attribute references a valid class - MTypeObject* refType = nullptr; - afterTypeField->GetValue(attribute, &refType); - if (refType == nullptr) - continue; - - MType* type = INTERNAL_TYPE_OBJECT_GET(refType); - if (type == nullptr) - continue; - MClass* typeClass = MCore::Type::GetClass(type); - - if (plugin->GetClass() == typeClass) - { - insertIndex = j; - break; - } - } - if (insertIndex == -1) - gamePlugins.Add(plugin); - else - gamePlugins.Insert(insertIndex, plugin); - } + auto gamePlugins = SortGamePlugins(GamePlugins, pluginLoadOrderAttribute, beforeTypeField); for (int32 i = gamePlugins.Count() - 1; i >= 0 && gamePlugins.Count() > 0; i--) { auto plugin = gamePlugins[i]; @@ -731,43 +530,8 @@ void PluginManager::InitializeGamePlugins() auto pluginLoadOrderAttribute = engineAssembly->GetClass("FlaxEngine.PluginLoadOrderAttribute"); auto afterTypeField = pluginLoadOrderAttribute->GetField("InitializeAfter"); ASSERT(afterTypeField); - - // Sort game plugins - Array gamePlugins; - for(int i = 0; i < GamePlugins.Count(); i++) - { - GamePlugin* plugin = GamePlugins[i]; - // Sort game plugin as needed - int insertIndex = -1; - for(int j = 0; j < gamePlugins.Count(); j++) - { - // Get first instance where a game plugin needs another one before it - auto attribute = gamePlugins[j]->GetClass()->GetAttribute(pluginLoadOrderAttribute); - if (attribute == nullptr || MCore::Object::GetClass(attribute) != pluginLoadOrderAttribute) - continue; - - // Check if attribute references a valid class - MTypeObject* refType = nullptr; - afterTypeField->GetValue(attribute, &refType); - if (refType == nullptr) - continue; - MType* type = INTERNAL_TYPE_OBJECT_GET(refType); - if (type == nullptr) - continue; - MClass* typeClass = MCore::Type::GetClass(type); - - if (plugin->GetClass() == typeClass) - { - insertIndex = j; - break; - } - } - if (insertIndex == -1) - gamePlugins.Add(plugin); - else - gamePlugins.Insert(insertIndex, plugin); - } + auto gamePlugins = SortGamePlugins(GamePlugins, pluginLoadOrderAttribute, afterTypeField); for (int32 i = 0; i < gamePlugins.Count(); i++) { PluginManagerService::InvokeInitialize(gamePlugins[i]); @@ -780,45 +544,10 @@ void PluginManager::DeinitializeGamePlugins() auto engineAssembly = ((NativeBinaryModule*)GetBinaryModuleFlaxEngine())->Assembly; auto pluginLoadOrderAttribute = engineAssembly->GetClass("FlaxEngine.PluginLoadOrderAttribute"); - auto afterTypeField = pluginLoadOrderAttribute->GetField("DeinitializeBefore"); - ASSERT(afterTypeField); - - // Sort game plugins - Array gamePlugins; - for(int i = 0; i < GamePlugins.Count(); i++) - { - GamePlugin* plugin = GamePlugins[i]; - // Sort game plugin as needed - int insertIndex = -1; - for(int j = 0; j < gamePlugins.Count(); j++) - { - // Get first instance where a game plugin needs another one before it - auto attribute = gamePlugins[j]->GetClass()->GetAttribute(pluginLoadOrderAttribute); - if (attribute == nullptr || MCore::Object::GetClass(attribute) != pluginLoadOrderAttribute) - continue; - - // Check if attribute references a valid class - MTypeObject* refType = nullptr; - afterTypeField->GetValue(attribute, &refType); - if (refType == nullptr) - continue; + auto beforeTypeField = pluginLoadOrderAttribute->GetField("DeinitializeBefore"); + ASSERT(beforeTypeField); - MType* type = INTERNAL_TYPE_OBJECT_GET(refType); - if (type == nullptr) - continue; - MClass* typeClass = MCore::Type::GetClass(type); - - if (plugin->GetClass() == typeClass) - { - insertIndex = j; - break; - } - } - if (insertIndex == -1) - gamePlugins.Add(plugin); - else - gamePlugins.Insert(insertIndex, plugin); - } + auto gamePlugins = SortGamePlugins(GamePlugins, pluginLoadOrderAttribute, beforeTypeField); for (int32 i = gamePlugins.Count() - 1; i >= 0; i--) { PluginManagerService::InvokeDeinitialize(gamePlugins[i]);