yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
background_renderer.cc
Go to the documentation of this file.
2
3#include <algorithm>
4#include <cmath>
5
8#include "imgui/imgui.h"
9
10#ifndef M_PI
11#define M_PI 3.14159265358979323846
12#endif
13
14namespace yaze {
15namespace gui {
16
17// BackgroundRenderer Implementation
19 static BackgroundRenderer instance;
20 return instance;
21}
22
24 const ImVec2& window_pos,
25 const ImVec2& window_size,
26 const Color& theme_color) {
27 if (!draw_list)
28 return;
29
30 UpdateAnimation(TimingManager::Get().GetDeltaTime());
31
32 // Get current theme colors
33 auto& theme_manager = ThemeManager::Get();
34 auto current_theme = theme_manager.GetCurrentTheme();
35
36 // Create a subtle tinted background
37 Color bg_tint = {current_theme.background.red * 1.1f,
38 current_theme.background.green * 1.1f,
39 current_theme.background.blue * 1.1f, 0.3f};
40
41 ImU32 bg_color =
42 ImGui::ColorConvertFloat4ToU32(ConvertColorToImVec4(bg_tint));
43 draw_list->AddRectFilled(
44 window_pos,
45 ImVec2(window_pos.x + window_size.x, window_pos.y + window_size.y),
46 bg_color);
47
48 // Render the grid if enabled
49 if (grid_settings_.grid_size > 0) {
50 RenderGridBackground(draw_list, window_pos, window_size, theme_color);
51 }
52
53 // Add subtle corner accents
54 if (current_theme.enable_glow_effects) {
55 float corner_size = 60.0f;
56 Color accent_faded = current_theme.accent;
57 accent_faded.alpha = 0.1f + 0.05f * sinf(animation_time_ * 2.0f);
58
59 ImU32 corner_color =
60 ImGui::ColorConvertFloat4ToU32(ConvertColorToImVec4(accent_faded));
61
62 // Top-left corner
63 draw_list->AddRectFilledMultiColor(
64 window_pos,
65 ImVec2(window_pos.x + corner_size, window_pos.y + corner_size),
66 corner_color, IM_COL32(0, 0, 0, 0), IM_COL32(0, 0, 0, 0), corner_color);
67
68 // Bottom-right corner
69 draw_list->AddRectFilledMultiColor(
70 ImVec2(window_pos.x + window_size.x - corner_size,
71 window_pos.y + window_size.y - corner_size),
72 ImVec2(window_pos.x + window_size.x, window_pos.y + window_size.y),
73 IM_COL32(0, 0, 0, 0), corner_color, corner_color, IM_COL32(0, 0, 0, 0));
74 }
75}
76
78 const ImVec2& window_pos,
79 const ImVec2& window_size,
80 const Color& grid_color) {
81 if (!draw_list || grid_settings_.grid_size <= 0)
82 return;
83
84 // Grid parameters with optional animation
85 float grid_size = grid_settings_.grid_size;
86 float offset_x = 0.0f;
87 float offset_y = 0.0f;
88
89 // Apply animation if enabled
91 float animation_offset =
93 offset_x = fmodf(animation_offset, grid_size);
94 offset_y = fmodf(animation_offset * 0.7f,
95 grid_size); // Different speed for interesting effect
96 }
97
98 // Window center for radial calculations
99 ImVec2 center = ImVec2(window_pos.x + window_size.x * 0.5f,
100 window_pos.y + window_size.y * 0.5f);
101 float max_distance =
102 sqrtf(window_size.x * window_size.x + window_size.y * window_size.y) *
103 0.5f;
104
105 // Apply breathing effect to color if enabled
106 Color themed_grid_color = grid_color;
107 themed_grid_color.alpha = grid_settings_.opacity;
108
110 float breathing_factor =
113 themed_grid_color.red =
114 std::min(1.0f, themed_grid_color.red * breathing_factor);
115 themed_grid_color.green =
116 std::min(1.0f, themed_grid_color.green * breathing_factor);
117 themed_grid_color.blue =
118 std::min(1.0f, themed_grid_color.blue * breathing_factor);
119 }
120
122 // Render grid as dots
123 for (float x = window_pos.x - offset_x;
124 x < window_pos.x + window_size.x + grid_size; x += grid_size) {
125 for (float y = window_pos.y - offset_y;
126 y < window_pos.y + window_size.y + grid_size; y += grid_size) {
127 ImVec2 dot_pos(x, y);
128
129 // Calculate radial fade
130 float fade_factor = 1.0f;
132 float distance =
133 sqrtf((dot_pos.x - center.x) * (dot_pos.x - center.x) +
134 (dot_pos.y - center.y) * (dot_pos.y - center.y));
135 fade_factor =
136 1.0f - std::min(distance / grid_settings_.fade_distance, 1.0f);
137 fade_factor =
138 fade_factor * fade_factor; // Square for smoother falloff
139 }
140
141 if (fade_factor > 0.01f) {
142 ImU32 dot_color = BlendColorWithFade(themed_grid_color, fade_factor);
143 DrawGridDot(draw_list, dot_pos, dot_color, grid_settings_.dot_size);
144 }
145 }
146 }
147 } else {
148 // Render grid as lines
149 // Vertical lines
150 for (float x = window_pos.x - offset_x;
151 x < window_pos.x + window_size.x + grid_size; x += grid_size) {
152 ImVec2 line_start(x, window_pos.y);
153 ImVec2 line_end(x, window_pos.y + window_size.y);
154
155 // Calculate average fade for this line
156 float avg_fade = 0.0f;
158 for (float y = window_pos.y; y < window_pos.y + window_size.y;
159 y += grid_size * 0.5f) {
160 float distance = sqrtf((x - center.x) * (x - center.x) +
161 (y - center.y) * (y - center.y));
162 float fade =
163 1.0f - std::min(distance / grid_settings_.fade_distance, 1.0f);
164 avg_fade += fade * fade;
165 }
166 avg_fade /= (window_size.y / (grid_size * 0.5f));
167 } else {
168 avg_fade = 1.0f;
169 }
170
171 if (avg_fade > 0.01f) {
172 ImU32 line_color = BlendColorWithFade(themed_grid_color, avg_fade);
173 DrawGridLine(draw_list, line_start, line_end, line_color,
175 }
176 }
177
178 // Horizontal lines
179 for (float y = window_pos.y - offset_y;
180 y < window_pos.y + window_size.y + grid_size; y += grid_size) {
181 ImVec2 line_start(window_pos.x, y);
182 ImVec2 line_end(window_pos.x + window_size.x, y);
183
184 // Calculate average fade for this line
185 float avg_fade = 0.0f;
187 for (float x = window_pos.x; x < window_pos.x + window_size.x;
188 x += grid_size * 0.5f) {
189 float distance = sqrtf((x - center.x) * (x - center.x) +
190 (y - center.y) * (y - center.y));
191 float fade =
192 1.0f - std::min(distance / grid_settings_.fade_distance, 1.0f);
193 avg_fade += fade * fade;
194 }
195 avg_fade /= (window_size.x / (grid_size * 0.5f));
196 } else {
197 avg_fade = 1.0f;
198 }
199
200 if (avg_fade > 0.01f) {
201 ImU32 line_color = BlendColorWithFade(themed_grid_color, avg_fade);
202 DrawGridLine(draw_list, line_start, line_end, line_color,
204 }
205 }
206 }
207}
208
210 const ImVec2& center,
211 float radius,
212 const Color& inner_color,
213 const Color& outer_color) {
214 if (!draw_list)
215 return;
216
217 const int segments = 32;
218 const int rings = 8;
219
220 for (int ring = 0; ring < rings; ++ring) {
221 float ring_radius = radius * (ring + 1) / rings;
222 float inner_ring_radius = radius * ring / rings;
223
224 // Interpolate colors for this ring
225 float t = static_cast<float>(ring) / rings;
226 Color ring_color = {inner_color.red * (1.0f - t) + outer_color.red * t,
227 inner_color.green * (1.0f - t) + outer_color.green * t,
228 inner_color.blue * (1.0f - t) + outer_color.blue * t,
229 inner_color.alpha * (1.0f - t) + outer_color.alpha * t};
230
231 ImU32 color =
232 ImGui::ColorConvertFloat4ToU32(ConvertColorToImVec4(ring_color));
233
234 if (ring == 0) {
235 // Center circle
236 draw_list->AddCircleFilled(center, ring_radius, color, segments);
237 } else {
238 // Ring
239 for (int i = 0; i < segments; ++i) {
240 float angle1 = (2.0f * M_PI * i) / segments;
241 float angle2 = (2.0f * M_PI * (i + 1)) / segments;
242
243 ImVec2 p1_inner = ImVec2(center.x + cosf(angle1) * inner_ring_radius,
244 center.y + sinf(angle1) * inner_ring_radius);
245 ImVec2 p2_inner = ImVec2(center.x + cosf(angle2) * inner_ring_radius,
246 center.y + sinf(angle2) * inner_ring_radius);
247 ImVec2 p1_outer = ImVec2(center.x + cosf(angle1) * ring_radius,
248 center.y + sinf(angle1) * ring_radius);
249 ImVec2 p2_outer = ImVec2(center.x + cosf(angle2) * ring_radius,
250 center.y + sinf(angle2) * ring_radius);
251
252 draw_list->AddQuadFilled(p1_inner, p2_inner, p2_outer, p1_outer, color);
253 }
254 }
255 }
256}
257
260 animation_time_ += delta_time;
261 }
262}
263
265 const Color& background_color) {
266 // Create a grid color that's a subtle blend of the theme's primary and
267 // background
269 (primary_color.red * 0.3f + background_color.red * 0.7f),
270 (primary_color.green * 0.3f + background_color.green * 0.7f),
271 (primary_color.blue * 0.3f + background_color.blue * 0.7f),
273}
274
276 if (ImGui::CollapsingHeader("Background Grid Settings")) {
277 ImGui::Indent();
278
279 ImGui::SliderFloat("Grid Size", &grid_settings_.grid_size, 8.0f, 128.0f,
280 "%.0f px");
281 ImGui::SliderFloat("Line Thickness", &grid_settings_.line_thickness, 0.5f,
282 3.0f, "%.1f px");
283 ImGui::SliderFloat("Opacity", &grid_settings_.opacity, 0.01f, 0.3f, "%.3f");
284 ImGui::SliderFloat("Fade Distance", &grid_settings_.fade_distance, 50.0f,
285 500.0f, "%.0f px");
286
287 ImGui::Separator();
288 ImGui::Text("Visual Effects:");
289 ImGui::Checkbox("Enable Animation", &grid_settings_.enable_animation);
290 ImGui::SameLine();
291 if (ImGui::IsItemHovered()) {
292 ImGui::SetTooltip("Makes the grid move slowly across the screen");
293 }
294
295 ImGui::Checkbox("Color Breathing", &grid_settings_.enable_breathing);
296 if (ImGui::IsItemHovered()) {
297 ImGui::SetTooltip("Grid color pulses with a breathing effect");
298 }
299
300 ImGui::Checkbox("Radial Fade", &grid_settings_.radial_fade);
301 ImGui::Checkbox("Use Dots Instead of Lines", &grid_settings_.enable_dots);
302
303 // Animation settings (only show if animation is enabled)
305 ImGui::Indent();
306 ImGui::SliderFloat("Animation Speed", &grid_settings_.animation_speed,
307 0.1f, 3.0f, "%.1fx");
308 ImGui::Unindent();
309 }
310
311 // Breathing settings (only show if breathing is enabled)
313 ImGui::Indent();
314 ImGui::SliderFloat("Breathing Speed", &grid_settings_.breathing_speed,
315 0.5f, 3.0f, "%.1fx");
316 ImGui::SliderFloat("Breathing Intensity",
318 "%.1f");
319 ImGui::Unindent();
320 }
321
323 ImGui::SliderFloat("Dot Size", &grid_settings_.dot_size, 1.0f, 8.0f,
324 "%.1f px");
325 }
326
327 // Preview
328 ImGui::Spacing();
329 ImGui::Text("Preview:");
330 ImVec2 preview_size(200, 100);
331 ImVec2 preview_pos = ImGui::GetCursorScreenPos();
332
333 ImDrawList* preview_draw_list = ImGui::GetWindowDrawList();
334 auto& theme_manager = ThemeManager::Get();
335 auto theme_color = theme_manager.GetCurrentTheme().primary;
336
337 // Draw preview background
338 preview_draw_list->AddRectFilled(
339 preview_pos,
340 ImVec2(preview_pos.x + preview_size.x, preview_pos.y + preview_size.y),
341 IM_COL32(30, 30, 30, 255));
342
343 // Draw preview grid
344 RenderGridBackground(preview_draw_list, preview_pos, preview_size,
345 theme_color);
346
347 // Advance cursor
348 ImGui::Dummy(preview_size);
349
350 ImGui::Unindent();
351 }
352}
353
355 const ImVec2& center,
356 float max_distance) const {
357 float distance = sqrtf((pos.x - center.x) * (pos.x - center.x) +
358 (pos.y - center.y) * (pos.y - center.y));
359 float fade = 1.0f - std::min(distance / max_distance, 1.0f);
360 return fade * fade; // Square for smoother falloff
361}
362
364 float fade_factor) const {
365 Color faded_color = {base_color.red, base_color.green, base_color.blue,
366 base_color.alpha * fade_factor};
367 return ImGui::ColorConvertFloat4ToU32(ConvertColorToImVec4(faded_color));
368}
369
370void BackgroundRenderer::DrawGridLine(ImDrawList* draw_list,
371 const ImVec2& start, const ImVec2& end,
372 ImU32 color, float thickness) const {
373 draw_list->AddLine(start, end, color, thickness);
374}
375
376void BackgroundRenderer::DrawGridDot(ImDrawList* draw_list, const ImVec2& pos,
377 ImU32 color, float size) const {
378 draw_list->AddCircleFilled(pos, size, color);
379}
380
381// DockSpaceRenderer Implementation
387
389 const ImVec2& size,
390 ImGuiDockNodeFlags flags) {
391 // Store window info
392 last_dockspace_pos_ = ImGui::GetWindowPos();
393 last_dockspace_size_ = ImGui::GetWindowSize();
394
395 // Create the actual dockspace
396 ImGui::DockSpace(dockspace_id, size, flags);
397
398 // NOTE: Grid background is rendered by UICoordinator::DrawBackground()
399 // on the background draw list. Do NOT render here on foreground draw list
400 // as that causes duplicate grid rendering (one behind content, one in front).
401}
402
404 // Additional post-processing effects could go here
405 // For now, this is just for API consistency
406}
407
408} // namespace gui
409} // namespace yaze
static TimingManager & Get()
Definition timing.h:20
Renders themed background effects for docking windows.
void RenderRadialGradient(ImDrawList *draw_list, const ImVec2 &center, float radius, const Color &inner_color, const Color &outer_color)
void RenderGridBackground(ImDrawList *draw_list, const ImVec2 &window_pos, const ImVec2 &window_size, const Color &grid_color)
void DrawGridLine(ImDrawList *draw_list, const ImVec2 &start, const ImVec2 &end, ImU32 color, float thickness) const
static BackgroundRenderer & Get()
float CalculateRadialFade(const ImVec2 &pos, const ImVec2 &center, float max_distance) const
void UpdateAnimation(float delta_time)
void UpdateForTheme(const Color &primary_color, const Color &background_color)
void DrawGridDot(ImDrawList *draw_list, const ImVec2 &pos, ImU32 color, float size) const
ImU32 BlendColorWithFade(const Color &base_color, float fade_factor) const
void RenderDockingBackground(ImDrawList *draw_list, const ImVec2 &window_pos, const ImVec2 &window_size, const Color &theme_color)
static void BeginEnhancedDockSpace(ImGuiID dockspace_id, const ImVec2 &size=ImVec2(0, 0), ImGuiDockNodeFlags flags=0)
static ThemeManager & Get()
ImVec4 ConvertColorToImVec4(const Color &color)
Definition color.h:23
float alpha
Definition color.h:18
float green
Definition color.h:16
#define M_PI