11#include "imgui/imgui.h"
23 : renderer_(nullptr), canvas_id_(id), context_id_(id +
"Context") {
28 : renderer_(nullptr), canvas_id_(id), context_id_(id +
"Context") {
35 : renderer_(nullptr), canvas_id_(id), context_id_(id +
"Context") {
43 : renderer_(nullptr), canvas_id_(id), context_id_(id +
"Context") {
55 : renderer_(renderer), canvas_id_(id), context_id_(id +
"Context") {
60 : renderer_(renderer), canvas_id_(id), context_id_(id +
"Context") {
67 : renderer_(renderer), canvas_id_(id), context_id_(id +
"Context") {
75 : renderer_(renderer), canvas_id_(id), context_id_(id +
"Context") {
85using ImGui::GetContentRegionAvail;
86using ImGui::GetCursorScreenPos;
88using ImGui::GetWindowDrawList;
89using ImGui::IsItemActive;
90using ImGui::IsItemHovered;
91using ImGui::IsMouseClicked;
92using ImGui::IsMouseDragging;
99 ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight;
103 return ImVec2(std::floor(pos.x / scale) * scale,
104 std::floor(pos.y / scale) * scale);
166 modals_ = std::make_unique<canvas::CanvasModals>();
169 context_menu_ = std::make_unique<canvas::CanvasContextMenu>();
179 std::make_shared<canvas::CanvasPerformanceIntegration>();
229 ImGui::OpenPopup(
"Canvas Usage Report");
230 if (ImGui::BeginPopupModal(
"Canvas Usage Report",
nullptr,
231 ImGuiWindowFlags_AlwaysAutoResize)) {
232 ImGui::Text(
"Canvas Usage Report");
234 ImGui::TextWrapped(
"%s", report.c_str());
236 if (ImGui::Button(
"Close")) {
237 ImGui::CloseCurrentPopup();
256 "Canvas Palette Editor");
296 std::string child_id =
canvas_id_ +
"_TableChild";
300 ImGui::BeginChild(child_id.c_str(), child_size,
302 ImGuiWindowFlags_AlwaysVerticalScrollbar);
304 if (!label.empty()) {
305 ImGui::Text(
"%s", label.c_str());
325 return ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(button) &&
333 return ImVec2(-1, -1);
358 const std::function<
void()>& event,
359 int tile_size,
float scale) {
386 ImVec2 content_region = GetContentRegionAvail();
400 if (scaled_size.x <= 0.0f)
401 scaled_size.x = 1.0f;
402 if (scaled_size.y <= 0.0f)
403 scaled_size.y = 1.0f;
416 if (IsItemHovered()) {
417 const ImGuiIO& io = GetIO();
419 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
424 const ImGuiIO& io = GetIO();
425 const bool is_active = IsItemActive();
428 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
431 if (
const float mouse_threshold_for_pan =
434 IsMouseDragging(ImGuiMouseButton_Right, mouse_threshold_for_pan)) {
442 const ImGuiIO& io = GetIO();
447 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
587 ImGui::BeginDisabled();
592 if (ImGui::MenuItem(item.
label.c_str(), item.
shortcut.empty()
599 if (ImGui::BeginMenu(item.
label.c_str())) {
600 for (
const auto& subitem : item.
subitems) {
608 ImGui::EndDisabled();
623 if (popup.popup_id == popup_id) {
624 popup.is_open =
true;
625 popup.render_callback = std::move(render_callback);
626 ImGui::OpenPopup(popup_id.c_str());
637 ImGui::OpenPopup(popup_id.c_str());
642 if (popup.popup_id == popup_id) {
643 popup.is_open =
false;
644 ImGui::CloseCurrentPopup();
654 if (it->is_open && it->render_callback) {
656 it->render_callback();
659 if (!ImGui::IsPopupOpen(it->popup_id.c_str())) {
677 ImVec2 available = ImGui::GetContentRegionAvail();
678 float scale_x = available.x / bitmap.
width();
679 float scale_y = available.y / bitmap.
height();
729 const ImGuiIO& io = GetIO();
730 const bool is_hovered = IsItemHovered();
734 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
735 const auto scaled_size = size * scale;
749 ImVec2 paint_pos = AlignPosToGrid(mouse_pos, scaled_size);
752 ImVec2(paint_pos.x + scaled_size, paint_pos.y + scaled_size);
754 points_.push_back(paint_pos_end);
758 ImVec2(origin.x + paint_pos.x, origin.y + paint_pos.y),
759 ImVec2(origin.x + paint_pos.x + scaled_size,
760 origin.y + paint_pos.y + scaled_size));
763 if (IsMouseClicked(ImGuiMouseButton_Left) &&
764 ImGui::IsMouseDragging(ImGuiMouseButton_Left)) {
775 const ImGuiIO& io = GetIO();
776 const bool is_hovered = IsItemHovered();
779 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
797 ImVec2 paint_pos = AlignPosToGrid(mouse_pos, scaled_size);
802 ImVec2(paint_pos.x + scaled_size, paint_pos.y + scaled_size));
809 if (tiles_per_row > 0) {
810 int tile_x = (current_tile % tiles_per_row) * tilemap.
tile_size.
x;
811 int tile_y = (current_tile / tiles_per_row) * tilemap.
tile_size.
y;
814 if (tile_x >= 0 && tile_x < tilemap.
atlas.
width() && tile_y >= 0 &&
819 ImVec2(
static_cast<float>(tile_x) / tilemap.
atlas.
width(),
820 static_cast<float>(tile_y) / tilemap.
atlas.
height());
821 ImVec2 uv1 = ImVec2(
static_cast<float>(tile_x + tilemap.
tile_size.
x) /
823 static_cast<float>(tile_y + tilemap.
tile_size.
y) /
828 ImVec2(origin.x + paint_pos.x, origin.y + paint_pos.y),
829 ImVec2(origin.x + paint_pos.x + scaled_size,
830 origin.y + paint_pos.y + scaled_size),
836 if (IsMouseClicked(ImGuiMouseButton_Left) ||
837 ImGui::IsMouseDragging(ImGuiMouseButton_Left)) {
846 const ImGuiIO& io = GetIO();
847 const bool is_hovered = IsItemHovered();
851 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
853 static bool is_dragging =
false;
854 static ImVec2 start_drag_pos;
868 ImVec2 paint_pos = AlignPosToGrid(mouse_pos, scaled_tile_size);
877 ImVec2(paint_pos.x + scaled_tile_size, paint_pos.y + scaled_tile_size));
880 ImVec2(origin.x + paint_pos.x + 1, origin.y + paint_pos.y + 1),
881 ImVec2(origin.x + paint_pos.x + scaled_tile_size,
882 origin.y + paint_pos.y + scaled_tile_size),
883 IM_COL32(color.x * 255, color.y * 255, color.z * 255, 255));
885 if (IsMouseClicked(ImGuiMouseButton_Left)) {
887 start_drag_pos = paint_pos;
890 if (is_dragging && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) {
902 int tile_index_x =
static_cast<int>(position.x /
global_scale_) / tile_size;
903 int tile_index_y =
static_cast<int>(position.y /
global_scale_) / tile_size;
905 ImVec2 start_position(tile_index_x * tile_size, tile_index_y * tile_size);
908 for (
int y = 0; y < tile_size; ++y) {
909 for (
int x = 0; x < tile_size; ++x) {
912 (start_position.y + y) * bitmap->
width() + (start_position.x + x);
921 const ImGuiIO& io = GetIO();
922 const bool is_hovered = IsItemHovered();
925 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
930 if (is_hovered && IsMouseClicked(ImGuiMouseButton_Left)) {
934 ImVec2 painter_pos = AlignPosToGrid(mouse_pos, size);
936 points_.push_back(painter_pos);
937 points_.push_back(ImVec2(painter_pos.x + size, painter_pos.y + size_y));
941 if (is_hovered && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
951 const ImGuiIO& io = GetIO();
953 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
954 static ImVec2 drag_start_pos;
955 const float scaled_size = tile_size * scale;
956 static bool dragging =
false;
957 constexpr int small_map_size = 0x200;
960 const bool is_hovered = IsItemHovered();
967 if (current_map < 0x40) {
969 superY = current_map / 8;
970 superX = current_map % 8;
971 }
else if (current_map < 0x80) {
973 superY = (current_map - 0x40) / 8;
974 superX = (current_map - 0x40) % 8;
977 superY = (current_map - 0x80) / 8;
978 superX = (current_map - 0x80) % 8;
982 if (IsMouseClicked(ImGuiMouseButton_Right)) {
983 ImVec2 painter_pos = AlignPosToGrid(mouse_pos, scaled_size);
984 int painter_x = painter_pos.x;
985 int painter_y = painter_pos.y;
987 auto tile16_x = (painter_x % small_map_size) / (small_map_size / 0x20);
988 auto tile16_y = (painter_y % small_map_size) / (small_map_size / 0x20);
990 int index_x = superX * 0x20 + tile16_x;
991 int index_y = superY * 0x20 + tile16_y;
997 drag_start_pos = AlignPosToGrid(mouse_pos, scaled_size);
1001 ImVec2 drag_end_pos = AlignPosToGrid(mouse_pos, scaled_size);
1002 if (ImGui::IsMouseDragging(ImGuiMouseButton_Right)) {
1004 auto start = ImVec2(origin.x + drag_start_pos.x,
1005 origin.y + drag_start_pos.y);
1006 auto end = ImVec2(origin.x + drag_end_pos.x + tile_size,
1007 origin.y + drag_end_pos.y + tile_size);
1012 if (dragging && !ImGui::IsMouseDown(ImGuiMouseButton_Right)) {
1017 constexpr int tile16_size = 16;
1018 int start_x = std::floor(drag_start_pos.x / scaled_size) * tile16_size;
1019 int start_y = std::floor(drag_start_pos.y / scaled_size) * tile16_size;
1020 int end_x = std::floor(drag_end_pos.x / scaled_size) * tile16_size;
1021 int end_y = std::floor(drag_end_pos.y / scaled_size) * tile16_size;
1024 if (start_x > end_x)
1025 std::swap(start_x, end_x);
1026 if (start_y > end_y)
1027 std::swap(start_y, end_y);
1031 ((end_y - start_y) / tile16_size + 1));
1034 constexpr int tiles_per_local_map = small_map_size / 16;
1037 for (
int y = start_y; y <= end_y; y += tile16_size) {
1038 for (
int x = start_x; x <= end_x; x += tile16_size) {
1040 int local_map_x = (x / small_map_size) % 8;
1041 int local_map_y = (y / small_map_size) % 8;
1044 int tile16_x = (x % small_map_size) / tile16_size;
1045 int tile16_y = (y % small_map_size) / tile16_size;
1048 int index_x = local_map_x * tiles_per_local_map + tile16_x;
1049 int index_y = local_map_y * tiles_per_local_map + tile16_y;
1091 ImVec2 rendered_size(bitmap.
width() * scale, bitmap.
height() * scale);
1092 ImVec2 total_size(x_offset + rendered_size.x, y_offset + rendered_size.y);
1098 (ImTextureID)(intptr_t)bitmap.
texture(),
1103 ImVec2(0, 0), ImVec2(1, 1), IM_COL32(255, 255, 255, alpha));
1109 ImVec2 src_pos, ImVec2 src_size) {
1119 (ImTextureID)(intptr_t)bitmap.
texture(),
1121 ImVec2(
canvas_p0_.x + dest_pos.x + dest_size.x,
1123 ImVec2(src_pos.x / bitmap.
width(), src_pos.y / bitmap.
height()),
1124 ImVec2((src_pos.x + src_size.x) / bitmap.
width(),
1125 (src_pos.y + src_size.y) / bitmap.
height()));
1130 for (
const auto& [key, value] : gfx_bin) {
1131 int offset = 0x40 * (key + 1);
1136 draw_list_->AddImage((ImTextureID)(intptr_t)value.texture(),
1144 IM_COL32(255, 255, 255, 200));
1158 int tile_size,
float scale,
int local_map_size,
1159 ImVec2 total_map_size) {
1164 if (group.empty()) {
1170 bool use_optimized_rendering =
1174 const int small_map = local_map_size;
1175 const float large_map_width = total_map_size.x;
1176 const float large_map_height = total_map_size.y;
1179 const float tile_scale = tile_size * scale;
1188 static_cast<int>(std::floor(rect_top_left.x / (tile_size * scale)));
1190 static_cast<int>(std::floor(rect_top_left.y / (tile_size * scale)));
1192 static_cast<int>(std::floor(rect_bottom_right.x / (tile_size * scale)));
1194 static_cast<int>(std::floor(rect_bottom_right.y / (tile_size * scale)));
1196 if (start_tile_x > end_tile_x)
1197 std::swap(start_tile_x, end_tile_x);
1198 if (start_tile_y > end_tile_y)
1199 std::swap(start_tile_y, end_tile_y);
1202 int rect_width = (end_tile_x - start_tile_x) * tile_size;
1203 int rect_height = (end_tile_y - start_tile_y) * tile_size;
1205 int tiles_per_row = rect_width / tile_size;
1206 int tiles_per_col = rect_height / tile_size;
1209 for (
int y = 0; y < tiles_per_col + 1; ++y) {
1210 for (
int x = 0; x < tiles_per_row + 1; ++x) {
1212 if (i >=
static_cast<int>(group.size())) {
1216 int tile_id = group[i];
1220 if (tile_id >= 0 && tile_id < tilemap_size) {
1222 int tile_pos_x = (x + start_tile_x) * tile_size * scale;
1223 int tile_pos_y = (y + start_tile_y) * tile_size * scale;
1227 atlas_tiles_per_row > 0) {
1229 (tile_id % atlas_tiles_per_row) * tilemap.
tile_size.
x;
1231 (tile_id / atlas_tiles_per_row) * tilemap.
tile_size.
y;
1234 if (atlas_tile_x >= 0 && atlas_tile_x < tilemap.
atlas.
width() &&
1235 atlas_tile_y >= 0 && atlas_tile_y < tilemap.
atlas.
height()) {
1238 const float atlas_width =
static_cast<float>(tilemap.
atlas.
width());
1239 const float atlas_height =
1242 ImVec2(atlas_tile_x / atlas_width, atlas_tile_y / atlas_height);
1244 ImVec2((atlas_tile_x + tilemap.
tile_size.
x) / atlas_width,
1245 (atlas_tile_y + tilemap.
tile_size.
y) / atlas_height);
1250 float screen_w = tilemap.
tile_size.
x * scale;
1251 float screen_h = tilemap.
tile_size.
y * scale;
1254 uint32_t alpha_color = use_optimized_rendering
1255 ? IM_COL32(255, 255, 255, 200)
1256 : IM_COL32(255, 255, 255, 150);
1261 ImVec2(screen_x, screen_y),
1262 ImVec2(screen_x + screen_w, screen_y + screen_h), uv0, uv1,
1270 if (i >=
static_cast<int>(group.size())) {
1278 const ImGuiIO& io = GetIO();
1280 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
1284 ImVec2 clamped_mouse_pos = mouse_pos;
1288 int mouse_local_map_x =
static_cast<int>(mouse_pos.x) / small_map;
1289 int mouse_local_map_y =
static_cast<int>(mouse_pos.y) / small_map;
1292 float potential_end_x = mouse_pos.x + rect_width;
1293 float potential_end_y = mouse_pos.y + rect_height;
1296 int potential_end_map_x =
static_cast<int>(potential_end_x) / small_map;
1297 int potential_end_map_y =
static_cast<int>(potential_end_y) / small_map;
1300 if (potential_end_map_x != mouse_local_map_x) {
1302 float max_mouse_x = (mouse_local_map_x + 1) * small_map - rect_width;
1303 clamped_mouse_pos.x = std::min(mouse_pos.x, max_mouse_x);
1306 if (potential_end_map_y != mouse_local_map_y) {
1308 float max_mouse_y = (mouse_local_map_y + 1) * small_map - rect_height;
1309 clamped_mouse_pos.y = std::min(mouse_pos.y, max_mouse_y);
1314 auto new_start_pos = AlignPosToGrid(clamped_mouse_pos, tile_size * scale);
1318 std::clamp(new_start_pos.x, 0.0f, large_map_width - rect_width);
1320 std::clamp(new_start_pos.y, 0.0f, large_map_height - rect_height);
1325 ImVec2(new_start_pos.x + rect_width, new_start_pos.y + rect_height));
1360 for (
float x = fmodf(
scrolling_.x, grid_step);
1362 for (
float y = fmodf(
scrolling_.y, grid_step);
1366 int tile_id = tile_x + (tile_y * tile_id_offset);
1368 if (tile_id >=
labels_[label_id].size()) {
1371 std::string label =
labels_[label_id][tile_id];
1373 ImVec2(
canvas_p0_.x + x + (grid_step / 2) - tile_id_offset,
1374 canvas_p0_.y + y + (grid_step / 2) - tile_id_offset),
1399 .grid_step = grid_step};
1434 ImDrawList*
draw_list = ImGui::GetWindowDrawList();
1436 Text(
"Blue shape is drawn first: appears in back");
1437 Text(
"Red shape is drawn after: appears in front");
1438 ImVec2 p0 = ImGui::GetCursorScreenPos();
1439 draw_list->AddRectFilled(ImVec2(p0.x, p0.y), ImVec2(p0.x + 50, p0.y + 50),
1440 IM_COL32(0, 0, 255, 255));
1441 draw_list->AddRectFilled(ImVec2(p0.x + 25, p0.y + 25),
1442 ImVec2(p0.x + 75, p0.y + 75),
1443 IM_COL32(255, 0, 0, 255));
1444 ImGui::Dummy(ImVec2(75, 75));
1448 Text(
"Blue shape is drawn first, into channel 1: appears in front");
1449 Text(
"Red shape is drawn after, into channel 0: appears in back");
1450 ImVec2 p1 = ImGui::GetCursorScreenPos();
1457 draw_list->AddRectFilled(ImVec2(p1.x, p1.y), ImVec2(p1.x + 50, p1.y + 50),
1458 IM_COL32(0, 0, 255, 255));
1460 draw_list->AddRectFilled(ImVec2(p1.x + 25, p1.y + 25),
1461 ImVec2(p1.x + 75, p1.y + 75),
1462 IM_COL32(255, 0, 0, 255));
1468 ImGui::Dummy(ImVec2(75, 75));
1469 Text(
"After reordering, contents of channel 0 appears below channel 1.");
1477 ImVec2 effective_size = child_size;
1478 if (child_size.x == 0 && child_size.y == 0) {
1487 ImGui::BeginChild(canvas.
canvas_id().c_str(), effective_size,
true,
1488 ImGuiWindowFlags_AlwaysVerticalScrollbar);
1501 int num_sheets_to_load,
int canvas_id,
1504 if (ImGuiID child_id =
1505 ImGui::GetID((ImTextureID)(intptr_t)(intptr_t)canvas_id);
1506 ImGui::BeginChild(child_id, ImGui::GetContentRegionAvail(),
true,
1507 ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
1508 canvas.
DrawBackground(ImVec2(width + 1, num_sheets_to_load * height + 1));
1511 for (
const auto& [key, value] : graphics_bin) {
1512 int offset = height * (key + 1);
1515 top_left_y = canvas.
zero_point().y + height * key;
1518 (ImTextureID)(intptr_t)value.texture(),
1519 ImVec2(canvas.
zero_point().x + 2, top_left_y),
1532 int height,
int tile_size,
bool is_loaded,
1533 bool scrollbar,
int canvas_id) {
1535 int height,
int tile_size,
bool is_loaded) {
1545 if (ImGuiID child_id =
1546 ImGui::GetID((ImTextureID)(intptr_t)(intptr_t)canvas_id);
1547 ImGui::BeginChild(child_id, ImGui::GetContentRegionAvail(),
true,
1548 ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
1549 draw_canvas(canvas, bitmap, width, height, tile_size, is_loaded);
1553 draw_canvas(canvas, bitmap, width, height, tile_size, is_loaded);
1558 const std::string& label,
bool auto_resize) {
1562 if (auto_resize && bitmap.
is_active()) {
1564 ImVec2 content_size = ImVec2(bitmap.
width(), bitmap.
height());
1619 if (ImGui::BeginPopupModal(
"Advanced Canvas Properties",
nullptr,
1620 ImGuiWindowFlags_AlwaysAutoResize)) {
1621 ImGui::Text(
"Advanced Canvas Configuration");
1625 ImGui::Text(
"Canvas Properties");
1637 ImGui::Text(
"Minimum Size: %.0f x %.0f", min_size.x, min_size.y);
1638 ImGui::Text(
"Preferred Size: %.0f x %.0f", preferred_size.x,
1644 ImGui::Text(
"View Settings");
1651 if (ImGui::Checkbox(
"Enable Custom Labels",
1667 ImGui::Text(
"Grid Configuration");
1675 ImGui::Text(
"Scale Configuration");
1683 ImGui::Text(
"Scrolling Configuration");
1685 if (ImGui::Button(
"Reset Scroll")) {
1689 if (ImGui::Button(
"Center View")) {
1700 if (ImGui::Button(
"Close")) {
1701 ImGui::CloseCurrentPopup();
1745 if (ImGui::BeginPopupModal(
"Scaling Controls",
nullptr,
1746 ImGuiWindowFlags_AlwaysAutoResize)) {
1747 ImGui::Text(
"Canvas Scaling and Display Controls");
1758 ImGui::Text(
"Preset Scales:");
1759 if (ImGui::Button(
"0.25x")) {
1764 if (ImGui::Button(
"0.5x")) {
1769 if (ImGui::Button(
"1x")) {
1774 if (ImGui::Button(
"2x")) {
1779 if (ImGui::Button(
"4x")) {
1784 if (ImGui::Button(
"8x")) {
1791 ImGui::Text(
"Grid Configuration");
1799 ImGui::Text(
"Grid Presets:");
1800 if (ImGui::Button(
"8x8")) {
1805 if (ImGui::Button(
"16x16")) {
1810 if (ImGui::Button(
"32x32")) {
1815 if (ImGui::Button(
"64x64")) {
1822 ImGui::Text(
"Canvas Information");
1825 ImGui::Text(
"Scaled Size: %.0f x %.0f",
1831 "Effective Scale: %.3f x %.3f",
1836 if (ImGui::Button(
"Close")) {
1837 ImGui::CloseCurrentPopup();
1847 std::make_unique<gui::BppFormatUI>(
canvas_id_ +
"_bpp_format");
1860 std::make_unique<gui::BppFormatUI>(
canvas_id_ +
"_bpp_format");
1878 ConvertBitmapFormat(format);
1890 if (current_format == target_format) {
1907 }
catch (
const std::exception& e) {
1908 SDL_Log(
"Failed to convert bitmap format: %s", e.what());
The Rom class is used to load, save, and modify Rom data.
Represents a bitmap image optimized for SNES ROM hacking.
const SnesPalette & palette() const
TextureHandle texture() const
const std::vector< uint8_t > & vector() const
SnesPalette * mutable_palette()
void WriteColor(int position, const ImVec4 &color)
Write a color to a pixel at the given position.
void set_data(const std::vector< uint8_t > &data)
void UpdateTexture()
Updates the underlying SDL_Texture when it already exists.
Defines an abstract interface for all rendering operations.
RAII timer for automatic timing management.
Programmatic interface for controlling canvas operations.
Modern, robust canvas for drawing and manipulating graphics.
ImVector< ImVec2 > points_
void DrawBitmap(Bitmap &bitmap, int border_offset, float scale)
void ShowScalingControls()
bool WasDoubleClicked(ImGuiMouseButton button=ImGuiMouseButton_Left) const
ImVec2 selected_tile_pos_
auto global_scale() const
void DrawOutlineWithColor(int x, int y, int w, int h, ImVec4 color)
void DrawBitmapGroup(std::vector< int > &group, gfx::Tilemap &tilemap, int tile_size, float scale=1.0f, int local_map_size=0x200, ImVec2 total_map_size=ImVec2(0x1000, 0x1000))
Draw group of bitmaps for multi-tile selection preview.
bool BeginTableCanvas(const std::string &label="")
void InitializeEnhancedComponents()
void ShowBppConversionDialog()
CanvasAutomationAPI * GetAutomationAPI()
std::vector< ContextMenuItem > context_menu_items_
void ShowAdvancedCanvasProperties()
void UpdateInfoGrid(ImVec2 bg_size, float grid_size=64.0f, int label_id=0)
std::unique_ptr< gui::BppFormatUI > bpp_format_ui_
canvas::CanvasUsage GetUsageMode() const
ImVec2 mouse_pos_in_canvas_
bool DrawTilemapPainter(gfx::Tilemap &tilemap, int current_tile)
bool DrawSolidTilePainter(const ImVec4 &color, int size)
bool enable_context_menu_
void DrawLayeredElements()
void ReserveTableSpace(const std::string &label="")
bool enable_custom_labels_
ImVec2 GetMinimumSize() const
bool DrawTileSelector(int size, int size_y=0)
bool ConvertBitmapFormat(gfx::BppFormat target_format)
void DrawGridLines(float grid_step)
void DrawContextMenuItem(const ContextMenuItem &item)
void ClearContextMenuItems()
void ApplyConfigSnapshot(const canvas::CanvasConfig &snapshot)
void DrawRect(int x, int y, int w, int h, ImVec4 color)
bool HasValidSelection() const
bool DrawTilePainter(const Bitmap &bitmap, int size, float scale=1.0f)
ImVector< ImVec2 > selected_points_
ImVec2 GetCurrentSize() const
void SetCanvasSize(ImVec2 canvas_size)
void UpdateColorPainter(gfx::IRenderer *renderer, gfx::Bitmap &bitmap, const ImVec4 &color, const std::function< void()> &event, int tile_size, float scale=1.0f)
void DrawTileOnBitmap(int tile_size, gfx::Bitmap *bitmap, ImVec4 color)
void DrawCustomHighlight(float grid_step)
CanvasGridSize grid_size() const
std::vector< PopupState > active_popups_
ImVec2 GetPreferredSize() const
void InitializePaletteEditor(Rom *rom)
void Begin(ImVec2 canvas_size=ImVec2(0, 0))
Begin canvas rendering (ImGui-style)
std::shared_ptr< canvas::CanvasUsageTracker > usage_tracker_
void SetZoomToFit(const gfx::Bitmap &bitmap)
bool WasClicked(ImGuiMouseButton button=ImGuiMouseButton_Left) const
ImVector< ImVector< std::string > > labels_
gfx::BppFormat GetCurrentBppFormat() const
void ClosePersistentPopup(const std::string &popup_id)
void ShowBppFormatSelector()
void RecordCanvasOperation(const std::string &operation_name, double time_ms)
void RenderPersistentPopups()
void SetGridSize(CanvasGridSize grid_size)
bool IsAutoResize() const
void SetUsageMode(canvas::CanvasUsage usage)
void End()
End canvas rendering (ImGui-style)
float GetGlobalScale() const
std::unique_ptr< gui::BppConversionDialog > bpp_conversion_dialog_
void DrawSelectRect(int current_map, int tile_size=0x10, float scale=1.0f)
std::unique_ptr< PaletteWidget > palette_editor_
std::unique_ptr< canvas::CanvasContextMenu > context_menu_
ImVec2 GetLastClickPosition() const
std::unique_ptr< canvas::CanvasModals > modals_
void DrawOutline(int x, int y, int w, int h)
void DrawInfoGrid(float grid_step=64.0f, int tile_id_offset=8, int label_id=0)
CanvasSelection selection_
bool enable_hex_tile_labels_
void OpenPersistentPopup(const std::string &popup_id, std::function< void()> render_callback)
void DrawBitmapTable(const BitmapTable &gfx_bin)
void DrawBackground(ImVec2 canvas_size=ImVec2(0, 0))
void InitializeDefaults()
std::shared_ptr< canvas::CanvasPerformanceIntegration > performance_integration_
std::unique_ptr< CanvasAutomationAPI > automation_api_
void SetAutoResize(bool auto_resize)
void SetGlobalScale(float scale)
void DrawGrid(float grid_step=64.0f, int tile_id_offset=8)
void DrawText(const std::string &text, int x, int y)
canvas::CanvasInteractionHandler interaction_handler_
void AddContextMenuItem(const ContextMenuItem &item)
std::vector< ImVec2 > selected_tiles_
bool ApplyROMPalette(int group_index, int palette_index)
void ApplyScaleSnapshot(const canvas::CanvasConfig &snapshot)
void Initialize(const std::string &canvas_id)
Initialize the interaction handler.
void RegisterTracker(const std::string &canvas_id, std::shared_ptr< CanvasUsageTracker > tracker)
Register a canvas tracker.
static CanvasUsageManager & Get()
BppFormat
BPP format enumeration for SNES graphics.
@ kBpp8
8 bits per pixel (256 colors)
std::unordered_map< int, gfx::Bitmap > BitmapTable
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)
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)
ImVec2 CalculateMinimumCanvasSize(ImVec2 content_size, float global_scale, float padding)
void DrawCanvasOutline(ImDrawList *draw_list, ImVec2 canvas_p0, ImVec2 scrolling, int x, int y, int w, int h, uint32_t color)
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 AlignPosToGrid(ImVec2 pos, float scale)
CanvasUsage
Canvas usage patterns and tracking.
Graphical User Interface (GUI) components for the application.
constexpr uint32_t kWhiteColor
constexpr uint32_t kRectangleColor
void BitmapCanvasPipeline(gui::Canvas &canvas, gfx::Bitmap &bitmap, int width, int height, int tile_size, bool is_loaded, bool scrollbar, int canvas_id)
void EndCanvas(Canvas &canvas)
void BeginCanvas(Canvas &canvas, ImVec2 child_size)
void GraphicsBinCanvasPipeline(int width, int height, int tile_size, int num_sheets_to_load, int canvas_id, bool is_loaded, gfx::BitmapTable &graphics_bin)
void TableCanvasPipeline(gui::Canvas &canvas, gfx::Bitmap &bitmap, const std::string &label, bool auto_resize)
constexpr ImGuiButtonFlags kMouseFlags
int y
Y coordinate or height.
int x
X coordinate or width.
Tilemap structure for SNES tile-based graphics management.
Pair tile_size
Size of individual tiles (8x8 or 16x16)
Pair map_size
Size of tilemap in tiles.
Bitmap atlas
Master bitmap containing all tiles.
bool clamp_rect_to_local_maps
bool enable_custom_labels
Canvas configuration options for modals.
bool enable_custom_labels
std::function< void(const CanvasConfig &)> on_config_changed
std::function< void(const CanvasConfig &)> on_scale_changed