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#include "util/i18n/tr.h"
3
4#include <algorithm>
5#include <array>
6#include <string>
7
8#include "absl/strings/str_format.h"
12#include "imgui/imgui.h"
13
14namespace yaze::editor {
15
16namespace {
17
18ImVec4 DoorTypeAccent(const AgentUITheme& theme, zelda3::DoorType type) {
19 const int type_val = static_cast<int>(type);
20 if (type_val <= 0x12) {
21 return theme.dungeon_object_door;
22 }
23 if (type_val <= 0x1E) {
24 return theme.status_warning;
25 }
26 return theme.status_success;
27}
28
29// Semantic icon prefix used by both the 20-type placement picker and the
30// "Selected Door" swap combo. Keeps the 20 core types scannable by category.
68
70 switch (type) {
72 return "Normal";
74 return "Lower";
76 return "Cave";
78 return "2-Side";
80 return "Eye";
82 return "S-Key";
84 return "B-Key";
86 return "Up";
88 return "Down";
90 return "Dash";
92 return "Bomb";
94 return "Blast";
96 return "Curtain";
98 return "Bottom";
100 return "Top";
102 return "Exit";
104 return "Water";
106 return "Marker";
108 return "Layer";
110 return "Swap";
111 }
112 return "Door";
113}
114
115} // namespace
116
123
131
135
136void DoorEditorContent::Draw(bool* p_open) {
137 (void)p_open;
139
140 const auto& theme = AgentUI::GetTheme();
141 static constexpr std::array<zelda3::DoorType, 20> kDoorTypes = {{
162 }};
163
164 if (ResolveCanvasViewer() &&
168 gui::SectionHeader(ICON_MD_SELECT_ALL, "Selected Door", theme.text_info);
170 ImGui::Button(ICON_MD_OPEN_IN_NEW " Inspect Selected", ImVec2(-1, 0))) {
172 }
173 ImGui::Spacing();
174 }
175
176 gui::SectionHeader(ICON_MD_DOOR_FRONT, "Door Styles", theme.text_info);
177 ImGui::TextColored(theme.text_secondary_gray,
178 tr("Select a door style, then click a wall in the room "
179 "canvas to place it."));
180
182 ImGui::TextColored(
183 theme.status_warning, ICON_MD_PLACE " Active: %s",
184 std::string(zelda3::GetDoorTypeName(selected_door_type_)).c_str());
185 ImGui::SameLine();
186 if (ImGui::SmallButton(ICON_MD_CANCEL " Cancel")) {
188 }
189 }
190
191 constexpr float kDoorCardHeight = 48.0f;
192 constexpr float kDoorCardSpacing = 6.0f;
193 constexpr float kMinDoorCardWidth = 92.0f;
194 const float panel_width = ImGui::GetContentRegionAvail().x;
195 const int items_per_row =
196 std::max(2, static_cast<int>((panel_width + kDoorCardSpacing) /
197 (kMinDoorCardWidth + kDoorCardSpacing)));
198 const float card_width = std::max(
199 kMinDoorCardWidth,
200 (panel_width - (items_per_row - 1) * kDoorCardSpacing) / items_per_row);
201
202 ImGui::BeginChild("##DoorTypeGrid", ImVec2(0, 150), true,
203 ImGuiWindowFlags_AlwaysVerticalScrollbar);
204
205 int col = 0;
206 for (size_t i = 0; i < kDoorTypes.size(); ++i) {
207 const auto door_type = kDoorTypes[i];
208 const bool is_selected = selected_door_type_ == door_type;
209 const int type_val = static_cast<int>(door_type);
210 ImGui::PushID(static_cast<int>(i));
211
212 ImVec4 button_color = DoorTypeAccent(theme, door_type);
213 if (is_selected) {
214 button_color.x = std::min(1.0f, button_color.x + 0.2f);
215 button_color.y = std::min(1.0f, button_color.y + 0.2f);
216 button_color.z = std::min(1.0f, button_color.z + 0.2f);
217 }
218
219 gui::StyleColorGuard btn_colors({
220 {ImGuiCol_Button, button_color},
221 {ImGuiCol_ButtonHovered,
222 ImVec4(button_color.x + 0.1f, button_color.y + 0.1f,
223 button_color.z + 0.1f, 1.0f)},
224 {ImGuiCol_ButtonActive,
225 ImVec4(button_color.x + 0.2f, button_color.y + 0.2f,
226 button_color.z + 0.2f, 1.0f)},
227 });
228
229 const std::string label =
230 absl::StrFormat("%s %02X\n%s", DoorTypeIcon(door_type), type_val,
231 ShortDoorTypeLabel(door_type).c_str());
232 if (ImGui::Button(label.c_str(), ImVec2(card_width, kDoorCardHeight))) {
233 selected_door_type_ = door_type;
235 if (ResolveCanvasViewer()) {
237 true, selected_door_type_);
238 }
239 }
240
241 if (ImGui::IsItemHovered()) {
242 ImGui::SetTooltip(tr("%s (0x%02X)\nClick to select for placement"),
243 std::string(zelda3::GetDoorTypeName(door_type)).c_str(),
244 type_val);
245 }
246
247 if (is_selected) {
248 ImVec2 min = ImGui::GetItemRectMin();
249 ImVec2 max = ImGui::GetItemRectMax();
250 ImGui::GetWindowDrawList()->AddRect(min, max, IM_COL32(255, 255, 0, 255),
251 0.0f, 0, 2.0f);
252 }
253
254 ImGui::PopID();
255 col++;
256 if (col < items_per_row && i < kDoorTypes.size() - 1) {
257 ImGui::SameLine();
258 } else {
259 col = 0;
260 }
261 }
262
263 ImGui::EndChild();
264
265 if (!rooms_ || current_room_id_ < 0 || current_room_id_ >= 296) {
266 return;
267 }
268
269 const auto& room = (*rooms_)[current_room_id_];
270 const auto& doors = room.GetDoors();
271
272 ImGui::Spacing();
273 gui::SectionHeader(ICON_MD_LIST, "Doors In Room", theme.text_info);
274 if (doors.empty()) {
275 ImGui::TextColored(theme.text_secondary_gray,
276 ICON_MD_INFO " No doors in this room");
277 return;
278 }
279
280 ImGui::BeginChild("##DoorList", ImVec2(0, 0), true);
281 int selected_door_index = -1;
282 if (ResolveCanvasViewer() &&
284 const auto selected_entity =
286 if (selected_entity.type == EntityType::Door) {
287 selected_door_index = static_cast<int>(selected_entity.index);
288 }
289 }
290 for (size_t i = 0; i < doors.size(); ++i) {
291 const auto& door = doors[i];
292 const auto [tile_x, tile_y] = door.GetTileCoords();
293 const std::string type_name(zelda3::GetDoorTypeName(door.type));
294 const std::string dir_name(zelda3::GetDoorDirectionName(door.direction));
295
296 ImGui::PushID(static_cast<int>(i));
297 const std::string row_label = absl::StrFormat("[%zu] %s", i, type_name);
298 if (ImGui::Selectable(row_label.c_str(),
299 selected_door_index == static_cast<int>(i))) {
300 if (canvas_viewer_) {
302 }
303 }
304 ImGui::SameLine();
305 ImGui::TextColored(theme.text_secondary_gray, "(%s @ %d,%d)",
306 dir_name.c_str(), tile_x, tile_y);
307 ImGui::PopID();
308 }
309 ImGui::EndChild();
310}
311
312} // 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.
std::function< void()> open_selection_inspector_callback_
DungeonObjectInteraction & object_interaction()
void SelectEntity(EntityType type, size_t index)
void SetDoorPlacementMode(bool enabled, zelda3::DoorType type=zelda3::DoorType::NormalDoor)
RAII guard for ImGui style colors.
Definition style_guard.h:27
#define ICON_MD_VIEW_DAY
Definition icons.h:2088
#define ICON_MD_EXIT_TO_APP
Definition icons.h:699
#define ICON_MD_INFO
Definition icons.h:993
#define ICON_MD_CANCEL
Definition icons.h:364
#define ICON_MD_DOOR_SLIDING
Definition icons.h:614
#define ICON_MD_PLACE
Definition icons.h:1477
#define ICON_MD_SWAP_HORIZ
Definition icons.h:1896
#define ICON_MD_STAIRS
Definition icons.h:1847
#define ICON_MD_VISIBILITY
Definition icons.h:2101
#define ICON_MD_WHATSHOT
Definition icons.h:2153
#define ICON_MD_LIST
Definition icons.h:1094
#define ICON_MD_DOOR_FRONT
Definition icons.h:613
#define ICON_MD_BOLT
Definition icons.h:282
#define ICON_MD_FLAG
Definition icons.h:784
#define ICON_MD_SELECT_ALL
Definition icons.h:1680
#define ICON_MD_KEY
Definition icons.h:1026
#define ICON_MD_OPEN_IN_NEW
Definition icons.h:1354
#define ICON_MD_WATER_DROP
Definition icons.h:2131
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:204
constexpr std::string_view GetDoorTypeName(DoorType type)
Get human-readable name for door type.
Definition door_types.h:110
Centralized theme colors for Agent UI components.
Definition agent_theme.h:19