Skip to content

Commit c4849db

Browse files
authored
(UI) Themes, Customization, Etc. (#597)
* (UI) Modular Theme - Added Modular Theme - Moved SetupStyle function to Themes.cpp for future impl - Ensured all themes use proper colore using ImGui::GetColorU32 to pull colors used in SetupStyle() * (UI) Small change * (UI) Implemented Color/Transparency/Rounding for all ImGui Elements. - Adds a file (GUISettings.json) to the appdata which saves/loads the custom colors, falls back to default if the file does not exist. * (UI) Added more customization abilities - This adds Layout, Borders and Global options for ImGui customization - Fixed some mismatched colors on buttons * (UI) Altered category name * (UI) Added more ImGui customization tabs - Moved default theme to DefaultStyle function * (UI) Fixed Exceptions in console thanks to Mr-X * small fix * (Fix) Font scaling - Removed rebuild fonts, useless for now * Added Helper Functions to utilize FloatCommand and minimize a bulky list Added PrettyPrintLabel to automatically print the slider labels accordingly * Ensured all settings save to GUISettings.json * UI backend refactors * Removed unnecessary includes already included in common.hpp
1 parent 2f7fbc4 commit c4849db

16 files changed

Lines changed: 673 additions & 119 deletions

File tree

src/core/commands/ColorCommand.hpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#pragma once
22
#include "Command.hpp"
3-
#include "imgui.h"
43

54
namespace YimMenu
65
{
@@ -9,14 +8,14 @@ namespace YimMenu
98
protected:
109
virtual void OnChange() {};
1110
virtual void OnCall() override;
12-
virtual void SaveState(nlohmann::json& value) override;
13-
virtual void LoadState(nlohmann::json& value) override;
1411

1512
ImVec4 m_State = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
1613

1714
public:
1815
ColorCommand(std::string name, std::string label, std::string description, ImVec4 color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
1916
ImVec4 GetState();
2017
void SetState(ImVec4 state);
18+
virtual void SaveState(nlohmann::json& value) override;
19+
virtual void LoadState(nlohmann::json& value) override;
2120
};
2221
}

src/core/commands/Command.hpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,15 @@ namespace YimMenu
99
class Command
1010
{
1111
private:
12-
std::string m_Name;
13-
std::string m_Label;
14-
std::string m_Description;
15-
joaat_t m_Hash;
16-
1712
int m_NumArgs = 0; // TODO: currently unused
1813

1914
protected:
2015
virtual void OnCall() = 0;
2116
void MarkDirty();
17+
std::string m_Name;
18+
std::string m_Label;
19+
std::string m_Description;
20+
joaat_t m_Hash;
2221

2322
public:
2423
Command(std::string name, std::string label, std::string description, int num_args = 0);

src/core/frontend/manager/UIManager.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ namespace YimMenu::Features
99
{0, "Classic"},
1010
{1, "Modern"},
1111
{2, "Modern (Vertical)"},
12+
{3, "Modern (Modular)"},
1213
};
1314

1415
// Expose as global reference so other code can use it
@@ -51,6 +52,9 @@ namespace YimMenu
5152
case UITheme::ModernV:
5253
RenderModernVTheme();
5354
break;
55+
case UITheme::Modular:
56+
RenderModularTheme();
57+
break;
5458
default:
5559
RenderClassicTheme(); // Default theme
5660
break;

src/core/frontend/manager/UIManager.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ namespace YimMenu
1111
Classic = 0,
1212
Modern,
1313
ModernV,
14+
Modular,
1415
};
1516

1617
class UIManager

src/core/frontend/manager/styles/Classic/Classic.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
#include "game/pointers/Pointers.hpp"
22
#include "game/frontend/Menu.hpp"
33
#include "core/frontend/manager/UIManager.hpp"
4+
#include "game/frontend/submenus/Settings/GUISettings.hpp"
45

56
namespace YimMenu
67
{
78
void RenderClassicTheme()
89
{
10+
YimMenu::SyncColorCommandsToStyle();
11+
912
float windowWidth = *YimMenu::Pointers.ScreenResX / 2.5f;
1013
float centerX = (*YimMenu::Pointers.ScreenResX - windowWidth) / 2.0f;
1114
float centerY = *YimMenu::Pointers.ScreenResY / 5.0f;

src/core/frontend/manager/styles/Modern/Modern.cpp

Lines changed: 27 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
#include "game/pointers/Pointers.hpp"
22
#include "game/frontend/Menu.hpp"
33
#include "core/frontend/manager/UIManager.hpp"
4+
#include "game/frontend/submenus/Settings/GUISettings.hpp"
45

56
namespace YimMenu
67
{
78
void RenderModernTheme()
89
{
10+
YimMenu::SyncColorCommandsToStyle();
11+
912
ImGuiIO& io = ImGui::GetIO();
1013
ImDrawList* drawList = ImGui::GetBackgroundDrawList();
1114

@@ -26,6 +29,8 @@ namespace YimMenu
2629
ImGui::Begin("##BubbleInputWindow", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoBringToFrontOnFocus);
2730

2831
const auto& submenus = YimMenu::UIManager::GetSubmenus();
32+
auto activeSubmenu = YimMenu::UIManager::GetActiveSubmenu();
33+
2934
for (size_t i = 0; i < submenus.size(); ++i)
3035
{
3136
auto& submenu = submenus[i];
@@ -35,62 +40,54 @@ namespace YimMenu
3540
ImGui::SetCursorScreenPos(bubblePos);
3641
ImGui::PushID(static_cast<int>(i));
3742

38-
ImVec2 bgPos(center.x - bgSize / 2.0f, center.y - bgSize / 2.0f);
39-
drawList->AddRectFilled(bgPos, ImVec2(bgPos.x + bgSize, bgPos.y + bgSize), IM_COL32(10, 10, 10, 255), rounding);
40-
drawList->AddRect(bgPos, ImVec2(bgPos.x + bgSize, bgPos.y + bgSize), IM_COL32(192, 192, 192, 32), rounding, ImDrawFlags_None, 1.0f);
41-
42-
ImU32 bubbleColor = IM_COL32(25, 25, 31, 255);
43-
ImU32 hoverColor = IM_COL32(46, 46, 51, 255);
4443
ImGui::InvisibleButton("##Bubble", ImVec2(bubbleSize, bubbleSize));
4544
bool hovered = ImGui::IsItemHovered();
4645
bool clicked = ImGui::IsItemClicked();
4746

48-
drawList->AddRectFilled(bubblePos, ImVec2(bubblePos.x + bubbleSize, bubblePos.y + bubbleSize), hovered ? hoverColor : bubbleColor, rounding);
49-
drawList->AddRect(bubblePos, ImVec2(bubblePos.x + bubbleSize, bubblePos.y + bubbleSize), IM_COL32(192, 192, 192, 16), rounding, ImDrawFlags_None, 1.0f);
50-
51-
auto activeSubmenu = YimMenu::UIManager::GetActiveSubmenu();
52-
5347
if (clicked)
5448
{
5549
if (submenu == activeSubmenu)
56-
{
5750
YimMenu::UIManager::SetShowContentWindow(!YimMenu::UIManager::ShowingContentWindow());
58-
}
5951
else
6052
{
6153
YimMenu::UIManager::SetActiveSubmenu(submenu);
6254
YimMenu::UIManager::SetShowContentWindow(true);
6355
}
6456
}
6557

66-
ImU32 defaultIconColor = IM_COL32(255, 255, 255, 255);
67-
ImU32 activeIconColor = IM_COL32(46, 204, 113, 255);
68-
ImU32 hoveredIconColor = IM_COL32(36, 174, 93, 255);
69-
ImU32 iconColor = submenu == activeSubmenu ? activeIconColor : (hovered ? hoveredIconColor : defaultIconColor);
58+
// Colors
59+
ImU32 buttonColor = ImGui::GetColorU32(ImGuiCol_Button);
60+
ImU32 hoverColor = ImGui::GetColorU32(ImGuiCol_ButtonHovered);
61+
ImU32 activeColor = ImGui::GetColorU32(ImGuiCol_ButtonActive);
62+
ImU32 borderColor = ImGui::GetColorU32(ImGuiCol_Border);
63+
ImU32 iconColor = ImGui::GetColorU32(ImGuiCol_Text);
64+
65+
ImU32 fillColor = (submenu == activeSubmenu) ? activeColor : (hovered ? hoverColor : buttonColor);
7066

67+
// Bubble background and border
68+
drawList->AddRectFilled(bubblePos, bubblePos + ImVec2(bubbleSize, bubbleSize), fillColor, rounding);
69+
drawList->AddRect(bubblePos, bubblePos + ImVec2(bubbleSize, bubbleSize), borderColor, rounding);
70+
71+
// Icon (text color only)
7172
ImGui::PushFont(YimMenu::Menu::Font::g_AwesomeFont);
7273
ImVec2 iconSize = ImGui::CalcTextSize(submenu->m_Icon.c_str());
7374
ImVec2 iconPos(center.x - iconSize.x / 2, center.y - iconSize.y / 2);
7475
drawList->AddText(YimMenu::Menu::Font::g_AwesomeFont, 0.0f, iconPos, iconColor, submenu->m_Icon.c_str());
7576
ImGui::PopFont();
7677

77-
ImU32 defaultTextColor = IM_COL32(255, 255, 255, 255);
78-
ImU32 activeTextColor = IM_COL32(46, 204, 113, 255);
79-
ImU32 hoveredTextColor = IM_COL32(36, 174, 93, 255);
80-
ImU32 textColor = submenu == activeSubmenu ? activeTextColor : (hovered ? hoveredTextColor : defaultTextColor);
81-
78+
// Label
8279
ImVec2 labelSize = ImGui::CalcTextSize(submenu->m_Name.c_str());
8380
ImVec2 labelPos(center.x - labelSize.x / 2, bubblePos.y + bubbleSize + 15.0f);
8481
ImVec2 bgMin = labelPos - ImVec2(6, 2);
8582
ImVec2 bgMax = labelPos + labelSize + ImVec2(6, 2);
86-
87-
drawList->AddRectFilled(bgMin, bgMax, IM_COL32(26, 26, 31, 120));
88-
drawList->AddRect(bgMin, bgMax, IM_COL32(192, 192, 192, 16), 4.0f);
89-
drawList->AddText(labelPos, textColor, submenu->m_Name.c_str());
83+
drawList->AddRectFilled(bgMin, bgMax, ImGui::GetColorU32(ImGuiCol_ChildBg));
84+
drawList->AddRect(bgMin, bgMax, borderColor, 4.0f);
85+
drawList->AddText(labelPos, iconColor, submenu->m_Name.c_str());
9086

9187
ImGui::PopID();
9288
}
9389

90+
// Drag zone
9491
ImVec2 dragZoneMin = ImVec2(basePos.x, basePos.y - 20);
9592
ImVec2 dragZoneMax = ImVec2(basePos.x + bubbleSpacing * submenus.size(), basePos.y + bubbleSize);
9693
ImGui::SetCursorScreenPos(dragZoneMin);
@@ -106,8 +103,7 @@ namespace YimMenu
106103
else
107104
{
108105
ImVec2 delta = io.MousePos - dragStart;
109-
basePosOffset.x += delta.x;
110-
basePosOffset.y += delta.y;
106+
basePosOffset += delta;
111107
dragStart = io.MousePos;
112108
}
113109
}
@@ -116,10 +112,9 @@ namespace YimMenu
116112
dragging = false;
117113
}
118114

119-
ImGui::End();
120-
121-
auto activeSubmenu = YimMenu::UIManager::GetActiveSubmenu();
115+
ImGui::End(); // ##BubbleInputWindow
122116

117+
// Content window
123118
if (YimMenu::UIManager::ShowingContentWindow() && activeSubmenu)
124119
{
125120
float windowWidth = *YimMenu::Pointers.ScreenResX / 2.5f;
@@ -129,14 +124,13 @@ namespace YimMenu
129124

130125
ImGui::SetNextWindowSize(windowSize, ImGuiCond_FirstUseEver);
131126
ImGui::SetNextWindowPos(ImVec2(centerX, centerY), ImGuiCond_FirstUseEver);
127+
132128
ImGuiWindowFlags flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse;
133129

134130
if (ImGui::Begin("##Categories&Content", nullptr, flags))
135131
{
136132
if (ImGui::BeginChild("##categorySelectors", ImVec2(0, 60), true))
137-
{
138133
activeSubmenu->DrawCategorySelectors();
139-
}
140134
ImGui::EndChild();
141135

142136
if (ImGui::BeginChild("##options", ImVec2(0, 0), true))

src/core/frontend/manager/styles/ModernVertical/ModernVertical.cpp

Lines changed: 29 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
#include "game/pointers/Pointers.hpp"
22
#include "game/frontend/Menu.hpp"
33
#include "core/frontend/manager/UIManager.hpp"
4+
#include "game/frontend/submenus/Settings/GUISettings.hpp"
45

56
namespace YimMenu
67
{
78
void RenderModernVTheme()
89
{
10+
YimMenu::SyncColorCommandsToStyle();
11+
912
ImGuiIO& io = ImGui::GetIO();
1013
ImDrawList* drawList = ImGui::GetBackgroundDrawList();
1114

@@ -26,72 +29,68 @@ namespace YimMenu
2629
ImGui::Begin("##BubbleInputWindow", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoBringToFrontOnFocus);
2730

2831
const auto& submenus = YimMenu::UIManager::GetSubmenus();
32+
auto activeSubmenu = YimMenu::UIManager::GetActiveSubmenu();
33+
2934
for (size_t i = 0; i < submenus.size(); ++i)
3035
{
3136
auto& submenu = submenus[i];
32-
// Changed horizontal to vertical:
37+
3338
ImVec2 bubblePos(basePos.x, basePos.y + i * bubbleSpacing + 2);
3439
ImVec2 center(bubblePos.x + bubbleSize / 2.0f, bubblePos.y + bubbleSize / 2.0f);
3540

3641
ImGui::SetCursorScreenPos(bubblePos);
3742
ImGui::PushID(static_cast<int>(i));
3843

39-
ImVec2 bgPos(center.x - bgSize / 2.0f, center.y - bgSize / 2.0f);
40-
drawList->AddRectFilled(bgPos, ImVec2(bgPos.x + bgSize, bgPos.y + bgSize), IM_COL32(10, 10, 10, 255), rounding);
41-
drawList->AddRect(bgPos, ImVec2(bgPos.x + bgSize, bgPos.y + bgSize), IM_COL32(192, 192, 192, 32), rounding, ImDrawFlags_None, 1.0f);
42-
43-
ImU32 bubbleColor = IM_COL32(25, 25, 31, 255);
44-
ImU32 hoverColor = IM_COL32(46, 46, 51, 255);
44+
// Invisible button logic
4545
ImGui::InvisibleButton("##Bubble", ImVec2(bubbleSize, bubbleSize));
4646
bool hovered = ImGui::IsItemHovered();
4747
bool clicked = ImGui::IsItemClicked();
4848

49-
drawList->AddRectFilled(bubblePos, ImVec2(bubblePos.x + bubbleSize, bubblePos.y + bubbleSize), hovered ? hoverColor : bubbleColor, rounding);
50-
drawList->AddRect(bubblePos, ImVec2(bubblePos.x + bubbleSize, bubblePos.y + bubbleSize), IM_COL32(192, 192, 192, 16), rounding, ImDrawFlags_None, 1.0f);
51-
52-
auto activeSubmenu = YimMenu::UIManager::GetActiveSubmenu();
53-
5449
if (clicked)
5550
{
5651
if (submenu == activeSubmenu)
57-
{
5852
YimMenu::UIManager::SetShowContentWindow(!YimMenu::UIManager::ShowingContentWindow());
59-
}
6053
else
6154
{
6255
YimMenu::UIManager::SetActiveSubmenu(submenu);
6356
YimMenu::UIManager::SetShowContentWindow(true);
6457
}
6558
}
6659

67-
ImU32 defaultIconColor = IM_COL32(255, 255, 255, 255);
68-
ImU32 activeIconColor = IM_COL32(46, 204, 113, 255);
69-
ImU32 hoveredIconColor = IM_COL32(36, 174, 93, 255);
70-
ImU32 iconColor = submenu == activeSubmenu ? activeIconColor : (hovered ? hoveredIconColor : defaultIconColor);
60+
// Colors from ImGui style
61+
ImU32 buttonColor = ImGui::GetColorU32(ImGuiCol_Button);
62+
ImU32 hoverColor = ImGui::GetColorU32(ImGuiCol_ButtonHovered);
63+
ImU32 activeColor = ImGui::GetColorU32(ImGuiCol_ButtonActive);
64+
ImU32 borderColor = ImGui::GetColorU32(ImGuiCol_Border);
65+
ImU32 iconColor = ImGui::GetColorU32(ImGuiCol_Text);
7166

67+
// Final fill color
68+
ImU32 fillColor = (submenu == activeSubmenu) ? activeColor : (hovered ? hoverColor : buttonColor);
69+
70+
// Draw filled button bubble
71+
drawList->AddRectFilled(bubblePos, bubblePos + ImVec2(bubbleSize, bubbleSize), fillColor, rounding);
72+
drawList->AddRect(bubblePos, bubblePos + ImVec2(bubbleSize, bubbleSize), borderColor, rounding, ImDrawFlags_None, 1.0f);
73+
74+
// Draw icon centered (text color always)
7275
ImGui::PushFont(YimMenu::Menu::Font::g_AwesomeFont);
7376
ImVec2 iconSize = ImGui::CalcTextSize(submenu->m_Icon.c_str());
7477
ImVec2 iconPos(center.x - iconSize.x / 2, center.y - iconSize.y / 2);
7578
drawList->AddText(YimMenu::Menu::Font::g_AwesomeFont, 0.0f, iconPos, iconColor, submenu->m_Icon.c_str());
7679
ImGui::PopFont();
7780

78-
ImU32 defaultTextColor = IM_COL32(255, 255, 255, 255);
79-
ImU32 activeTextColor = IM_COL32(46, 204, 113, 255);
80-
ImU32 hoveredTextColor = IM_COL32(36, 174, 93, 255);
81-
ImU32 textColor = submenu == activeSubmenu ? activeTextColor : (hovered ? hoveredTextColor : defaultTextColor);
82-
81+
// Draw label below bubble
8382
ImVec2 labelSize = ImGui::CalcTextSize(submenu->m_Name.c_str());
8483
ImVec2 labelPos(center.x - labelSize.x / 2, bubblePos.y + bubbleSize + 15.0f);
8584
ImVec2 bgMin = labelPos - ImVec2(6, 2);
8685
ImVec2 bgMax = labelPos + labelSize + ImVec2(6, 2);
87-
88-
drawList->AddRectFilled(bgMin, bgMax, IM_COL32(26, 26, 31, 120));
89-
drawList->AddRect(bgMin, bgMax, IM_COL32(192, 192, 192, 16), 4.0f);
90-
drawList->AddText(labelPos, textColor, submenu->m_Name.c_str());
86+
drawList->AddRectFilled(bgMin, bgMax, ImGui::GetColorU32(ImGuiCol_ChildBg));
87+
drawList->AddRect(bgMin, bgMax, borderColor, 4.0f);
88+
drawList->AddText(labelPos, iconColor, submenu->m_Name.c_str());
9189

9290
ImGui::PopID();
9391
}
9492

93+
// Drag zone (optional repositioning)
9594
ImVec2 dragZoneMin = ImVec2(basePos.x + bubbleSize + 10, basePos.y);
9695
ImVec2 dragZoneMax = ImVec2(basePos.x + bubbleSize + 10 + bubbleSpacing, basePos.y + bubbleSpacing * submenus.size());
9796
ImGui::SetCursorScreenPos(dragZoneMin);
@@ -107,8 +106,7 @@ namespace YimMenu
107106
else
108107
{
109108
ImVec2 delta = io.MousePos - dragStart;
110-
basePosOffset.x += delta.x;
111-
basePosOffset.y += delta.y;
109+
basePosOffset += delta;
112110
dragStart = io.MousePos;
113111
}
114112
}
@@ -119,8 +117,7 @@ namespace YimMenu
119117

120118
ImGui::End();
121119

122-
auto activeSubmenu = YimMenu::UIManager::GetActiveSubmenu();
123-
120+
// Content window
124121
if (YimMenu::UIManager::ShowingContentWindow() && activeSubmenu)
125122
{
126123
float windowWidth = *YimMenu::Pointers.ScreenResX / 2.5f;
@@ -130,14 +127,11 @@ namespace YimMenu
130127

131128
ImGui::SetNextWindowSize(windowSize, ImGuiCond_FirstUseEver);
132129
ImGui::SetNextWindowPos(ImVec2(centerX, centerY), ImGuiCond_FirstUseEver);
133-
ImGuiWindowFlags flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse;
134130

135-
if (ImGui::Begin("##Categories&Content", nullptr, flags))
131+
if (ImGui::Begin("##Categories&Content", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse))
136132
{
137133
if (ImGui::BeginChild("##categorySelectors", ImVec2(0, 60), true))
138-
{
139134
activeSubmenu->DrawCategorySelectors();
140-
}
141135
ImGui::EndChild();
142136

143137
if (ImGui::BeginChild("##options", ImVec2(0, 0), true))

0 commit comments

Comments
 (0)