#pragma once #include #include #include #include #include #include #include struct ImGuiContext; namespace hex { struct SubCommand { std::string commandLong; std::string commandShort; std::string commandDescription; std::function&)> callback; }; struct Feature { std::string name; bool enabled; }; struct PluginFunctions { 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 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; SetImGuiContextFunc setImGuiContextLibraryFunction = nullptr; GetSubCommandsFunc getSubCommandsFunction = nullptr; GetFeaturesFunc getFeaturesFunction = nullptr; }; class Plugin { public: explicit Plugin(const std::fs::path &path); explicit Plugin(const std::string &name, const PluginFunctions &functions); Plugin(const Plugin &) = delete; Plugin(Plugin &&other) noexcept; ~Plugin(); Plugin& operator=(const Plugin &) = delete; Plugin& operator=(Plugin &&other) noexcept; [[nodiscard]] bool initializePlugin() const; [[nodiscard]] std::string getPluginName() const; [[nodiscard]] std::string getPluginAuthor() const; [[nodiscard]] std::string getPluginDescription() const; [[nodiscard]] std::string getCompatibleVersion() const; void setImGuiContext(ImGuiContext *ctx) const; [[nodiscard]] const std::fs::path &getPath() const; [[nodiscard]] bool isValid() const; [[nodiscard]] bool isLoaded() const; [[nodiscard]] std::span getSubCommands() const; [[nodiscard]] std::span getFeatures() const; [[nodiscard]] bool isLibraryPlugin() const; [[nodiscard]] bool wasAddedManually() const; private: uintptr_t m_handle = 0; std::fs::path m_path; mutable bool m_initialized = false; bool m_addedManually = false; PluginFunctions m_functions = {}; template [[nodiscard]] auto getPluginFunction(const std::string &symbol) { return reinterpret_cast(this->getPluginFunction(symbol)); } [[nodiscard]] void *getPluginFunction(const std::string &symbol) const; }; class PluginManager { public: PluginManager() = delete; static bool load(); static bool load(const std::fs::path &pluginFolder); static bool loadLibraries(); static bool loadLibraries(const std::fs::path &libraryFolder); static void unload(); static void reload(); static void initializeNewPlugins(); static void addLoadPath(const std::fs::path &path); static void addPlugin(const std::string &name, PluginFunctions functions); static Plugin* getPlugin(const std::string &name); static const std::list& getPlugins(); static const std::vector& getPluginPaths(); static const std::vector& getPluginLoadPaths(); static bool isPluginLoaded(const std::fs::path &path); private: static std::list& getPluginsMutable(); static AutoReset> s_pluginPaths, s_pluginLoadPaths; static AutoReset> s_loadedLibraries; }; }