yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
canvas_rendering.cc
Go to the documentation of this file.
1#include "canvas_rendering.h"
2
3#include <algorithm>
4#include <cmath>
5
8
9namespace yaze {
10namespace gui {
11
12void RenderCanvasBackground(ImDrawList* draw_list,
13 const CanvasGeometry& geometry) {
14 const auto& theme = ThemeManager::Get().GetCurrentTheme();
15
16 // Draw primary background color from theme
17 draw_list->AddRectFilled(geometry.canvas_p0, geometry.canvas_p1,
18 ImGui::GetColorU32(ConvertColorToImVec4(theme.editor_background)));
19
20 // Add a subtle pattern to the background (e.g., very faint dots)
21 if (theme.enable_glow_effects) {
22 const float dot_spacing = 32.0f;
23 const uint32_t dot_color = ImGui::GetColorU32(ConvertColorToImVec4(theme.editor_grid));
24
25 for (float x = geometry.canvas_p0.x + fmodf(geometry.scrolling.x, dot_spacing); x < geometry.canvas_p1.x; x += dot_spacing) {
26 for (float y = geometry.canvas_p0.y + fmodf(geometry.scrolling.y, dot_spacing); y < geometry.canvas_p1.y; y += dot_spacing) {
27 draw_list->AddCircleFilled(ImVec2(x, y), 1.0f, dot_color);
28 }
29 }
30 }
31
32 // Draw theme-aware border
33 draw_list->AddRect(geometry.canvas_p0, geometry.canvas_p1,
34 ImGui::GetColorU32(ConvertColorToImVec4(theme.border)),
35 0.0f, 0, theme.window_border_size > 0 ? theme.window_border_size : 1.0f);
36}
37
38void RenderCanvasGrid(ImDrawList* draw_list, const CanvasGeometry& geometry,
39 const CanvasConfig& config, int highlight_tile_id) {
40 if (!config.enable_grid) {
41 return;
42 }
43
44 // Create render context for utility functions (extracted from
45 // Canvas::DrawGrid)
47 .draw_list = draw_list,
48 .canvas_p0 = geometry.canvas_p0,
49 .canvas_p1 = geometry.canvas_p1,
50 .scrolling = geometry.scrolling,
51 .global_scale = config.global_scale,
52 .enable_grid = config.enable_grid,
53 .enable_hex_labels = config.enable_hex_labels,
54 .grid_step = config.grid_step};
55
56 // Use high-level utility function
57 CanvasUtils::DrawCanvasGrid(ctx, highlight_tile_id);
58}
59
60void RenderCanvasOverlay(ImDrawList* draw_list, const CanvasGeometry& geometry,
61 const CanvasConfig& config,
62 const ImVector<ImVec2>& points,
63 const ImVector<ImVec2>& selected_points) {
64 // Create render context for utility functions (extracted from
65 // Canvas::DrawOverlay)
67 .draw_list = draw_list,
68 .canvas_p0 = geometry.canvas_p0,
69 .canvas_p1 = geometry.canvas_p1,
70 .scrolling = geometry.scrolling,
71 .global_scale = config.global_scale,
72 .enable_grid = config.enable_grid,
73 .enable_hex_labels = config.enable_hex_labels,
74 .grid_step = config.grid_step};
75
76 // Use high-level utility function
77 CanvasUtils::DrawCanvasOverlay(ctx, points, selected_points);
78}
79
80void RenderCanvasLabels(ImDrawList* draw_list, const CanvasGeometry& geometry,
81 const CanvasConfig& config,
82 const ImVector<ImVector<std::string>>& labels,
83 int current_labels, int tile_id_offset) {
84 if (!config.enable_custom_labels || current_labels >= labels.size()) {
85 return;
86 }
87
88 // Push clip rect to prevent drawing outside canvas
89 draw_list->PushClipRect(geometry.canvas_p0, geometry.canvas_p1, true);
90
91 // Create render context for utility functions
93 .draw_list = draw_list,
94 .canvas_p0 = geometry.canvas_p0,
95 .canvas_p1 = geometry.canvas_p1,
96 .scrolling = geometry.scrolling,
97 .global_scale = config.global_scale,
98 .enable_grid = config.enable_grid,
99 .enable_hex_labels = config.enable_hex_labels,
100 .grid_step = config.grid_step};
101
102 // Use high-level utility function (extracted from Canvas::DrawInfoGrid)
103 CanvasUtils::DrawCanvasLabels(ctx, labels, current_labels, tile_id_offset);
104
105 draw_list->PopClipRect();
106}
107
108void RenderBitmapOnCanvas(ImDrawList* draw_list, const CanvasGeometry& geometry,
109 gfx::Bitmap& bitmap, int /*border_offset*/,
110 float scale) {
111 if (!bitmap.is_active() || !bitmap.texture()) {
112 return;
113 }
114
115 // Extracted from Canvas::DrawBitmap (border offset variant)
116 draw_list->AddImage((ImTextureID)(intptr_t)bitmap.texture(),
117 ImVec2(geometry.canvas_p0.x, geometry.canvas_p0.y),
118 ImVec2(geometry.canvas_p0.x + (bitmap.width() * scale),
119 geometry.canvas_p0.y + (bitmap.height() * scale)));
120 // NOTE: Canvas border is drawn once by RenderCanvasBackground().
121 // Do NOT draw border here - this function is called per-bitmap, which would
122 // cause N stacked border rectangles (e.g., 64 in overworld editor).
123}
124
125void RenderBitmapOnCanvas(ImDrawList* draw_list, const CanvasGeometry& geometry,
126 gfx::Bitmap& bitmap, int x_offset, int y_offset,
127 float scale, int alpha) {
128 if (!bitmap.is_active() || !bitmap.texture()) {
129 return;
130 }
131
132 // Calculate the actual rendered size including scale and offsets
133 // CRITICAL: Use scale parameter (NOT global_scale_) for per-bitmap scaling
134 // Extracted from Canvas::DrawBitmap (x/y offset variant)
135 ImVec2 rendered_size(bitmap.width() * scale, bitmap.height() * scale);
136
137 // CRITICAL FIX: Draw bitmap WITHOUT additional global_scale multiplication
138 // The scale parameter already contains the correct scale factor
139 // The scrolling should NOT be scaled - it's already in screen space
140 draw_list->AddImage(
141 (ImTextureID)(intptr_t)bitmap.texture(),
142 ImVec2(geometry.canvas_p0.x + x_offset + geometry.scrolling.x,
143 geometry.canvas_p0.y + y_offset + geometry.scrolling.y),
144 ImVec2(geometry.canvas_p0.x + x_offset + geometry.scrolling.x +
145 rendered_size.x,
146 geometry.canvas_p0.y + y_offset + geometry.scrolling.y +
147 rendered_size.y),
148 ImVec2(0, 0), ImVec2(1, 1), IM_COL32(255, 255, 255, alpha));
149}
150
151void RenderBitmapOnCanvas(ImDrawList* draw_list, const CanvasGeometry& geometry,
152 gfx::Bitmap& bitmap, ImVec2 dest_pos,
153 ImVec2 dest_size, ImVec2 src_pos, ImVec2 src_size) {
154 if (!bitmap.is_active() || !bitmap.texture()) {
155 return;
156 }
157
158 // Extracted from Canvas::DrawBitmap (custom source/dest regions variant)
159 draw_list->AddImage(
160 (ImTextureID)(intptr_t)bitmap.texture(),
161 ImVec2(geometry.canvas_p0.x + dest_pos.x,
162 geometry.canvas_p0.y + dest_pos.y),
163 ImVec2(geometry.canvas_p0.x + dest_pos.x + dest_size.x,
164 geometry.canvas_p0.y + dest_pos.y + dest_size.y),
165 ImVec2(src_pos.x / bitmap.width(), src_pos.y / bitmap.height()),
166 ImVec2((src_pos.x + src_size.x) / bitmap.width(),
167 (src_pos.y + src_size.y) / bitmap.height()));
168}
169
170void RenderBitmapGroup(ImDrawList* draw_list, const CanvasGeometry& geometry,
171 std::vector<int>& group, gfx::Tilemap& tilemap,
172 int tile_size, float scale, int local_map_size,
173 ImVec2 total_map_size) {
174 // Extracted from Canvas::DrawBitmapGroup (lines 1148-1264)
175 // This is used for multi-tile selection preview in overworld editor
176
177 if (group.empty()) {
178 return;
179 }
180
181 // OPTIMIZATION: Use optimized rendering for large groups to improve
182 // performance
183 bool use_optimized_rendering = group.size() > 128;
184
185 // Pre-calculate common values to avoid repeated computation
186 const float tile_scale = tile_size * scale;
187 const int atlas_tiles_per_row = tilemap.atlas.width() / tilemap.tile_size.x;
188
189 // Get selected points (note: this assumes selected_points are available in
190 // context) For now, we'll just render tiles at their grid positions The full
191 // implementation would need the selected_points passed in
192
193 int i = 0;
194 for (const auto tile_id : group) {
195 // Calculate grid position for this tile
196 int tiles_per_row = 32; // Default for standard maps
197 int x = i % tiles_per_row;
198 int y = i / tiles_per_row;
199
200 int tile_pos_x = x * tile_size * scale;
201 int tile_pos_y = y * tile_size * scale;
202
203 // Check if tile_id is within the range
204 auto tilemap_size = tilemap.map_size.x;
205 if (tile_id >= 0 && tile_id < tilemap_size) {
206 if (tilemap.atlas.is_active() && tilemap.atlas.texture() &&
207 atlas_tiles_per_row > 0) {
208 int atlas_tile_x =
209 (tile_id % atlas_tiles_per_row) * tilemap.tile_size.x;
210 int atlas_tile_y =
211 (tile_id / atlas_tiles_per_row) * tilemap.tile_size.y;
212
213 // Simple bounds check
214 if (atlas_tile_x >= 0 && atlas_tile_x < tilemap.atlas.width() &&
215 atlas_tile_y >= 0 && atlas_tile_y < tilemap.atlas.height()) {
216 // Calculate UV coordinates once for efficiency
217 const float atlas_width = static_cast<float>(tilemap.atlas.width());
218 const float atlas_height = static_cast<float>(tilemap.atlas.height());
219 ImVec2 uv0 =
220 ImVec2(atlas_tile_x / atlas_width, atlas_tile_y / atlas_height);
221 ImVec2 uv1 =
222 ImVec2((atlas_tile_x + tilemap.tile_size.x) / atlas_width,
223 (atlas_tile_y + tilemap.tile_size.y) / atlas_height);
224
225 // Calculate screen positions
226 float screen_x =
227 geometry.canvas_p0.x + geometry.scrolling.x + tile_pos_x;
228 float screen_y =
229 geometry.canvas_p0.y + geometry.scrolling.y + tile_pos_y;
230 float screen_w = tilemap.tile_size.x * scale;
231 float screen_h = tilemap.tile_size.y * scale;
232
233 // Use higher alpha for large selections to make them more visible
234 uint32_t alpha_color = use_optimized_rendering
235 ? IM_COL32(255, 255, 255, 200)
236 : IM_COL32(255, 255, 255, 150);
237
238 // Draw from atlas texture with optimized parameters
239 draw_list->AddImage((ImTextureID)(intptr_t)tilemap.atlas.texture(),
240 ImVec2(screen_x, screen_y),
241 ImVec2(screen_x + screen_w, screen_y + screen_h),
242 uv0, uv1, alpha_color);
243 }
244 }
245 }
246 i++;
247 }
248}
249
250} // namespace gui
251} // namespace yaze
Represents a bitmap image optimized for SNES ROM hacking.
Definition bitmap.h:67
TextureHandle texture() const
Definition bitmap.h:380
bool is_active() const
Definition bitmap.h:384
int height() const
Definition bitmap.h:374
int width() const
Definition bitmap.h:373
const Theme & GetCurrentTheme() const
static ThemeManager & Get()
void DrawCanvasLabels(const CanvasRenderContext &ctx, const ImVector< ImVector< std::string > > &labels, int current_labels, int tile_id_offset)
void DrawCanvasOverlay(const CanvasRenderContext &ctx, const ImVector< ImVec2 > &points, const ImVector< ImVec2 > &selected_points)
void DrawCanvasGrid(const CanvasRenderContext &ctx, int highlight_tile_id)
ImVec4 ConvertColorToImVec4(const Color &color)
Definition color.h:134
void RenderBitmapGroup(ImDrawList *draw_list, const CanvasGeometry &geometry, std::vector< int > &group, gfx::Tilemap &tilemap, int tile_size, float scale, int local_map_size, ImVec2 total_map_size)
Render group of bitmaps from tilemap.
void RenderCanvasLabels(ImDrawList *draw_list, const CanvasGeometry &geometry, const CanvasConfig &config, const ImVector< ImVector< std::string > > &labels, int current_labels, int tile_id_offset)
Render canvas labels on grid.
void RenderCanvasBackground(ImDrawList *draw_list, const CanvasGeometry &geometry)
Render canvas background and border.
void RenderCanvasGrid(ImDrawList *draw_list, const CanvasGeometry &geometry, const CanvasConfig &config, int highlight_tile_id)
Render canvas grid with optional highlighting.
void RenderBitmapOnCanvas(ImDrawList *draw_list, const CanvasGeometry &geometry, gfx::Bitmap &bitmap, int, float scale)
Render bitmap on canvas (border offset variant)
void RenderCanvasOverlay(ImDrawList *draw_list, const CanvasGeometry &geometry, const CanvasConfig &config, const ImVector< ImVec2 > &points, const ImVector< ImVec2 > &selected_points)
Render canvas overlay (hover and selection points)
int y
Y coordinate or height.
Definition tilemap.h:21
int x
X coordinate or width.
Definition tilemap.h:20
Tilemap structure for SNES tile-based graphics management.
Definition tilemap.h:118
Pair tile_size
Size of individual tiles (8x8 or 16x16)
Definition tilemap.h:123
Pair map_size
Size of tilemap in tiles.
Definition tilemap.h:124
Bitmap atlas
Master bitmap containing all tiles.
Definition tilemap.h:119
Unified configuration for canvas display and interaction.
Canvas geometry calculated per-frame.