6#include "imgui/imgui.h"
15 return ImVec2(std::floor(pos.x / grid_step) * grid_step,
16 std::floor(pos.y / grid_step) * grid_step);
37 ImVec2 canvas_p0, ImVec2 scrolling,
float ,
38 float , ImVec2 ,
bool is_hovered) {
46 const ImGuiIO& imgui_io = ImGui::GetIO();
47 const ImVec2 origin(canvas_p0.x + scrolling.x, canvas_p0.y + scrolling.y);
49 ImVec2(imgui_io.MousePos.x - origin.x, imgui_io.MousePos.y - origin.y);
59 const gfx::Bitmap& bitmap, ImDrawList* draw_list, ImVec2 canvas_p0,
60 ImVec2 scrolling,
float global_scale,
float tile_size,
bool is_hovered) {
61 const ImGuiIO& imgui_io = ImGui::GetIO();
62 const ImVec2 origin(canvas_p0.x + scrolling.x, canvas_p0.y + scrolling.y);
63 const ImVec2 mouse_pos(imgui_io.MousePos.x - origin.x,
64 imgui_io.MousePos.y - origin.y);
65 const auto scaled_size = tile_size * global_scale;
77 ImVec2 paint_pos = AlignToGridLocal(mouse_pos, scaled_size);
80 ImVec2(paint_pos.x + scaled_size, paint_pos.y + scaled_size);
87 draw_list->AddImage(
reinterpret_cast<ImTextureID
>(bitmap.
texture()),
88 ImVec2(origin.x + paint_pos.x, origin.y + paint_pos.y),
89 ImVec2(origin.x + paint_pos.x + scaled_size,
90 origin.y + paint_pos.y + scaled_size),
91 ImVec2(0, 0), ImVec2(1, 1),
92 ImGui::GetColorU32(ImVec4(1, 1, 1, 1)));
96 if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) &&
97 ImGui::IsMouseDragging(ImGuiMouseButton_Left)) {
106 gfx::Tilemap& tilemap,
int current_tile, ImDrawList* draw_list,
107 ImVec2 canvas_p0, ImVec2 scrolling,
float global_scale,
bool is_hovered) {
108 const ImGuiIO& imgui_io = ImGui::GetIO();
109 const ImVec2 origin(canvas_p0.x + scrolling.x, canvas_p0.y + scrolling.y);
110 const ImVec2 mouse_pos(imgui_io.MousePos.x - origin.x,
111 imgui_io.MousePos.y - origin.y);
118 const auto scaled_size = tilemap.
tile_size.
x * global_scale;
127 ImVec2 paint_pos =
AlignToGrid(mouse_pos, scaled_size);
132 ImVec2(paint_pos.x + scaled_size, paint_pos.y + scaled_size));
137 if (tiles_per_row > 0) {
138 int tile_x = (current_tile % tiles_per_row) * tilemap.
tile_size.
x;
139 int tile_y = (current_tile / tiles_per_row) * tilemap.
tile_size.
y;
141 if (tile_x >= 0 && tile_x < tilemap.
atlas.
width() && tile_y >= 0 &&
144 ImVec2(
static_cast<float>(tile_x) / tilemap.
atlas.
width(),
145 static_cast<float>(tile_y) / tilemap.
atlas.
height());
146 ImVec2 uv1 = ImVec2(
static_cast<float>(tile_x + tilemap.
tile_size.
x) /
148 static_cast<float>(tile_y + tilemap.
tile_size.
y) /
153 ImVec2(origin.x + paint_pos.x, origin.y + paint_pos.y),
154 ImVec2(origin.x + paint_pos.x + scaled_size,
155 origin.y + paint_pos.y + scaled_size),
156 uv0, uv1, ImGui::GetColorU32(ImVec4(1, 1, 1, 1)));
161 if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) ||
162 ImGui::IsMouseDragging(ImGuiMouseButton_Left)) {
171 const ImVec4& color, ImDrawList* draw_list, ImVec2 canvas_p0,
172 ImVec2 scrolling,
float global_scale,
float tile_size,
bool is_hovered) {
173 const ImGuiIO& imgui_io = ImGui::GetIO();
174 const ImVec2 origin(canvas_p0.x + scrolling.x, canvas_p0.y + scrolling.y);
175 const ImVec2 mouse_pos(imgui_io.MousePos.x - origin.x,
176 imgui_io.MousePos.y - origin.y);
177 auto scaled_tile_size = tile_size * global_scale;
178 static bool is_dragging =
false;
179 static ImVec2 start_drag_pos;
188 ImVec2 paint_pos =
AlignToGrid(mouse_pos, scaled_tile_size);
196 ImVec2(paint_pos.x + scaled_tile_size, paint_pos.y + scaled_tile_size));
199 draw_list->AddRectFilled(
200 ImVec2(origin.x + paint_pos.x + 1, origin.y + paint_pos.y + 1),
201 ImVec2(origin.x + paint_pos.x + scaled_tile_size,
202 origin.y + paint_pos.y + scaled_tile_size),
203 IM_COL32(color.x * 255, color.y * 255, color.z * 255, 255));
206 if (ImGui::IsMouseClicked(ImGuiMouseButton_Left)) {
208 start_drag_pos = paint_pos;
211 if (is_dragging && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) {
225 const ImGuiIO& imgui_io = ImGui::GetIO();
226 const ImVec2 origin(canvas_p0.x + scrolling.x, canvas_p0.y + scrolling.y);
227 const ImVec2 mouse_pos(imgui_io.MousePos.x - origin.x,
228 imgui_io.MousePos.y - origin.y);
230 if (is_hovered && ImGui::IsMouseClicked(ImGuiMouseButton_Left)) {
232 ImVec2 painter_pos = AlignToGridLocal(mouse_pos, tile_size);
236 ImVec2(painter_pos.x + tile_size, painter_pos.y + tile_size));
240 if (is_hovered && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
248 int current_map, ImDrawList* draw_list, ImVec2 canvas_p0, ImVec2 scrolling,
249 float global_scale,
float tile_size,
bool is_hovered) {
259 ImVec2(tile_size * global_scale, tile_size * global_scale);
261 ImVec2(tile_size, tile_size);
265 geometry, current_map, tile_size, draw_list, ImGuiMouseButton_Right);
268 if (event.is_complete) {
277 if (!event.selected_tiles.empty() && !event.is_complete) {
292 return AlignToGridLocal(pos, grid_step);
297 const ImGuiIO& imgui_io = ImGui::GetIO();
298 const ImVec2 origin(canvas_p0.x + scrolling.x, canvas_p0.y + scrolling.y);
299 return ImVec2(imgui_io.MousePos.x - origin.x, imgui_io.MousePos.y - origin.y);
303 return ImGui::IsMouseClicked(button);
307 return ImGui::IsMouseDoubleClicked(button);
311 return ImGui::IsMouseDragging(button);
315 return ImGui::IsMouseReleased(button);
Free functions for canvas interaction handling.
Represents a bitmap image optimized for SNES ROM hacking.
TextureHandle texture() const
ImVector< ImVec2 > hover_points_
bool DrawSelectRect(int current_map, ImDrawList *draw_list, ImVec2 canvas_p0, ImVec2 scrolling, float global_scale, float tile_size, bool is_hovered)
Draw rectangle selector (multi-tile selection)
ImVector< ImVec2 > selected_points_
void ClearState()
Clear all interaction state.
bool DrawTilemapPainter(gfx::Tilemap &tilemap, int current_tile, ImDrawList *draw_list, ImVec2 canvas_p0, ImVec2 scrolling, float global_scale, bool is_hovered)
Draw tilemap painter (preview + interaction)
ImVec2 AlignPosToGrid(ImVec2 pos, float grid_step)
ImVec2 selected_tile_pos_
TileInteractionResult Update(ImVec2 canvas_p0, ImVec2 scrolling, float global_scale, float tile_size, ImVec2 canvas_size, bool is_hovered)
Update interaction state (call once per frame)
ImVec2 mouse_pos_in_canvas_
bool DrawTileSelector(ImDrawList *draw_list, ImVec2 canvas_p0, ImVec2 scrolling, float tile_size, bool is_hovered)
Draw tile selector (single tile selection)
bool DrawSolidTilePainter(const ImVec4 &color, ImDrawList *draw_list, ImVec2 canvas_p0, ImVec2 scrolling, float global_scale, float tile_size, bool is_hovered)
Draw solid color painter.
bool IsMouseClicked(ImGuiMouseButton button)
bool IsMouseDragging(ImGuiMouseButton button)
bool IsMouseReleased(ImGuiMouseButton button)
bool IsMouseDoubleClicked(ImGuiMouseButton button)
std::vector< ImVec2 > selected_tiles_
bool DrawTilePainter(const gfx::Bitmap &bitmap, ImDrawList *draw_list, ImVec2 canvas_p0, ImVec2 scrolling, float global_scale, float tile_size, bool is_hovered)
Draw tile painter (preview + interaction)
ImVec2 GetMousePosition(ImVec2 canvas_p0, ImVec2 scrolling)
void Initialize(const std::string &canvas_id)
Initialize the interaction handler.
TileInteractionMode current_mode_
ImVec2 AlignToGridLocal(ImVec2 pos, float grid_step)
ImVec2 AlignToGrid(ImVec2 pos, float grid_step)
Align position to grid.
RectSelectionEvent HandleRectangleSelection(const CanvasGeometry &geometry, int current_map, float tile_size, ImDrawList *draw_list, ImGuiMouseButton mouse_button)
Handle rectangle selection interaction.
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)
Bitmap atlas
Master bitmap containing all tiles.
Canvas geometry calculated per-frame.
Event payload for rectangle selection operations.
Result of a tile interaction operation.