From 8771d75beae2f70c6a75b32217af80377d124a0b Mon Sep 17 00:00:00 2001 From: Caladius Date: Tue, 1 Oct 2024 11:05:34 -0400 Subject: [PATCH 1/2] Plugin Manager --- .../PluginManager/PluginManager.cpp | 48 ++++++++++++++ .../PluginManager/PluginManager.h | 16 +++++ .../Plugins/ElectrocuteButton.cpp | 62 +++++++++++++++++++ soh/soh/Enhancements/PluginManager/Widget.h | 12 ++++ .../PluginManager/WidgetFactory.h | 57 +++++++++++++++++ soh/soh/OTRGlobals.cpp | 2 + soh/soh/SohGui.cpp | 7 +++ soh/soh/SohGui.hpp | 2 + soh/soh/SohMenuBar.cpp | 10 +++ 9 files changed, 216 insertions(+) create mode 100644 soh/soh/Enhancements/PluginManager/PluginManager.cpp create mode 100644 soh/soh/Enhancements/PluginManager/PluginManager.h create mode 100644 soh/soh/Enhancements/PluginManager/Plugins/ElectrocuteButton.cpp create mode 100644 soh/soh/Enhancements/PluginManager/Widget.h create mode 100644 soh/soh/Enhancements/PluginManager/WidgetFactory.h diff --git a/soh/soh/Enhancements/PluginManager/PluginManager.cpp b/soh/soh/Enhancements/PluginManager/PluginManager.cpp new file mode 100644 index 00000000000..0f94e163277 --- /dev/null +++ b/soh/soh/Enhancements/PluginManager/PluginManager.cpp @@ -0,0 +1,48 @@ +#include "PluginManager.h" +#include "../../UIWidgets.hpp" +#include "../../util.h" +#include "../../OTRGlobals.h" + +#include "WidgetFactory.h" + +void PluginManagerDrawPlugins() { + ImGui::Text("Plugins"); + + WidgetFactory& factory = WidgetFactory::GetInstance(); + + // Retrieve all registered widget names + std::vector widgetNames = factory.GetRegisteredWidgetNames(); + + // Create a table to show the widgets + if (ImGui::BeginTable("WidgetTable", 2, ImGuiTableFlags_Borders)) { + ImGui::TableSetupColumn("Plugin Name"); + ImGui::TableSetupColumn("Plugin Options"); + ImGui::TableHeadersRow(); + + for (const std::string& widgetName : widgetNames) { + std::unique_ptr widget = factory.CreateWidget(widgetName); + + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); + ImGui::Text("%s", widget->GetLabel().c_str()); + ImGui::TableSetColumnIndex(1); + widget->Draw(); + if (widgetName.find("Settings") != std::string::npos) { + widget->Settings(); + } + } + + ImGui::EndTable(); + } + +} + + +void PluginManager::DrawElement() { + ImGui::SetNextWindowSize(ImVec2(400, 400), ImGuiCond_FirstUseEver); + PluginManagerDrawPlugins(); +} + +void PluginManager::InitElement() { + +} \ No newline at end of file diff --git a/soh/soh/Enhancements/PluginManager/PluginManager.h b/soh/soh/Enhancements/PluginManager/PluginManager.h new file mode 100644 index 00000000000..57c95be2d43 --- /dev/null +++ b/soh/soh/Enhancements/PluginManager/PluginManager.h @@ -0,0 +1,16 @@ +#ifndef PLUGINMANAGER_H +#define PLUGINMANAGER_H + +#include "GuiWindow.h" + + +class PluginManager : public Ship::GuiWindow { + public: + using GuiWindow::GuiWindow; + + void InitElement(); + void DrawElement(); + void UpdateElement() override{}; +}; + +#endif // PLUGINMANAGER_H \ No newline at end of file diff --git a/soh/soh/Enhancements/PluginManager/Plugins/ElectrocuteButton.cpp b/soh/soh/Enhancements/PluginManager/Plugins/ElectrocuteButton.cpp new file mode 100644 index 00000000000..5593a34b384 --- /dev/null +++ b/soh/soh/Enhancements/PluginManager/Plugins/ElectrocuteButton.cpp @@ -0,0 +1,62 @@ +#include "../WidgetFactory.h" + +bool openSettings = false; + +// Derived widget class for a button +class ButtonWidget : public Widget { +public: + ButtonWidget(const std::string& tableLabel, const std::string& buttonLabel, std::function onClickAction) + : tableLabel(tableLabel), buttonLabel(buttonLabel), onClickAction(onClickAction) {} + + const std::string& GetLabel() const override { + return tableLabel; + } + + void Draw() override { + if (ImGui::Button(buttonLabel.c_str())) { + onClickAction(); + } + } + + void Settings() override { + if (openSettings) { + ImGui::SetNextWindowSize(ImVec2(400, 400), ImGuiCond_FirstUseEver); + ImGui::Begin("Electrocute Settings", &openSettings); + + UIWidgets::PaddedEnhancementCheckbox("Enable Button", "gEnhancements.CanShock", true, true); + + ImGui::End(); + } + } + +private: + std::string tableLabel; // Label for the table + std::string buttonLabel; // Label for the button + std::function onClickAction; +}; + +static WidgetRegistrar electrocuteButtonRegistrar( + "ElectrocuteButton", + []() -> std::unique_ptr { + return std::make_unique( + "Electrocute Player", // Table label + "Electrocute", // Button label + []() { + if (CVarGetInteger("gEnhancements.CanShock", 0) == 1) { + GameInteractor::RawAction::ElectrocutePlayer(); + } + } + ); + } +); + +static WidgetRegistrar electrocuteSettingsButtonRegistrar( + "ElectrocuteSettingsButton", + []() -> std::unique_ptr { + return std::make_unique( + "Open Settings", // Table label + "Settings", // Button label + []() { openSettings = !openSettings; } + ); + } +); \ No newline at end of file diff --git a/soh/soh/Enhancements/PluginManager/Widget.h b/soh/soh/Enhancements/PluginManager/Widget.h new file mode 100644 index 00000000000..e74cc9b0e09 --- /dev/null +++ b/soh/soh/Enhancements/PluginManager/Widget.h @@ -0,0 +1,12 @@ +#pragma once +#include +#include + +// Base class for all widgets +class Widget { +public: + virtual ~Widget() = default; + virtual const std::string& GetLabel() const = 0; + virtual void Draw() = 0; + virtual void Settings() = 0; +}; \ No newline at end of file diff --git a/soh/soh/Enhancements/PluginManager/WidgetFactory.h b/soh/soh/Enhancements/PluginManager/WidgetFactory.h new file mode 100644 index 00000000000..d5ac5f9e931 --- /dev/null +++ b/soh/soh/Enhancements/PluginManager/WidgetFactory.h @@ -0,0 +1,57 @@ +#pragma once +#include "soh/OTRGlobals.h" +#include +#include +#include +#include +#include +#include "Widget.h" +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/UIWidgets.hpp" + + +// WidgetFactory responsible for creating widgets and storing registrations +class WidgetFactory { +public: + // A map that stores creation functions by widget name + using CreateWidgetFunc = std::function()>; + + static WidgetFactory& GetInstance() { + static WidgetFactory instance; + return instance; + } + + // Registers a widget creation function with the given name + void RegisterWidget(const std::string& name, CreateWidgetFunc func) { + widgetCreators[name] = func; + } + + // Creates a widget by name + std::unique_ptr CreateWidget(const std::string& name) const { + auto it = widgetCreators.find(name); + if (it != widgetCreators.end()) { + return it->second(); + } + return nullptr; + } + + // Returns a list of registered widget names + std::vector GetRegisteredWidgetNames() const { + std::vector names; + for (const auto& pair : widgetCreators) { + names.push_back(pair.first); + } + return names; + } + +private: + std::unordered_map widgetCreators; +}; + +// Helper class for static registration of widgets +class WidgetRegistrar { +public: + WidgetRegistrar(const std::string& name, WidgetFactory::CreateWidgetFunc func) { + WidgetFactory::GetInstance().RegisterWidget(name, func); + } +}; \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 6ab2f658aa7..cf2a69f58c8 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -48,6 +48,8 @@ #include "util.h" #include +#include "soh/Enhancements/PluginManager/PluginManager.h" + #if not defined (__SWITCH__) && not defined(__WIIU__) #include "Extractor/Extract.h" #endif diff --git a/soh/soh/SohGui.cpp b/soh/soh/SohGui.cpp index df475447d44..0c17467a7e9 100644 --- a/soh/soh/SohGui.cpp +++ b/soh/soh/SohGui.cpp @@ -135,6 +135,8 @@ namespace SohGui { std::shared_ptr mAdvancedResolutionSettingsWindow; std::shared_ptr mModalWindow; + std::shared_ptr mPluginManager; + void SetupGuiElements() { auto gui = Ship::Context::GetInstance()->GetWindow()->GetGui(); @@ -203,6 +205,9 @@ namespace SohGui { mModalWindow = std::make_shared(CVAR_WINDOW("ModalWindow"), "Modal Window"); gui->AddGuiWindow(mModalWindow); mModalWindow->Show(); + + mPluginManager = std::make_shared(CVAR_WINDOW("PluginManager"), "Plugin Manager"); + gui->AddGuiWindow(mPluginManager); } void Destroy() { @@ -232,6 +237,8 @@ namespace SohGui { mSohMenuBar = nullptr; mInputViewer = nullptr; mInputViewerSettings = nullptr; + + mPluginManager = nullptr; } void RegisterPopup(std::string title, std::string message, std::string button1, std::string button2, std::function button1callback, std::function button2callback) { diff --git a/soh/soh/SohGui.hpp b/soh/soh/SohGui.hpp index 5152bf69c53..0746bca347d 100644 --- a/soh/soh/SohGui.hpp +++ b/soh/soh/SohGui.hpp @@ -25,6 +25,8 @@ #include "Enhancements/randomizer/randomizer_settings_window.h" #include "SohModals.h" +#include "soh/Enhancements/PluginManager/PluginManager.h" + #ifdef __cplusplus extern "C" { #endif diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 7286fe0b964..e64ae84f339 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -37,6 +37,8 @@ #include "Enhancements/randomizer/randomizer_settings_window.h" #include "Enhancements/resolution-editor/ResolutionEditor.h" +#include "Enhancements/PluginManager/PluginManager.h" + extern bool isBetaQuestEnabled; extern "C" PlayState* gPlayState; @@ -551,6 +553,7 @@ void DrawSettingsMenu() { extern std::shared_ptr mAudioEditorWindow; extern std::shared_ptr mCosmeticsEditorWindow; extern std::shared_ptr mGameplayStatsWindow; +extern std::shared_ptr mPluginManager; void DrawEnhancementsMenu() { if (ImGui::BeginMenu("Enhancements")) @@ -1456,6 +1459,13 @@ void DrawEnhancementsMenu() { mGameplayStatsWindow->ToggleVisibility(); } } + + if (mPluginManager) { + if (ImGui::Button(GetWindowButtonText("Plugin Manager", CVarGetInteger(CVAR_WINDOW("PluginManager"), 0)).c_str(), ImVec2(-1.0f, 0.0f))) { + mPluginManager->ToggleVisibility(); + } + } + ImGui::PopStyleVar(3); ImGui::PopStyleColor(1); From bb188a07a5fb51fec0617dd53d2b886de34c2f9d Mon Sep 17 00:00:00 2001 From: Caladius Date: Tue, 1 Oct 2024 11:17:54 -0400 Subject: [PATCH 2/2] Same Line Settings Button --- .../Enhancements/PluginManager/PluginManager.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/soh/soh/Enhancements/PluginManager/PluginManager.cpp b/soh/soh/Enhancements/PluginManager/PluginManager.cpp index 0f94e163277..d17c5d1e20e 100644 --- a/soh/soh/Enhancements/PluginManager/PluginManager.cpp +++ b/soh/soh/Enhancements/PluginManager/PluginManager.cpp @@ -22,14 +22,18 @@ void PluginManagerDrawPlugins() { for (const std::string& widgetName : widgetNames) { std::unique_ptr widget = factory.CreateWidget(widgetName); - ImGui::TableNextRow(); - ImGui::TableSetColumnIndex(0); - ImGui::Text("%s", widget->GetLabel().c_str()); - ImGui::TableSetColumnIndex(1); - widget->Draw(); if (widgetName.find("Settings") != std::string::npos) { + ImGui::SameLine(); + widget->Draw(); widget->Settings(); + } else { + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); + ImGui::Text("%s", widget->GetLabel().c_str()); + ImGui::TableSetColumnIndex(1); + widget->Draw(); } + } ImGui::EndTable();