yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
tile_selector_widget.cc
Go to the documentation of this file.
2
3#include <algorithm>
4
5namespace yaze::gui {
6
8 : config_(), total_tiles_(config_.total_tiles), widget_id_(std::move(widget_id)) {}
9
10TileSelectorWidget::TileSelectorWidget(std::string widget_id, Config config)
11 : config_(config), total_tiles_(config.total_tiles), widget_id_(std::move(widget_id)) {}
12
14
15void TileSelectorWidget::SetTileCount(int total_tiles) {
16 total_tiles_ = std::max(total_tiles, 0);
19 }
20}
21
23 if (IsValidTileId(tile_id)) {
24 selected_tile_id_ = tile_id;
25 }
26}
27
29 bool atlas_ready) {
30 RenderResult result;
31
32 if (!canvas_) {
33 return result;
34 }
35
36 const int tile_display_size =
37 static_cast<int>(config_.tile_size * config_.display_scale);
38
39 // Calculate total content size for ImGui child window scrolling
40 const int num_rows = (total_tiles_ + config_.tiles_per_row - 1) / config_.tiles_per_row;
41 const ImVec2 content_size(
42 config_.tiles_per_row * tile_display_size + config_.draw_offset.x * 2,
43 num_rows * tile_display_size + config_.draw_offset.y * 2
44 );
45
46 // Set content size for ImGui child window (must be called before DrawBackground)
47 ImGui::SetCursorPos(ImVec2(0, 0));
48 ImGui::Dummy(content_size);
49 ImGui::SetCursorPos(ImVec2(0, 0));
50
51 // Handle pending scroll (deferred from ScrollToTile call outside render context)
52 if (pending_scroll_tile_id_ >= 0) {
54 const ImVec2 target = TileOrigin(pending_scroll_tile_id_);
56 const ImVec2 window_size = ImGui::GetWindowSize();
57 float scroll_x = target.x - (window_size.x / 2.0f) + (tile_display_size / 2.0f);
58 float scroll_y = target.y - (window_size.y / 2.0f) + (tile_display_size / 2.0f);
59 scroll_x = std::max(0.0f, scroll_x);
60 scroll_y = std::max(0.0f, scroll_y);
61 ImGui::SetScrollX(scroll_x);
62 ImGui::SetScrollY(scroll_y);
63 }
64 }
65 pending_scroll_tile_id_ = -1; // Clear pending scroll
66 }
67
70
71 if (atlas_ready && atlas.is_active()) {
72 canvas_->DrawBitmap(atlas, static_cast<int>(config_.draw_offset.x),
73 static_cast<int>(config_.draw_offset.y),
75
76 result = HandleInteraction(tile_display_size);
77
79 DrawTileIdLabels(tile_display_size);
80 }
81
82 DrawHighlight(tile_display_size);
83 }
84
87
88 return result;
89}
90
92 int tile_display_size) {
93 RenderResult result;
94
95 if (!ImGui::IsItemHovered()) {
96 return result;
97 }
98
99 const bool clicked = ImGui::IsMouseClicked(ImGuiMouseButton_Left);
100 const bool double_clicked =
101 ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left);
102
103 if (clicked || double_clicked) {
104 const int hovered_tile = ResolveTileAtCursor(tile_display_size);
105 if (IsValidTileId(hovered_tile)) {
106 result.tile_clicked = clicked;
107 result.tile_double_clicked = double_clicked;
108 if (hovered_tile != selected_tile_id_) {
109 selected_tile_id_ = hovered_tile;
110 result.selection_changed = true;
111 }
113 }
114 }
115
116 return result;
117}
118
119int TileSelectorWidget::ResolveTileAtCursor(int tile_display_size) const {
120 if (!canvas_) {
121 return -1;
122 }
123
124 const ImVec2 screen_pos = ImGui::GetIO().MousePos;
125 const ImVec2 origin = canvas_->zero_point();
126 const ImVec2 scroll = canvas_->scrolling();
127
128 // Convert screen position to canvas content position (accounting for scroll)
129 ImVec2 local = ImVec2(screen_pos.x - origin.x - config_.draw_offset.x - scroll.x,
130 screen_pos.y - origin.y - config_.draw_offset.y - scroll.y);
131
132 if (local.x < 0.0f || local.y < 0.0f) {
133 return -1;
134 }
135
136 const int column = static_cast<int>(local.x / tile_display_size);
137 const int row = static_cast<int>(local.y / tile_display_size);
138
139 return row * config_.tiles_per_row + column;
140}
141
142void TileSelectorWidget::DrawHighlight(int tile_display_size) const {
144 return;
145 }
146
147 const int column = selected_tile_id_ % config_.tiles_per_row;
148 const int row = selected_tile_id_ / config_.tiles_per_row;
149
150 const float x = config_.draw_offset.x + column * tile_display_size;
151 const float y = config_.draw_offset.y + row * tile_display_size;
152
153 canvas_->DrawOutlineWithColor(static_cast<int>(x), static_cast<int>(y),
154 tile_display_size, tile_display_size,
156}
157
159 // Future enhancement: draw ImGui text overlay with tile indices.
160}
161
162void TileSelectorWidget::ScrollToTile(int tile_id, bool use_imgui_scroll) {
163 if (!canvas_ || !IsValidTileId(tile_id)) {
164 return;
165 }
166
167 // Defer scroll until next render (when we're in the correct ImGui window context)
168 pending_scroll_tile_id_ = tile_id;
169 pending_scroll_use_imgui_ = use_imgui_scroll;
170}
171
172ImVec2 TileSelectorWidget::TileOrigin(int tile_id) const {
173 if (!IsValidTileId(tile_id)) {
174 return ImVec2(-1, -1);
175 }
176 const int tile_display_size =
177 static_cast<int>(config_.tile_size * config_.display_scale);
178 const int column = tile_id % config_.tiles_per_row;
179 const int row = tile_id / config_.tiles_per_row;
180 return ImVec2(config_.draw_offset.x + column * tile_display_size,
181 config_.draw_offset.y + row * tile_display_size);
182}
183
184bool TileSelectorWidget::IsValidTileId(int tile_id) const {
185 return tile_id >= 0 && tile_id < total_tiles_;
186}
187
188} // namespace yaze::gui
189
190
Represents a bitmap image optimized for SNES ROM hacking.
Definition bitmap.h:66
bool is_active() const
Definition bitmap.h:264
Modern, robust canvas for drawing and manipulating graphics.
Definition canvas.h:54
void DrawBitmap(Bitmap &bitmap, int border_offset, float scale)
Definition canvas.cc:1062
void DrawOutlineWithColor(int x, int y, int w, int h, ImVec4 color)
Definition canvas.cc:1147
void DrawContextMenu()
Definition canvas.cc:441
auto zero_point() const
Definition canvas.h:310
auto scrolling() const
Definition canvas.h:311
void DrawBackground(ImVec2 canvas_size=ImVec2(0, 0))
Definition canvas.cc:381
void DrawGrid(float grid_step=64.0f, int tile_id_offset=8)
Definition canvas.cc:1386
int ResolveTileAtCursor(int tile_display_size) const
RenderResult Render(gfx::Bitmap &atlas, bool atlas_ready)
bool IsValidTileId(int tile_id) const
ImVec2 TileOrigin(int tile_id) const
RenderResult HandleInteraction(int tile_display_size)
void ScrollToTile(int tile_id, bool use_imgui_scroll=true)
void DrawTileIdLabels(int tile_display_size) const
void DrawHighlight(int tile_display_size) const
TileSelectorWidget(std::string widget_id)
Graphical User Interface (GUI) components for the application.