-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathUIUtils.hpp
More file actions
110 lines (103 loc) · 4.24 KB
/
UIUtils.hpp
File metadata and controls
110 lines (103 loc) · 4.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#pragma once
#include "imgui.h"
#include <unordered_map>
#include <string>
// BackdropStyle defines how the small rectangle behind a control is drawn.
// baseColor/hoverColor use IM_COL32 RGBA, padX/padY expand around the item,
// radius controls corner rounding.
struct BackdropStyle {
ImU32 baseColor;
ImU32 hoverColor;
float padX;
float padY;
float radius;
};
struct Rect { ImVec2 min; ImVec2 max; };
// Compute the rectangle around the next item based on current cursor position
// and ImGui frame height. Does not depend on draw lists (pure computation).
inline Rect ComputeBackdropRect(ImVec2 cursor, float frameH, const BackdropStyle& s) {
Rect r;
r.min = ImVec2(cursor.x - s.padX, cursor.y - s.padY * 0.5f);
r.max = ImVec2(cursor.x + frameH + s.padX, cursor.y + frameH + s.padY * 0.5f);
return r;
}
// Draw a backdrop rectangle behind the next item. Call BEFORE rendering the item.
inline void DrawBackdropForNextItem(const BackdropStyle& s) {
ImDrawList* dl = ImGui::GetWindowDrawList();
if (!dl) return;
ImVec2 cursor = ImGui::GetCursorScreenPos();
float frameH = ImGui::GetFrameHeight() - ImGui::GetStyle().FramePadding.y;
if (frameH < 12.0f) frameH = ImGui::GetFrameHeight();
Rect r = ComputeBackdropRect(cursor, frameH, s);
bool hover = ImGui::IsMouseHoveringRect(r.min, r.max);
ImU32 col = hover ? s.hoverColor : s.baseColor;
dl->AddRectFilled(r.min, r.max, col, s.radius);
}
// Draw a full-row backdrop that covers from the current cursor to the right edge
// of the window's content region. Pads and rounds per style. Use for controls
// that include text labels to ensure left/right coverage.
inline void DrawBackdropRowFull(const BackdropStyle& s) {
ImDrawList* dl = ImGui::GetWindowDrawList();
if (!dl) return;
ImVec2 cursor = ImGui::GetCursorScreenPos();
ImVec2 winPos = ImGui::GetWindowPos();
float full = ImGui::GetContentRegionAvail().x;
float frameH = ImGui::GetFrameHeight() - ImGui::GetStyle().FramePadding.y;
if (frameH < 12.0f) frameH = ImGui::GetFrameHeight();
Rect r = ComputeBackdropRect(cursor, frameH, s);
r.max.x = cursor.x + full + s.padX; // extend to right edge
bool hover = ImGui::IsMouseHoveringRect(r.min, r.max);
ImU32 col = hover ? s.hoverColor : s.baseColor;
dl->AddRectFilled(r.min, r.max, col, s.radius);
}
/**
* @function FeatureCheckbox
* @description Renders a checkbox with animated text color based on activation state.
* @param {const char*} name - Feature display name
* @param {bool*} active - Pointer to current activation status; true = green, false = red
* @returns {bool} true if the checkbox value changed
*/
inline bool FeatureCheckbox(const char* name, bool* active) {
if (!name || !active) return false;
static std::unordered_map<std::string, float> anim;
float& a = anim[std::string(name)];
float target = *active ? 1.0f : 0.0f;
float dt = ImGui::GetIO().DeltaTime;
a += (target - a) * (dt * 12.0f);
if (a < 0.0f) a = 0.0f; if (a > 1.0f) a = 1.0f;
ImVec4 red = ImVec4(1.0f, 0.0f, 0.0f, 1.0f);
ImVec4 green = ImVec4(0.0f, 1.0f, 0.0f, 1.0f);
ImVec4 mix = ImVec4(
red.x + (green.x - red.x) * a,
red.y + (green.y - red.y) * a,
red.z + (green.z - red.z) * a,
1.0f
);
ImGui::PushStyleColor(ImGuiCol_Text, mix);
bool changed = ImGui::Checkbox(name, active);
ImGui::PopStyleColor();
return changed;
}
/**
* @function ComputeFeatureColor
* @description Returns the current animated color for a feature without rendering.
* @param {const char*} name - Feature name key
* @param {bool} active - Activation state
* @returns {ImVec4} RGBA color
*/
inline ImVec4 ComputeFeatureColor(const char* name, bool active) {
static std::unordered_map<std::string, float> anim;
float& a = anim[std::string(name ? name : "__invalid__")];
float target = active ? 1.0f : 0.0f;
float dt = ImGui::GetIO().DeltaTime;
a += (target - a) * (dt * 12.0f);
if (a < 0.0f) a = 0.0f; if (a > 1.0f) a = 1.0f;
ImVec4 red = ImVec4(1.0f, 0.0f, 0.0f, 1.0f);
ImVec4 green = ImVec4(0.0f, 1.0f, 0.0f, 1.0f);
return ImVec4(
red.x + (green.x - red.x) * a,
red.y + (green.y - red.y) * a,
red.z + (green.z - red.z) * a,
1.0f
);
}