10namespace CanvasUtils {
13 return ImVec2(std::floor(pos.x / grid_step) * grid_step,
14 std::floor(pos.y / grid_step) * grid_step);
19 if (content_size.x <= 0 || content_size.y <= 0)
22 float scale_x = (canvas_size.x * global_scale) / content_size.x;
23 float scale_y = (canvas_size.y * global_scale) / content_size.y;
24 return std::min(scale_x, scale_y);
29 float scaled_tile_size = tile_size * scale;
30 int tile_x =
static_cast<int>(mouse_pos.x / scaled_tile_size);
31 int tile_y =
static_cast<int>(mouse_pos.y / scaled_tile_size);
33 return tile_x + (tile_y * tiles_per_row);
47 if (palette_groups.overworld_main.size() > 0) {
49 palette_groups.overworld_main[0]);
52 if (palette_groups.overworld_aux.size() > 0) {
54 palette_groups.overworld_aux[0]);
57 if (palette_groups.overworld_animated.size() > 0) {
59 palette_groups.overworld_animated[0]);
64 if (palette_groups.dungeon_main.size() > 0) {
66 palette_groups.dungeon_main[0]);
71 if (palette_groups.global_sprites.size() > 0) {
73 palette_groups.global_sprites[0]);
76 if (palette_groups.armors.size() > 0) {
80 if (palette_groups.swords.size() > 0) {
86 LOG_DEBUG(
"Canvas",
"Loaded %zu ROM palette groups",
90 }
catch (
const std::exception& e) {
91 LOG_ERROR(
"Canvas",
"Failed to load ROM palette groups");
97 int group_index,
int palette_index) {
98 if (!bitmap)
return false;
107 if (palette_index == 0) {
124 int x,
int y,
int w,
int h, ImVec4 color,
125 float global_scale) {
127 float scaled_x = x * global_scale;
128 float scaled_y = y * global_scale;
129 float scaled_w = w * global_scale;
130 float scaled_h = h * global_scale;
132 ImVec2 origin(canvas_p0.x + scrolling.x + scaled_x,
133 canvas_p0.y + scrolling.y + scaled_y);
134 ImVec2 size(canvas_p0.x + scrolling.x + scaled_x + scaled_w,
135 canvas_p0.y + scrolling.y + scaled_y + scaled_h);
137 uint32_t color_u32 = IM_COL32(color.x * 255, color.y * 255, color.z * 255, color.w * 255);
138 draw_list->AddRectFilled(origin, size, color_u32);
141 ImVec2 outline_origin(origin.x - 1, origin.y - 1);
142 ImVec2 outline_size(size.x + 1, size.y + 1);
143 draw_list->AddRect(outline_origin, outline_size, IM_COL32(0, 0, 0, 255));
147 const std::string& text,
int x,
int y,
float global_scale) {
149 float scaled_x = x * global_scale;
150 float scaled_y = y * global_scale;
152 ImVec2 text_pos(canvas_p0.x + scrolling.x + scaled_x,
153 canvas_p0.y + scrolling.y + scaled_y);
156 draw_list->AddText(ImVec2(text_pos.x + 1, text_pos.y + 1),
157 IM_COL32(0, 0, 0, 255), text.c_str());
158 draw_list->AddText(text_pos, IM_COL32(255, 255, 255, 255), text.c_str());
162 ImVec2 scrolling,
int x,
int y,
int w,
int h,
164 ImVec2 origin(canvas_p0.x + scrolling.x + x, canvas_p0.y + scrolling.y + y);
165 ImVec2 size(canvas_p0.x + scrolling.x + x + w,
166 canvas_p0.y + scrolling.y + y + h);
167 draw_list->AddRect(origin, size, color, 0, 0, 1.5f);
171 ImVec2 scrolling,
int x,
int y,
int w,
int h,
174 IM_COL32(color.x * 255, color.y * 255, color.z * 255, color.w * 255);
180 ImVec2 canvas_p1, ImVec2 scrolling,
float grid_step,
181 float global_scale) {
182 const uint32_t grid_color = IM_COL32(200, 200, 200, 50);
183 const float grid_thickness = 0.5f;
185 float scaled_grid_step = grid_step * global_scale;
187 for (
float x = fmodf(scrolling.x, scaled_grid_step);
188 x < (canvas_p1.x - canvas_p0.x); x += scaled_grid_step) {
189 draw_list->AddLine(ImVec2(canvas_p0.x + x, canvas_p0.y),
190 ImVec2(canvas_p0.x + x, canvas_p1.y), grid_color,
194 for (
float y = fmodf(scrolling.y, scaled_grid_step);
195 y < (canvas_p1.y - canvas_p0.y); y += scaled_grid_step) {
196 draw_list->AddLine(ImVec2(canvas_p0.x, canvas_p0.y + y),
197 ImVec2(canvas_p1.x, canvas_p0.y + y), grid_color,
203 ImVec2 scrolling,
int highlight_tile_id,
205 if (highlight_tile_id == -1)
208 int tile_x = highlight_tile_id % 8;
209 int tile_y = highlight_tile_id / 8;
210 ImVec2 tile_pos(canvas_p0.x + scrolling.x + tile_x * grid_step,
211 canvas_p0.y + scrolling.y + tile_y * grid_step);
212 ImVec2 tile_pos_end(tile_pos.x + grid_step, tile_pos.y + grid_step);
214 draw_list->AddRectFilled(tile_pos, tile_pos_end, IM_COL32(255, 0, 255, 255));
218 ImVec2 scrolling, ImVec2 canvas_sz,
float grid_step,
219 float global_scale) {
220 float scaled_grid_step = grid_step * global_scale;
222 for (
float x = fmodf(scrolling.x, scaled_grid_step);
223 x < canvas_sz.x * global_scale; x += scaled_grid_step) {
224 for (
float y = fmodf(scrolling.y, scaled_grid_step);
225 y < canvas_sz.y * global_scale; y += scaled_grid_step) {
226 int tile_x = (x - scrolling.x) / scaled_grid_step;
227 int tile_y = (y - scrolling.y) / scaled_grid_step;
228 int tile_id = tile_x + (tile_y * 16);
231 snprintf(hex_id,
sizeof(hex_id),
"%02X", tile_id);
233 draw_list->AddText(ImVec2(canvas_p0.x + x + (scaled_grid_step / 2) - 4,
234 canvas_p0.y + y + (scaled_grid_step / 2) - 4),
235 IM_COL32(255, 255, 255, 255), hex_id);
243 return use_custom ? custom_size : content_region;
247 return ImVec2(canvas_size.x * global_scale, canvas_size.y * global_scale);
251 return point.x >= canvas_p0.x && point.x <= canvas_p1.x &&
252 point.y >= canvas_p0.y && point.y <= canvas_p1.y;
259 ImVec2 min_size = ImVec2(content_size.x * global_scale + padding * 2,
260 content_size.y * global_scale + padding * 2);
263 min_size.x = std::max(min_size.x, 64.0f);
264 min_size.y = std::max(min_size.y, 64.0f);
272 float effective_scale = std::max(global_scale, min_scale);
273 ImVec2 preferred_size = ImVec2(content_size.x * effective_scale + 8.0f,
274 content_size.y * effective_scale + 8.0f);
277 preferred_size.x = std::min(preferred_size.x, 800.0f);
278 preferred_size.y = std::min(preferred_size.y, 600.0f);
280 return preferred_size;
285 if (!label.empty()) {
286 ImGui::Text(
"%s", label.c_str());
288 ImGui::Dummy(canvas_size);
290 ImGui::SetCursorPosX(ImGui::GetCursorPosX() -
297 ImGui::SetNextWindowContentSize(size);
300 ImGui::SetNextWindowSize(size);
316 if (highlight_tile_id != -1) {
333 const ImVector<ImVec2>& points,
334 const ImVector<ImVec2>& selected_points) {
339 for (
int n = 0; n < points.Size; n += 2) {
341 ImVec2(origin.x + points[n].x, origin.y + points[n].y),
342 ImVec2(origin.x + points[n + 1].x, origin.y + points[n + 1].y),
343 IM_COL32(255, 255, 255, 255), 1.0f);
347 if (!selected_points.empty()) {
348 for (
int n = 0; n < selected_points.size(); n += 2) {
349 ctx.
draw_list->AddRect(ImVec2(origin.x + selected_points[n].x,
350 origin.y + selected_points[n].y),
351 ImVec2(origin.x + selected_points[n + 1].x + 0x10,
352 origin.y + selected_points[n + 1].y + 0x10),
353 IM_COL32(255, 255, 255, 255), 1.0f);
359 const ImVector<ImVector<std::string>>& labels,
360 int current_labels,
int tile_id_offset) {
361 if (current_labels >= labels.size())
366 for (
float x = fmodf(ctx.
scrolling.x, scaled_grid_step);
368 for (
float y = fmodf(ctx.
scrolling.y, scaled_grid_step);
370 int tile_x = (x - ctx.
scrolling.x) / scaled_grid_step;
371 int tile_y = (y - ctx.
scrolling.y) / scaled_grid_step;
372 int tile_id = tile_x + (tile_y * tile_id_offset);
374 if (tile_id >= labels[current_labels].size()) {
378 const std::string& label = labels[current_labels][tile_id];
380 ImVec2(ctx.
canvas_p0.x + x + (scaled_grid_step / 2) - tile_id_offset,
381 ctx.
canvas_p0.y + y + (scaled_grid_step / 2) - tile_id_offset),
382 IM_COL32(255, 255, 255, 255), label.c_str());
The Rom class is used to load, save, and modify Rom data.
auto palette_group() const
void QueueTextureCommand(TextureCommandType type, Bitmap *bitmap)
Represents a bitmap image optimized for SNES ROM hacking.
void set_modified(bool modified)
void SetPalette(const SnesPalette &palette)
Set the palette for the bitmap.
void SetPaletteWithTransparent(const SnesPalette &palette, size_t index, int length=7)
Set the palette with a transparent color.
Defines an abstract interface for all rendering operations.
#define LOG_DEBUG(category, format,...)
#define LOG_ERROR(category, format,...)
void ReserveCanvasSpace(ImVec2 canvas_size, const std::string &label)
void SetNextCanvasSize(ImVec2 size, bool auto_resize)
void DrawCanvasRect(ImDrawList *draw_list, ImVec2 canvas_p0, ImVec2 scrolling, int x, int y, int w, int h, ImVec4 color, float global_scale)
void DrawCanvasLabels(const CanvasRenderContext &ctx, const ImVector< ImVector< std::string > > &labels, int current_labels, int tile_id_offset)
bool IsPointInCanvas(ImVec2 point, ImVec2 canvas_p0, ImVec2 canvas_p1)
void DrawCanvasOverlay(const CanvasRenderContext &ctx, const ImVector< ImVec2 > &points, const ImVector< ImVec2 > &selected_points)
ImVec2 CalculateCanvasSize(ImVec2 content_region, ImVec2 custom_size, bool use_custom)
bool LoadROMPaletteGroups(Rom *rom, CanvasPaletteManager &palette_manager)
ImVec2 CalculateMinimumCanvasSize(ImVec2 content_size, float global_scale, float padding)
bool ApplyPaletteGroup(gfx::IRenderer *renderer, gfx::Bitmap *bitmap, const CanvasPaletteManager &palette_manager, int group_index, int palette_index)
float CalculateEffectiveScale(ImVec2 canvas_size, ImVec2 content_size, float global_scale)
void DrawCanvasOutline(ImDrawList *draw_list, ImVec2 canvas_p0, ImVec2 scrolling, int x, int y, int w, int h, uint32_t color)
int GetTileIdFromPosition(ImVec2 mouse_pos, float tile_size, float scale, int tiles_per_row)
void DrawCanvasOutlineWithColor(ImDrawList *draw_list, ImVec2 canvas_p0, ImVec2 scrolling, int x, int y, int w, int h, ImVec4 color)
void DrawCanvasGrid(const CanvasRenderContext &ctx, int highlight_tile_id)
ImVec2 CalculatePreferredCanvasSize(ImVec2 content_size, float global_scale, float min_scale)
void DrawCanvasText(ImDrawList *draw_list, ImVec2 canvas_p0, ImVec2 scrolling, const std::string &text, int x, int y, float global_scale)
ImVec2 CalculateScaledCanvasSize(ImVec2 canvas_size, float global_scale)
void DrawCustomHighlight(ImDrawList *draw_list, ImVec2 canvas_p0, ImVec2 scrolling, int highlight_tile_id, float grid_step)
void DrawCanvasGridLines(ImDrawList *draw_list, ImVec2 canvas_p0, ImVec2 canvas_p1, ImVec2 scrolling, float grid_step, float global_scale)
ImVec2 AlignToGrid(ImVec2 pos, float grid_step)
void DrawHexTileLabels(ImDrawList *draw_list, ImVec2 canvas_p0, ImVec2 scrolling, ImVec2 canvas_sz, float grid_step, float global_scale)
Main namespace for the application.
Palette management state for canvas.
std::vector< gfx::SnesPalette > rom_palette_groups
std::vector< std::string > palette_group_names