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