diff --git a/src/shared/config.cpp b/src/shared/config.cpp index e8a2de9..af5c779 100644 --- a/src/shared/config.cpp +++ b/src/shared/config.cpp @@ -16,7 +16,7 @@ namespace openhack::config { setIfEmpty("menu.frameRounding", 4.f); setIfEmpty("menu.windowSnap", 3.f); setIfEmpty("menu.stackWindows", true); - setIfEmpty("menu.theme", gui::Themes::MegaHack); + setIfEmpty("menu.theme", gui::Themes::Modern); setIfEmpty("menu.toggleKey", "Tab"); setIfEmpty("menu.font", "Poppins"); setIfEmpty("menu.fontSize", 20.f); diff --git a/src/shared/gui/themes/modern/modern.cpp b/src/shared/gui/themes/modern/modern.cpp new file mode 100644 index 0000000..cc1dff2 --- /dev/null +++ b/src/shared/gui/themes/modern/modern.cpp @@ -0,0 +1,268 @@ +#include "modern.hpp" + +namespace openhack::gui { + + void ModernTheme::setStyles() { + auto &style = ImGui::GetStyle(); + style.WindowPadding = ImVec2(5, 4); + style.WindowRounding = config::get("menu.windowRounding"); + style.FramePadding = ImVec2(4, 3); + style.FrameRounding = config::get("menu.frameRounding"); + style.PopupRounding = config::get("menu.frameRounding"); + style.ItemSpacing = ImVec2(12, 3); + style.ItemInnerSpacing = ImVec2(8, 6); + style.WindowTitleAlign = ImVec2(0.0f, 0.5f); + style.IndentSpacing = 25.0f; + style.ScrollbarSize = 15.0f; + style.ScrollbarRounding = 9.0f; + style.GrabMinSize = 5.0f; + style.GrabRounding = 3.0f; + style.WindowBorderSize = config::get("menu.borderSize"); + style.WindowMinSize = ImVec2(32, 32); + style.DisplayWindowPadding = ImVec2(0, 0); + style.ScaleAllSizes(config::getGlobal("UIScale")); + + auto &colors = style.Colors; + colors[ImGuiCol_Text] = config::get("menu.color.text"); + colors[ImGuiCol_TextDisabled] = config::get("menu.color.textDisabled"); + + colors[ImGuiCol_WindowBg] = config::get("menu.color.background"); + colors[ImGuiCol_FrameBg] = config::get("menu.color.secondary"); + colors[ImGuiCol_TitleBg] = + colors[ImGuiCol_TitleBgActive] = + colors[ImGuiCol_TitleBgCollapsed] = + config::get("menu.color.accent"); + + colors[ImGuiCol_Button] = config::get("menu.color.primary"); + colors[ImGuiCol_ButtonHovered] = config::get("menu.color.hovered"); + colors[ImGuiCol_ButtonActive] = config::get("menu.color.clicked"); + + colors[ImGuiCol_FrameBgHovered] = config::get("menu.color.secondary"); + + colors[ImGuiCol_ScrollbarBg] = config::get("menu.color.secondary"); + colors[ImGuiCol_ScrollbarGrab] = config::get("menu.color.primary"); + colors[ImGuiCol_ScrollbarGrabHovered] = config::get("menu.color.hovered"); + colors[ImGuiCol_ScrollbarGrabActive] = config::get("menu.color.clicked"); + + colors[ImGuiCol_CheckMark] = config::get("menu.color.primary"); + colors[ImGuiCol_SliderGrab] = config::get("menu.color.primary"); + colors[ImGuiCol_SliderGrabActive] = config::get("menu.color.clicked"); + + colors[ImGuiCol_Border] = config::get("menu.color.border"); + colors[ImGuiCol_BorderShadow] = config::get("menu.color.border"); + + colors[ImGuiCol_PopupBg] = config::get("menu.color.background"); + colors[ImGuiCol_Header] = config::get("menu.color.primary"); + colors[ImGuiCol_HeaderHovered] = config::get("menu.color.hovered"); + colors[ImGuiCol_HeaderActive] = config::get("menu.color.clicked"); + } + + void ModernTheme::loadPalette() { + config::set("menu.color.text", Color(1.0f, 1.0f, 1.0f, 1.0f)); // Text color + config::set("menu.color.textDisabled", Color(0.5f, 0.5f, 0.5f, 0.95f)); // Disabled text color + config::set("menu.color.background", Color(0.07f, 0.07f, 0.07f, 0.9f)); // Window background + config::set("menu.color.accent", Color(0.12f, 0.12f, 0.12f, 1.0f)); // Title background + config::set("menu.color.primary", Color(0.73f, 0.53f, 0.99f, 1.00f)); // Buttons, etc. + config::set("menu.color.secondary", Color(0.12f, 0.12f, 0.12f, 0.95f)); // Frame background + config::set("menu.color.border", Color(0.0f, 0.0f, 0.0f, 1.0f)); // Border color + config::set("menu.color.hovered", Color(0.58f, 0.42f, 0.79f, 1.00f)); // Item hovered + config::set("menu.color.clicked", Color(0.44f, 0.31f, 0.58f, 1.00f)); // Item clicked + } + + bool ModernTheme::inputFloat(const char *label, float *value, float min, float max, const char *format) { + // Transparent background with a line border on the bottom + ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0, 0, 0, 0)); + ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImVec4(0, 0, 0, 0)); + ImGui::PushStyleColor(ImGuiCol_FrameBgActive, ImVec4(0, 0, 0, 0)); + + // Add a line border on the bottom + auto drawList = ImGui::GetWindowDrawList(); + auto cursorPos = ImGui::GetCursorScreenPos(); + auto availWidth = ImGui::CalcItemWidth(); + + auto color = config::get("menu.color.primary"); + color.a = 0.4f; + drawList->AddLine(ImVec2(cursorPos.x, cursorPos.y + 20), ImVec2(cursorPos.x + availWidth, cursorPos.y + 20), color); + bool changed = ImGui::InputFloat(label, value, 0.0f, 0.0f, format); + + ImGui::PopStyleColor(3); + + if (*value < min) + *value = min; + if (*value > max) + *value = max; + return changed; + } + + bool ModernTheme::button(const char *label, const ImVec2 &size) { + auto textColor = config::get("menu.color.text"); + auto buttonColor = config::get("menu.color.primary"); + auto hoveredColor = config::get("menu.color.hovered"); + auto clickedColor = config::get("menu.color.clicked"); + ImGui::PushStyleColor(ImGuiCol_Text, (ImVec4) textColor); + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(buttonColor.r, buttonColor.g, buttonColor.b, 0.4f)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(hoveredColor.r, hoveredColor.g, hoveredColor.b, 0.4f)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(clickedColor.r, clickedColor.g, clickedColor.b, 0.6f)); + ImGui::PushStyleColor(ImGuiCol_Border, (ImVec4) buttonColor); + ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.f); + + if (size.x == 0) + ImGui::PushItemWidth(-1); + + auto availWidth = ImGui::GetContentRegionAvail().x; + if (size.x > 0) + availWidth *= size.x; + bool clicked = ImGui::Button(label, ImVec2(availWidth, size.y)); + + if (size.x == 0) + ImGui::PopItemWidth(); + + ImGui::PopStyleColor(5); + ImGui::PopStyleVar(); + + return clicked; + } + + bool ModernTheme::checkbox(const char *label, bool *value) { + ImGui::PushItemWidth(-1.0f); + auto textColor = *value ? config::get("menu.color.primary") : config::get( + "menu.color.textDisabled"); + + if (utils::isSearching()) { + if (utils::isSearched(label)) { + ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1, 1, 1, 1)); + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0, 0, 0, 0.1f)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0, 0, 0, 0.2f)); + } else { + ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.5f, 0.5f, 0.5f, 0.5f)); + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0, 0, 0, 0)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0, 0, 0, 0)); + } + } else { + ImGui::PushStyleColor(ImGuiCol_Text, (ImVec4) textColor); + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0, 0, 0, 0.1f)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0, 0, 0, 0.2f)); + } + + bool clicked = ImGui::Button(label, ImVec2(ImGui::GetContentRegionAvail().x, 0)); + + ImGui::PopStyleColor(4); + + if (clicked) *value = !*value; + ImGui::PopItemWidth(); + return clicked; + } + + bool ModernTheme::toggleSetting(const char *label, bool *value, const std::function &popupDraw, ImVec2 size, + float minWidth) { + ImGui::PushItemWidth(-1.0f); + auto textColor = *value ? config::get("menu.color.primary") : config::get( + "menu.color.textDisabled"); + + if (utils::isSearching()) { + if (utils::isSearched(label)) { + ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1, 1, 1, 1)); + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0, 0, 0, 0.1f)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0, 0, 0, 0.2f)); + } else { + ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.5f, 0.5f, 0.5f, 0.5f)); + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0, 0, 0, 0)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0, 0, 0, 0)); + } + } else { + ImGui::PushStyleColor(ImGuiCol_Text, (ImVec4) textColor); + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0, 0, 0, 0.1f)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0, 0, 0, 0.2f)); + } + + auto availWidth = ImGui::GetContentRegionAvail().x; + auto buttonSize = ImVec2(availWidth * 0.88f, 0); + auto arrowSize = ImVec2(availWidth * 0.12f, 0); + + if (size.x > 0) { + buttonSize.x *= size.x; + arrowSize.x *= size.x; + } + + bool clicked = ImGui::Button(label, buttonSize); + ImGui::PopStyleColor(3); + ImGui::PushStyleColor(ImGuiCol_Text, (ImVec4) config::get("menu.color.text")); + gui::callback(); + ImGui::PopStyleColor(); + ImGui::SameLine(0, 0); + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0, 0, 0, 0.1f)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0, 0, 0, 0.2f)); + ImGui::SetNextItemWidth(arrowSize.x); + bool openPopup = ImGui::ArrowButton((std::string("##open_") + label).c_str(), ImGuiDir_Right); + ImGui::PopItemWidth(); + ImGui::PopStyleColor(4); + ImGui::PopItemWidth(); + + if (clicked) *value = !*value; + + std::string popupName = std::string("##") + label; + if (openPopup) + ImGui::OpenPopup(popupName.c_str()); + + auto scale = config::getGlobal("UIScale"); + ImGui::SetNextWindowSizeConstraints(ImVec2(minWidth * scale, 0), ImVec2(FLT_MAX, FLT_MAX)); + if (ImGui::BeginPopup(popupName.c_str())) { + popupDraw(); + ImGui::EndPopup(); + } + + return clicked; + } + + void ModernTheme::popupSettings(const char *label, const std::function &content, ImVec2 size) { + ImGui::PushItemWidth(-1.0f); + + if (utils::isSearching() && !utils::isSearched(label)) { + ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.5f, 0.5f, 0.5f, 0.5f)); + } else { + ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1, 1, 1, 1)); + } + + auto availWidth = ImGui::GetContentRegionAvail().x; + auto buttonSize = ImVec2(availWidth * 0.88f, 0); + auto arrowSize = ImVec2(availWidth * 0.12f, 0); + + if (size.x > 0) { + buttonSize.x *= size.x; + arrowSize.x *= size.x; + } + + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0, 0, 0, 0)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0, 0, 0, 0)); + ImGui::Button(label, buttonSize); + ImGui::PopStyleColor(4); + ImGui::SameLine(0, 0); + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0, 0, 0, 0.1f)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0, 0, 0, 0.2f)); + ImGui::SetNextItemWidth(arrowSize.x); + bool openPopup = ImGui::ArrowButton((std::string("##open_") + label).c_str(), ImGuiDir_Right); + ImGui::PopItemWidth(); + ImGui::PopStyleColor(3); + ImGui::PopItemWidth(); + + std::string popupName = std::string("##") + label; + if (openPopup) + ImGui::OpenPopup(popupName.c_str()); + + if (ImGui::BeginPopup(popupName.c_str())) { + content(); + ImGui::EndPopup(); + } + + } + +} \ No newline at end of file diff --git a/src/shared/gui/themes/modern/modern.hpp b/src/shared/gui/themes/modern/modern.hpp new file mode 100644 index 0000000..fb7d750 --- /dev/null +++ b/src/shared/gui/themes/modern/modern.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include "../themes.hpp" + +namespace openhack::gui { + class ModernTheme : public Theme { + public: + std::string getName() override { return "Modern"; } + + void setStyles() override; + + void loadPalette() override; + + bool inputFloat(const char *label, float *value, float min, float max, const char *format) override; + + bool button(const char *label, const ImVec2 &size) override; + + bool checkbox(const char *label, bool *value) override; + + void popupSettings(const char* label, const std::function &content, ImVec2 size) override; + + bool toggleSetting(const char *label, bool *value, const std::function &popupDraw, ImVec2 size, float minWidth) override; + }; +} \ No newline at end of file diff --git a/src/shared/gui/themes/themes.cpp b/src/shared/gui/themes/themes.cpp index 9c12443..afa2ec4 100644 --- a/src/shared/gui/themes/themes.cpp +++ b/src/shared/gui/themes/themes.cpp @@ -2,7 +2,7 @@ #include "classic/classic.hpp" #include "megahack/megahack.hpp" -// #include "modern/modern.hpp" +#include "modern/modern.hpp" // #include "steam2000/steam2000.hpp" namespace openhack::gui { @@ -308,6 +308,9 @@ namespace openhack::gui { case Themes::Classic: setTheme(new ClassicTheme()); break; + case Themes::Modern: + setTheme(new ModernTheme()); + break; case Themes::MegaHack: setTheme(new MegaHackTheme()); break; diff --git a/src/shared/gui/themes/themes.hpp b/src/shared/gui/themes/themes.hpp index 3bfa9ac..42c1256 100644 --- a/src/shared/gui/themes/themes.hpp +++ b/src/shared/gui/themes/themes.hpp @@ -120,20 +120,17 @@ namespace openhack::gui { /// @brief Classic ImGui theme. Classic = 0, - /// @brief Theme based on the MegaHack v8 - MegaHack = 1, /// @brief Modern UI theme. - // Modern = 2, - /// @brief Theme based on the old Steam UI. - // Steam2000 = 3, + Modern = 1, + /// @brief Theme based on the MegaHack v8 + MegaHack = 2, }; /// @brief The names of the themes. const char *const THEME_NAMES[] = { "Classic", + "Modern", "MegaHack", - // "Modern", - // "Steam2000", }; /// @brief The count of the themes.