19#include "imgui/imgui.h"
38 for (
auto& label_group :
labels_) {
44 Init(
id, ImVec2(0, 0));
73 Init(
id, ImVec2(0, 0));
148 extensions_ = std::make_unique<CanvasExtensions>();
153using ImGui::GetContentRegionAvail;
154using ImGui::GetCursorScreenPos;
156using ImGui::GetWindowDrawList;
157using ImGui::IsItemActive;
158using ImGui::IsItemHovered;
159using ImGui::IsMouseClicked;
160using ImGui::IsMouseDragging;
167 ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight;
171 return ImVec2(std::floor(pos.x / scale) * scale,
172 std::floor(pos.y / scale) * scale);
245 if (old_scale != scale) {
334 ImGui::OpenPopup(
"Canvas Usage Report");
335 if (ImGui::BeginPopupModal(
"Canvas Usage Report",
nullptr,
336 ImGuiWindowFlags_AlwaysAutoResize)) {
337 ImGui::Text(tr(
"Canvas Usage Report"));
339 ImGui::TextWrapped(
"%s", report.c_str());
341 if (ImGui::Button(tr(
"Close"))) {
342 ImGui::CloseCurrentPopup();
352 ext.InitializePaletteEditor();
353 if (ext.palette_editor) {
354 ext.palette_editor->Initialize(
rom);
368 ext.InitializePaletteEditor();
369 if (ext.palette_editor) {
371 ext.palette_editor->ShowPaletteEditor(*mutable_palette,
372 "Canvas Palette Editor");
380 ext.InitializePaletteEditor();
381 if (ext.palette_editor) {
382 ext.palette_editor->ShowColorAnalysis(*
bitmap_,
"Canvas Color Analysis");
418 std::string child_id =
canvas_id_ +
"_TableChild";
423 ImGui::BeginChild(child_id.c_str(), child_size,
425 ImGuiWindowFlags_NoScrollbar);
427 if (!label.empty()) {
428 ImGui::Text(
"%s", label.c_str());
442 if (child_size.x <= 0 || child_size.y <= 0) {
452 std::string child_id =
canvas_id_ +
"_TableChild";
453 ImGuiWindowFlags child_flags = ImGuiWindowFlags_NoScrollbar;
455 child_flags = ImGuiWindowFlags_AlwaysVerticalScrollbar;
457 ImGui::BeginChild(child_id.c_str(), child_size,
true, child_flags);
459 if (!label.empty()) {
460 ImGui::Text(
"%s", label.c_str());
505 return ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(button) &&
513 return ImVec2(-1, -1);
542 if (effective_size.x == 0 && effective_size.y == 0) {
550 ImGuiWindowFlags child_flags = ImGuiWindowFlags_None;
552 child_flags |= ImGuiWindowFlags_AlwaysVerticalScrollbar;
554 ImGui::BeginChild(
canvas_id().c_str(), effective_size,
true, child_flags);
590 const std::function<
void()>& event,
591 int tile_size,
float scale) {
636 if (IsItemHovered()) {
637 const ImGuiIO& io = GetIO();
650 ImGuiIO& io = GetIO();
651 const float wheel_x = io.MouseWheelH;
652 const float wheel_y = io.MouseWheel;
654 if (wheel_x != 0.0f || wheel_y != 0.0f) {
656 io.MouseWheelH = 0.0f;
657 io.MouseWheel = 0.0f;
659 if (io.KeyCtrl && wheel_y != 0.0f) {
661 constexpr float kMinScale = 0.25f;
662 constexpr float kMaxScale = 8.0f;
664 const float new_scale = std::clamp(unclamped, kMinScale, kMaxScale);
676 constexpr float kTouchWheelToPixels = 10.0f;
678 ImVec2(wheel_x * kTouchWheelToPixels,
679 wheel_y * kTouchWheelToPixels));
688 const ImGuiIO& io = GetIO();
689 const bool is_active = IsItemActive();
692 if (
const float mouse_threshold_for_pan =
695 IsMouseDragging(ImGuiMouseButton_Right, mouse_threshold_for_pan)) {
704 const ImGuiIO& io = GetIO();
709 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
791 ext.InitializeModals();
802 ext.modals->ShowAdvancedProperties(
canvas_id_, modal_config,
808 ext.InitializeModals();
819 ext.modals->ShowScalingControls(
canvas_id_, modal_config,
843 auto popup_callback = [
this](
const std::string& id,
844 std::function<void()> callback) {
870 last_section.items.push_back(item);
879 std::function<
void()> render_callback) {
898 ImVec2 available = ImGui::GetContentRegionAvail();
899 float scale_x = available.x / bitmap.
width();
900 float scale_y = available.y / bitmap.
height();
951 const ImGuiIO& io = GetIO();
952 const bool is_hovered = IsItemHovered();
956 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
957 const auto scaled_size = size * scale;
971 ImVec2 paint_pos = AlignPosToGrid(mouse_pos, scaled_size);
974 ImVec2(paint_pos.x + scaled_size, paint_pos.y + scaled_size);
976 points_.push_back(paint_pos_end);
980 ImVec2(origin.x + paint_pos.x, origin.y + paint_pos.y),
981 ImVec2(origin.x + paint_pos.x + scaled_size,
982 origin.y + paint_pos.y + scaled_size));
985 if (IsMouseClicked(ImGuiMouseButton_Left) &&
986 ImGui::IsMouseDragging(ImGuiMouseButton_Left)) {
1013 const ImGuiIO& io = GetIO();
1016 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
1018 ImVec2 paint_pos = AlignPosToGrid(mouse_pos, scaled_size);
1024 ImVec2(paint_pos.x + scaled_size, paint_pos.y + scaled_size));
1035 const ImGuiIO& io = GetIO();
1036 const bool is_hovered = IsItemHovered();
1040 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
1042 static bool is_dragging =
false;
1043 static ImVec2 start_drag_pos;
1057 ImVec2 paint_pos = AlignPosToGrid(mouse_pos, scaled_tile_size);
1066 ImVec2(paint_pos.x + scaled_tile_size, paint_pos.y + scaled_tile_size));
1069 ImVec2(origin.x + paint_pos.x + 1, origin.y + paint_pos.y + 1),
1070 ImVec2(origin.x + paint_pos.x + scaled_tile_size,
1071 origin.y + paint_pos.y + scaled_tile_size),
1072 IM_COL32(color.x * 255, color.y * 255, color.z * 255, 255));
1074 if (IsMouseClicked(ImGuiMouseButton_Left)) {
1076 start_drag_pos = paint_pos;
1079 if (is_dragging && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) {
1080 is_dragging =
false;
1091 int tile_index_x =
static_cast<int>(position.x /
global_scale_) / tile_size;
1092 int tile_index_y =
static_cast<int>(position.y /
global_scale_) / tile_size;
1094 ImVec2 start_position(tile_index_x * tile_size, tile_index_y * tile_size);
1097 for (
int y = 0; y < tile_size; ++y) {
1098 for (
int x = 0; x < tile_size; ++x) {
1101 (start_position.y + y) * bitmap->
width() + (start_position.x + x);
1119 ImVec2 selected_pos;
1123 if (
is_hovered_ && IsMouseClicked(ImGuiMouseButton_Left)) {
1124 const ImGuiIO& io = GetIO();
1127 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
1128 ImVec2 painter_pos = AlignPosToGrid(mouse_pos,
static_cast<float>(size));
1131 points_.push_back(painter_pos);
1132 points_.push_back(ImVec2(painter_pos.x + size, painter_pos.y + size_y));
1136 return double_clicked;
1205 ImVec2 src_pos, ImVec2 src_size) {
1221 for (
const auto& [key, value] : gfx_bin) {
1223 if (!value || !value->is_active() || !value->texture()) {
1226 int offset = 0x40 * (key + 1);
1231 draw_list_->AddImage((ImTextureID)(intptr_t)value->texture(),
1239 IM_COL32(255, 255, 255, 200));
1253 int tile_size,
float ,
int local_map_size,
1254 ImVec2 total_map_size) {
1259 if (group.empty()) {
1271 bool use_optimized_rendering =
1275 const int small_map = local_map_size;
1276 const float large_map_width = total_map_size.x;
1277 const float large_map_height = total_map_size.y;
1280 const float tile_scale = tile_size * effective_scale;
1289 int start_tile_x =
static_cast<int>(std::floor(rect_top_left.x / tile_size));
1290 int start_tile_y =
static_cast<int>(std::floor(rect_top_left.y / tile_size));
1292 static_cast<int>(std::floor(rect_bottom_right.x / tile_size));
1294 static_cast<int>(std::floor(rect_bottom_right.y / tile_size));
1296 if (start_tile_x > end_tile_x)
1297 std::swap(start_tile_x, end_tile_x);
1298 if (start_tile_y > end_tile_y)
1299 std::swap(start_tile_y, end_tile_y);
1302 int rect_width = (end_tile_x - start_tile_x) * tile_size;
1303 int rect_height = (end_tile_y - start_tile_y) * tile_size;
1305 int tiles_per_row = rect_width / tile_size;
1306 int tiles_per_col = rect_height / tile_size;
1309 for (
int y = 0; y < tiles_per_col + 1; ++y) {
1310 for (
int x = 0; x < tiles_per_row + 1; ++x) {
1312 if (i >=
static_cast<int>(group.size())) {
1316 int tile_id = group[i];
1320 if (tile_id >= 0 && tile_id < tilemap_size) {
1322 int tile_pos_x = (x + start_tile_x) * tile_size * effective_scale;
1323 int tile_pos_y = (y + start_tile_y) * tile_size * effective_scale;
1328 atlas_tiles_per_row > 0) {
1330 (tile_id % atlas_tiles_per_row) * tilemap.
tile_size.
x;
1332 (tile_id / atlas_tiles_per_row) * tilemap.
tile_size.
y;
1335 if (atlas_tile_x >= 0 && atlas_tile_x < tilemap.
atlas.
width() &&
1336 atlas_tile_y >= 0 && atlas_tile_y < tilemap.
atlas.
height()) {
1338 const float atlas_width =
static_cast<float>(tilemap.
atlas.
width());
1339 const float atlas_height =
1342 ImVec2(atlas_tile_x / atlas_width, atlas_tile_y / atlas_height);
1344 ImVec2((atlas_tile_x + tilemap.
tile_size.
x) / atlas_width,
1345 (atlas_tile_y + tilemap.
tile_size.
y) / atlas_height);
1350 float screen_w = tilemap.
tile_size.
x * effective_scale;
1351 float screen_h = tilemap.
tile_size.
y * effective_scale;
1354 uint32_t alpha_color = use_optimized_rendering
1355 ? IM_COL32(255, 255, 255, 200)
1356 : IM_COL32(255, 255, 255, 150);
1361 ImVec2(screen_x, screen_y),
1362 ImVec2(screen_x + screen_w, screen_y + screen_h), uv0, uv1,
1370 if (i >=
static_cast<int>(group.size())) {
1380 const ImGuiIO& io = GetIO();
1382 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
1387 ImVec2 clamped_mouse_pos = mouse_pos;
1391 int mouse_local_map_x =
static_cast<int>(mouse_pos.x) / small_map;
1392 int mouse_local_map_y =
static_cast<int>(mouse_pos.y) / small_map;
1396 float potential_end_x = mouse_pos.x + rect_width;
1397 float potential_end_y = mouse_pos.y + rect_height;
1400 int potential_end_map_x =
static_cast<int>(potential_end_x) / small_map;
1401 int potential_end_map_y =
static_cast<int>(potential_end_y) / small_map;
1404 if (potential_end_map_x != mouse_local_map_x) {
1406 float max_mouse_x = (mouse_local_map_x + 1) * small_map - rect_width;
1407 clamped_mouse_pos.x = std::min(mouse_pos.x, max_mouse_x);
1410 if (potential_end_map_y != mouse_local_map_y) {
1412 float max_mouse_y = (mouse_local_map_y + 1) * small_map - rect_height;
1413 clamped_mouse_pos.y = std::min(mouse_pos.y, max_mouse_y);
1418 auto new_start_pos_screen =
1419 AlignPosToGrid(clamped_mouse_pos, tile_size * effective_scale);
1422 ImVec2 new_start_pos_world(new_start_pos_screen.x / effective_scale,
1423 new_start_pos_screen.y / effective_scale);
1426 new_start_pos_world.x =
1427 std::clamp(new_start_pos_world.x, 0.0f, large_map_width - rect_width);
1428 new_start_pos_world.y =
1429 std::clamp(new_start_pos_world.y, 0.0f, large_map_height - rect_height);
1434 new_start_pos_world.y + rect_height));
1469 for (
float x = fmodf(
scrolling_.x, grid_step);
1471 for (
float y = fmodf(
scrolling_.y, grid_step);
1475 int tile_id = tile_x + (tile_y * tile_id_offset);
1477 if (tile_id >=
labels_[label_id].size()) {
1480 std::string label =
labels_[label_id][tile_id];
1482 ImVec2(
canvas_p0_.x + x + (grid_step / 2) - tile_id_offset,
1483 canvas_p0_.y + y + (grid_step / 2) - tile_id_offset),
1508 .grid_step = grid_step};
1544 ImDrawList*
draw_list = ImGui::GetWindowDrawList();
1546 Text(tr(
"Blue shape is drawn first: appears in back"));
1547 Text(tr(
"Red shape is drawn after: appears in front"));
1548 ImVec2 p0 = ImGui::GetCursorScreenPos();
1549 draw_list->AddRectFilled(ImVec2(p0.x, p0.y), ImVec2(p0.x + 50, p0.y + 50),
1550 IM_COL32(0, 0, 255, 255));
1551 draw_list->AddRectFilled(ImVec2(p0.x + 25, p0.y + 25),
1552 ImVec2(p0.x + 75, p0.y + 75),
1553 IM_COL32(255, 0, 0, 255));
1554 ImGui::Dummy(ImVec2(75, 75));
1558 Text(tr(
"Blue shape is drawn first, into channel 1: appears in front"));
1559 Text(tr(
"Red shape is drawn after, into channel 0: appears in back"));
1560 ImVec2 p1 = ImGui::GetCursorScreenPos();
1567 draw_list->AddRectFilled(ImVec2(p1.x, p1.y), ImVec2(p1.x + 50, p1.y + 50),
1568 IM_COL32(0, 0, 255, 255));
1570 draw_list->AddRectFilled(ImVec2(p1.x + 25, p1.y + 25),
1571 ImVec2(p1.x + 75, p1.y + 75),
1572 IM_COL32(255, 0, 0, 255));
1578 ImGui::Dummy(ImVec2(75, 75));
1580 tr(
"After reordering, contents of channel 0 appears below channel 1."));
1587 ext.InitializeModals();
1618 if (ImGui::BeginPopupModal(
"Advanced Canvas Properties",
nullptr,
1619 ImGuiWindowFlags_AlwaysAutoResize)) {
1620 ImGui::Text(tr(
"Advanced Canvas Configuration"));
1624 ImGui::Text(tr(
"Canvas Properties"));
1625 ImGui::Text(tr(
"ID: %s"),
canvas_id_.c_str());
1636 ImGui::Text(tr(
"Minimum Size: %.0f x %.0f"), min_size.x, min_size.y);
1637 ImGui::Text(tr(
"Preferred Size: %.0f x %.0f"), preferred_size.x,
1643 ImGui::Text(tr(
"View Settings"));
1650 if (ImGui::Checkbox(tr(
"Enable Custom Labels"),
1654 if (ImGui::Checkbox(tr(
"Enable Context Menu"),
1667 ImGui::Text(tr(
"Grid Configuration"));
1675 ImGui::Text(tr(
"Scale Configuration"));
1683 ImGui::Text(tr(
"Scrolling Configuration"));
1685 if (ImGui::Button(tr(
"Reset Scroll"))) {
1689 if (ImGui::Button(tr(
"Center View"))) {
1700 if (ImGui::Button(tr(
"Close"))) {
1701 ImGui::CloseCurrentPopup();
1712 ext.InitializeModals();
1741 ext.modals->ShowScalingControls(
canvas_id_, modal_config);
1746 if (ImGui::BeginPopupModal(
"Scaling Controls",
nullptr,
1747 ImGuiWindowFlags_AlwaysAutoResize)) {
1748 ImGui::Text(tr(
"Canvas Scaling and Display Controls"));
1759 ImGui::Text(tr(
"Preset Scales:"));
1760 if (ImGui::Button(tr(
"0.25x"))) {
1765 if (ImGui::Button(tr(
"0.5x"))) {
1770 if (ImGui::Button(tr(
"1x"))) {
1775 if (ImGui::Button(tr(
"2x"))) {
1780 if (ImGui::Button(tr(
"4x"))) {
1785 if (ImGui::Button(tr(
"8x"))) {
1792 ImGui::Text(tr(
"Grid Configuration"));
1800 ImGui::Text(tr(
"Grid Presets:"));
1801 if (ImGui::Button(tr(
"8x8"))) {
1806 if (ImGui::Button(tr(
"16x16"))) {
1811 if (ImGui::Button(tr(
"32x32"))) {
1816 if (ImGui::Button(tr(
"64x64"))) {
1823 ImGui::Text(tr(
"Canvas Information"));
1826 ImGui::Text(tr(
"Scaled Size: %.0f x %.0f"),
1830 ImGui::Text(tr(
"Bitmap Size: %d x %d"),
bitmap_->
width(),
1833 tr(
"Effective Scale: %.3f x %.3f"),
1838 if (ImGui::Button(tr(
"Close"))) {
1839 ImGui::CloseCurrentPopup();
1850 if (
bitmap_ && ext.bpp_format_ui) {
1851 ext.bpp_format_ui->RenderFormatSelector(
1861 if (
bitmap_ && ext.bpp_format_ui) {
1868 if (!ext.bpp_conversion_dialog) {
1869 ext.bpp_conversion_dialog = std::make_unique<gui::BppConversionDialog>(
1873 if (
bitmap_ && ext.bpp_conversion_dialog) {
1874 ext.bpp_conversion_dialog->Show(
1877 ConvertBitmapFormat(format);
1881 if (ext.bpp_conversion_dialog) {
1882 ext.bpp_conversion_dialog->Render();
1891 if (current_format == target_format) {
1908 }
catch (
const std::exception& e) {
1909 SDL_Log(
"Failed to convert bitmap format: %s", e.what());
1925 ext.InitializeAutomation(
this);
1926 return ext.automation_api.get();
1941 draw_list_->AddImage(texture, screen_pos, screen_end);
1952 draw_list_->AddRectFilled(screen_pos, screen_end, color);
1961 draw_list_->AddText(screen_pos, color, text.c_str());
1969 : canvas_(&canvas), options_(options), active_(true) {
1980 : canvas_(other.canvas_), options_(other.options_), active_(other.active_) {
1981 other.active_ =
false;
1985 if (
this != &other) {
1987 canvas_->
End(options_);
1989 canvas_ = other.canvas_;
1990 options_ = other.options_;
1991 active_ = other.active_;
1992 other.active_ =
false;
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
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.
Lightweight RAII guard for existing Canvas instances.
CanvasFrameOptions options_
CanvasFrame & operator=(const CanvasFrame &)=delete
CanvasFrame(Canvas &canvas, CanvasFrameOptions options=CanvasFrameOptions())
void ClearState()
Clear all interaction state.
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
gfx::IRenderer * renderer() 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()
CanvasRuntime BuildCurrentRuntime() const
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)
void EnsurePerformanceIntegration()
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_
void ApplyConfigSnapshot(const CanvasConfig &snapshot)
void DrawLayeredElements()
void ReserveTableSpace(const std::string &label="")
bool enable_custom_labels_
void AddTextAt(ImVec2 local_pos, const std::string &text, uint32_t color)
void SetRenderer(gfx::IRenderer *renderer)
ImVec2 GetMinimumSize() const
void AddRectFilledAt(ImVec2 local_top_left, ImVec2 size, uint32_t color)
bool DrawTileSelector(int size, int size_y=0)
bool ConvertBitmapFormat(gfx::BppFormat target_format)
void DrawGridLines(float grid_step)
void SetCustomGridStep(float step)
zelda3::GameData * game_data() const
void ClearContextMenuItems()
void AddImageAt(ImTextureID texture, ImVec2 local_top_left, ImVec2 size)
void SetGameData(zelda3::GameData *game_data)
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 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)
std::unique_ptr< CanvasExtensions > extensions_
CanvasGridSize grid_size() const
void AddContextMenuItem(const gui::CanvasMenuItem &item)
ImVec2 GetPreferredSize() const
float GetGridStep() 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 set_global_scale(float scale)
void SetGridSize(CanvasGridSize grid_size)
bool IsAutoResize() const
std::shared_ptr< CanvasUsageTracker > usage_tracker_
void End()
End canvas rendering (ImGui-style)
void EndInTable(CanvasRuntime &runtime, const CanvasFrameOptions &options)
void DrawSelectRect(int current_map, int tile_size=0x10, float scale=1.0f)
std::unique_ptr< CanvasContextMenu > context_menu_
ImVec2 GetLastClickPosition() const
zelda3::GameData * game_data_
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_
CanvasRuntime BeginInTable(const std::string &label, const CanvasFrameOptions &options)
Begin canvas in table cell with frame options (modern API) Returns CanvasRuntime for stateless helper...
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< CanvasPerformanceIntegration > performance_integration_
void Init(const CanvasConfig &config)
Initialize canvas with configuration (post-construction) Preferred over constructor parameters for ne...
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)
void SyncLegacyGeometryFromState()
CanvasExtensions & EnsureExtensions()
std::vector< ImVec2 > selected_tiles_
bool ApplyROMPalette(int group_index, int palette_index)
static bool IsTouchDevice()
::yaze::EventBus * event_bus()
Get the current EventBus instance.
BppFormat
BPP format enumeration for SNES graphics.
@ kBpp8
8 bits per pixel (256 colors)
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
CanvasUsage
Canvas usage patterns and tracking.
bool DrawTileSelector(const CanvasRuntime &rt, int size, int size_y, ImVec2 *out_selected_pos)
bool DrawTilemapPainter(const CanvasRuntime &rt, gfx::Tilemap &tilemap, int current_tile, ImVec2 *out_drawn_pos)
void ApplyScrollDelta(CanvasGeometry &geometry, ImVec2 delta)
Apply scroll delta to geometry.
ImVec2 ComputeScrollForZoomAtScreenPos(const CanvasGeometry &geometry, float old_scale, float new_scale, ImVec2 mouse_screen_pos)
Compute new scroll offset to keep a canvas point locked under the mouse.
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)
constexpr ImGuiButtonFlags kMouseFlags
void DrawSelectRect(const CanvasRuntime &rt, int current_map, int tile_size, float scale, CanvasSelection &selection)
static ZoomChangedEvent Create(const std::string &src, float old_z, float new_z, size_t session=0)
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)
bool clamp_rect_to_local_maps
std::function< void(const CanvasConfig &) on_scale_changed)
bool enable_custom_labels
Optional extension modules for Canvas.
std::optional< float > grid_step
Selection state for canvas interactions.
std::vector< ImVec2 > selected_tiles
std::vector< ImVec2 > selected_points
ImVec2 mouse_pos_in_canvas