diff --git a/src/core/commands/ColorCommand.hpp b/src/core/commands/ColorCommand.hpp index 6034d09d..62f1366b 100644 --- a/src/core/commands/ColorCommand.hpp +++ b/src/core/commands/ColorCommand.hpp @@ -1,6 +1,5 @@ #pragma once #include "Command.hpp" -#include "imgui.h" namespace YimMenu { @@ -9,8 +8,6 @@ namespace YimMenu protected: virtual void OnChange() {}; virtual void OnCall() override; - virtual void SaveState(nlohmann::json& value) override; - virtual void LoadState(nlohmann::json& value) override; ImVec4 m_State = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); @@ -18,5 +15,7 @@ namespace YimMenu ColorCommand(std::string name, std::string label, std::string description, ImVec4 color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f)); ImVec4 GetState(); void SetState(ImVec4 state); + virtual void SaveState(nlohmann::json& value) override; + virtual void LoadState(nlohmann::json& value) override; }; } \ No newline at end of file diff --git a/src/core/commands/Command.hpp b/src/core/commands/Command.hpp index 4ed51f1f..5fe89b7d 100644 --- a/src/core/commands/Command.hpp +++ b/src/core/commands/Command.hpp @@ -9,16 +9,15 @@ namespace YimMenu class Command { private: - std::string m_Name; - std::string m_Label; - std::string m_Description; - joaat_t m_Hash; - int m_NumArgs = 0; // TODO: currently unused protected: virtual void OnCall() = 0; void MarkDirty(); + std::string m_Name; + std::string m_Label; + std::string m_Description; + joaat_t m_Hash; public: Command(std::string name, std::string label, std::string description, int num_args = 0); diff --git a/src/core/frontend/manager/UIManager.cpp b/src/core/frontend/manager/UIManager.cpp index 628a0bba..1fbe4850 100644 --- a/src/core/frontend/manager/UIManager.cpp +++ b/src/core/frontend/manager/UIManager.cpp @@ -9,6 +9,7 @@ namespace YimMenu::Features {0, "Classic"}, {1, "Modern"}, {2, "Modern (Vertical)"}, + {3, "Modern (Modular)"}, }; // Expose as global reference so other code can use it @@ -51,6 +52,9 @@ namespace YimMenu case UITheme::ModernV: RenderModernVTheme(); break; + case UITheme::Modular: + RenderModularTheme(); + break; default: RenderClassicTheme(); // Default theme break; diff --git a/src/core/frontend/manager/UIManager.hpp b/src/core/frontend/manager/UIManager.hpp index b43d8253..685c979f 100644 --- a/src/core/frontend/manager/UIManager.hpp +++ b/src/core/frontend/manager/UIManager.hpp @@ -11,6 +11,7 @@ namespace YimMenu Classic = 0, Modern, ModernV, + Modular, }; class UIManager diff --git a/src/core/frontend/manager/styles/Classic/Classic.cpp b/src/core/frontend/manager/styles/Classic/Classic.cpp index 11318c51..5cb48c7e 100644 --- a/src/core/frontend/manager/styles/Classic/Classic.cpp +++ b/src/core/frontend/manager/styles/Classic/Classic.cpp @@ -1,11 +1,14 @@ #include "game/pointers/Pointers.hpp" #include "game/frontend/Menu.hpp" #include "core/frontend/manager/UIManager.hpp" +#include "game/frontend/submenus/Settings/GUISettings.hpp" namespace YimMenu { void RenderClassicTheme() { + YimMenu::SyncColorCommandsToStyle(); + float windowWidth = *YimMenu::Pointers.ScreenResX / 2.5f; float centerX = (*YimMenu::Pointers.ScreenResX - windowWidth) / 2.0f; float centerY = *YimMenu::Pointers.ScreenResY / 5.0f; diff --git a/src/core/frontend/manager/styles/Modern/Modern.cpp b/src/core/frontend/manager/styles/Modern/Modern.cpp index f45e2114..033e2351 100644 --- a/src/core/frontend/manager/styles/Modern/Modern.cpp +++ b/src/core/frontend/manager/styles/Modern/Modern.cpp @@ -1,11 +1,14 @@ #include "game/pointers/Pointers.hpp" #include "game/frontend/Menu.hpp" #include "core/frontend/manager/UIManager.hpp" +#include "game/frontend/submenus/Settings/GUISettings.hpp" namespace YimMenu { void RenderModernTheme() { + YimMenu::SyncColorCommandsToStyle(); + ImGuiIO& io = ImGui::GetIO(); ImDrawList* drawList = ImGui::GetBackgroundDrawList(); @@ -26,6 +29,8 @@ namespace YimMenu ImGui::Begin("##BubbleInputWindow", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoBringToFrontOnFocus); const auto& submenus = YimMenu::UIManager::GetSubmenus(); + auto activeSubmenu = YimMenu::UIManager::GetActiveSubmenu(); + for (size_t i = 0; i < submenus.size(); ++i) { auto& submenu = submenus[i]; @@ -35,27 +40,14 @@ namespace YimMenu ImGui::SetCursorScreenPos(bubblePos); ImGui::PushID(static_cast(i)); - ImVec2 bgPos(center.x - bgSize / 2.0f, center.y - bgSize / 2.0f); - drawList->AddRectFilled(bgPos, ImVec2(bgPos.x + bgSize, bgPos.y + bgSize), IM_COL32(10, 10, 10, 255), rounding); - drawList->AddRect(bgPos, ImVec2(bgPos.x + bgSize, bgPos.y + bgSize), IM_COL32(192, 192, 192, 32), rounding, ImDrawFlags_None, 1.0f); - - ImU32 bubbleColor = IM_COL32(25, 25, 31, 255); - ImU32 hoverColor = IM_COL32(46, 46, 51, 255); ImGui::InvisibleButton("##Bubble", ImVec2(bubbleSize, bubbleSize)); bool hovered = ImGui::IsItemHovered(); bool clicked = ImGui::IsItemClicked(); - drawList->AddRectFilled(bubblePos, ImVec2(bubblePos.x + bubbleSize, bubblePos.y + bubbleSize), hovered ? hoverColor : bubbleColor, rounding); - drawList->AddRect(bubblePos, ImVec2(bubblePos.x + bubbleSize, bubblePos.y + bubbleSize), IM_COL32(192, 192, 192, 16), rounding, ImDrawFlags_None, 1.0f); - - auto activeSubmenu = YimMenu::UIManager::GetActiveSubmenu(); - if (clicked) { if (submenu == activeSubmenu) - { YimMenu::UIManager::SetShowContentWindow(!YimMenu::UIManager::ShowingContentWindow()); - } else { YimMenu::UIManager::SetActiveSubmenu(submenu); @@ -63,34 +55,39 @@ namespace YimMenu } } - ImU32 defaultIconColor = IM_COL32(255, 255, 255, 255); - ImU32 activeIconColor = IM_COL32(46, 204, 113, 255); - ImU32 hoveredIconColor = IM_COL32(36, 174, 93, 255); - ImU32 iconColor = submenu == activeSubmenu ? activeIconColor : (hovered ? hoveredIconColor : defaultIconColor); + // Colors + ImU32 buttonColor = ImGui::GetColorU32(ImGuiCol_Button); + ImU32 hoverColor = ImGui::GetColorU32(ImGuiCol_ButtonHovered); + ImU32 activeColor = ImGui::GetColorU32(ImGuiCol_ButtonActive); + ImU32 borderColor = ImGui::GetColorU32(ImGuiCol_Border); + ImU32 iconColor = ImGui::GetColorU32(ImGuiCol_Text); + + ImU32 fillColor = (submenu == activeSubmenu) ? activeColor : (hovered ? hoverColor : buttonColor); + // Bubble background and border + drawList->AddRectFilled(bubblePos, bubblePos + ImVec2(bubbleSize, bubbleSize), fillColor, rounding); + drawList->AddRect(bubblePos, bubblePos + ImVec2(bubbleSize, bubbleSize), borderColor, rounding); + + // Icon (text color only) ImGui::PushFont(YimMenu::Menu::Font::g_AwesomeFont); ImVec2 iconSize = ImGui::CalcTextSize(submenu->m_Icon.c_str()); ImVec2 iconPos(center.x - iconSize.x / 2, center.y - iconSize.y / 2); drawList->AddText(YimMenu::Menu::Font::g_AwesomeFont, 0.0f, iconPos, iconColor, submenu->m_Icon.c_str()); ImGui::PopFont(); - ImU32 defaultTextColor = IM_COL32(255, 255, 255, 255); - ImU32 activeTextColor = IM_COL32(46, 204, 113, 255); - ImU32 hoveredTextColor = IM_COL32(36, 174, 93, 255); - ImU32 textColor = submenu == activeSubmenu ? activeTextColor : (hovered ? hoveredTextColor : defaultTextColor); - + // Label ImVec2 labelSize = ImGui::CalcTextSize(submenu->m_Name.c_str()); ImVec2 labelPos(center.x - labelSize.x / 2, bubblePos.y + bubbleSize + 15.0f); ImVec2 bgMin = labelPos - ImVec2(6, 2); ImVec2 bgMax = labelPos + labelSize + ImVec2(6, 2); - - drawList->AddRectFilled(bgMin, bgMax, IM_COL32(26, 26, 31, 120)); - drawList->AddRect(bgMin, bgMax, IM_COL32(192, 192, 192, 16), 4.0f); - drawList->AddText(labelPos, textColor, submenu->m_Name.c_str()); + drawList->AddRectFilled(bgMin, bgMax, ImGui::GetColorU32(ImGuiCol_ChildBg)); + drawList->AddRect(bgMin, bgMax, borderColor, 4.0f); + drawList->AddText(labelPos, iconColor, submenu->m_Name.c_str()); ImGui::PopID(); } + // Drag zone ImVec2 dragZoneMin = ImVec2(basePos.x, basePos.y - 20); ImVec2 dragZoneMax = ImVec2(basePos.x + bubbleSpacing * submenus.size(), basePos.y + bubbleSize); ImGui::SetCursorScreenPos(dragZoneMin); @@ -106,8 +103,7 @@ namespace YimMenu else { ImVec2 delta = io.MousePos - dragStart; - basePosOffset.x += delta.x; - basePosOffset.y += delta.y; + basePosOffset += delta; dragStart = io.MousePos; } } @@ -116,10 +112,9 @@ namespace YimMenu dragging = false; } - ImGui::End(); - - auto activeSubmenu = YimMenu::UIManager::GetActiveSubmenu(); + ImGui::End(); // ##BubbleInputWindow + // Content window if (YimMenu::UIManager::ShowingContentWindow() && activeSubmenu) { float windowWidth = *YimMenu::Pointers.ScreenResX / 2.5f; @@ -129,14 +124,13 @@ namespace YimMenu ImGui::SetNextWindowSize(windowSize, ImGuiCond_FirstUseEver); ImGui::SetNextWindowPos(ImVec2(centerX, centerY), ImGuiCond_FirstUseEver); + ImGuiWindowFlags flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse; if (ImGui::Begin("##Categories&Content", nullptr, flags)) { if (ImGui::BeginChild("##categorySelectors", ImVec2(0, 60), true)) - { activeSubmenu->DrawCategorySelectors(); - } ImGui::EndChild(); if (ImGui::BeginChild("##options", ImVec2(0, 0), true)) diff --git a/src/core/frontend/manager/styles/ModernVertical/ModernVertical.cpp b/src/core/frontend/manager/styles/ModernVertical/ModernVertical.cpp index 2ff25360..b90c1482 100644 --- a/src/core/frontend/manager/styles/ModernVertical/ModernVertical.cpp +++ b/src/core/frontend/manager/styles/ModernVertical/ModernVertical.cpp @@ -1,11 +1,14 @@ #include "game/pointers/Pointers.hpp" #include "game/frontend/Menu.hpp" #include "core/frontend/manager/UIManager.hpp" +#include "game/frontend/submenus/Settings/GUISettings.hpp" namespace YimMenu { void RenderModernVTheme() { + YimMenu::SyncColorCommandsToStyle(); + ImGuiIO& io = ImGui::GetIO(); ImDrawList* drawList = ImGui::GetBackgroundDrawList(); @@ -26,37 +29,27 @@ namespace YimMenu ImGui::Begin("##BubbleInputWindow", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoBringToFrontOnFocus); const auto& submenus = YimMenu::UIManager::GetSubmenus(); + auto activeSubmenu = YimMenu::UIManager::GetActiveSubmenu(); + for (size_t i = 0; i < submenus.size(); ++i) { auto& submenu = submenus[i]; - // Changed horizontal to vertical: + ImVec2 bubblePos(basePos.x, basePos.y + i * bubbleSpacing + 2); ImVec2 center(bubblePos.x + bubbleSize / 2.0f, bubblePos.y + bubbleSize / 2.0f); ImGui::SetCursorScreenPos(bubblePos); ImGui::PushID(static_cast(i)); - ImVec2 bgPos(center.x - bgSize / 2.0f, center.y - bgSize / 2.0f); - drawList->AddRectFilled(bgPos, ImVec2(bgPos.x + bgSize, bgPos.y + bgSize), IM_COL32(10, 10, 10, 255), rounding); - drawList->AddRect(bgPos, ImVec2(bgPos.x + bgSize, bgPos.y + bgSize), IM_COL32(192, 192, 192, 32), rounding, ImDrawFlags_None, 1.0f); - - ImU32 bubbleColor = IM_COL32(25, 25, 31, 255); - ImU32 hoverColor = IM_COL32(46, 46, 51, 255); + // Invisible button logic ImGui::InvisibleButton("##Bubble", ImVec2(bubbleSize, bubbleSize)); bool hovered = ImGui::IsItemHovered(); bool clicked = ImGui::IsItemClicked(); - drawList->AddRectFilled(bubblePos, ImVec2(bubblePos.x + bubbleSize, bubblePos.y + bubbleSize), hovered ? hoverColor : bubbleColor, rounding); - drawList->AddRect(bubblePos, ImVec2(bubblePos.x + bubbleSize, bubblePos.y + bubbleSize), IM_COL32(192, 192, 192, 16), rounding, ImDrawFlags_None, 1.0f); - - auto activeSubmenu = YimMenu::UIManager::GetActiveSubmenu(); - if (clicked) { if (submenu == activeSubmenu) - { YimMenu::UIManager::SetShowContentWindow(!YimMenu::UIManager::ShowingContentWindow()); - } else { YimMenu::UIManager::SetActiveSubmenu(submenu); @@ -64,34 +57,40 @@ namespace YimMenu } } - ImU32 defaultIconColor = IM_COL32(255, 255, 255, 255); - ImU32 activeIconColor = IM_COL32(46, 204, 113, 255); - ImU32 hoveredIconColor = IM_COL32(36, 174, 93, 255); - ImU32 iconColor = submenu == activeSubmenu ? activeIconColor : (hovered ? hoveredIconColor : defaultIconColor); + // Colors from ImGui style + ImU32 buttonColor = ImGui::GetColorU32(ImGuiCol_Button); + ImU32 hoverColor = ImGui::GetColorU32(ImGuiCol_ButtonHovered); + ImU32 activeColor = ImGui::GetColorU32(ImGuiCol_ButtonActive); + ImU32 borderColor = ImGui::GetColorU32(ImGuiCol_Border); + ImU32 iconColor = ImGui::GetColorU32(ImGuiCol_Text); + // Final fill color + ImU32 fillColor = (submenu == activeSubmenu) ? activeColor : (hovered ? hoverColor : buttonColor); + + // Draw filled button bubble + drawList->AddRectFilled(bubblePos, bubblePos + ImVec2(bubbleSize, bubbleSize), fillColor, rounding); + drawList->AddRect(bubblePos, bubblePos + ImVec2(bubbleSize, bubbleSize), borderColor, rounding, ImDrawFlags_None, 1.0f); + + // Draw icon centered (text color always) ImGui::PushFont(YimMenu::Menu::Font::g_AwesomeFont); ImVec2 iconSize = ImGui::CalcTextSize(submenu->m_Icon.c_str()); ImVec2 iconPos(center.x - iconSize.x / 2, center.y - iconSize.y / 2); drawList->AddText(YimMenu::Menu::Font::g_AwesomeFont, 0.0f, iconPos, iconColor, submenu->m_Icon.c_str()); ImGui::PopFont(); - ImU32 defaultTextColor = IM_COL32(255, 255, 255, 255); - ImU32 activeTextColor = IM_COL32(46, 204, 113, 255); - ImU32 hoveredTextColor = IM_COL32(36, 174, 93, 255); - ImU32 textColor = submenu == activeSubmenu ? activeTextColor : (hovered ? hoveredTextColor : defaultTextColor); - + // Draw label below bubble ImVec2 labelSize = ImGui::CalcTextSize(submenu->m_Name.c_str()); ImVec2 labelPos(center.x - labelSize.x / 2, bubblePos.y + bubbleSize + 15.0f); ImVec2 bgMin = labelPos - ImVec2(6, 2); ImVec2 bgMax = labelPos + labelSize + ImVec2(6, 2); - - drawList->AddRectFilled(bgMin, bgMax, IM_COL32(26, 26, 31, 120)); - drawList->AddRect(bgMin, bgMax, IM_COL32(192, 192, 192, 16), 4.0f); - drawList->AddText(labelPos, textColor, submenu->m_Name.c_str()); + drawList->AddRectFilled(bgMin, bgMax, ImGui::GetColorU32(ImGuiCol_ChildBg)); + drawList->AddRect(bgMin, bgMax, borderColor, 4.0f); + drawList->AddText(labelPos, iconColor, submenu->m_Name.c_str()); ImGui::PopID(); } + // Drag zone (optional repositioning) ImVec2 dragZoneMin = ImVec2(basePos.x + bubbleSize + 10, basePos.y); ImVec2 dragZoneMax = ImVec2(basePos.x + bubbleSize + 10 + bubbleSpacing, basePos.y + bubbleSpacing * submenus.size()); ImGui::SetCursorScreenPos(dragZoneMin); @@ -107,8 +106,7 @@ namespace YimMenu else { ImVec2 delta = io.MousePos - dragStart; - basePosOffset.x += delta.x; - basePosOffset.y += delta.y; + basePosOffset += delta; dragStart = io.MousePos; } } @@ -119,8 +117,7 @@ namespace YimMenu ImGui::End(); - auto activeSubmenu = YimMenu::UIManager::GetActiveSubmenu(); - + // Content window if (YimMenu::UIManager::ShowingContentWindow() && activeSubmenu) { float windowWidth = *YimMenu::Pointers.ScreenResX / 2.5f; @@ -130,14 +127,11 @@ namespace YimMenu ImGui::SetNextWindowSize(windowSize, ImGuiCond_FirstUseEver); ImGui::SetNextWindowPos(ImVec2(centerX, centerY), ImGuiCond_FirstUseEver); - ImGuiWindowFlags flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse; - if (ImGui::Begin("##Categories&Content", nullptr, flags)) + if (ImGui::Begin("##Categories&Content", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse)) { if (ImGui::BeginChild("##categorySelectors", ImVec2(0, 60), true)) - { activeSubmenu->DrawCategorySelectors(); - } ImGui::EndChild(); if (ImGui::BeginChild("##options", ImVec2(0, 0), true)) diff --git a/src/core/frontend/manager/styles/Modular/Modular.cpp b/src/core/frontend/manager/styles/Modular/Modular.cpp new file mode 100644 index 00000000..384563e6 --- /dev/null +++ b/src/core/frontend/manager/styles/Modular/Modular.cpp @@ -0,0 +1,116 @@ +#include +#include "game/pointers/Pointers.hpp" +#include "game/frontend/Menu.hpp" +#include "core/frontend/manager/UIManager.hpp" +#include "game/frontend/submenus/Settings/GUISettings.hpp" + +namespace YimMenu +{ + void RenderModularTheme() + { + YimMenu::SyncColorCommandsToStyle(); + + ImGuiIO& io = ImGui::GetIO(); + ImDrawList* drawList = ImGui::GetBackgroundDrawList(); + const auto& submenus = UIManager::GetSubmenus(); + auto activeSubmenu = UIManager::GetActiveSubmenu(); + + const float bubblePadding = 10.0f; + const float leftOffset = 25.0f; + const float topOffset = 25.0f; + const float defaultWidth = 80.0f; + const float defaultHeight = 80.0f; + + for (size_t i = 0; i < submenus.size(); ++i) + { + auto& submenu = submenus[i]; + std::string windowId = "NavItem_" + submenu->m_Name; + + ImVec2 startPos(leftOffset, topOffset + i * (defaultHeight + bubblePadding)); + ImVec2 defaultSize(defaultWidth, defaultHeight); + + ImGui::SetNextWindowPos(startPos, ImGuiCond_FirstUseEver); + ImGui::SetNextWindowSize(defaultSize, ImGuiCond_FirstUseEver); + ImGui::SetNextWindowSizeConstraints(ImVec2(60, 80), ImVec2(200, 200)); + ImGui::SetNextWindowBgAlpha(0.0f); // Transparent background + + if (ImGui::Begin(windowId.c_str(), nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoScrollbar)) + { + ImVec2 winPos = ImGui::GetWindowPos(); + ImVec2 winSize = ImGui::GetWindowSize(); + ImVec2 center(winPos.x + winSize.x / 2, winPos.y + winSize.y / 2 - 10); + + ImU32 borderColor = ImGui::GetColorU32(ImGuiCol_Border); + ImU32 textColor = ImGui::GetColorU32(ImGuiCol_Text); + ImU32 buttonColor = ImGui::GetColorU32(ImGuiCol_Button); + ImU32 hoverColor = ImGui::GetColorU32(ImGuiCol_ButtonHovered); + ImU32 activeColor = ImGui::GetColorU32(ImGuiCol_ButtonActive); + + ImVec2 bubbleSize = winSize - ImVec2(20, 30); + ImVec2 bubblePos(winPos.x + (winSize.x - bubbleSize.x) / 2, winPos.y + 10); + + ImGui::SetCursorScreenPos(bubblePos); + ImGui::InvisibleButton(("##bubble_" + submenu->m_Name).c_str(), bubbleSize); + bool hovered = ImGui::IsItemHovered(); + bool clicked = ImGui::IsItemClicked(); + + if (clicked) + { + if (activeSubmenu == submenu) + UIManager::SetShowContentWindow(!UIManager::ShowingContentWindow()); + else + { + UIManager::SetActiveSubmenu(submenu); + UIManager::SetShowContentWindow(true); + } + } + + ImU32 bubbleBgColor = (submenu == activeSubmenu) ? activeColor : (hovered ? hoverColor : buttonColor); + // Button + drawList->AddRectFilled(bubblePos, bubblePos + bubbleSize, bubbleBgColor, 10.0f); + drawList->AddRect(bubblePos, bubblePos + bubbleSize, borderColor, 10.0f, 0, 1.5f); + + // Icon + ImGui::PushFont(Menu::Font::g_AwesomeFont); + float iconScale = std::clamp(bubbleSize.y * 0.4f, 14.0f, 32.0f); + ImVec2 iconSize = ImGui::CalcTextSize(submenu->m_Icon.c_str()); + ImVec2 iconPos(center.x - iconSize.x / 2, bubblePos.y + bubbleSize.y / 2 - iconSize.y / 2); + drawList->AddText(Menu::Font::g_AwesomeFont, iconScale, iconPos, textColor, submenu->m_Icon.c_str()); + ImGui::PopFont(); + + // Label below button + ImVec2 labelSize = ImGui::CalcTextSize(submenu->m_Name.c_str()); + ImVec2 labelPos(center.x - labelSize.x / 2, bubblePos.y + bubbleSize.y + 6); + drawList->AddText(labelPos, textColor, submenu->m_Name.c_str()); + } + ImGui::End(); + } + + if (activeSubmenu) + { + ImGui::SetNextWindowSizeConstraints(ImVec2(100, 40), ImVec2(io.DisplaySize.x * 0.9f, 200)); + if (ImGui::Begin("##CategorySelectorWindow", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_AlwaysAutoResize)) + { + activeSubmenu->DrawCategorySelectors(); + } + ImGui::End(); + } + + if (UIManager::ShowingContentWindow() && activeSubmenu) + { + ImVec2 defaultSize(*Pointers.ScreenResX / 2.8f, *Pointers.ScreenResY / 2.5f); + ImGui::SetNextWindowSize(defaultSize, ImGuiCond_FirstUseEver); + + if (ImGui::Begin("##OptionsContentWindow", nullptr, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar)) + { + ImFont* optionsFont = UIManager::GetOptionsFont(); + if (optionsFont) + ImGui::PushFont(optionsFont); + activeSubmenu->Draw(); + if (optionsFont) + ImGui::PopFont(); + } + ImGui::End(); + } + } +} diff --git a/src/core/frontend/manager/styles/Themes.cpp b/src/core/frontend/manager/styles/Themes.cpp new file mode 100644 index 00000000..a55ce2e2 --- /dev/null +++ b/src/core/frontend/manager/styles/Themes.cpp @@ -0,0 +1,104 @@ +#include "Themes.hpp" +#include "core/commands/ColorCommand.hpp" +#include "game/frontend/submenus/Settings/GUISettings.hpp" + +namespace YimMenu +{ + void DefaultStyle() + { + ImGuiStyle& style = ImGui::GetStyle(); + // Text + style.Colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f); + style.Colors[ImGuiCol_TextDisabled] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); + + // Backgrounds + style.Colors[ImGuiCol_WindowBg] = ImVec4(0.08f, 0.08f, 0.09f, 1.00f); + style.Colors[ImGuiCol_ChildBg] = ImVec4(0.10f, 0.10f, 0.12f, 1.00f); + style.Colors[ImGuiCol_PopupBg] = ImVec4(0.07f, 0.07f, 0.09f, 0.95f); + + // Borders + style.Colors[ImGuiCol_Border] = ImVec4(0.28f, 0.28f, 0.28f, 0.25f); + style.Colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); + + // Frames + style.Colors[ImGuiCol_FrameBg] = ImVec4(0.15f, 0.15f, 0.17f, 1.00f); + style.Colors[ImGuiCol_FrameBgHovered] = ImVec4(0.35f, 0.59f, 0.35f, 0.75f); + style.Colors[ImGuiCol_FrameBgActive] = ImVec4(0.47f, 0.75f, 0.47f, 0.85f); + + // Title bars + style.Colors[ImGuiCol_TitleBg] = ImVec4(0.06f, 0.06f, 0.07f, 1.00f); + style.Colors[ImGuiCol_TitleBgActive] = ImVec4(0.09f, 0.09f, 0.11f, 1.00f); + style.Colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.04f, 0.04f, 0.05f, 1.00f); + + // Menus/tabs + style.Colors[ImGuiCol_MenuBarBg] = ImVec4(0.10f, 0.10f, 0.12f, 1.00f); + style.Colors[ImGuiCol_Tab] = ImVec4(0.30f, 0.55f, 0.30f, 0.85f); + style.Colors[ImGuiCol_TabHovered] = ImVec4(0.40f, 0.65f, 0.40f, 0.85f); + style.Colors[ImGuiCol_TabActive] = ImVec4(0.47f, 0.75f, 0.47f, 1.00f); + style.Colors[ImGuiCol_TabUnfocused] = ImVec4(0.25f, 0.40f, 0.25f, 0.70f); + style.Colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.30f, 0.55f, 0.30f, 0.85f); + + // Scrollbar + style.Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.05f, 0.05f, 0.05f, 0.80f); + style.Colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.30f, 0.30f, 0.30f, 1.00f); + style.Colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.40f, 0.40f, 1.00f); + style.Colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); + + // Checkmarks, sliders + style.Colors[ImGuiCol_CheckMark] = ImVec4(0.36f, 0.85f, 0.56f, 1.00f); + style.Colors[ImGuiCol_SliderGrab] = ImVec4(0.35f, 0.59f, 0.35f, 1.00f); + style.Colors[ImGuiCol_SliderGrabActive] = ImVec4(0.47f, 0.75f, 0.47f, 1.00f); + + // Buttons + style.Colors[ImGuiCol_Button] = ImVec4(0.35f, 0.59f, 0.35f, 1.00f); + style.Colors[ImGuiCol_ButtonHovered] = ImVec4(0.40f, 0.65f, 0.40f, 1.00f); + style.Colors[ImGuiCol_ButtonActive] = ImVec4(0.47f, 0.75f, 0.47f, 1.00f); + + // Headers + style.Colors[ImGuiCol_Header] = ImVec4(0.30f, 0.50f, 0.30f, 1.00f); + style.Colors[ImGuiCol_HeaderHovered] = ImVec4(0.40f, 0.65f, 0.40f, 1.00f); + style.Colors[ImGuiCol_HeaderActive] = ImVec4(0.47f, 0.75f, 0.47f, 1.00f); + + // Separators + style.Colors[ImGuiCol_Separator] = ImVec4(0.28f, 0.28f, 0.28f, 0.50f); + style.Colors[ImGuiCol_SeparatorHovered] = ImVec4(0.45f, 0.80f, 0.45f, 0.78f); + style.Colors[ImGuiCol_SeparatorActive] = ImVec4(0.55f, 0.90f, 0.55f, 1.00f); + + // Resize grips + style.Colors[ImGuiCol_ResizeGrip] = ImVec4(0.50f, 0.50f, 0.50f, 0.30f); + style.Colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.60f, 0.85f, 0.60f, 0.60f); + style.Colors[ImGuiCol_ResizeGripActive] = ImVec4(0.70f, 0.95f, 0.70f, 0.90f); + + // Plots + style.Colors[ImGuiCol_PlotLines] = ImVec4(0.80f, 0.80f, 0.00f, 0.00f); + style.Colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.85f, 0.00f, 1.00f); + style.Colors[ImGuiCol_PlotHistogram] = ImVec4(0.35f, 0.59f, 0.35f, 1.00f); + style.Colors[ImGuiCol_PlotHistogramHovered] = ImVec4(0.47f, 0.75f, 0.47f, 1.00f); + + // Drag & drop + style.Colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f); + + // Navigation highlighting + style.Colors[ImGuiCol_NavHighlight] = ImVec4(0.40f, 0.90f, 0.40f, 1.00f); + style.Colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); + style.Colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.20f); + + // Modal/background dimming + style.Colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.10f, 0.10f, 0.10f, 0.35f); + + // Rounding + style.GrabRounding = style.FrameRounding = style.ChildRounding = style.WindowRounding = 8.0f; + } + + void SetupStyle() + { + // Apply default style first + DefaultStyle(); + + // Initialize the color/rounding commands and load saved settings + InitializeColorCommands(); // This will call LoadSettings internally + + // Apply loaded colors/rounding to ImGui + ApplyThemeToImGui(); + } +} diff --git a/src/core/frontend/manager/styles/Themes.hpp b/src/core/frontend/manager/styles/Themes.hpp index 3a14d852..d7649232 100644 --- a/src/core/frontend/manager/styles/Themes.hpp +++ b/src/core/frontend/manager/styles/Themes.hpp @@ -1,9 +1,15 @@ #pragma once +#include "core/frontend/manager/Category.hpp" +#include "game/frontend/items/Items.hpp" + namespace YimMenu { // Forward declarations of each theme's render function, append when adding new themes extern void RenderClassicTheme(); extern void RenderModernTheme(); extern void RenderModernVTheme(); -} \ No newline at end of file + extern void RenderModularTheme(); + extern void SetupStyle(); + extern void DefaultStyle(); +} diff --git a/src/game/frontend/GUI.cpp b/src/game/frontend/GUI.cpp index 558c3f77..c665bd9c 100644 --- a/src/game/frontend/GUI.cpp +++ b/src/game/frontend/GUI.cpp @@ -9,6 +9,7 @@ #include "game/frontend/ChatDisplay.hpp" #include "game/gta/Natives.hpp" #include "types/pad/ControllerInputs.hpp" +#include "core/frontend/manager/styles/Themes.hpp" namespace YimMenu { @@ -16,7 +17,7 @@ namespace YimMenu m_IsOpen(false) { Menu::SetupFonts(); - Menu::SetupStyle(); + SetupStyle(); Menu::Init(); Renderer::AddWindowProcedureCallback([this](HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { diff --git a/src/game/frontend/Menu.cpp b/src/game/frontend/Menu.cpp index 55f5e9a0..9193cdb2 100644 --- a/src/game/frontend/Menu.cpp +++ b/src/game/frontend/Menu.cpp @@ -20,11 +20,13 @@ #include "core/filemgr/FileMgr.hpp" #include "core/memory/ModuleMgr.hpp" #include "Onboarding.hpp" +#include "core/frontend/manager/styles/Themes.hpp" namespace YimMenu { void Menu::Init() { + SetupStyle(); // Arguably the only place this file should be edited at for more menus UIManager::AddSubmenu(std::make_shared()); UIManager::AddSubmenu(std::make_shared()); @@ -53,46 +55,6 @@ namespace YimMenu -1); } - void Menu::SetupStyle() - { - ImGuiStyle& style = ImGui::GetStyle(); - - style.Colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f); - style.Colors[ImGuiCol_TextDisabled] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); - - style.Colors[ImGuiCol_WindowBg] = ImVec4(0.08f, 0.08f, 0.09f, 1.00f); - style.Colors[ImGuiCol_ChildBg] = ImVec4(0.10f, 0.10f, 0.12f, 1.00f); - style.Colors[ImGuiCol_PopupBg] = ImVec4(0.07f, 0.07f, 0.09f, 0.95f); - - style.Colors[ImGuiCol_Border] = ImVec4(0.28f, 0.28f, 0.28f, 0.25f); - style.Colors[ImGuiCol_FrameBg] = ImVec4(0.15f, 0.15f, 0.17f, 1.00f); - style.Colors[ImGuiCol_FrameBgHovered] = ImVec4(0.35f, 0.59f, 0.35f, 0.75f); - style.Colors[ImGuiCol_FrameBgActive] = ImVec4(0.47f, 0.75f, 0.47f, 0.85f); - - style.Colors[ImGuiCol_Button] = ImVec4(0.35f, 0.59f, 0.35f, 1.00f); - style.Colors[ImGuiCol_ButtonHovered] = ImVec4(0.40f, 0.65f, 0.40f, 1.00f); - style.Colors[ImGuiCol_ButtonActive] = ImVec4(0.47f, 0.75f, 0.47f, 1.00f); - - style.Colors[ImGuiCol_TitleBg] = ImVec4(0.06f, 0.06f, 0.07f, 1.00f); - style.Colors[ImGuiCol_TitleBgActive] = ImVec4(0.09f, 0.09f, 0.11f, 1.00f); - style.Colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.04f, 0.04f, 0.05f, 1.00f); - - style.Colors[ImGuiCol_Tab] = ImVec4(0.30f, 0.55f, 0.30f, 0.85f); - style.Colors[ImGuiCol_TabHovered] = ImVec4(0.40f, 0.65f, 0.40f, 0.85f); - style.Colors[ImGuiCol_TabActive] = ImVec4(0.47f, 0.75f, 0.47f, 1.00f); - - style.Colors[ImGuiCol_Header] = ImVec4(0.30f, 0.50f, 0.30f, 1.00f); - style.Colors[ImGuiCol_HeaderHovered] = ImVec4(0.40f, 0.65f, 0.40f, 1.00f); - style.Colors[ImGuiCol_HeaderActive] = ImVec4(0.47f, 0.75f, 0.47f, 1.00f); - - style.Colors[ImGuiCol_PlotLines] = ImVec4(0.80f, 0.80f, 0.00f, 0.00f); - style.Colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.85f, 0.00f, 1.00f); - style.Colors[ImGuiCol_PlotHistogram] = ImVec4(0.35f, 0.59f, 0.35f, 1.00f); - style.Colors[ImGuiCol_PlotHistogramHovered] = ImVec4(0.47f, 0.75f, 0.47f, 1.00f); - - style.GrabRounding = style.FrameRounding = style.ChildRounding = style.WindowRounding = 8.0f; - } - static const ImWchar* GetGlyphRangesCyrillicOnly() { static const ImWchar ranges[] = diff --git a/src/game/frontend/Menu.hpp b/src/game/frontend/Menu.hpp index 346e5b98..65ae018e 100644 --- a/src/game/frontend/Menu.hpp +++ b/src/game/frontend/Menu.hpp @@ -4,7 +4,6 @@ namespace YimMenu::Menu { extern void Init(); - extern void SetupStyle(); extern void SetupFonts(); namespace Font diff --git a/src/game/frontend/submenus/Settings.cpp b/src/game/frontend/submenus/Settings.cpp index 23c85b1d..8121aa64 100644 --- a/src/game/frontend/submenus/Settings.cpp +++ b/src/game/frontend/submenus/Settings.cpp @@ -7,6 +7,7 @@ #include "game/frontend/items/Items.hpp" #include "game/frontend/items/DrawHotkey.hpp" #include "game/frontend/submenus/Settings/LuaScripts.hpp" +#include "game/frontend/submenus/Settings/GUISettings.hpp" namespace YimMenu::Submenus { @@ -111,6 +112,7 @@ namespace YimMenu::Submenus AddCategory(std::move(hotkeys)); AddCategory(std::move(gui)); AddCategory(std::move(game)); + AddCategory(DrawGUISettingsMenu()); AddCategory(BuildLuaScriptsMenu()); } } \ No newline at end of file diff --git a/src/game/frontend/submenus/Settings/GUISettings.cpp b/src/game/frontend/submenus/Settings/GUISettings.cpp new file mode 100644 index 00000000..5fda30c8 --- /dev/null +++ b/src/game/frontend/submenus/Settings/GUISettings.cpp @@ -0,0 +1,353 @@ +#include "GUISettings.hpp" +#include "core/commands/ColorCommand.hpp" +#include "core/commands/Command.hpp" +#include "core/commands/FloatCommand.hpp" +#include "core/frontend/manager/styles/Themes.hpp" +#include + +namespace YimMenu +{ + static std::vector> g_ColorCommands; + static std::unordered_map g_RoundingValues; + static std::unordered_map> g_FloatCommands; // Global map for all FloatCommands + static bool g_ColorInit = false, g_RoundingInit = false; + + static const std::string kSettingsFile = [] { + char* path = nullptr; + size_t len = 0; + _dupenv_s(&path, &len, "APPDATA"); + std::string full = std::string(path ? path : "") + "\\YimMenuV2\\themes.json"; + free(path); + return full; + }(); + + static std::string PrettyPrintLabel(const std::string& raw) + { + std::string out = raw; + if (out.size() > 2 && out.compare(out.size() - 2, 2, "_X") == 0) + out.replace(out.size() - 2, 2, " Horizontal"); + else if (out.size() > 2 && out.compare(out.size() - 2, 2, "_Y") == 0) + out.replace(out.size() - 2, 2, " Vertical"); + + std::string spaced; + spaced.reserve(out.size() + 10); + for (size_t i = 0; i < out.size(); ++i) + { + if (i > 0 && isupper(out[i]) && islower(out[i - 1])) + spaced += ' '; + spaced += out[i]; + } + + std::regex uscore_re("_"); + spaced = std::regex_replace(spaced, uscore_re, " "); + + return spaced; + } + + void SyncColorCommandsToStyle() + { + auto& style = ImGui::GetStyle(); + for (int i = 0; i < ImGuiCol_COUNT; i++) + style.Colors[i] = g_ColorCommands[i]->GetState(); + } + + static void SyncRoundingToStyle() + { + auto& s = ImGui::GetStyle(); + for (auto& [k, v] : g_RoundingValues) + if (k == "WindowRounding") + s.WindowRounding = v; + else if (k == "FrameRounding") + s.FrameRounding = v; + else if (k == "GrabRounding") + s.GrabRounding = v; + else if (k == "ScrollbarRounding") + s.ScrollbarRounding = v; + else if (k == "ChildRounding") + s.ChildRounding = v; + else if (k == "PopupRounding") + s.PopupRounding = v; + else if (k == "TabRounding") + s.TabRounding = v; + } + + static void LoadSettings() + { + if (!std::filesystem::exists(kSettingsFile)) + return; + std::ifstream file(kSettingsFile); + nlohmann::json json; + file >> json; + + // Load colors + for (int i = 0; i < ImGuiCol_COUNT; ++i) + if (auto it = json.find(ImGui::GetStyleColorName(i)); it != json.end() && it->is_array()) + g_ColorCommands[i]->SetState(ImVec4((*it)[0], (*it)[1], (*it)[2], (*it)[3])); + + // Load rounding values + for (const char* key : {"WindowRounding", "FrameRounding", "GrabRounding", "ScrollbarRounding", "ChildRounding", "PopupRounding", "TabRounding"}) + if (auto it = json.find(key); it != json.end()) + g_RoundingValues[key] = *it; + + // Load all float command values (except colors and rounding, which are handled) + for (auto& [key, cmd] : g_FloatCommands) + { + if (auto it = json.find(key); it != json.end() && it->is_number()) + { + cmd->SetState(it->get()); + } + } + } + + static void SaveSettings() + { + nlohmann::json json; + + // Save colors + for (int i = 0; i < ImGuiCol_COUNT; ++i) + { + auto c = g_ColorCommands[i]->GetState(); + json[ImGui::GetStyleColorName(i)] = {c.x, c.y, c.z, c.w}; + } + + // Save rounding + for (auto& [k, v] : g_RoundingValues) + json[k] = v; + + // Save floats + for (auto& [k, cmd] : g_FloatCommands) + json[k] = cmd->GetState(); + + std::filesystem::create_directories(std::filesystem::path(kSettingsFile).parent_path()); + std::ofstream(kSettingsFile) << json.dump(4); + } + + void ApplyThemeToImGui() + { + auto& style = ImGui::GetStyle(); + + for (int i = 0; i < ImGuiCol_COUNT; ++i) + style.Colors[i] = g_ColorCommands[i]->GetState(); + + style.WindowRounding = g_RoundingValues["WindowRounding"]; + style.FrameRounding = g_RoundingValues["FrameRounding"]; + style.GrabRounding = g_RoundingValues["GrabRounding"]; + style.ScrollbarRounding = g_RoundingValues["ScrollbarRounding"]; + style.ChildRounding = g_RoundingValues["ChildRounding"]; + style.PopupRounding = g_RoundingValues["PopupRounding"]; + style.TabRounding = g_RoundingValues["TabRounding"]; + } + + + void InitializeColorCommands() + { + if (g_ColorInit) + return; + auto& style = ImGui::GetStyle(); + for (int i = 0; i < ImGuiCol_COUNT; ++i) + g_ColorCommands.emplace_back(std::make_unique( + "ColorCommand." + std::string(ImGui::GetStyleColorName(i)), + ImGui::GetStyleColorName(i), + "Edit color for " + std::string(ImGui::GetStyleColorName(i)), + style.Colors[i])); + + if (!g_RoundingInit) + { + g_RoundingInit = true; + g_RoundingValues = { + {"WindowRounding", style.WindowRounding}, + {"FrameRounding", style.FrameRounding}, + {"GrabRounding", style.GrabRounding}, + {"ScrollbarRounding", style.ScrollbarRounding}, + {"ChildRounding", style.ChildRounding}, + {"PopupRounding", style.PopupRounding}, + {"TabRounding", style.TabRounding}}; + } + + LoadSettings(); + SyncColorCommandsToStyle(); + SyncRoundingToStyle(); + g_ColorInit = true; + } + + static void DrawStyleVec2(const char* label, float& x, float& y, float min, float max) + { + std::string nameX = std::string(label) + "_X"; + std::string nameY = std::string(label) + "_Y"; + + // Use global float commands map + if (!g_FloatCommands.count(nameX)) + g_FloatCommands[nameX] = std::make_unique(nameX.c_str(), nameX.c_str(), "Adjust " + nameX, min, max, x); + if (!g_FloatCommands.count(nameY)) + g_FloatCommands[nameY] = std::make_unique(nameY.c_str(), nameY.c_str(), "Adjust " + nameY, min, max, y); + + float newX = g_FloatCommands[nameX]->GetState(); + float newY = g_FloatCommands[nameY]->GetState(); + + bool changed = false; + changed |= ImGui::SliderFloat(PrettyPrintLabel(nameX).c_str(), &newX, min, max, "%.1f"); + changed |= ImGui::SliderFloat(PrettyPrintLabel(nameY).c_str(), &newY, min, max, "%.1f"); + + if (changed) + { + g_FloatCommands[nameX]->SetState(newX); + g_FloatCommands[nameY]->SetState(newY); + x = newX; + y = newY; + SaveSettings(); + } + } + + static void DrawStyleFloat(const char* label, float& v, float min, float max) + { + std::string name(label); + + if (!g_FloatCommands.count(name)) + g_FloatCommands[name] = std::make_unique(name.c_str(), name.c_str(), "Adjust " + name, min, max, v); + + float newVal = g_FloatCommands[name]->GetState(); + if (ImGui::SliderFloat(PrettyPrintLabel(name).c_str(), &newVal, min, max, "%.1f")) + { + g_FloatCommands[name]->SetState(newVal); + v = newVal; + SaveSettings(); + } + } + + static void DrawColorsTab() + { + bool changed = false; + ImGui::Text("Modify Colors:"); + ImGui::Separator(); + for (int i = 0; i < ImGuiCol_COUNT; ++i) + { + auto& cmd = g_ColorCommands[i]; + auto col = cmd->GetState(); + + if (ImGui::ColorEdit4(PrettyPrintLabel(ImGui::GetStyleColorName(i)).c_str(), (float*)&col)) + { + cmd->SetState(col); + changed = true; + } + } + if (changed) + { + SyncColorCommandsToStyle(); + SaveSettings(); + } + } + + static void DrawRoundingTab() + { + bool changed = false; + ImGui::Text("Adjust Rounding:"); + ImGui::Separator(); + for (auto& [k, v] : g_RoundingValues) + if (ImGui::SliderFloat(PrettyPrintLabel(k).c_str(), &v, 0.0f, 20.0f, "%.1f")) + changed = true; + + if (changed) + { + SyncRoundingToStyle(); + SaveSettings(); + } + } + + static void DrawLayoutTab() + { + auto& s = ImGui::GetStyle(); + ImGui::Text("Layout & Alignment:"); + ImGui::Separator(); + DrawStyleVec2("WindowPadding", s.WindowPadding.x, s.WindowPadding.y, 0.f, 32.f); + DrawStyleVec2("ItemSpacing", s.ItemSpacing.x, s.ItemSpacing.y, 0.f, 32.f); + DrawStyleVec2("ItemInnerSpacing", s.ItemInnerSpacing.x, s.ItemInnerSpacing.y, 0.f, 32.f); + DrawStyleVec2("TouchExtraPadding", s.TouchExtraPadding.x, s.TouchExtraPadding.y, 0.f, 32.f); + DrawStyleVec2("DisplaySafeAreaPadding", s.DisplaySafeAreaPadding.x, s.DisplaySafeAreaPadding.y, 0.f, 32.f); + + DrawStyleFloat("IndentSpacing", s.IndentSpacing, 0.f, 64.f); + DrawStyleFloat("ColumnsMinSpacing", s.ColumnsMinSpacing, 0.f, 64.f); + + DrawStyleVec2("WindowTitleAlign", s.WindowTitleAlign.x, s.WindowTitleAlign.y, 0.f, 1.f); + DrawStyleVec2("ButtonTextAlign", s.ButtonTextAlign.x, s.ButtonTextAlign.y, 0.f, 1.f); + DrawStyleVec2("SelectableTextAlign", s.SelectableTextAlign.x, s.SelectableTextAlign.y, 0.f, 1.f); + } + + static void DrawBorderTab() + { + auto& s = ImGui::GetStyle(); + ImGui::Text("Border Sizes:"); + ImGui::Separator(); + DrawStyleFloat("WindowBorderSize", s.WindowBorderSize, 0.f, 8.f); + DrawStyleFloat("FrameBorderSize", s.FrameBorderSize, 0.f, 8.f); + DrawStyleFloat("TabBorderSize", s.TabBorderSize, 0.f, 8.f); + DrawStyleFloat("PopupBorderSize", s.PopupBorderSize, 0.f, 8.f); + } + + static void DrawGlobalTab() + { + auto& s = ImGui::GetStyle(); + ImGui::Text("Global Settings:"); + ImGui::Separator(); + DrawStyleFloat("GlobalAlpha", s.Alpha, 0.1f, 1.f); + DrawStyleFloat("DisabledAlpha", s.DisabledAlpha, 0.f, 1.f); + DrawStyleFloat("MouseCursorScale", s.MouseCursorScale, 0.5f, 2.f); + DrawStyleFloat("CurveTessellationTol", s.CurveTessellationTol, 0.1f, 10.f); + } + + static void DrawFontTab() + { + ImGuiIO& io = ImGui::GetIO(); + static float scale = io.FontGlobalScale; + ImGui::Text("Font Configuration:"); + ImGui::Separator(); + ImGui::Text("Current Scale: %.2f", io.FontGlobalScale); + ImGui::SliderFloat("Font Scale", &scale, 0.5f, 2.0f, "%.2f"); + if (ImGui::Button("Apply Font Scale")) + io.FontGlobalScale = scale; + } + + std::shared_ptr DrawGUISettingsMenu() + { + InitializeColorCommands(); + auto imGuiCustomStyle = std::make_shared("Customize"); + imGuiCustomStyle->AddItem(std::make_unique([] { + ImGui::Text("ImGui Style Editor"); + ImGui::Separator(); + if (ImGui::BeginTabBar("StyleTabs")) + { + if (ImGui::BeginTabItem("Colors")) + { + DrawColorsTab(); + ImGui::EndTabItem(); + } + if (ImGui::BeginTabItem("Rounding")) + { + DrawRoundingTab(); + ImGui::EndTabItem(); + } + if (ImGui::BeginTabItem("Layout")) + { + DrawLayoutTab(); + ImGui::EndTabItem(); + } + if (ImGui::BeginTabItem("Border")) + { + DrawBorderTab(); + ImGui::EndTabItem(); + } + if (ImGui::BeginTabItem("Global")) + { + DrawGlobalTab(); + ImGui::EndTabItem(); + } + if (ImGui::BeginTabItem("Fonts")) + { + DrawFontTab(); + ImGui::EndTabItem(); + } + ImGui::EndTabBar(); + } + })); + return imGuiCustomStyle; + } +} diff --git a/src/game/frontend/submenus/Settings/GUISettings.hpp b/src/game/frontend/submenus/Settings/GUISettings.hpp new file mode 100644 index 00000000..b9f408b9 --- /dev/null +++ b/src/game/frontend/submenus/Settings/GUISettings.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include "core/frontend/manager/Category.hpp" +#include "game/frontend/items/Items.hpp" +#include + +namespace YimMenu +{ + std::shared_ptr DrawGUISettingsMenu(); + void InitializeColorCommands(); + void SyncColorCommandsToStyle(); + void LoadSettings(); + void SaveSettings(); + void ApplyThemeToImGui(); + static void DrawStyleVec2(const char* label, float& x, float& y, float min, float max); + static void DrawStyleFloat(const char* label, float& v, float min, float max); +}