8#include "absl/strings/str_format.h"
9#include "imgui/imgui.h"
31 if (sprite_index.has_value()) {
35 static_cast<float>(canvas_y));
70 auto& sprites = room->GetSprites();
87 if (!canvas->IsMouseHovering())
return;
89 const ImGuiIO& io = ImGui::GetIO();
90 ImVec2 canvas_pos = canvas->zero_point();
94 int canvas_x =
static_cast<int>((io.MousePos.x - canvas_pos.x) / scale);
95 int canvas_y =
static_cast<int>((io.MousePos.y - canvas_pos.y) / scale);
104 ImVec2 rect_min(canvas_pos.x + snapped_x * scale,
105 canvas_pos.y + snapped_y * scale);
110 ImU32 fill_color = IM_COL32(50, 200, 50, 100);
111 ImU32 outline_color = IM_COL32(50, 255, 50, 200);
113 canvas->draw_list()->AddRectFilled(rect_min, rect_max, fill_color);
114 canvas->draw_list()->AddRect(rect_min, rect_max, outline_color, 0.0f, 0,
119 canvas->draw_list()->AddText(rect_min, IM_COL32(255, 255, 255, 255),
129 const auto& sprites = room->GetSprites();
149 ImDrawList* draw_list = ImGui::GetWindowDrawList();
153 ImVec2 pos(canvas_pos.x + pixel_x * scale, canvas_pos.y + pixel_y * scale);
158 static float pulse = 0.0f;
159 pulse += ImGui::GetIO().DeltaTime * 3.0f;
160 float alpha = 0.5f + 0.3f * sinf(pulse);
162 ImU32 color = IM_COL32(0, 255, 0, 180);
164 (color & 0x00FFFFFF) | (
static_cast<ImU32
>(alpha * 100) << 24);
166 draw_list->AddRectFilled(pos, ImVec2(pos.x + size.x, pos.y + size.y),
168 draw_list->AddRect(pos, ImVec2(pos.x + size.x, pos.y + size.y), color, 0.0f,
172 ImVec2 text_pos(pos.x, pos.y - 14 * scale);
173 draw_list->AddText(text_pos, IM_COL32(255, 255, 255, 220),
"Sprite");
177 int canvas_x,
int canvas_y)
const {
181 if (!room)
return std::nullopt;
185 int room_x =
static_cast<int>(canvas_x / scale);
186 int room_y =
static_cast<int>(canvas_y / scale);
189 const auto& sprites = room->GetSprites();
190 for (
size_t i = 0; i < sprites.size(); ++i) {
191 const auto& sprite = sprites[i];
198 if (room_x >= sprite_x &&
200 room_y >= sprite_y &&
225 auto& sprites = room->GetSprites();
229 sprites.erase(sprites.begin() +
252 static_cast<uint8_t
>(sprite_y), 0, 0);
255 room->GetSprites().push_back(new_sprite);
261 int canvas_x,
int canvas_y)
const {
264 int pixel_x =
static_cast<int>(canvas_x / scale);
265 int pixel_y =
static_cast<int>(canvas_y / scale);
InteractionContext * ctx_
float GetCanvasScale() const
Get canvas global scale.
zelda3::Room * GetCurrentRoom() const
Get current room (convenience method)
bool HasValidContext() const
Check if context is valid.
ImVec2 GetCanvasZeroPoint() const
Get canvas zero point (for screen coordinate conversion)
void PlaceSpriteAtPosition(int canvas_x, int canvas_y)
Place sprite at position.
void ClearSelection()
Clear sprite selection.
void HandleRelease() override
Handle mouse release.
void SelectSprite(size_t index)
Select sprite at index.
std::optional< size_t > selected_sprite_index_
std::optional< size_t > GetEntityAtPosition(int canvas_x, int canvas_y) const override
Get entity at canvas position.
void DrawGhostPreview() override
Draw ghost preview during placement.
uint8_t preview_sprite_id_
bool sprite_placement_mode_
void DrawSelectionHighlight() override
Draw selection highlight for selected entities.
void HandleDrag(ImVec2 current_pos, ImVec2 delta) override
Handle mouse drag.
bool HandleClick(int canvas_x, int canvas_y) override
Handle mouse click at canvas position.
std::pair< int, int > CanvasToSpriteCoords(int canvas_x, int canvas_y) const
Convert canvas to sprite coordinates (16-pixel grid)
void BeginPlacement() override
Begin placement mode.
void DeleteSelected()
Delete selected sprite.
A class for managing sprites in the overworld and underworld.
constexpr int kSpriteGridMax
constexpr int kSpriteTileSize
Editors are the view controllers for the application.
const zelda3::Room * GetCurrentRoomConst() const
Get const pointer to current room.
void NotifyEntityChanged() const
Notify that entity has changed.
void NotifyInvalidateCache() const
Notify that cache invalidation is needed.
void NotifyMutation() const
Notify that a mutation is about to happen.