11using ImGui::BeginChild;
16using ImGui::Selectable;
22 ImVec2 canvas_p0, ImVec2 scrolling) {
24 const ImGuiIO &io = ImGui::GetIO();
25 const ImVec2 origin(canvas_p0.x + scrolling.x, canvas_p0.y + scrolling.y);
26 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
29 if (mouse_pos.x >= entity.
x_ && mouse_pos.x <= entity.
x_ + 16 &&
30 mouse_pos.y >= entity.
y_ && mouse_pos.y <= entity.
y_ + 16) {
37 ImVec2 scrolling,
bool free_movement) {
39 const ImGuiIO &io = ImGui::GetIO();
40 const ImVec2 origin(canvas_p0.x + scrolling.x, canvas_p0.y + scrolling.y);
41 const ImVec2 mouse_pos(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
44 int new_x =
static_cast<int>(mouse_pos.x) / 16 * 16;
45 int new_y =
static_cast<int>(mouse_pos.y) / 16 * 16;
47 new_x =
static_cast<int>(mouse_pos.x) / 8 * 8;
48 new_y =
static_cast<int>(mouse_pos.y) / 8 * 8;
57 ImVec2 scrolling,
bool &is_dragging_entity,
61 std::string entity_type =
"Entity";
66 entity_type =
"Entrance";
68 entity_type =
"Sprite";
72 const auto is_hovering =
75 const auto drag_or_clicked = ImGui::IsMouseDragging(ImGuiMouseButton_Left) ||
76 ImGui::IsMouseClicked(ImGuiMouseButton_Left);
78 if (is_hovering && drag_or_clicked && !is_dragging_entity) {
79 dragged_entity = entity;
80 is_dragging_entity =
true;
81 }
else if (is_hovering && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
82 current_entity = entity;
83 ImGui::OpenPopup(absl::StrFormat(
"%s editor", entity_type.c_str()).c_str());
84 }
else if (is_dragging_entity && dragged_entity == entity &&
85 ImGui::IsMouseReleased(ImGuiMouseButton_Left)) {
88 is_dragging_entity =
false;
89 dragged_entity =
nullptr;
90 }
else if (is_dragging_entity && dragged_entity == entity) {
91 if (ImGui::BeginDragDropSource()) {
92 ImGui::SetDragDropPayload(
"ENTITY_PAYLOAD", &entity,
94 Text(
"Moving %s ID: %s", entity_type.c_str(),
96 ImGui::EndDragDropSource();
99 entity->
x_ = dragged_entity->
x_;
100 entity->
y_ = dragged_entity->
y_;
106 bool set_done =
false;
110 if (ImGui::BeginPopup(
"Entrance Inserter")) {
111 static int entrance_id = 0;
116 ImGui::CloseCurrentPopup();
121 ImGui::CloseCurrentPopup();
132 static bool set_done =
false;
136 if (ImGui::BeginPopupModal(
"Entrance editor", NULL,
137 ImGuiWindowFlags_AlwaysAutoResize)) {
145 ImGui::CloseCurrentPopup();
150 ImGui::CloseCurrentPopup();
155 ImGui::CloseCurrentPopup();
164 if (ImGui::BeginPopup(
"Exit Inserter")) {
165 static int exit_id = 0;
169 ImGui::CloseCurrentPopup();
174 ImGui::CloseCurrentPopup();
182 static bool set_done =
false;
186 if (ImGui::BeginPopupModal(
"Exit editor", NULL,
187 ImGuiWindowFlags_AlwaysAutoResize)) {
197 static int centerY = 0;
198 static int centerX = 0;
201 static int linkPosture = 0;
202 static int spriteGFX = 0;
203 static int bgGFX = 0;
204 static int palette = 0;
205 static int sprPal = 0;
207 static int bottom = 0;
209 static int right = 0;
210 static int leftEdgeOfMap = 0;
233 static bool show_properties =
false;
234 Checkbox(
"Show properties", &show_properties);
235 if (show_properties) {
236 Text(
"Deleted? %s", exit.
deleted_ ?
"true" :
"false");
237 Text(
"Hole? %s", exit.
is_hole_ ?
"true" :
"false");
238 Text(
"Large Map? %s", exit.
large_map_ ?
"true" :
"false");
243 ImGui::RadioButton(
"None", &doorType, 0);
245 ImGui::RadioButton(
"Wooden", &doorType, 1);
247 ImGui::RadioButton(
"Bombable", &doorType, 2);
254 ImGui::RadioButton(
"None##Fancy", &fancyDoorType, 0);
256 ImGui::RadioButton(
"Sanctuary", &fancyDoorType, 1);
258 ImGui::RadioButton(
"Palace", &fancyDoorType, 2);
260 if (fancyDoorType != 0) {
267 static bool special_exit =
false;
268 Checkbox(
"Special exit", &special_exit);
291 ImGui::CloseCurrentPopup();
298 ImGui::CloseCurrentPopup();
304 ImGui::CloseCurrentPopup();
315 if (ImGui::BeginPopup(
"Item Inserter")) {
316 static size_t new_item_id = 0;
318 BeginChild(
"ScrollRegion", ImVec2(150, 150),
true,
319 ImGuiWindowFlags_AlwaysVerticalScrollbar);
331 ImGui::CloseCurrentPopup();
336 ImGui::CloseCurrentPopup();
345 static bool set_done =
false;
349 if (ImGui::BeginPopupModal(
"Item editor", NULL,
350 ImGuiWindowFlags_AlwaysAutoResize)) {
351 BeginChild(
"ScrollRegion", ImVec2(150, 150),
true,
352 ImGuiWindowFlags_AlwaysVerticalScrollbar);
367 ImGui::CloseCurrentPopup();
372 ImGui::CloseCurrentPopup();
383 static ImGuiTextFilter filter;
384 static int selected_id = 0;
385 static std::vector<SpriteItem> items;
389 for (
int i = 0; i < 256; ++i) {
390 items.push_back(
SpriteItem{i, zelda3::kSpriteDefaultNames[i].data()});
394 filter.Draw(
"Filter", 180);
396 if (ImGui::BeginTable(
"##sprites", 2,
397 ImGuiTableFlags_Sortable | ImGuiTableFlags_Resizable)) {
398 ImGui::TableSetupColumn(
"ID", ImGuiTableColumnFlags_DefaultSort, 0.0f,
401 ImGui::TableHeadersRow();
404 if (ImGuiTableSortSpecs *sort_specs = ImGui::TableGetSortSpecs()) {
405 if (sort_specs->SpecsDirty) {
407 sort_specs->SpecsDirty =
false;
412 for (
const auto &item : items) {
413 if (filter.PassFilter(item.name)) {
414 ImGui::TableNextRow();
415 ImGui::TableSetColumnIndex(0);
417 ImGui::TableSetColumnIndex(1);
419 if (Selectable(item.name, selected_id == item.id,
420 ImGuiSelectableFlags_SpanAllColumns)) {
421 selected_id = item.id;
422 onSpriteSelect(item.id);
432 if (ImGui::BeginPopup(
"Sprite Inserter")) {
433 static int new_sprite_id = 0;
435 BeginChild(
"ScrollRegion", ImVec2(250, 250),
true,
436 ImGuiWindowFlags_AlwaysVerticalScrollbar);
443 ImGui::CloseCurrentPopup();
448 ImGui::CloseCurrentPopup();
456 static bool set_done =
false;
460 if (ImGui::BeginPopupModal(
"Sprite editor", NULL,
461 ImGuiWindowFlags_AlwaysAutoResize)) {
462 BeginChild(
"ScrollRegion", ImVec2(350, 350),
true,
463 ImGuiWindowFlags_AlwaysVerticalScrollbar);
465 Text(
"%s", sprite.
name().c_str());
468 sprite.
set_id(selected_id);
478 ImGui::CloseCurrentPopup();
483 ImGui::CloseCurrentPopup();
Base class for all overworld and dungeon entities.
virtual void UpdateMapProperties(uint16_t map_id)=0
enum yaze::app::zelda3::GameEntity::EntityType entity_type_
A class for managing sprites in the overworld and underworld.
void UpdateMapProperties(uint16_t map_id) override
auto set_deleted(bool deleted)
std::string UppercaseHexByte(uint8_t byte, bool leading)
void DrawSpriteInserterPopup()
bool IsMouseHoveringOverEntity(const zelda3::GameEntity &entity, ImVec2 canvas_p0, ImVec2 scrolling)
bool DrawEntranceInserterPopup()
bool DrawExitEditorPopup(zelda3::overworld::OverworldExit &exit)
bool DrawOverworldEntrancePopup(zelda3::overworld::OverworldEntrance &entrance)
bool DrawSpriteEditorPopup(zelda3::Sprite &sprite)
void DrawItemInsertPopup()
void DrawExitInserterPopup()
void MoveEntityOnGrid(zelda3::GameEntity *entity, ImVec2 canvas_p0, ImVec2 scrolling, bool free_movement)
void DrawSpriteTable(std::function< void(int)> onSpriteSelect)
void HandleEntityDragging(zelda3::GameEntity *entity, ImVec2 canvas_p0, ImVec2 scrolling, bool &is_dragging_entity, zelda3::GameEntity *&dragged_entity, zelda3::GameEntity *¤t_entity, bool free_movement)
bool DrawItemEditorPopup(zelda3::overworld::OverworldItem &item)
constexpr float kInputFieldSize
bool InputHexByte(const char *label, uint8_t *data, float input_width, bool no_step)
bool InputHex(const char *label, uint64_t *data)
void TextWithSeparators(const absl::string_view &text)
bool InputHexWord(const char *label, uint16_t *data, float input_width, bool no_step)
const std::vector< std::string > kSecretItemNames
static const ImGuiTableSortSpecs * s_current_sort_specs
static void SortWithSortSpecs(ImGuiTableSortSpecs *sort_specs, std::vector< SpriteItem > &items)