diff --git a/OTRExporter/assets/ship_of_harkinian/fonts/Fipps-Regular.otf b/OTRExporter/assets/ship_of_harkinian/fonts/Fipps-Regular.otf new file mode 100644 index 000000000..9334dad59 Binary files /dev/null and b/OTRExporter/assets/ship_of_harkinian/fonts/Fipps-Regular.otf differ diff --git a/OTRExporter/assets/ship_of_harkinian/fonts/PressStart2P-Regular.ttf b/OTRExporter/assets/ship_of_harkinian/fonts/PressStart2P-Regular.ttf new file mode 100644 index 000000000..2442affbf Binary files /dev/null and b/OTRExporter/assets/ship_of_harkinian/fonts/PressStart2P-Regular.ttf differ diff --git a/libultraship/libultraship/SohConsole.cpp b/libultraship/libultraship/SohConsole.cpp index c360ea968..330326e72 100644 --- a/libultraship/libultraship/SohConsole.cpp +++ b/libultraship/libultraship/SohConsole.cpp @@ -26,6 +26,32 @@ static bool ClearCommand(const std::vector&) { return CMD_SUCCESS; } +static bool OverlayCommand(const std::vector& args) { + SohImGui::console->Log[SohImGui::console->selected_channel].clear(); + if(args.size() < 3) { + return CMD_FAILED; + } + + if(CVar_GetVar(args[2].c_str()) != nullptr) { + const char* key = ImStrdup(args[2].c_str()); + if (args[1] == "add") { + if (std::ranges::find(SohImGui::CustomTexts, key) == SohImGui::CustomTexts.end()) { + SohImGui::CustomTexts.push_back(key); + INFO("Added overlay: %s ", key); + } + } else if (args[1] == "remove") { + if (std::ranges::find(SohImGui::CustomTexts, key) != SohImGui::CustomTexts.end()) { + SohImGui::CustomTexts.push_back(key); + INFO("Removed overlay: %s ", key); + } + } else { + return CMD_FAILED; + } + } + + return CMD_SUCCESS; +} + std::string toLowerCase(std::string in) { std::string cpy(in); std::ranges::transform(cpy, cpy.begin(), [](unsigned char c) { return std::tolower(c); }); @@ -84,6 +110,7 @@ void Console::Init() { this->Commands["clear"] = { ClearCommand, "Clear the console history" }; this->Commands["bind"] = { BindCommand, "Binds key to commands" }; this->Commands["bind-toggle"] = { BindToggleCommand, "Bind key as a bool toggle" }; + this->Commands["overlay"] = { OverlayCommand, "Overlay cvar value" }; } void Console::Update() { diff --git a/libultraship/libultraship/SohImGuiImpl.cpp b/libultraship/libultraship/SohImGuiImpl.cpp index ccb3b4a75..8d2c0f8b5 100644 --- a/libultraship/libultraship/SohImGuiImpl.cpp +++ b/libultraship/libultraship/SohImGuiImpl.cpp @@ -53,6 +53,7 @@ bool oldCursorState = true; OSContPad* pads; std::map DefaultAssets; +std::map Fonts; namespace SohImGui { @@ -61,6 +62,7 @@ namespace SohImGui { Console* console = new Console; bool p_open = false; bool needs_save = false; + std::vector CustomTexts; int SelectedLanguage = CVar_GetS32("gLanguages", 0); //Default Language to 0=English 1=German 2=French float kokiri_col[3] = { 0.118f, 0.41f, 0.106f }; float goron_col[3] = { 0.392f, 0.078f, 0.0f }; @@ -297,6 +299,16 @@ namespace SohImGui { ImGui::SetCurrentContext(ctx); io = &ImGui::GetIO(); io->ConfigFlags |= ImGuiConfigFlags_DockingEnable; + io->Fonts->AddFontDefault(); + std::shared_ptr base = GlobalCtx2::GetInstance()->GetResourceManager()->GetArchive(); + std::shared_ptr font = std::make_shared(); + base->LoadFile("assets\\ship_of_harkinian\\fonts\\PressStart2P-Regular.ttf", false, font); + if(font->bIsLoaded) { + char* font_data = new char[font->dwBufferSize]; + memcpy(font_data, font->buffer.get(), font->dwBufferSize); + Fonts["Player2"] = io->Fonts->AddFontFromMemoryTTF(font_data, font->dwBufferSize, 14.0f); + } + if (UseViewports()) { io->ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; } @@ -464,6 +476,48 @@ namespace SohImGui { } } + #define TextDraw(x, y, shadow, text, ...) { \ + ImGui::PushFont(Fonts["Player2"]); \ + if(shadow) { \ + ImGui::SetCursorPos(ImVec2(x + 1, y + 1)); \ + ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(.0f, .0f, .0f, 255)); \ + ImGui::Text(text, __VA_ARGS__); \ + } \ + ImGui::PopStyleColor(); \ + ImGui::SetCursorPos(ImVec2(x, y)); \ + ImGui::Text(text, __VA_ARGS__); \ + ImGui::PopFont(); \ + } \ + + void DrawCustomText() { + const ImGuiViewport* viewport = ImGui::GetMainViewport(); + + ImGui::SetNextWindowPos(viewport->Pos, ImGuiCond_Always); + ImGui::SetNextWindowSize(viewport->Size, ImGuiCond_Always); + ImGui::Begin("SoHOverlay", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoBackground | + ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoInputs); + + for (int xId = 0; xId < CustomTexts.size(); xId++) { + const char* text = CustomTexts[xId]; + const CVar* var = CVar_GetVar(text); + int textY = 50 + (xId * 30); + + switch (var->type) { + case CVAR_TYPE_FLOAT: + TextDraw(30, textY, true, "%s %.2f", text, var->value.valueFloat); + break; + case CVAR_TYPE_S32: + TextDraw(30, textY, true, "%s %d", text, var->value.valueS32); + break; + case CVAR_TYPE_STRING: + TextDraw(30, textY, true, "%s %s", text, var->value.valueStr); + break; + } + } + + ImGui::End(); + } + void DrawMainMenuAndCalculateGameSize() { console->Update(); ImGuiBackendNewFrame(); @@ -770,6 +824,8 @@ namespace SohImGui { pos = ImVec2(size.x / 2 - sw / 2, 0); size = ImVec2(sw, size.y); } + + DrawCustomText(); } void DrawFramebufferAndGameInput() { diff --git a/libultraship/libultraship/SohImGuiImpl.h b/libultraship/libultraship/SohImGuiImpl.h index c4fe3f825..387fb179f 100644 --- a/libultraship/libultraship/SohImGuiImpl.h +++ b/libultraship/libultraship/SohImGuiImpl.h @@ -58,6 +58,7 @@ namespace SohImGui { } CustomWindow; extern Console* console; + extern std::vector CustomTexts; void Init(WindowImpl window_impl); void Update(EventImpl event);