8#include "absl/strings/str_format.h"
9#include "imgui/imgui.h"
35 if (item_index.has_value()) {
39 ImVec2(
static_cast<float>(canvas_x),
static_cast<float>(canvas_y));
73 const int encoded_x = pixel_x / 4;
74 const int encoded_y = pixel_y / 16;
75 const uint16_t next_position =
76 static_cast<uint16_t
>((encoded_y << 8) | encoded_x);
78 auto& pot_items = room->GetPotItems();
87 room->MarkPotItemsDirty();
101 if (!pointer_screen_pos.has_value())
105 const auto [canvas_x, canvas_y] =
116 ImVec2(
static_cast<float>(snapped_x),
static_cast<float>(snapped_y)));
118 const ImVec2 rect_max(rect_min.x + rect_size.x, rect_min.y + rect_size.y);
121 ImVec4 fill_color = theme.dungeon_selection_primary;
122 fill_color.w = 0.35f;
123 ImVec4 outline_color = theme.dungeon_selection_primary;
124 outline_color.w = 0.85f;
126 canvas->draw_list()->AddRectFilled(rect_min, rect_max,
127 ImGui::GetColorU32(fill_color));
128 canvas->draw_list()->AddRect(
129 rect_min, rect_max, ImGui::GetColorU32(outline_color), 0.0f, 0, 2.0f);
133 canvas->draw_list()->AddText(rect_min, ImGui::GetColorU32(theme.text_primary),
145 const auto& pot_items = room->GetPotItems();
150 int pixel_x = pot_item.GetPixelX();
151 int pixel_y = pot_item.GetPixelY();
162 ImDrawList* draw_list = ImGui::GetWindowDrawList();
164 const float scale = transform.
scale();
166 ImVec2(
static_cast<float>(pixel_x),
static_cast<float>(pixel_y)));
170 static float pulse = 0.0f;
171 pulse += ImGui::GetIO().DeltaTime * 3.0f;
172 float alpha = 0.5f + 0.3f * sinf(pulse);
174 ImU32 color = IM_COL32(255, 255, 0, 180);
176 (color & 0x00FFFFFF) | (
static_cast<ImU32
>(alpha * 100) << 24);
178 draw_list->AddRectFilled(pos, ImVec2(pos.x + size.x, pos.y + size.y),
180 draw_list->AddRect(pos, ImVec2(pos.x + size.x, pos.y + size.y), color, 0.0f,
184 ImVec2 text_pos(pos.x, pos.y - 14 * scale);
185 draw_list->AddText(text_pos, IM_COL32(255, 255, 255, 220),
"Item");
189 int canvas_x,
int canvas_y)
const {
199 for (
size_t i = 0; i < pot_items.size(); ++i) {
200 const auto& pot_item = pot_items[i];
202 int item_x = pot_item.GetPixelX();
203 int item_y = pot_item.GetPixelY();
206 if (canvas_x >= item_x && canvas_x < item_x + 16 && canvas_y >= item_y &&
207 canvas_y < item_y + 16) {
233 auto& pot_items = room->GetPotItems();
238 pot_items.erase(pot_items.begin() +
240 room->MarkPotItemsDirty();
252 if (!room || room->GetPotItems().empty()) {
257 room->GetPotItems().clear();
258 room->MarkPotItemsDirty();
275 auto& pot_items = room->GetPotItems();
281 constexpr int kRoomPixelMax = 511;
282 const int next_pixel_x =
283 std::clamp(pot_item.GetPixelX() + delta_pixel_x, 0, kRoomPixelMax);
284 const int next_pixel_y =
285 std::clamp(pot_item.GetPixelY() + delta_pixel_y, 0, kRoomPixelMax);
286 const int encoded_x = std::clamp(next_pixel_x / 4, 0, 255);
287 const int encoded_y = std::clamp(next_pixel_y / 16, 0, 255);
288 const uint16_t next_position =
289 static_cast<uint16_t
>((encoded_y << 8) | encoded_x);
290 if (next_position == pot_item.position) {
295 pot_item.position = next_position;
296 room->MarkPotItemsDirty();
310 int pixel_x = canvas_x;
311 int pixel_y = canvas_y;
315 int encoded_x = pixel_x / 4;
316 int encoded_y = pixel_y / 16;
319 encoded_x = std::clamp(encoded_x, 0, 255);
320 encoded_y = std::clamp(encoded_y, 0, 255);
326 new_item.
position =
static_cast<uint16_t
>((encoded_y << 8) | encoded_x);
330 room->GetPotItems().push_back(new_item);
331 room->MarkPotItemsDirty();
std::optional< ImVec2 > GetPointerScreenPosition() const
DungeonCanvasTransform GetCanvasTransform() const
InteractionContext * ctx_
bool IsWithinBounds(int canvas_x, int canvas_y) const
Check if coordinates are within room bounds.
zelda3::Room * GetCurrentRoom() const
Get current room (convenience method)
bool HasValidContext() const
Check if context is valid.
void DrawSelectionHighlight() override
Draw selection highlight for selected entities.
std::optional< size_t > selected_item_index_
bool HandleClick(int canvas_x, int canvas_y) override
Handle mouse click at canvas position.
void DrawGhostPreview() override
Draw ghost preview during placement.
void BeginPlacement() override
Begin placement mode.
void PlaceItemAtPosition(int canvas_x, int canvas_y)
Place item at position.
void HandleDrag(ImVec2 current_pos, ImVec2 delta) override
Handle mouse drag.
void ClearSelection()
Clear item selection.
std::optional< size_t > GetEntityAtPosition(int canvas_x, int canvas_y) const override
Get entity at canvas position.
bool item_placement_mode_
void DeleteSelected()
Delete selected item.
bool NudgeSelected(int delta_pixel_x, int delta_pixel_y)
void HandleRelease() override
Handle mouse release.
void SelectItem(size_t index)
Select item at index.
const std::vector< PotItem > & GetPotItems() const
const AgentUITheme & GetTheme()
constexpr int kRoomPixelHeight
constexpr int kRoomPixelWidth
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(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.