From ea7483f9a77837ece5bfae02819f1d0eda8409d1 Mon Sep 17 00:00:00 2001 From: WerWolv Date: Fri, 12 Jan 2024 23:03:13 +0100 Subject: [PATCH] impr: Get rid of the concept of built-in plugins #1489 --- .../include/hex/api/plugin_manager.hpp | 9 ++- lib/libimhex/include/hex/plugin.hpp | 7 ++- lib/libimhex/source/api/plugin_manager.cpp | 32 ++++------ main/gui/source/init/tasks.cpp | 60 ++++++------------- main/gui/source/window/window.cpp | 34 +++-------- .../source/content/command_line_interface.cpp | 7 +-- .../source/content/views/view_about.cpp | 2 +- plugins/builtin/source/plugin_builtin.cpp | 4 -- 8 files changed, 47 insertions(+), 108 deletions(-) diff --git a/lib/libimhex/include/hex/api/plugin_manager.hpp b/lib/libimhex/include/hex/api/plugin_manager.hpp index d9b6d5e3c..d9776b97b 100644 --- a/lib/libimhex/include/hex/api/plugin_manager.hpp +++ b/lib/libimhex/include/hex/api/plugin_manager.hpp @@ -26,22 +26,22 @@ namespace hex { using InitializePluginFunc = void (*)(); using InitializeLibraryFunc = void (*)(); using GetPluginNameFunc = const char *(*)(); + using GetLibraryNameFunc = const char *(*)(); using GetPluginAuthorFunc = const char *(*)(); using GetPluginDescriptionFunc = const char *(*)(); using GetCompatibleVersionFunc = const char *(*)(); using SetImGuiContextFunc = void (*)(ImGuiContext *); - using IsBuiltinPluginFunc = bool (*)(); using GetSubCommandsFunc = void* (*)(); using GetFeaturesFunc = void* (*)(); InitializePluginFunc initializePluginFunction = nullptr; InitializeLibraryFunc initializeLibraryFunction = nullptr; GetPluginNameFunc getPluginNameFunction = nullptr; + GetLibraryNameFunc getLibraryNameFunction = nullptr; GetPluginAuthorFunc getPluginAuthorFunction = nullptr; GetPluginDescriptionFunc getPluginDescriptionFunction = nullptr; GetCompatibleVersionFunc getCompatibleVersionFunction = nullptr; SetImGuiContextFunc setImGuiContextFunction = nullptr; - IsBuiltinPluginFunc isBuiltinPluginFunction = nullptr; GetSubCommandsFunc getSubCommandsFunction = nullptr; GetFeaturesFunc getFeaturesFunction = nullptr; }; @@ -49,7 +49,7 @@ namespace hex { class Plugin { public: explicit Plugin(const std::fs::path &path); - explicit Plugin(const PluginFunctions &functions); + explicit Plugin(const std::string &name, const PluginFunctions &functions); Plugin(const Plugin &) = delete; Plugin(Plugin &&other) noexcept; @@ -64,7 +64,6 @@ namespace hex { [[nodiscard]] std::string getPluginDescription() const; [[nodiscard]] std::string getCompatibleVersion() const; void setImGuiContext(ImGuiContext *ctx) const; - [[nodiscard]] bool isBuiltinPlugin() const; [[nodiscard]] const std::fs::path &getPath() const; @@ -100,7 +99,7 @@ namespace hex { static void unload(); static void reload(); - static void addPlugin(PluginFunctions functions); + static void addPlugin(const std::string &name, PluginFunctions functions); static std::vector &getPlugins(); static std::vector &getPluginPaths(); diff --git a/lib/libimhex/include/hex/plugin.hpp b/lib/libimhex/include/hex/plugin.hpp index cfefe704d..879eb404d 100644 --- a/lib/libimhex/include/hex/plugin.hpp +++ b/lib/libimhex/include/hex/plugin.hpp @@ -29,15 +29,17 @@ #define IMHEX_LIBRARY_SETUP_IMPL(name) \ namespace { static struct EXIT_HANDLER { ~EXIT_HANDLER() { hex::log::info("Unloaded library '{}'", name); } } HANDLER; } \ IMHEX_PLUGIN_VISIBILITY_PREFIX void initializeLibrary(); \ + IMHEX_PLUGIN_VISIBILITY_PREFIX const char *getLibraryName() { return name; } \ IMHEX_PLUGIN_VISIBILITY_PREFIX void setImGuiContext(ImGuiContext *ctx) { \ ImGui::SetCurrentContext(ctx); \ GImGui = ctx; \ } \ extern "C" [[gnu::visibility("default")]] void WOLV_TOKEN_CONCAT(forceLinkPlugin_, IMHEX_PLUGIN_NAME)() { \ - hex::PluginManager::addPlugin(hex::PluginFunctions { \ + hex::PluginManager::addPlugin(name, hex::PluginFunctions { \ nullptr, \ initializeLibrary, \ nullptr, \ + getLibraryName, \ nullptr, \ nullptr, \ nullptr, \ @@ -60,10 +62,11 @@ } \ IMHEX_PLUGIN_VISIBILITY_PREFIX void initializePlugin(); \ extern "C" [[gnu::visibility("default")]] void WOLV_TOKEN_CONCAT(forceLinkPlugin_, IMHEX_PLUGIN_NAME)() { \ - hex::PluginManager::addPlugin(hex::PluginFunctions { \ + hex::PluginManager::addPlugin(name, hex::PluginFunctions { \ initializePlugin, \ nullptr, \ getPluginName, \ + nullptr, \ getPluginAuthor, \ getPluginDescription, \ getCompatibleVersion, \ diff --git a/lib/libimhex/source/api/plugin_manager.cpp b/lib/libimhex/source/api/plugin_manager.cpp index b681afe7a..f73e60be3 100644 --- a/lib/libimhex/source/api/plugin_manager.cpp +++ b/lib/libimhex/source/api/plugin_manager.cpp @@ -39,18 +39,19 @@ namespace hex { m_functions.initializePluginFunction = getPluginFunction("initializePlugin"); m_functions.initializeLibraryFunction = getPluginFunction("initializeLibrary"); m_functions.getPluginNameFunction = getPluginFunction("getPluginName"); + m_functions.getLibraryNameFunction = getPluginFunction("getLibraryName"); m_functions.getPluginAuthorFunction = getPluginFunction("getPluginAuthor"); m_functions.getPluginDescriptionFunction = getPluginFunction("getPluginDescription"); m_functions.getCompatibleVersionFunction = getPluginFunction("getCompatibleVersion"); m_functions.setImGuiContextFunction = getPluginFunction("setImGuiContext"); - m_functions.isBuiltinPluginFunction = getPluginFunction("isBuiltinPlugin"); m_functions.getSubCommandsFunction = getPluginFunction("getSubCommands"); m_functions.getFeaturesFunction = getPluginFunction("getFeatures"); } - Plugin::Plugin(const hex::PluginFunctions &functions) { + Plugin::Plugin(const std::string &name, const hex::PluginFunctions &functions) { m_handle = 0; m_functions = functions; + m_path = name; } @@ -137,7 +138,7 @@ namespace hex { return m_functions.getPluginNameFunction(); } else { if (this->isLibraryPlugin()) - return "Library Plugin"; + return m_functions.getLibraryNameFunction(); else return hex::format("Unknown Plugin @ 0x{0:016X}", m_handle); } @@ -170,13 +171,6 @@ namespace hex { m_functions.setImGuiContextFunction(ctx); } - [[nodiscard]] bool Plugin::isBuiltinPlugin() const { - if (m_functions.isBuiltinPluginFunction != nullptr) - return m_functions.isBuiltinPluginFunction(); - else - return false; - } - const std::fs::path &Plugin::getPath() const { return m_path; } @@ -191,7 +185,8 @@ namespace hex { std::span Plugin::getSubCommands() const { if (m_functions.getSubCommandsFunction != nullptr) { - auto result = m_functions.getSubCommandsFunction(); + const auto result = m_functions.getSubCommandsFunction(); + return *static_cast*>(result); } else { return { }; @@ -200,7 +195,8 @@ namespace hex { std::span Plugin::getFeatures() const { if (m_functions.getFeaturesFunction != nullptr) { - auto result = m_functions.getFeaturesFunction(); + const auto result = m_functions.getFeaturesFunction(); + return *static_cast*>(result); } else { return { }; @@ -274,16 +270,8 @@ namespace hex { } } - void PluginManager::reload() { - auto paths = getPluginPaths(); - - PluginManager::unload(); - for (const auto &path : paths) - PluginManager::load(path); - } - - void PluginManager::addPlugin(hex::PluginFunctions functions) { - getPlugins().emplace_back(functions); + void PluginManager::addPlugin(const std::string &name, hex::PluginFunctions functions) { + getPlugins().emplace_back(name, functions); } std::vector &PluginManager::getPlugins() { diff --git a/main/gui/source/init/tasks.cpp b/main/gui/source/init/tasks.cpp index c3bdf6f65..dc46231af 100644 --- a/main/gui/source/init/tasks.cpp +++ b/main/gui/source/init/tasks.cpp @@ -157,9 +157,11 @@ namespace hex::init { bool loadPlugins() { // Load all plugins - for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Plugins)) { - PluginManager::load(dir); - } + #if !defined(IMHEX_STATIC_LINK_PLUGINS) + for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Plugins)) { + PluginManager::load(dir); + } + #endif // Get loaded plugins auto &plugins = PluginManager::getPlugins(); @@ -185,44 +187,28 @@ namespace hex::init { return !std::fs::relative(plugin.getPath(), executablePath->parent_path()).string().starts_with(".."); }; + u32 loadErrors = 0; + std::set pluginNames; + // Load library plugins first since plugins might depend on them for (const auto &plugin : plugins) { if (!plugin.isLibraryPlugin()) continue; - // Initialize the plugin - if (!plugin.initializePlugin()) { - log::error("Failed to initialize library plugin {}", wolv::util::toUTF8String(plugin.getPath().filename())); - } - } - - u32 builtinPlugins = 0; - u32 loadErrors = 0; - - // Load the builtin plugin first, so it can initialize everything that's necessary for ImHex to work - for (const auto &plugin : plugins) { - if (!plugin.isBuiltinPlugin()) continue; - if (plugin.isLibraryPlugin()) continue; - if (!shouldLoadPlugin(plugin)) { - log::debug("Skipping built-in plugin {}", plugin.getPath().string()); + log::debug("Skipping library plugin {}", plugin.getPath().string()); continue; } - // Make sure there's only one built-in plugin - if (builtinPlugins > 1) continue; - - // Initialize the plugin + // Initialize the library if (!plugin.initializePlugin()) { - log::error("Failed to initialize plugin {}", wolv::util::toUTF8String(plugin.getPath().filename())); + log::error("Failed to initialize library plugin {}", wolv::util::toUTF8String(plugin.getPath().filename())); loadErrors++; - } else { - builtinPlugins++; } + pluginNames.insert(plugin.getPluginName()); } - // Load all other plugins + // Load all plugins for (const auto &plugin : plugins) { - if (plugin.isBuiltinPlugin()) continue; if (plugin.isLibraryPlugin()) continue; if (!shouldLoadPlugin(plugin)) { @@ -235,6 +221,7 @@ namespace hex::init { log::error("Failed to initialize plugin {}", wolv::util::toUTF8String(plugin.getPath().filename())); loadErrors++; } + pluginNames.insert(plugin.getPluginName()); } // If no plugins were loaded successfully, ImHex wasn't installed properly. This will trigger an error popup later on @@ -243,20 +230,11 @@ namespace hex::init { ImHexApi::System::impl::addInitArgument("no-plugins"); return false; } - - // ImHex requires exactly one built-in plugin - // If no built-in plugin or more than one was found, something's wrong and we can't continue - #if !defined(EMSCRIPTEN) - if (builtinPlugins == 0) { - log::error("Built-in plugin not found!"); - ImHexApi::System::impl::addInitArgument("no-builtin-plugin"); - return false; - } else if (builtinPlugins > 1) { - log::error("Found more than one built-in plugin!"); - ImHexApi::System::impl::addInitArgument("multiple-builtin-plugins"); - return false; - } - #endif + if (pluginNames.size() != plugins.size()) { + log::error("Duplicate plugins detected!"); + ImHexApi::System::impl::addInitArgument("duplicate-plugins"); + return false; + } return true; } diff --git a/main/gui/source/window/window.cpp b/main/gui/source/window/window.cpp index 69beb2d12..10c1ab8ae 100644 --- a/main/gui/source/window/window.cpp +++ b/main/gui/source/window/window.cpp @@ -60,10 +60,8 @@ namespace hex { for (const auto &[argument, value] : ImHexApi::System::getInitArguments()) { if (argument == "no-plugins") { openEmergencyPopup("No Plugins"); - } else if (argument == "no-builtin-plugin") { - openEmergencyPopup("No Builtin Plugin"); - } else if (argument == "multiple-builtin-plugins") { - openEmergencyPopup("Multiple Builtin Plugins"); + } else if (argument == "duplicate-plugins") { + openEmergencyPopup("Duplicate Plugins loaded"); } } } @@ -620,31 +618,13 @@ namespace hex { ImGui::EndPopup(); } - // No built-in plugin error popup + // Duplicate plugins error popup ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5F, 0.5F)); - if (ImGui::BeginPopupModal("No Builtin Plugin", nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove)) { - ImGui::TextUnformatted("The ImHex built-in plugins could not be loaded!"); - ImGui::TextUnformatted("Make sure you installed ImHex correctly."); - ImGui::TextUnformatted("There should be at least a 'builtin.hexplug' file in your plugins folder."); - - ImGui::NewLine(); - - drawPluginFolderTable(); - - ImGui::NewLine(); - if (ImGui::Button("Close ImHex", ImVec2(ImGui::GetContentRegionAvail().x, 0))) - ImHexApi::System::closeImHex(true); - - ImGui::EndPopup(); - } - - // Multiple built-in plugins error popup - ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5F, 0.5F)); - if (ImGui::BeginPopupModal("Multiple Builtin Plugins", nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove)) { - ImGui::TextUnformatted("ImHex found and attempted to load multiple built-in plugins!"); + if (ImGui::BeginPopupModal("Duplicate Plugins loaded", nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove)) { + ImGui::TextUnformatted("ImHex found and attempted to load multiple plugins with the same name!"); ImGui::TextUnformatted("Make sure you installed ImHex correctly and, if needed,"); - ImGui::TextUnformatted("cleaned up older installations correctly,"); - ImGui::TextUnformatted("There should be exactly one 'builtin.hexplug' file in any one your plugin folders."); + ImGui::TextUnformatted("cleaned up older installations correctly."); + ImGui::TextUnformatted("Each plugin should only ever be loaded once."); ImGui::NewLine(); diff --git a/plugins/builtin/source/content/command_line_interface.cpp b/plugins/builtin/source/content/command_line_interface.cpp index 1d3d30b4a..199467880 100644 --- a/plugins/builtin/source/content/command_line_interface.cpp +++ b/plugins/builtin/source/content/command_line_interface.cpp @@ -114,12 +114,7 @@ namespace hex::plugin::builtin { hex::log::println("Loaded plugins:"); for (const auto &plugin : PluginManager::getPlugins()) { - hex::log::print("- "); - - if (plugin.isBuiltinPlugin()) - hex::log::print("\033[1;43m{}\033[0m", plugin.getPluginName()); - else - hex::log::print("\033[1m{}\033[0m", plugin.getPluginName()); + hex::log::print("- \033[1m{}\033[0m", plugin.getPluginName()); hex::log::println(" by {}", plugin.getPluginAuthor()); diff --git a/plugins/builtin/source/content/views/view_about.cpp b/plugins/builtin/source/content/views/view_about.cpp index a80bbe2b8..0be9e6c6a 100644 --- a/plugins/builtin/source/content/views/view_about.cpp +++ b/plugins/builtin/source/content/views/view_about.cpp @@ -369,7 +369,7 @@ namespace hex::plugin::builtin { ImGui::TableNextColumn(); bool open = false; - ImGui::PushStyleColor(ImGuiCol_Text, plugin.isBuiltinPlugin() ? ImGuiExt::GetCustomColorU32(ImGuiCustomCol_Highlight) : ImGui::GetColorU32(ImGuiCol_Text)); + ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(ImGuiCol_Text)); if (features.empty()) ImGui::BulletText("%s", plugin.getPluginName().c_str()); else diff --git a/plugins/builtin/source/plugin_builtin.cpp b/plugins/builtin/source/plugin_builtin.cpp index bbea1f24a..fd27bc77a 100644 --- a/plugins/builtin/source/plugin_builtin.cpp +++ b/plugins/builtin/source/plugin_builtin.cpp @@ -119,7 +119,3 @@ IMHEX_PLUGIN_SETUP("Built-in", "WerWolv", "Default ImHex functionality") { handleBorderlessWindowMode(); } - -// This is the default plugin -// DO NOT USE THIS IN ANY OTHER PLUGIN -extern "C" bool isBuiltinPlugin() { return true; }