mirror of https://github.com/WerWolv/ImHex.git
parent
7441720a88
commit
ea7483f9a7
|
@ -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<Plugin> &getPlugins();
|
||||
static std::vector<std::fs::path> &getPluginPaths();
|
||||
|
|
|
@ -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, \
|
||||
|
|
|
@ -39,18 +39,19 @@ namespace hex {
|
|||
m_functions.initializePluginFunction = getPluginFunction<PluginFunctions::InitializePluginFunc>("initializePlugin");
|
||||
m_functions.initializeLibraryFunction = getPluginFunction<PluginFunctions::InitializePluginFunc>("initializeLibrary");
|
||||
m_functions.getPluginNameFunction = getPluginFunction<PluginFunctions::GetPluginNameFunc>("getPluginName");
|
||||
m_functions.getLibraryNameFunction = getPluginFunction<PluginFunctions::GetLibraryNameFunc>("getLibraryName");
|
||||
m_functions.getPluginAuthorFunction = getPluginFunction<PluginFunctions::GetPluginAuthorFunc>("getPluginAuthor");
|
||||
m_functions.getPluginDescriptionFunction = getPluginFunction<PluginFunctions::GetPluginDescriptionFunc>("getPluginDescription");
|
||||
m_functions.getCompatibleVersionFunction = getPluginFunction<PluginFunctions::GetCompatibleVersionFunc>("getCompatibleVersion");
|
||||
m_functions.setImGuiContextFunction = getPluginFunction<PluginFunctions::SetImGuiContextFunc>("setImGuiContext");
|
||||
m_functions.isBuiltinPluginFunction = getPluginFunction<PluginFunctions::IsBuiltinPluginFunc>("isBuiltinPlugin");
|
||||
m_functions.getSubCommandsFunction = getPluginFunction<PluginFunctions::GetSubCommandsFunc>("getSubCommands");
|
||||
m_functions.getFeaturesFunction = getPluginFunction<PluginFunctions::GetSubCommandsFunc>("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<SubCommand> Plugin::getSubCommands() const {
|
||||
if (m_functions.getSubCommandsFunction != nullptr) {
|
||||
auto result = m_functions.getSubCommandsFunction();
|
||||
const auto result = m_functions.getSubCommandsFunction();
|
||||
|
||||
return *static_cast<std::vector<SubCommand>*>(result);
|
||||
} else {
|
||||
return { };
|
||||
|
@ -200,7 +195,8 @@ namespace hex {
|
|||
|
||||
std::span<Feature> Plugin::getFeatures() const {
|
||||
if (m_functions.getFeaturesFunction != nullptr) {
|
||||
auto result = m_functions.getFeaturesFunction();
|
||||
const auto result = m_functions.getFeaturesFunction();
|
||||
|
||||
return *static_cast<std::vector<Feature>*>(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<Plugin> &PluginManager::getPlugins() {
|
||||
|
|
|
@ -157,9 +157,11 @@ namespace hex::init {
|
|||
|
||||
bool loadPlugins() {
|
||||
// Load all plugins
|
||||
#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<std::string> 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");
|
||||
if (pluginNames.size() != plugins.size()) {
|
||||
log::error("Duplicate plugins detected!");
|
||||
ImHexApi::System::impl::addInitArgument("duplicate-plugins");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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; }
|
||||
|
|
Loading…
Reference in New Issue