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<CanvasModals>();
180 std::make_shared<CanvasPerformanceIntegration>();
220 ImGui::OpenPopup(
"Canvas Usage Report");
221 if (ImGui::BeginPopupModal(
"Canvas Usage Report",
nullptr,
222 ImGuiWindowFlags_AlwaysAutoResize)) {
223 ImGui::Text(
"Canvas Usage Report");
225 ImGui::TextWrapped(
"%s", report.c_str());
227 if (ImGui::Button(
"Close")) {
228 ImGui::CloseCurrentPopup();
247 "Canvas Palette Editor");
287 std::string child_id =
canvas_id_ +
"_TableChild";
291 ImGui::BeginChild(child_id.c_str(), child_size,
293 ImGuiWindowFlags_AlwaysVerticalScrollbar);
295 if (!label.empty()) {
296 ImGui::Text(
"%s", label.c_str());
316 return ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(button) &&
324 return ImVec2(-1, -1);
349 const std::function<
void()>& event,
350 int tile_size,
float scale) {
378 GetCursorScreenPos(),
379 GetContentRegionAvail());
400 if (IsItemHovered()) {
401 const ImGuiIO& io = GetIO();
413 const ImGuiIO& io = GetIO();
414 const bool is_active = IsItemActive();
417 if (
const float mouse_threshold_for_pan =
420 IsMouseDragging(ImGuiMouseButton_Right, mouse_threshold_for_pan)) {
429 const ImGuiIO& io = GetIO();
434 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
565 auto popup_callback = [
this](
const std::string& id, std::function<void()> callback) {
591 last_section.items.push_back(item);
600 std::function<
void()> render_callback) {
619 ImVec2 available = ImGui::GetContentRegionAvail();
620 float scale_x = available.x / bitmap.
width();
621 float scale_y = available.y / bitmap.
height();
671 const ImGuiIO& io = GetIO();
672 const bool is_hovered = IsItemHovered();
676 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
677 const auto scaled_size = size * scale;
691 ImVec2 paint_pos = AlignPosToGrid(mouse_pos, scaled_size);
694 ImVec2(paint_pos.x + scaled_size, paint_pos.y + scaled_size);
696 points_.push_back(paint_pos_end);
700 ImVec2(origin.x + paint_pos.x, origin.y + paint_pos.y),
701 ImVec2(origin.x + paint_pos.x + scaled_size,
702 origin.y + paint_pos.y + scaled_size));
705 if (IsMouseClicked(ImGuiMouseButton_Left) &&
706 ImGui::IsMouseDragging(ImGuiMouseButton_Left)) {
717 const ImGuiIO& io = GetIO();
718 const bool is_hovered = IsItemHovered();
721 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
739 ImVec2 paint_pos = AlignPosToGrid(mouse_pos, scaled_size);
744 ImVec2(paint_pos.x + scaled_size, paint_pos.y + scaled_size));
751 if (tiles_per_row > 0) {
752 int tile_x = (current_tile % tiles_per_row) * tilemap.
tile_size.
x;
753 int tile_y = (current_tile / tiles_per_row) * tilemap.
tile_size.
y;
756 if (tile_x >= 0 && tile_x < tilemap.
atlas.
width() && tile_y >= 0 &&
761 ImVec2(
static_cast<float>(tile_x) / tilemap.
atlas.
width(),
762 static_cast<float>(tile_y) / tilemap.
atlas.
height());
763 ImVec2 uv1 = ImVec2(
static_cast<float>(tile_x + tilemap.
tile_size.
x) /
765 static_cast<float>(tile_y + tilemap.
tile_size.
y) /
770 ImVec2(origin.x + paint_pos.x, origin.y + paint_pos.y),
771 ImVec2(origin.x + paint_pos.x + scaled_size,
772 origin.y + paint_pos.y + scaled_size),
778 if (IsMouseClicked(ImGuiMouseButton_Left) ||
779 ImGui::IsMouseDragging(ImGuiMouseButton_Left)) {
788 const ImGuiIO& io = GetIO();
789 const bool is_hovered = IsItemHovered();
793 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
795 static bool is_dragging =
false;
796 static ImVec2 start_drag_pos;
810 ImVec2 paint_pos = AlignPosToGrid(mouse_pos, scaled_tile_size);
819 ImVec2(paint_pos.x + scaled_tile_size, paint_pos.y + scaled_tile_size));
822 ImVec2(origin.x + paint_pos.x + 1, origin.y + paint_pos.y + 1),
823 ImVec2(origin.x + paint_pos.x + scaled_tile_size,
824 origin.y + paint_pos.y + scaled_tile_size),
825 IM_COL32(color.x * 255, color.y * 255, color.z * 255, 255));
827 if (IsMouseClicked(ImGuiMouseButton_Left)) {
829 start_drag_pos = paint_pos;
832 if (is_dragging && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) {
844 int tile_index_x =
static_cast<int>(position.x /
global_scale_) / tile_size;
845 int tile_index_y =
static_cast<int>(position.y /
global_scale_) / tile_size;
847 ImVec2 start_position(tile_index_x * tile_size, tile_index_y * tile_size);
850 for (
int y = 0; y < tile_size; ++y) {
851 for (
int x = 0; x < tile_size; ++x) {
854 (start_position.y + y) * bitmap->
width() + (start_position.x + x);
863 const ImGuiIO& io = GetIO();
864 const bool is_hovered = IsItemHovered();
867 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
872 if (is_hovered && IsMouseClicked(ImGuiMouseButton_Left)) {
876 ImVec2 painter_pos = AlignPosToGrid(mouse_pos, size);
878 points_.push_back(painter_pos);
879 points_.push_back(ImVec2(painter_pos.x + size, painter_pos.y + size_y));
883 if (is_hovered && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
893 const ImGuiIO& io = GetIO();
895 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
896 static ImVec2 drag_start_pos;
897 const float scaled_size = tile_size * scale;
898 static bool dragging =
false;
899 constexpr int small_map_size = 0x200;
902 const bool is_hovered = IsItemHovered();
909 if (current_map < 0x40) {
911 superY = current_map / 8;
912 superX = current_map % 8;
913 }
else if (current_map < 0x80) {
915 superY = (current_map - 0x40) / 8;
916 superX = (current_map - 0x40) % 8;
919 superY = (current_map - 0x80) / 8;
920 superX = (current_map - 0x80) % 8;
924 if (IsMouseClicked(ImGuiMouseButton_Right)) {
925 ImVec2 painter_pos = AlignPosToGrid(mouse_pos, scaled_size);
926 int painter_x = painter_pos.x;
927 int painter_y = painter_pos.y;
929 auto tile16_x = (painter_x % small_map_size) / (small_map_size / 0x20);
930 auto tile16_y = (painter_y % small_map_size) / (small_map_size / 0x20);
932 int index_x = superX * 0x20 + tile16_x;
933 int index_y = superY * 0x20 + tile16_y;
939 drag_start_pos = AlignPosToGrid(mouse_pos, scaled_size);
943 ImVec2 drag_end_pos = AlignPosToGrid(mouse_pos, scaled_size);
944 if (ImGui::IsMouseDragging(ImGuiMouseButton_Right)) {
946 auto start = ImVec2(origin.x + drag_start_pos.x,
947 origin.y + drag_start_pos.y);
948 auto end = ImVec2(origin.x + drag_end_pos.x + tile_size,
949 origin.y + drag_end_pos.y + tile_size);
954 if (dragging && !ImGui::IsMouseDown(ImGuiMouseButton_Right)) {
959 constexpr int tile16_size = 16;
960 int start_x = std::floor(drag_start_pos.x / scaled_size) * tile16_size;
961 int start_y = std::floor(drag_start_pos.y / scaled_size) * tile16_size;
962 int end_x = std::floor(drag_end_pos.x / scaled_size) * tile16_size;
963 int end_y = std::floor(drag_end_pos.y / scaled_size) * tile16_size;
967 std::swap(start_x, end_x);
969 std::swap(start_y, end_y);
973 ((end_y - start_y) / tile16_size + 1));
976 constexpr int tiles_per_local_map = small_map_size / 16;
979 for (
int y = start_y; y <= end_y; y += tile16_size) {
980 for (
int x = start_x; x <= end_x; x += tile16_size) {
982 int local_map_x = (x / small_map_size) % 8;
983 int local_map_y = (y / small_map_size) % 8;
986 int tile16_x = (x % small_map_size) / tile16_size;
987 int tile16_y = (y % small_map_size) / tile16_size;
990 int index_x = local_map_x * tiles_per_local_map + tile16_x;
991 int index_y = local_map_y * tiles_per_local_map + tile16_y;
1033 ImVec2 src_pos, ImVec2 src_size) {
1048 for (
const auto& [key, value] : gfx_bin) {
1049 int offset = 0x40 * (key + 1);
1054 draw_list_->AddImage((ImTextureID)(intptr_t)value.texture(),
1062 IM_COL32(255, 255, 255, 200));
1076 int tile_size,
float scale,
int local_map_size,
1077 ImVec2 total_map_size) {
1082 if (group.empty()) {
1088 bool use_optimized_rendering =
1092 const int small_map = local_map_size;
1093 const float large_map_width = total_map_size.x;
1094 const float large_map_height = total_map_size.y;
1097 const float tile_scale = tile_size * scale;
1106 static_cast<int>(std::floor(rect_top_left.x / (tile_size * scale)));
1108 static_cast<int>(std::floor(rect_top_left.y / (tile_size * scale)));
1110 static_cast<int>(std::floor(rect_bottom_right.x / (tile_size * scale)));
1112 static_cast<int>(std::floor(rect_bottom_right.y / (tile_size * scale)));
1114 if (start_tile_x > end_tile_x)
1115 std::swap(start_tile_x, end_tile_x);
1116 if (start_tile_y > end_tile_y)
1117 std::swap(start_tile_y, end_tile_y);
1120 int rect_width = (end_tile_x - start_tile_x) * tile_size;
1121 int rect_height = (end_tile_y - start_tile_y) * tile_size;
1123 int tiles_per_row = rect_width / tile_size;
1124 int tiles_per_col = rect_height / tile_size;
1127 for (
int y = 0; y < tiles_per_col + 1; ++y) {
1128 for (
int x = 0; x < tiles_per_row + 1; ++x) {
1130 if (i >=
static_cast<int>(group.size())) {
1134 int tile_id = group[i];
1138 if (tile_id >= 0 && tile_id < tilemap_size) {
1140 int tile_pos_x = (x + start_tile_x) * tile_size * scale;
1141 int tile_pos_y = (y + start_tile_y) * tile_size * scale;
1145 atlas_tiles_per_row > 0) {
1147 (tile_id % atlas_tiles_per_row) * tilemap.
tile_size.
x;
1149 (tile_id / atlas_tiles_per_row) * tilemap.
tile_size.
y;
1152 if (atlas_tile_x >= 0 && atlas_tile_x < tilemap.
atlas.
width() &&
1153 atlas_tile_y >= 0 && atlas_tile_y < tilemap.
atlas.
height()) {
1156 const float atlas_width =
static_cast<float>(tilemap.
atlas.
width());
1157 const float atlas_height =
1160 ImVec2(atlas_tile_x / atlas_width, atlas_tile_y / atlas_height);
1162 ImVec2((atlas_tile_x + tilemap.
tile_size.
x) / atlas_width,
1163 (atlas_tile_y + tilemap.
tile_size.
y) / atlas_height);
1168 float screen_w = tilemap.
tile_size.
x * scale;
1169 float screen_h = tilemap.
tile_size.
y * scale;
1172 uint32_t alpha_color = use_optimized_rendering
1173 ? IM_COL32(255, 255, 255, 200)
1174 : IM_COL32(255, 255, 255, 150);
1179 ImVec2(screen_x, screen_y),
1180 ImVec2(screen_x + screen_w, screen_y + screen_h), uv0, uv1,
1188 if (i >=
static_cast<int>(group.size())) {
1196 const ImGuiIO& io = GetIO();
1198 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
1202 ImVec2 clamped_mouse_pos = mouse_pos;
1206 int mouse_local_map_x =
static_cast<int>(mouse_pos.x) / small_map;
1207 int mouse_local_map_y =
static_cast<int>(mouse_pos.y) / small_map;
1210 float potential_end_x = mouse_pos.x + rect_width;
1211 float potential_end_y = mouse_pos.y + rect_height;
1214 int potential_end_map_x =
static_cast<int>(potential_end_x) / small_map;
1215 int potential_end_map_y =
static_cast<int>(potential_end_y) / small_map;
1218 if (potential_end_map_x != mouse_local_map_x) {
1220 float max_mouse_x = (mouse_local_map_x + 1) * small_map - rect_width;
1221 clamped_mouse_pos.x = std::min(mouse_pos.x, max_mouse_x);
1224 if (potential_end_map_y != mouse_local_map_y) {
1226 float max_mouse_y = (mouse_local_map_y + 1) * small_map - rect_height;
1227 clamped_mouse_pos.y = std::min(mouse_pos.y, max_mouse_y);
1232 auto new_start_pos = AlignPosToGrid(clamped_mouse_pos, tile_size * scale);
1236 std::clamp(new_start_pos.x, 0.0f, large_map_width - rect_width);
1238 std::clamp(new_start_pos.y, 0.0f, large_map_height - rect_height);
1243 ImVec2(new_start_pos.x + rect_width, new_start_pos.y + rect_height));
1278 for (
float x = fmodf(
scrolling_.x, grid_step);
1280 for (
float y = fmodf(
scrolling_.y, grid_step);
1284 int tile_id = tile_x + (tile_y * tile_id_offset);
1286 if (tile_id >=
labels_[label_id].size()) {
1289 std::string label =
labels_[label_id][tile_id];
1291 ImVec2(
canvas_p0_.x + x + (grid_step / 2) - tile_id_offset,
1292 canvas_p0_.y + y + (grid_step / 2) - tile_id_offset),
1317 .grid_step = grid_step};
1352 ImDrawList*
draw_list = ImGui::GetWindowDrawList();
1354 Text(
"Blue shape is drawn first: appears in back");
1355 Text(
"Red shape is drawn after: appears in front");
1356 ImVec2 p0 = ImGui::GetCursorScreenPos();
1357 draw_list->AddRectFilled(ImVec2(p0.x, p0.y), ImVec2(p0.x + 50, p0.y + 50),
1358 IM_COL32(0, 0, 255, 255));
1359 draw_list->AddRectFilled(ImVec2(p0.x + 25, p0.y + 25),
1360 ImVec2(p0.x + 75, p0.y + 75),
1361 IM_COL32(255, 0, 0, 255));
1362 ImGui::Dummy(ImVec2(75, 75));
1366 Text(
"Blue shape is drawn first, into channel 1: appears in front");
1367 Text(
"Red shape is drawn after, into channel 0: appears in back");
1368 ImVec2 p1 = ImGui::GetCursorScreenPos();
1375 draw_list->AddRectFilled(ImVec2(p1.x, p1.y), ImVec2(p1.x + 50, p1.y + 50),
1376 IM_COL32(0, 0, 255, 255));
1378 draw_list->AddRectFilled(ImVec2(p1.x + 25, p1.y + 25),
1379 ImVec2(p1.x + 75, p1.y + 75),
1380 IM_COL32(255, 0, 0, 255));
1386 ImGui::Dummy(ImVec2(75, 75));
1387 Text(
"After reordering, contents of channel 0 appears below channel 1.");
1395 ImVec2 effective_size = child_size;
1396 if (child_size.x == 0 && child_size.y == 0) {
1405 ImGui::BeginChild(canvas.
canvas_id().c_str(), effective_size,
true,
1406 ImGuiWindowFlags_AlwaysVerticalScrollbar);
1419 int num_sheets_to_load,
int canvas_id,
1422 if (ImGuiID child_id =
1423 ImGui::GetID((ImTextureID)(intptr_t)(intptr_t)canvas_id);
1424 ImGui::BeginChild(child_id, ImGui::GetContentRegionAvail(),
true,
1425 ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
1426 canvas.
DrawBackground(ImVec2(width + 1, num_sheets_to_load * height + 1));
1429 for (
const auto& [key, value] : graphics_bin) {
1430 int offset = height * (key + 1);
1433 top_left_y = canvas.
zero_point().y + height * key;
1436 (ImTextureID)(intptr_t)value.texture(),
1437 ImVec2(canvas.
zero_point().x + 2, top_left_y),
1452 int height,
int tile_size,
bool is_loaded,
1453 bool scrollbar,
int canvas_id) {
1455 int height,
int tile_size,
bool is_loaded) {
1467 if (ImGuiID child_id =
1468 ImGui::GetID((ImTextureID)(intptr_t)(intptr_t)canvas_id);
1469 ImGui::BeginChild(child_id, ImGui::GetContentRegionAvail(),
true,
1470 ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
1471 draw_canvas(canvas, bitmap, width, height, tile_size, is_loaded);
1475 draw_canvas(canvas, bitmap, width, height, tile_size, is_loaded);
1480 const std::string& label,
bool auto_resize) {
1484 if (auto_resize && bitmap.
is_active()) {
1486 ImVec2 content_size = ImVec2(bitmap.
width(), bitmap.
height());
1543 if (ImGui::BeginPopupModal(
"Advanced Canvas Properties",
nullptr,
1544 ImGuiWindowFlags_AlwaysAutoResize)) {
1545 ImGui::Text(
"Advanced Canvas Configuration");
1549 ImGui::Text(
"Canvas Properties");
1561 ImGui::Text(
"Minimum Size: %.0f x %.0f", min_size.x, min_size.y);
1562 ImGui::Text(
"Preferred Size: %.0f x %.0f", preferred_size.x,
1568 ImGui::Text(
"View Settings");
1575 if (ImGui::Checkbox(
"Enable Custom Labels",
1591 ImGui::Text(
"Grid Configuration");
1599 ImGui::Text(
"Scale Configuration");
1607 ImGui::Text(
"Scrolling Configuration");
1609 if (ImGui::Button(
"Reset Scroll")) {
1613 if (ImGui::Button(
"Center View")) {
1624 if (ImGui::Button(
"Close")) {
1625 ImGui::CloseCurrentPopup();
1669 if (ImGui::BeginPopupModal(
"Scaling Controls",
nullptr,
1670 ImGuiWindowFlags_AlwaysAutoResize)) {
1671 ImGui::Text(
"Canvas Scaling and Display Controls");
1682 ImGui::Text(
"Preset Scales:");
1683 if (ImGui::Button(
"0.25x")) {
1688 if (ImGui::Button(
"0.5x")) {
1693 if (ImGui::Button(
"1x")) {
1698 if (ImGui::Button(
"2x")) {
1703 if (ImGui::Button(
"4x")) {
1708 if (ImGui::Button(
"8x")) {
1715 ImGui::Text(
"Grid Configuration");
1723 ImGui::Text(
"Grid Presets:");
1724 if (ImGui::Button(
"8x8")) {
1729 if (ImGui::Button(
"16x16")) {
1734 if (ImGui::Button(
"32x32")) {
1739 if (ImGui::Button(
"64x64")) {
1746 ImGui::Text(
"Canvas Information");
1749 ImGui::Text(
"Scaled Size: %.0f x %.0f",
1755 "Effective Scale: %.3f x %.3f",
1760 if (ImGui::Button(
"Close")) {
1761 ImGui::CloseCurrentPopup();
1771 std::make_unique<gui::BppFormatUI>(
canvas_id_ +
"_bpp_format");
1784 std::make_unique<gui::BppFormatUI>(
canvas_id_ +
"_bpp_format");
1802 ConvertBitmapFormat(format);
1814 if (current_format == target_format) {
1831 }
catch (
const std::exception& e) {
1832 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.
void Initialize(const std::string &canvas_id)
Initialize the interaction handler.
Modern, robust canvas for drawing and manipulating graphics.
ImVector< ImVec2 > points_
void DrawBitmap(Bitmap &bitmap, int border_offset, float scale)
PopupRegistry popup_registry_
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 SetUsageMode(CanvasUsage usage)
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()
void ShowAdvancedCanvasProperties()
void ApplyScaleSnapshot(const CanvasConfig &snapshot)
void UpdateInfoGrid(ImVec2 bg_size, float grid_size=64.0f, int label_id=0)
std::unique_ptr< gui::BppFormatUI > bpp_format_ui_
ImVec2 mouse_pos_in_canvas_
bool DrawTilemapPainter(gfx::Tilemap &tilemap, int current_tile)
bool DrawSolidTilePainter(const ImVec4 &color, int size)
bool enable_context_menu_
CanvasMenuDefinition editor_menu_
std::unique_ptr< CanvasModals > modals_
void ApplyConfigSnapshot(const CanvasConfig &snapshot)
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 ClearContextMenuItems()
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
void AddContextMenuItem(const gui::CanvasMenuItem &item)
ImVec2 GetPreferredSize() const
CanvasInteractionHandler interaction_handler_
void InitializePaletteEditor(Rom *rom)
void Begin(ImVec2 canvas_size=ImVec2(0, 0))
Begin canvas rendering (ImGui-style)
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
std::shared_ptr< CanvasUsageTracker > usage_tracker_
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< CanvasContextMenu > context_menu_
ImVec2 GetLastClickPosition() const
void DrawOutline(int x, int y, int w, int h)
std::unique_ptr< PaletteEditorWidget > palette_editor_
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::unique_ptr< CanvasAutomationAPI > automation_api_
std::shared_ptr< CanvasPerformanceIntegration > performance_integration_
void SetAutoResize(bool auto_resize)
void SetGlobalScale(float scale)
void DrawGrid(float grid_step=64.0f, int tile_id_offset=8)
void DrawContextMenuItem(const gui::CanvasMenuItem &item)
void DrawText(const std::string &text, int x, int y)
std::vector< ImVec2 > selected_tiles_
bool ApplyROMPalette(int group_index, int palette_index)
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 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)
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)
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)
CanvasUsage
Canvas usage patterns and tracking.
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 ApplyScrollDelta(CanvasGeometry &geometry, ImVec2 delta)
Apply scroll delta to geometry.
ImVec2 CalculateMouseInCanvas(const CanvasGeometry &geometry, ImVec2 mouse_screen_pos)
Calculate mouse position in canvas space.
void RenderCanvasBackground(ImDrawList *draw_list, const CanvasGeometry &geometry)
Render canvas background and border.
CanvasGeometry CalculateCanvasGeometry(const CanvasConfig &config, ImVec2 requested_size, ImVec2 cursor_screen_pos, ImVec2 content_region_avail)
Calculate canvas geometry from configuration and ImGui context.
void RenderMenuItem(const CanvasMenuItem &item, std::function< void(const std::string &, std::function< void()>)> popup_opened_callback)
Render a single menu item.
void RenderBitmapOnCanvas(ImDrawList *draw_list, const CanvasGeometry &geometry, gfx::Bitmap &bitmap, int, float scale)
Render bitmap on canvas (border offset variant)
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.
Unified configuration for canvas display and interaction.
std::function< void(const CanvasConfig &)> on_config_changed
std::function< void(const CanvasConfig &)> on_scale_changed
bool clamp_rect_to_local_maps
bool enable_custom_labels
ImVec2 mouse_pos_in_canvas