diff --git a/libultraship/libultraship/Console.cpp b/libultraship/libultraship/Console.cpp index efc13ca2c..d93a4e500 100644 --- a/libultraship/libultraship/Console.cpp +++ b/libultraship/libultraship/Console.cpp @@ -1,20 +1,22 @@ #include "Console.h" -#include -#include - #include "Cvar.h" #include "GlobalCtx2.h" #include "ImGuiImpl.h" #include "Lib/ImGui/imgui.h" #include "Utils/StringHelper.h" #include "Lib/ImGui/imgui_internal.h" +#include "Utils.h" namespace Ship { - std::map Bindings; - std::map BindingToggle; + std::string BuildUsage(const CommandEntry& entry) { + std::string usage; + for (const auto& arg : entry.arguments) + usage += StringHelper::Sprintf(arg.optional ? "[%s] " : "<%s> ", arg.info.c_str()); + return usage; + } - static bool HelpCommand(const std::vector&) { + static bool HelpCommand(std::shared_ptr Console, const std::vector& args) { SohImGui::console->SendInfoMessage("SoH Commands:"); for (const auto& cmd : SohImGui::console->Commands) { SohImGui::console->SendInfoMessage(" - " + cmd.first); @@ -22,18 +24,12 @@ namespace Ship { return CMD_SUCCESS; } - static bool ClearCommand(const std::vector&) { + static bool ClearCommand(std::shared_ptr Console, const std::vector& args) { SohImGui::console->Log[SohImGui::console->selected_channel].clear(); return CMD_SUCCESS; } - std::string toLowerCase(std::string in) { - std::string cpy(in); - std::transform(cpy.begin(), cpy.end(), cpy.begin(), ::tolower); - return cpy; - } - - static bool BindCommand(const std::vector& args) { + static bool BindCommand(std::shared_ptr Console, const std::vector& args) { if (args.size() > 2) { const ImGuiIO* io = &ImGui::GetIO();; for (size_t k = 0; k < std::size(io->KeysData); k++) { @@ -44,8 +40,8 @@ namespace Ship { const char* const delim = " "; std::ostringstream imploded; std::copy(args.begin() + 2, args.end(), std::ostream_iterator(imploded, delim)); - Bindings[k] = imploded.str(); - SohImGui::console->SendInfoMessage("Binding '%s' to %s", args[1].c_str(), Bindings[k].c_str()); + Console->Bindings[k] = imploded.str(); + SohImGui::console->SendInfoMessage("Binding '%s' to %s", args[1].c_str(), Console->Bindings[k].c_str()); break; } } @@ -53,15 +49,15 @@ namespace Ship { return CMD_SUCCESS; } - static bool BindToggleCommand(const std::vector& args) { + static bool BindToggleCommand(std::shared_ptr Console, const std::vector& args) { if (args.size() > 2) { const ImGuiIO* io = &ImGui::GetIO();; for (size_t k = 0; k < std::size(io->KeysData); k++) { std::string key(ImGui::GetKeyName(k)); if (toLowerCase(args[1]) == toLowerCase(key)) { - BindingToggle[k] = args[2]; - SohImGui::console->SendInfoMessage("Binding toggle '%s' to %s", args[1].c_str(), BindingToggle[k].c_str()); + Console->BindingToggle[k] = args[2]; + SohImGui::console->SendInfoMessage("Binding toggle '%s' to %s", args[1].c_str(), Console->BindingToggle[k].c_str()); break; } } @@ -69,13 +65,6 @@ namespace Ship { return CMD_SUCCESS; } - std::string BuildUsage(const CommandEntry& entry) { - std::string usage; - for (const auto& arg : entry.arguments) - usage += StringHelper::Sprintf(arg.optional ? "[%s] " : "<%s> ", arg.info.c_str()); - return usage; - } - void Console::Init() { this->InputBuffer = new char[MAX_BUFFER_SIZE]; strcpy(this->InputBuffer, ""); @@ -281,8 +270,10 @@ namespace Ship { const std::vector cmd_args = StringHelper::Split(line, " "); if (this->Commands.contains(cmd_args[0])) { const CommandEntry entry = this->Commands[cmd_args[0]]; - if (!entry.handler(cmd_args) && !entry.arguments.empty()) + if (!entry.handler(shared_from_this(), cmd_args) && !entry.arguments.empty()) { SendErrorMessage("[SOH] Usage: " + cmd_args[0] + " " + BuildUsage(entry)); + } + return; } SendErrorMessage("[SOH] Command not found"); diff --git a/libultraship/libultraship/Console.h b/libultraship/libultraship/Console.h index 00ca518e2..e81964aee 100644 --- a/libultraship/libultraship/Console.h +++ b/libultraship/libultraship/Console.h @@ -16,7 +16,8 @@ namespace Ship { #define MAX_BUFFER_SIZE 255 #define NULLSTR "None" - typedef std::function args)> CommandHandler; + class Console; + typedef std::function Console, std::vector args)> CommandHandler; enum class ArgumentType { TEXT, NUMBER, PLAYER_POS, PLAYER_ROT @@ -40,14 +41,15 @@ namespace Ship { std::string channel = "Console"; }; - class Console { + class Console : public std::enable_shared_from_this { + private: int selectedId = -1; std::vector selectedEntries; std::string filter; spdlog::level::level_enum level_filter = spdlog::level::trace; - std::vector log_channels = { "Console", "Logs" }; - std::vector priority_filters = { spdlog::level::off, spdlog::level::critical, spdlog::level::err, spdlog::level::warn, spdlog::level::info, spdlog::level::debug, spdlog::level::trace }; - std::vector priority_colors = { + const std::vector log_channels = { "Console", "Logs" }; + const std::vector priority_filters = { spdlog::level::off, spdlog::level::critical, spdlog::level::err, spdlog::level::warn, spdlog::level::info, spdlog::level::debug, spdlog::level::trace }; + const std::vector priority_colors = { ImVec4(0.8f, 0.8f, 0.8f, 1.0f), // TRACE ImVec4(0.9f, 0.9f, 0.9f, 1.0f), // DEBUG ImVec4(1.0f, 1.0f, 1.0f, 1.0f), // INFO @@ -60,6 +62,8 @@ namespace Ship { void Append(const std::string& channel, spdlog::level::level_enum priority, const char* fmt, va_list args); public: + std::map Bindings; + std::map BindingToggle; std::map> Log; std::map Commands; std::vector Autocomplete; @@ -69,8 +73,8 @@ namespace Ship { char* InputBuffer = nullptr; bool OpenAutocomplete = false; int HistoryIndex = -1; - std::string selected_channel = "Console"; bool opened = false; + std::string selected_channel = "Console"; void Init(); void Update(); void Draw(); diff --git a/libultraship/libultraship/ImGuiImpl.cpp b/libultraship/libultraship/ImGuiImpl.cpp index cd2ca1af3..b76739e7a 100644 --- a/libultraship/libultraship/ImGuiImpl.cpp +++ b/libultraship/libultraship/ImGuiImpl.cpp @@ -91,7 +91,7 @@ namespace SohImGui { WindowImpl impl; ImGuiIO* io; - Console* console = new Console; + std::shared_ptr console = std::make_shared(); GameOverlay* overlay = new GameOverlay; InputEditor* controller = new InputEditor; static ImVector s_GroupPanelLabelStack; @@ -863,7 +863,7 @@ namespace SohImGui { if ((ImGui::IsKeyDown(ImGuiKey_LeftCtrl) || ImGui::IsKeyDown(ImGuiKey_RightCtrl)) && ImGui::IsKeyPressed(ImGuiKey_R, false)) { - console->Commands["reset"].handler(emptyArgs); + console->Commands["reset"].handler(console, emptyArgs); } #endif @@ -891,7 +891,7 @@ namespace SohImGui { "Ctrl+R" #endif )) { - console->Commands["reset"].handler(emptyArgs); + console->Commands["reset"].handler(console, emptyArgs); } ImGui::EndMenu(); } @@ -1638,7 +1638,7 @@ namespace SohImGui { CVar_SetS32("gEnableBetaQuest", betaQuestEnabled); CVar_SetS32("gBetaQuestWorld", betaQuestWorld); - console->Commands["reset"].handler(emptyArgs); + console->Commands["reset"].handler(console, emptyArgs); needs_save = true; } diff --git a/libultraship/libultraship/ImGuiImpl.h b/libultraship/libultraship/ImGuiImpl.h index fd0aced6a..8e20d415c 100644 --- a/libultraship/libultraship/ImGuiImpl.h +++ b/libultraship/libultraship/ImGuiImpl.h @@ -69,7 +69,7 @@ namespace SohImGui { WindowDrawFunc drawFunc; } CustomWindow; - extern Ship::Console* console; + extern std::shared_ptr console; extern Ship::InputEditor* controller; extern Ship::GameOverlay* overlay; extern bool needs_save; diff --git a/libultraship/libultraship/Utils.cpp b/libultraship/libultraship/Utils.cpp index 185c21c24..6d0e50f5c 100644 --- a/libultraship/libultraship/Utils.cpp +++ b/libultraship/libultraship/Utils.cpp @@ -1,5 +1,6 @@ #include "Utils.h" #include +#include #ifdef _MSC_VER #define strdup _strdup @@ -58,4 +59,10 @@ namespace Ship { return args; } + + std::string toLowerCase(std::string in) { + std::string cpy(in); + std::transform(cpy.begin(), cpy.end(), cpy.begin(), ::tolower); + return cpy; + } } diff --git a/libultraship/libultraship/Utils.h b/libultraship/libultraship/Utils.h index 1dc3d3491..256db35e7 100644 --- a/libultraship/libultraship/Utils.h +++ b/libultraship/libultraship/Utils.h @@ -10,4 +10,5 @@ namespace Ship { } std::vector SplitText(const std::string& text, char separator, bool keep_quotes); + std::string toLowerCase(std::string in); } \ No newline at end of file diff --git a/soh/soh/Enhancements/debugconsole.cpp b/soh/soh/Enhancements/debugconsole.cpp index 203e5521a..8e72392ca 100644 --- a/soh/soh/Enhancements/debugconsole.cpp +++ b/soh/soh/Enhancements/debugconsole.cpp @@ -5,6 +5,7 @@ #include "debugconsole.h" #include "../libultraship/ImGuiImpl.h" #include "savestates.h" +#include "Console.h" #include #include @@ -32,7 +33,7 @@ extern GlobalContext* gGlobalCtx; #define CMD_REGISTER SohImGui::BindCmd -static bool ActorSpawnHandler(const std::vector& args) { +static bool ActorSpawnHandler(std::shared_ptr Console, const std::vector& args) { if ((args.size() != 9) && (args.size() != 3) && (args.size() != 6)) { SohImGui::console->SendErrorMessage("Not enough arguments passed to actorspawn"); return CMD_FAILED; @@ -82,13 +83,13 @@ static bool ActorSpawnHandler(const std::vector& args) { } -static bool KillPlayerHandler([[maybe_unused]] const std::vector&) { +static bool KillPlayerHandler(std::shared_ptr Console, const std::vector&) { gSaveContext.health = 0; SohImGui::console->SendInfoMessage("[SOH] You've met with a terrible fate, haven't you?"); return CMD_SUCCESS; } -static bool SetPlayerHealthHandler(const std::vector& args) { +static bool SetPlayerHealthHandler(std::shared_ptr Console, const std::vector& args) { if (args.size() != 2) { SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed"); return CMD_FAILED; @@ -115,7 +116,7 @@ static bool SetPlayerHealthHandler(const std::vector& args) { } -static bool LoadSceneHandler(const std::vector&) { +static bool LoadSceneHandler(std::shared_ptr Console, const std::vector&) { gSaveContext.respawnFlag = 0; gSaveContext.seqId = 0xFF; gSaveContext.gameMode = 0; @@ -123,7 +124,7 @@ static bool LoadSceneHandler(const std::vector&) { return CMD_SUCCESS; } -static bool RuppeHandler(const std::vector& args) { +static bool RuppeHandler(std::shared_ptr Console, const std::vector& args) { if (args.size() < 2) return CMD_FAILED; @@ -147,7 +148,7 @@ static bool RuppeHandler(const std::vector& args) { return CMD_SUCCESS; } -static bool SetPosHandler(const std::vector args) { +static bool SetPosHandler(std::shared_ptr Console, const std::vector args) { if (gGlobalCtx == nullptr) { SohImGui::console->SendErrorMessage("GlobalCtx == nullptr"); return CMD_FAILED; @@ -174,7 +175,7 @@ static bool SetPosHandler(const std::vector args) { return CMD_SUCCESS; } -static bool ResetHandler(std::vector args) { +static bool ResetHandler(std::shared_ptr Console, std::vector args) { if (gGlobalCtx == nullptr) { SohImGui::console->SendErrorMessage("GlobalCtx == nullptr"); return CMD_FAILED; @@ -195,7 +196,7 @@ const static std::map ammoItems{ { "magic_beans", ITEM_BEAN }, }; -static bool AmmoHandler(const std::vector& args) { +static bool AmmoHandler(std::shared_ptr Console, const std::vector& args) { if (args.size() != 3) { SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed"); return CMD_FAILED; @@ -238,7 +239,7 @@ const static std::map bottleItems{ { "big_poe", ITEM_BIG_POE }, { "blue_fire", ITEM_BLUE_FIRE }, { "rutos_letter", ITEM_LETTER_RUTO }, }; -static bool BottleHandler(const std::vector& args) { +static bool BottleHandler(std::shared_ptr Console, const std::vector& args) { if (args.size() != 3) { SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed"); return CMD_FAILED; @@ -270,7 +271,7 @@ static bool BottleHandler(const std::vector& args) { return CMD_SUCCESS; } -static bool BHandler(const std::vector& args) { +static bool BHandler(std::shared_ptr Console, const std::vector& args) { if (args.size() != 2) { SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed"); return CMD_FAILED; @@ -280,7 +281,7 @@ static bool BHandler(const std::vector& args) { return CMD_SUCCESS; } -static bool ItemHandler(const std::vector& args) { +static bool ItemHandler(std::shared_ptr Console, const std::vector& args) { if (args.size() != 3) { SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed"); return CMD_FAILED; @@ -291,7 +292,7 @@ static bool ItemHandler(const std::vector& args) { return CMD_SUCCESS; } -static bool EntranceHandler(const std::vector& args) { +static bool EntranceHandler(std::shared_ptr Console, const std::vector& args) { if (args.size() != 2) { SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed"); return CMD_FAILED; @@ -312,7 +313,7 @@ static bool EntranceHandler(const std::vector& args) { gSaveContext.nextTransition = 11; } -static bool SaveStateHandler(const std::vector& args) { +static bool SaveStateHandler(std::shared_ptr Console, const std::vector& args) { unsigned int slot = OTRGlobals::Instance->gSaveStateMgr->GetCurrentSlot(); const SaveStateReturn rtn = OTRGlobals::Instance->gSaveStateMgr->AddRequest({ slot, RequestType::SAVE }); @@ -323,11 +324,10 @@ static bool SaveStateHandler(const std::vector& args) { case SaveStateReturn::FAIL_WRONG_GAMESTATE: SohImGui::console->SendErrorMessage("[SOH] Can not save a state outside of \"GamePlay\""); return CMD_FAILED; - } } -static bool LoadStateHandler(const std::vector& args) { +static bool LoadStateHandler(std::shared_ptr Console, const std::vector& args) { unsigned int slot = OTRGlobals::Instance->gSaveStateMgr->GetCurrentSlot(); const SaveStateReturn rtn = OTRGlobals::Instance->gSaveStateMgr->AddRequest({ slot, RequestType::LOAD }); @@ -348,7 +348,7 @@ static bool LoadStateHandler(const std::vector& args) { } -static bool StateSlotSelectHandler(const std::vector& args) { +static bool StateSlotSelectHandler(std::shared_ptr Console, const std::vector& args) { if (args.size() != 2) { SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed"); return CMD_FAILED; @@ -404,7 +404,7 @@ static int CheckVarType(const std::string& input) return result; } -static bool SetCVarHandler(const std::vector& args) { +static bool SetCVarHandler(std::shared_ptr Console, const std::vector& args) { if (args.size() < 3) return CMD_FAILED; @@ -434,7 +434,7 @@ static bool SetCVarHandler(const std::vector& args) { } -static bool GetCVarHandler(const std::vector& args) { +static bool GetCVarHandler(std::shared_ptr Console, const std::vector& args) { if (args.size() < 2) return CMD_FAILED;