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) {
323 ImGui::OpenPopup(
"Canvas Usage Report");
324 if (ImGui::BeginPopupModal(
"Canvas Usage Report",
nullptr,
325 ImGuiWindowFlags_AlwaysAutoResize)) {
326 ImGui::Text(tr(
"Canvas Usage Report"));
328 ImGui::TextWrapped(
"%s", report.c_str());
330 if (ImGui::Button(tr(
"Close"))) {
331 ImGui::CloseCurrentPopup();
341 ext.InitializePaletteEditor();
342 if (ext.palette_editor) {
343 ext.palette_editor->Initialize(
rom);
357 ext.InitializePaletteEditor();
358 if (ext.palette_editor) {
360 ext.palette_editor->ShowPaletteEditor(*mutable_palette,
361 "Canvas Palette Editor");
369 ext.InitializePaletteEditor();
370 if (ext.palette_editor) {
371 ext.palette_editor->ShowColorAnalysis(*
bitmap_,
"Canvas Color Analysis");
407 std::string child_id =
canvas_id_ +
"_TableChild";
412 ImGui::BeginChild(child_id.c_str(), child_size,
414 ImGuiWindowFlags_NoScrollbar);
416 if (!label.empty()) {
417 ImGui::Text(
"%s", label.c_str());
431 if (child_size.x <= 0 || child_size.y <= 0) {
441 std::string child_id =
canvas_id_ +
"_TableChild";
442 ImGuiWindowFlags child_flags = ImGuiWindowFlags_NoScrollbar;
444 child_flags = ImGuiWindowFlags_AlwaysVerticalScrollbar;
446 ImGui::BeginChild(child_id.c_str(), child_size,
true, child_flags);
448 if (!label.empty()) {
449 ImGui::Text(
"%s", label.c_str());
494 return ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(button) &&
502 return ImVec2(-1, -1);
531 if (effective_size.x == 0 && effective_size.y == 0) {
539 ImGuiWindowFlags child_flags = ImGuiWindowFlags_None;
541 child_flags |= ImGuiWindowFlags_AlwaysVerticalScrollbar;
543 ImGui::BeginChild(
canvas_id().c_str(), effective_size,
true, child_flags);
579 const std::function<
void()>& event,
580 int tile_size,
float scale) {
625 if (IsItemHovered()) {
626 const ImGuiIO& io = GetIO();
639 ImGuiIO& io = GetIO();
640 const float wheel_x = io.MouseWheelH;
641 const float wheel_y = io.MouseWheel;
643 if (wheel_x != 0.0f || wheel_y != 0.0f) {
645 io.MouseWheelH = 0.0f;
646 io.MouseWheel = 0.0f;
648 if (io.KeyCtrl && wheel_y != 0.0f) {
650 constexpr float kMinScale = 0.25f;
651 constexpr float kMaxScale = 8.0f;
653 const float new_scale = std::clamp(unclamped, kMinScale, kMaxScale);
665 constexpr float kTouchWheelToPixels = 10.0f;
667 ImVec2(wheel_x * kTouchWheelToPixels,
668 wheel_y * kTouchWheelToPixels));
677 const ImGuiIO& io = GetIO();
678 const bool is_active = IsItemActive();
681 if (
const float mouse_threshold_for_pan =
684 IsMouseDragging(ImGuiMouseButton_Right, mouse_threshold_for_pan)) {
693 const ImGuiIO& io = GetIO();
698 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
780 ext.InitializeModals();
791 ext.modals->ShowAdvancedProperties(
canvas_id_, modal_config,
797 ext.InitializeModals();
808 ext.modals->ShowScalingControls(
canvas_id_, modal_config,
832 auto popup_callback = [
this](
const std::string& id,
833 std::function<void()> callback) {
859 last_section.items.push_back(item);
868 std::function<
void()> render_callback) {
887 ImVec2 available = ImGui::GetContentRegionAvail();
888 float scale_x = available.x / bitmap.
width();
889 float scale_y = available.y / bitmap.
height();
940 const ImGuiIO& io = GetIO();
941 const bool is_hovered = IsItemHovered();
945 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
946 const auto scaled_size = size * scale;
960 ImVec2 paint_pos = AlignPosToGrid(mouse_pos, scaled_size);
963 ImVec2(paint_pos.x + scaled_size, paint_pos.y + scaled_size);
965 points_.push_back(paint_pos_end);
969 ImVec2(origin.x + paint_pos.x, origin.y + paint_pos.y),
970 ImVec2(origin.x + paint_pos.x + scaled_size,
971 origin.y + paint_pos.y + scaled_size));
974 if (IsMouseClicked(ImGuiMouseButton_Left) &&
975 ImGui::IsMouseDragging(ImGuiMouseButton_Left)) {
1002 const ImGuiIO& io = GetIO();
1005 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
1007 ImVec2 paint_pos = AlignPosToGrid(mouse_pos, scaled_size);
1013 ImVec2(paint_pos.x + scaled_size, paint_pos.y + scaled_size));
1024 const ImGuiIO& io = GetIO();
1025 const bool is_hovered = IsItemHovered();
1029 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
1031 static bool is_dragging =
false;
1032 static ImVec2 start_drag_pos;
1046 ImVec2 paint_pos = AlignPosToGrid(mouse_pos, scaled_tile_size);
1055 ImVec2(paint_pos.x + scaled_tile_size, paint_pos.y + scaled_tile_size));
1058 ImVec2(origin.x + paint_pos.x + 1, origin.y + paint_pos.y + 1),
1059 ImVec2(origin.x + paint_pos.x + scaled_tile_size,
1060 origin.y + paint_pos.y + scaled_tile_size),
1061 IM_COL32(color.x * 255, color.y * 255, color.z * 255, 255));
1063 if (IsMouseClicked(ImGuiMouseButton_Left)) {
1065 start_drag_pos = paint_pos;
1068 if (is_dragging && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) {
1069 is_dragging =
false;
1080 int tile_index_x =
static_cast<int>(position.x /
global_scale_) / tile_size;
1081 int tile_index_y =
static_cast<int>(position.y /
global_scale_) / tile_size;
1083 ImVec2 start_position(tile_index_x * tile_size, tile_index_y * tile_size);
1086 for (
int y = 0; y < tile_size; ++y) {
1087 for (
int x = 0; x < tile_size; ++x) {
1090 (start_position.y + y) * bitmap->
width() + (start_position.x + x);
1108 ImVec2 selected_pos;
1112 if (
is_hovered_ && IsMouseClicked(ImGuiMouseButton_Left)) {
1113 const ImGuiIO& io = GetIO();
1116 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
1117 ImVec2 painter_pos = AlignPosToGrid(mouse_pos,
static_cast<float>(size));
1120 points_.push_back(painter_pos);
1121 points_.push_back(ImVec2(painter_pos.x + size, painter_pos.y + size_y));
1125 return double_clicked;
1194 ImVec2 src_pos, ImVec2 src_size) {
1210 for (
const auto& [key, value] : gfx_bin) {
1212 if (!value || !value->is_active() || !value->texture()) {
1215 int offset = 0x40 * (key + 1);
1220 draw_list_->AddImage((ImTextureID)(intptr_t)value->texture(),
1228 IM_COL32(255, 255, 255, 200));
1242 int tile_size,
float ,
int local_map_size,
1243 ImVec2 total_map_size) {
1248 if (group.empty()) {
1260 bool use_optimized_rendering =
1264 const int small_map = local_map_size;
1265 const float large_map_width = total_map_size.x;
1266 const float large_map_height = total_map_size.y;
1269 const float tile_scale = tile_size * effective_scale;
1278 int start_tile_x =
static_cast<int>(std::floor(rect_top_left.x / tile_size));
1279 int start_tile_y =
static_cast<int>(std::floor(rect_top_left.y / tile_size));
1281 static_cast<int>(std::floor(rect_bottom_right.x / tile_size));
1283 static_cast<int>(std::floor(rect_bottom_right.y / tile_size));
1285 if (start_tile_x > end_tile_x)
1286 std::swap(start_tile_x, end_tile_x);
1287 if (start_tile_y > end_tile_y)
1288 std::swap(start_tile_y, end_tile_y);
1291 int rect_width = (end_tile_x - start_tile_x) * tile_size;
1292 int rect_height = (end_tile_y - start_tile_y) * tile_size;
1294 int tiles_per_row = rect_width / tile_size;
1295 int tiles_per_col = rect_height / tile_size;
1298 for (
int y = 0; y < tiles_per_col + 1; ++y) {
1299 for (
int x = 0; x < tiles_per_row + 1; ++x) {
1301 if (i >=
static_cast<int>(group.size())) {
1305 int tile_id = group[i];
1309 if (tile_id >= 0 && tile_id < tilemap_size) {
1311 int tile_pos_x = (x + start_tile_x) * tile_size * effective_scale;
1312 int tile_pos_y = (y + start_tile_y) * tile_size * effective_scale;
1317 atlas_tiles_per_row > 0) {
1319 (tile_id % atlas_tiles_per_row) * tilemap.
tile_size.
x;
1321 (tile_id / atlas_tiles_per_row) * tilemap.
tile_size.
y;
1324 if (atlas_tile_x >= 0 && atlas_tile_x < tilemap.
atlas.
width() &&
1325 atlas_tile_y >= 0 && atlas_tile_y < tilemap.
atlas.
height()) {
1327 const float atlas_width =
static_cast<float>(tilemap.
atlas.
width());
1328 const float atlas_height =
1331 ImVec2(atlas_tile_x / atlas_width, atlas_tile_y / atlas_height);
1333 ImVec2((atlas_tile_x + tilemap.
tile_size.
x) / atlas_width,
1334 (atlas_tile_y + tilemap.
tile_size.
y) / atlas_height);
1339 float screen_w = tilemap.
tile_size.
x * effective_scale;
1340 float screen_h = tilemap.
tile_size.
y * effective_scale;
1343 uint32_t alpha_color = use_optimized_rendering
1344 ? IM_COL32(255, 255, 255, 200)
1345 : IM_COL32(255, 255, 255, 150);
1350 ImVec2(screen_x, screen_y),
1351 ImVec2(screen_x + screen_w, screen_y + screen_h), uv0, uv1,
1359 if (i >=
static_cast<int>(group.size())) {
1369 const ImGuiIO& io = GetIO();
1371 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
1376 ImVec2 clamped_mouse_pos = mouse_pos;
1380 int mouse_local_map_x =
static_cast<int>(mouse_pos.x) / small_map;
1381 int mouse_local_map_y =
static_cast<int>(mouse_pos.y) / small_map;
1385 float potential_end_x = mouse_pos.x + rect_width;
1386 float potential_end_y = mouse_pos.y + rect_height;
1389 int potential_end_map_x =
static_cast<int>(potential_end_x) / small_map;
1390 int potential_end_map_y =
static_cast<int>(potential_end_y) / small_map;
1393 if (potential_end_map_x != mouse_local_map_x) {
1395 float max_mouse_x = (mouse_local_map_x + 1) * small_map - rect_width;
1396 clamped_mouse_pos.x = std::min(mouse_pos.x, max_mouse_x);
1399 if (potential_end_map_y != mouse_local_map_y) {
1401 float max_mouse_y = (mouse_local_map_y + 1) * small_map - rect_height;
1402 clamped_mouse_pos.y = std::min(mouse_pos.y, max_mouse_y);
1407 auto new_start_pos_screen =
1408 AlignPosToGrid(clamped_mouse_pos, tile_size * effective_scale);
1411 ImVec2 new_start_pos_world(new_start_pos_screen.x / effective_scale,
1412 new_start_pos_screen.y / effective_scale);
1415 new_start_pos_world.x =
1416 std::clamp(new_start_pos_world.x, 0.0f, large_map_width - rect_width);
1417 new_start_pos_world.y =
1418 std::clamp(new_start_pos_world.y, 0.0f, large_map_height - rect_height);
1423 new_start_pos_world.y + rect_height));
1458 for (
float x = fmodf(
scrolling_.x, grid_step);
1460 for (
float y = fmodf(
scrolling_.y, grid_step);
1464 int tile_id = tile_x + (tile_y * tile_id_offset);
1466 if (tile_id >=
labels_[label_id].size()) {
1469 std::string label =
labels_[label_id][tile_id];
1471 ImVec2(
canvas_p0_.x + x + (grid_step / 2) - tile_id_offset,
1472 canvas_p0_.y + y + (grid_step / 2) - tile_id_offset),
1497 .grid_step = grid_step};
1533 ImDrawList*
draw_list = ImGui::GetWindowDrawList();
1535 Text(tr(
"Blue shape is drawn first: appears in back"));
1536 Text(tr(
"Red shape is drawn after: appears in front"));
1537 ImVec2 p0 = ImGui::GetCursorScreenPos();
1538 draw_list->AddRectFilled(ImVec2(p0.x, p0.y), ImVec2(p0.x + 50, p0.y + 50),
1539 IM_COL32(0, 0, 255, 255));
1540 draw_list->AddRectFilled(ImVec2(p0.x + 25, p0.y + 25),
1541 ImVec2(p0.x + 75, p0.y + 75),
1542 IM_COL32(255, 0, 0, 255));
1543 ImGui::Dummy(ImVec2(75, 75));
1547 Text(tr(
"Blue shape is drawn first, into channel 1: appears in front"));
1548 Text(tr(
"Red shape is drawn after, into channel 0: appears in back"));
1549 ImVec2 p1 = ImGui::GetCursorScreenPos();
1556 draw_list->AddRectFilled(ImVec2(p1.x, p1.y), ImVec2(p1.x + 50, p1.y + 50),
1557 IM_COL32(0, 0, 255, 255));
1559 draw_list->AddRectFilled(ImVec2(p1.x + 25, p1.y + 25),
1560 ImVec2(p1.x + 75, p1.y + 75),
1561 IM_COL32(255, 0, 0, 255));
1567 ImGui::Dummy(ImVec2(75, 75));
1569 tr(
"After reordering, contents of channel 0 appears below channel 1."));
1576 ext.InitializeModals();
1607 if (ImGui::BeginPopupModal(
"Advanced Canvas Properties",
nullptr,
1608 ImGuiWindowFlags_AlwaysAutoResize)) {
1609 ImGui::Text(tr(
"Advanced Canvas Configuration"));
1613 ImGui::Text(tr(
"Canvas Properties"));
1614 ImGui::Text(tr(
"ID: %s"),
canvas_id_.c_str());
1625 ImGui::Text(tr(
"Minimum Size: %.0f x %.0f"), min_size.x, min_size.y);
1626 ImGui::Text(tr(
"Preferred Size: %.0f x %.0f"), preferred_size.x,
1632 ImGui::Text(tr(
"View Settings"));
1639 if (ImGui::Checkbox(tr(
"Enable Custom Labels"),
1643 if (ImGui::Checkbox(tr(
"Enable Context Menu"),
1656 ImGui::Text(tr(
"Grid Configuration"));
1664 ImGui::Text(tr(
"Scale Configuration"));
1672 ImGui::Text(tr(
"Scrolling Configuration"));
1674 if (ImGui::Button(tr(
"Reset Scroll"))) {
1678 if (ImGui::Button(tr(
"Center View"))) {
1689 if (ImGui::Button(tr(
"Close"))) {
1690 ImGui::CloseCurrentPopup();
1701 ext.InitializeModals();
1730 ext.modals->ShowScalingControls(
canvas_id_, modal_config);
1735 if (ImGui::BeginPopupModal(
"Scaling Controls",
nullptr,
1736 ImGuiWindowFlags_AlwaysAutoResize)) {
1737 ImGui::Text(tr(
"Canvas Scaling and Display Controls"));
1748 ImGui::Text(tr(
"Preset Scales:"));
1749 if (ImGui::Button(tr(
"0.25x"))) {
1754 if (ImGui::Button(tr(
"0.5x"))) {
1759 if (ImGui::Button(tr(
"1x"))) {
1764 if (ImGui::Button(tr(
"2x"))) {
1769 if (ImGui::Button(tr(
"4x"))) {
1774 if (ImGui::Button(tr(
"8x"))) {
1781 ImGui::Text(tr(
"Grid Configuration"));
1789 ImGui::Text(tr(
"Grid Presets:"));
1790 if (ImGui::Button(tr(
"8x8"))) {
1795 if (ImGui::Button(tr(
"16x16"))) {
1800 if (ImGui::Button(tr(
"32x32"))) {
1805 if (ImGui::Button(tr(
"64x64"))) {
1812 ImGui::Text(tr(
"Canvas Information"));
1815 ImGui::Text(tr(
"Scaled Size: %.0f x %.0f"),
1819 ImGui::Text(tr(
"Bitmap Size: %d x %d"),
bitmap_->
width(),
1822 tr(
"Effective Scale: %.3f x %.3f"),
1827 if (ImGui::Button(tr(
"Close"))) {
1828 ImGui::CloseCurrentPopup();
1839 if (
bitmap_ && ext.bpp_format_ui) {
1840 ext.bpp_format_ui->RenderFormatSelector(
1850 if (
bitmap_ && ext.bpp_format_ui) {
1857 if (!ext.bpp_conversion_dialog) {
1858 ext.bpp_conversion_dialog = std::make_unique<gui::BppConversionDialog>(
1862 if (
bitmap_ && ext.bpp_conversion_dialog) {
1863 ext.bpp_conversion_dialog->Show(
1866 ConvertBitmapFormat(format);
1870 if (ext.bpp_conversion_dialog) {
1871 ext.bpp_conversion_dialog->Render();
1880 if (current_format == target_format) {
1897 }
catch (
const std::exception& e) {
1898 SDL_Log(
"Failed to convert bitmap format: %s", e.what());
1914 ext.InitializeAutomation(
this);
1915 return ext.automation_api.get();
1930 draw_list_->AddImage(texture, screen_pos, screen_end);
1941 draw_list_->AddRectFilled(screen_pos, screen_end, color);
1950 draw_list_->AddText(screen_pos, color, text.c_str());
1958 : canvas_(&canvas), options_(options), active_(true) {
1969 : canvas_(other.canvas_), options_(other.options_), active_(other.active_) {
1970 other.active_ =
false;
1974 if (
this != &other) {
1976 canvas_->
End(options_);
1978 canvas_ = other.canvas_;
1979 options_ = other.options_;
1980 active_ = other.active_;
1981 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 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