8#include "absl/strings/str_format.h"
9#include "imgui/imgui.h"
34 if (sprite_index.has_value()) {
38 ImVec2(
static_cast<float>(canvas_x),
static_cast<float>(canvas_y));
66 auto [tile_x, tile_y] =
74 auto& sprites = room->GetSprites();
92 if (!canvas->IsMouseHovering())
95 const ImGuiIO& io = ImGui::GetIO();
96 ImVec2 canvas_pos = canvas->zero_point();
100 int canvas_x =
static_cast<int>((io.MousePos.x - canvas_pos.x) / scale);
101 int canvas_y =
static_cast<int>((io.MousePos.y - canvas_pos.y) / scale);
110 size_t current_sprite_count = room ? room->GetSprites().size() : 0;
115 ImVec2 rect_min(canvas_pos.x + snapped_x * scale,
116 canvas_pos.y + snapped_y * scale);
121 ImVec4 fill_color = theme.status_success;
122 fill_color.w = 0.40f;
123 ImVec4 outline_color = theme.status_success;
124 outline_color.w = 0.85f;
125 if (at_sprite_limit) {
126 fill_color = theme.status_error;
127 fill_color.w = 0.40f;
128 outline_color = theme.status_error;
129 outline_color.w = 0.85f;
130 }
else if (near_sprite_limit) {
131 fill_color = theme.status_warning;
132 fill_color.w = 0.40f;
133 outline_color = theme.status_warning;
134 outline_color.w = 0.85f;
137 canvas->draw_list()->AddRectFilled(rect_min, rect_max,
138 ImGui::GetColorU32(fill_color));
139 canvas->draw_list()->AddRect(rect_min, rect_max, ImGui::GetColorU32(outline_color),
144 canvas->draw_list()->AddText(rect_min, ImGui::GetColorU32(theme.text_primary),
148 if ((at_sprite_limit || near_sprite_limit) &&
149 ImGui::IsMouseHoveringRect(rect_min, rect_max)) {
151 at_sprite_limit ?
"\nPlacement blocked" :
"\nNear limit");
164 const auto& sprites = room->GetSprites();
176 auto [tile_x, tile_y] =
185 ImDrawList* draw_list = ImGui::GetWindowDrawList();
189 ImVec2 pos(canvas_pos.x + pixel_x * scale, canvas_pos.y + pixel_y * scale);
194 static float pulse = 0.0f;
195 pulse += ImGui::GetIO().DeltaTime * 3.0f;
196 float alpha = 0.5f + 0.3f * sinf(pulse);
198 ImU32 color = IM_COL32(0, 255, 0, 180);
200 (color & 0x00FFFFFF) | (
static_cast<ImU32
>(alpha * 100) << 24);
202 draw_list->AddRectFilled(pos, ImVec2(pos.x + size.x, pos.y + size.y),
204 draw_list->AddRect(pos, ImVec2(pos.x + size.x, pos.y + size.y), color, 0.0f,
208 ImVec2 text_pos(pos.x, pos.y - 14 * scale);
209 draw_list->AddText(text_pos, IM_COL32(255, 255, 255, 220),
"Sprite");
213 int canvas_x,
int canvas_y)
const {
223 int room_x =
static_cast<int>(canvas_x / scale);
224 int room_y =
static_cast<int>(canvas_y / scale);
227 const auto& sprites = room->GetSprites();
228 for (
size_t i = 0; i < sprites.size(); ++i) {
229 const auto& sprite = sprites[i];
236 if (room_x >= sprite_x &&
238 room_y >= sprite_y &&
265 auto& sprites = room->GetSprites();
270 sprites.erase(sprites.begin() +
307 static_cast<uint8_t
>(sprite_y), 0, 0);
310 room->GetSprites().push_back(new_sprite);
317 int canvas_x,
int canvas_y)
const {
320 int pixel_x =
static_cast<int>(canvas_x / scale);
321 int pixel_y =
static_cast<int>(canvas_y / scale);
void TriggerSuccessToast()
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.
PlacementBlockReason placement_block_reason_
void DeleteSelected()
Delete selected sprite.
A class for managing sprites in the overworld and underworld.
const AgentUITheme & GetTheme()
constexpr int kSpriteGridMax
constexpr int kSpriteTileSize
Editors are the view controllers for the application.
constexpr size_t kMaxTotalSprites
const zelda3::Room * GetCurrentRoomConst() const
Get const pointer to current room.
void NotifyEntityChanged() const
Notify that entity has changed.
void NotifyInvalidateCache(MutationDomain domain=MutationDomain::kUnknown) const
Notify that cache invalidation is needed.
void NotifyMutation(MutationDomain domain=MutationDomain::kUnknown) const
Notify that a mutation is about to happen.