yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
door_editor_content.cc
Go to the documentation of this file.
2
3#include <algorithm>
4#include <array>
5#include <string>
6
7#include "absl/strings/str_format.h"
11#include "imgui/imgui.h"
12
13namespace yaze::editor {
14
15namespace {
16
17ImVec4 DoorTypeAccent(const AgentUITheme& theme, zelda3::DoorType type) {
18 const int type_val = static_cast<int>(type);
19 if (type_val <= 0x12) {
20 return theme.dungeon_object_door;
21 }
22 if (type_val <= 0x1E) {
23 return theme.status_warning;
24 }
25 return theme.status_success;
26}
27
29 switch (type) {
31 return "Normal";
33 return "Lower";
35 return "Cave";
37 return "2-Side";
39 return "Eye";
41 return "S-Key";
43 return "B-Key";
45 return "Up";
47 return "Down";
49 return "Dash";
51 return "Bomb";
53 return "Blast";
55 return "Curtain";
57 return "Bottom";
59 return "Top";
61 return "Exit";
63 return "Water";
65 return "Marker";
67 return "Layer";
69 return "Swap";
70 }
71 return "Door";
72}
73
74} // namespace
75
82
90
94
95void DoorEditorContent::Draw(bool* p_open) {
96 (void)p_open;
98
99 const auto& theme = AgentUI::GetTheme();
100 static constexpr std::array<zelda3::DoorType, 20> kDoorTypes = {{
121 }};
122
123 gui::SectionHeader(ICON_MD_DOOR_FRONT, "Door Styles", theme.text_info);
124 ImGui::TextColored(theme.text_secondary_gray,
125 "Select a door style, then click a wall in the room "
126 "canvas to place it.");
127
129 ImGui::TextColored(theme.status_warning, ICON_MD_PLACE " Active: %s",
131 .c_str());
132 ImGui::SameLine();
133 if (ImGui::SmallButton(ICON_MD_CANCEL " Cancel")) {
135 }
136 }
137
138 constexpr float kDoorCardHeight = 48.0f;
139 constexpr float kDoorCardSpacing = 6.0f;
140 constexpr float kMinDoorCardWidth = 92.0f;
141 const float panel_width = ImGui::GetContentRegionAvail().x;
142 const int items_per_row = std::max(
143 2, static_cast<int>((panel_width + kDoorCardSpacing) /
144 (kMinDoorCardWidth + kDoorCardSpacing)));
145 const float card_width =
146 std::max(kMinDoorCardWidth,
147 (panel_width - (items_per_row - 1) * kDoorCardSpacing) /
148 items_per_row);
149
150 ImGui::BeginChild("##DoorTypeGrid", ImVec2(0, 150), true,
151 ImGuiWindowFlags_AlwaysVerticalScrollbar);
152
153 int col = 0;
154 for (size_t i = 0; i < kDoorTypes.size(); ++i) {
155 const auto door_type = kDoorTypes[i];
156 const bool is_selected = selected_door_type_ == door_type;
157 const int type_val = static_cast<int>(door_type);
158 ImGui::PushID(static_cast<int>(i));
159
160 ImVec4 button_color = DoorTypeAccent(theme, door_type);
161 if (is_selected) {
162 button_color.x = std::min(1.0f, button_color.x + 0.2f);
163 button_color.y = std::min(1.0f, button_color.y + 0.2f);
164 button_color.z = std::min(1.0f, button_color.z + 0.2f);
165 }
166
167 gui::StyleColorGuard btn_colors({
168 {ImGuiCol_Button, button_color},
169 {ImGuiCol_ButtonHovered,
170 ImVec4(button_color.x + 0.1f, button_color.y + 0.1f,
171 button_color.z + 0.1f, 1.0f)},
172 {ImGuiCol_ButtonActive,
173 ImVec4(button_color.x + 0.2f, button_color.y + 0.2f,
174 button_color.z + 0.2f, 1.0f)},
175 });
176
177 const std::string label =
178 absl::StrFormat("%02X\n%s", type_val,
179 ShortDoorTypeLabel(door_type).c_str());
180 if (ImGui::Button(label.c_str(), ImVec2(card_width, kDoorCardHeight))) {
181 selected_door_type_ = door_type;
183 if (ResolveCanvasViewer()) {
185 true, selected_door_type_);
186 }
187 }
188
189 if (ImGui::IsItemHovered()) {
190 ImGui::SetTooltip("%s (0x%02X)\nClick to select for placement",
191 std::string(zelda3::GetDoorTypeName(door_type)).c_str(),
192 type_val);
193 }
194
195 if (is_selected) {
196 ImVec2 min = ImGui::GetItemRectMin();
197 ImVec2 max = ImGui::GetItemRectMax();
198 ImGui::GetWindowDrawList()->AddRect(min, max, IM_COL32(255, 255, 0, 255),
199 0.0f, 0, 2.0f);
200 }
201
202 ImGui::PopID();
203 col++;
204 if (col < items_per_row && i < kDoorTypes.size() - 1) {
205 ImGui::SameLine();
206 } else {
207 col = 0;
208 }
209 }
210
211 ImGui::EndChild();
212
213 if (!rooms_ || current_room_id_ < 0 || current_room_id_ >= 296) {
214 return;
215 }
216
217 const auto& room = (*rooms_)[current_room_id_];
218 const auto& doors = room.GetDoors();
219
220 ImGui::Spacing();
221 gui::SectionHeader(ICON_MD_LIST, "Doors In Room", theme.text_info);
222 if (doors.empty()) {
223 ImGui::TextColored(theme.text_secondary_gray,
224 ICON_MD_INFO " No doors in this room");
225 return;
226 }
227
228 ImGui::BeginChild("##DoorList", ImVec2(0, 0), true);
229 for (size_t i = 0; i < doors.size(); ++i) {
230 const auto& door = doors[i];
231 const auto [tile_x, tile_y] = door.GetTileCoords();
232 const std::string type_name(zelda3::GetDoorTypeName(door.type));
233 const std::string dir_name(zelda3::GetDoorDirectionName(door.direction));
234
235 ImGui::PushID(static_cast<int>(i));
236 ImGui::Text("[%zu] %s", i, type_name.c_str());
237 ImGui::SameLine();
238 ImGui::TextColored(theme.text_secondary_gray, "(%s @ %d,%d)",
239 dir_name.c_str(), tile_x, tile_y);
240 ImGui::SameLine();
241 if (ImGui::SmallButton(ICON_MD_DELETE "##DeleteDoor")) {
242 auto& mutable_room = (*rooms_)[current_room_id_];
243 mutable_room.RemoveDoor(i);
244 }
245 ImGui::PopID();
246 }
247 ImGui::EndChild();
248}
249
250} // namespace yaze::editor
DungeonCanvasViewer * ResolveCanvasViewer()
std::function< DungeonCanvasViewer *()> canvas_viewer_provider_
void OnClose() override
Called when panel is hidden.
void Draw(bool *p_open) override
Draw the panel content.
DungeonObjectInteraction & object_interaction()
void SetDoorPlacementMode(bool enabled, zelda3::DoorType type=zelda3::DoorType::NormalDoor)
RAII guard for ImGui style colors.
Definition style_guard.h:27
#define ICON_MD_INFO
Definition icons.h:993
#define ICON_MD_CANCEL
Definition icons.h:364
#define ICON_MD_PLACE
Definition icons.h:1477
#define ICON_MD_LIST
Definition icons.h:1094
#define ICON_MD_DOOR_FRONT
Definition icons.h:613
#define ICON_MD_DELETE
Definition icons.h:530
const AgentUITheme & GetTheme()
ImVec4 DoorTypeAccent(const AgentUITheme &theme, zelda3::DoorType type)
Editors are the view controllers for the application.
void SectionHeader(const char *icon, const char *label, const ImVec4 &color)
DoorType
Door types from ALTTP.
Definition door_types.h:33
@ FancyDungeonExit
Fancy dungeon exit.
@ SmallKeyDoor
Small key door.
@ SmallKeyStairsDown
Small key stairs (downwards)
@ SmallKeyStairsUp
Small key stairs (upwards)
@ DungeonSwapMarker
Dungeon swap marker.
@ NormalDoor
Normal door (upper layer)
@ BombableDoor
Bombable door.
@ LayerSwapMarker
Layer swap marker.
@ ExplodingWall
Exploding wall.
@ TopSidedShutter
Top-sided shutter door.
@ NormalDoorLower
Normal door (lower layer)
@ BottomSidedShutter
Bottom-sided shutter door.
@ CurtainDoor
Curtain door.
@ WaterfallDoor
Waterfall door.
@ BigKeyDoor
Big key door.
@ EyeWatchDoor
Eye watch door.
@ ExitMarker
Exit marker.
@ DoubleSidedShutter
Double sided shutter door.
constexpr std::string_view GetDoorDirectionName(DoorDirection dir)
Get human-readable name for door direction.
Definition door_types.h:161
constexpr std::string_view GetDoorTypeName(DoorType type)
Get human-readable name for door type.
Definition door_types.h:106
Centralized theme colors for Agent UI components.
Definition agent_theme.h:19