yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
dungeon_entrances_panel.h
Go to the documentation of this file.
1#ifndef YAZE_APP_EDITOR_DUNGEON_PANELS_DUNGEON_ENTRANCES_PANEL_H_
2#define YAZE_APP_EDITOR_DUNGEON_PANELS_DUNGEON_ENTRANCES_PANEL_H_
3
4#include <array>
5#include <cstdio>
6#include <functional>
7#include <string>
8#include <utility>
9
12#include "app/gui/core/icons.h"
13#include "app/gui/core/input.h"
14#include "imgui/imgui.h"
15#include "util/i18n/tr.h"
16#include "zelda3/common.h"
19
20namespace yaze {
21namespace editor {
22
33 public:
35 std::array<zelda3::RoomEntrance, zelda3::kNumDungeonEntranceSlots>*
36 entrances,
37 std::array<zelda3::DungeonSpawnPoint, zelda3::kNumDungeonSpawnPoints>*
38 spawn_points,
39 int* current_entrance_id, std::function<void(int)> on_entrance_selected)
40 : entrances_(entrances),
41 spawn_points_(spawn_points),
42 current_entrance_id_(current_entrance_id),
43 on_entrance_selected_(std::move(on_entrance_selected)) {}
44
45 // ==========================================================================
46 // WindowContent Identity
47 // ==========================================================================
48
49 std::string GetId() const override { return "dungeon.entrance_properties"; }
50 std::string GetDisplayName() const override { return "Entrance Properties"; }
51 std::string GetIcon() const override { return ICON_MD_TUNE; }
52 std::string GetEditorCategory() const override { return "Dungeon"; }
53 int GetPriority() const override { return 26; }
54 std::string GetWorkflowGroup() const override { return "Core"; }
55
56 // ==========================================================================
57 // WindowContent Drawing
58 // ==========================================================================
59
60 void Draw(bool* p_open) override {
62 return;
63 if (*current_entrance_id_ < 0 ||
64 *current_entrance_id_ >= static_cast<int>(entrances_->size())) {
66 }
67
70 } else {
72 }
73
74 ImGui::Separator();
75
76 // Entrance list
77 // Array layout (from LoadRoomEntrances):
78 // indices 0-6 (0x00-0x06): Spawn points (7 entries)
79 // indices 7-139 (0x07-0x8B): Regular entrances (133 entries)
80 constexpr int kNumSpawnPoints = zelda3::kNumDungeonSpawnPoints;
81 constexpr int kNumEntrances = zelda3::kNumRegularDungeonEntrances;
82 constexpr int kTotalEntries = zelda3::kNumDungeonEntranceSlots;
83
84 if (ImGui::BeginChild("##EntrancesList", ImVec2(0, 0), true,
85 ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
86 for (int i = 0; i < kTotalEntries; i++) {
87 std::string entrance_name;
88 if (i < kNumSpawnPoints) {
89 // Spawn points at indices 0-6
90 char buf[32];
91 snprintf(buf, sizeof(buf), "Spawn Point %d", i);
92 entrance_name = buf;
93 } else {
94 // Regular entrances at indices 7-139, mapped to kEntranceNames[0-132]
95 int entrance_id = i - kNumSpawnPoints;
96 if (entrance_id < kNumEntrances) {
97 // Use unified ResourceLabelProvider for entrance names
98 entrance_name = zelda3::GetEntranceLabel(entrance_id);
99 } else {
100 char buf[32];
101 snprintf(buf, sizeof(buf), "Unknown %d", i);
102 entrance_name = buf;
103 }
104 }
105
106 const int room_id = i < kNumSpawnPoints ? (*spawn_points_)[i].room_id
107 : (*entrances_)[i].room_;
108 // Use unified ResourceLabelProvider for room names
109 std::string room_name = zelda3::GetRoomLabel(room_id);
110
111 char label[256];
112 snprintf(label, sizeof(label), "[%02X] %s -> %s (%03X)", i,
113 entrance_name.c_str(), room_name.c_str(), room_id);
114
115 bool is_selected = (*current_entrance_id_ == i);
116 if (ImGui::Selectable(label, is_selected)) {
120 }
121 }
122 }
123 }
124 ImGui::EndChild();
125 }
126
127 private:
128 void DrawSpawnPointProperties(int slot_index) {
129 auto& spawn = (*spawn_points_)[slot_index];
130 const bool properties_editable =
131 CanEditDungeonSpawnPoint(slot_index, spawn);
132 bool changed = false;
133
134 ImGui::Text(tr("Spawn Point %d"), slot_index);
135 if (!properties_editable) {
136 ImGui::TextWrapped(tr(
137 "Spawn point data is unavailable; reload the ROM before editing."));
138 }
139 ImGui::BeginDisabled(!properties_editable);
140
141 changed |= gui::InputHexWord("Entrance ID", &spawn.entrance_id);
142 changed |= gui::InputHexWord("Room ID", &spawn.room_id);
143 ImGui::SameLine();
144 changed |= gui::InputHexByte("Dungeon ID", &spawn.dungeon_id, 50.f, true);
145
146 changed |= gui::InputHexByte("Main GFX", &spawn.main_gfx, 50.f, true);
147 ImGui::SameLine();
148 changed |= gui::InputHexByte("Song", &spawn.song, 50.f, true);
149 ImGui::SameLine();
150 changed |= gui::InputHexByte("Floor", &spawn.floor);
151
152 ImGui::Separator();
153
154 changed |= gui::InputHexWord("Player X", &spawn.x_coordinate);
155 ImGui::SameLine();
156 changed |= gui::InputHexWord("Player Y", &spawn.y_coordinate);
157
158 changed |= gui::InputHexWord("Camera Trigger X", &spawn.camera_trigger_x);
159 ImGui::SameLine();
160 changed |= gui::InputHexWord("Camera Trigger Y", &spawn.camera_trigger_y);
161
162 changed |= gui::InputHexWord("Horizontal Scroll", &spawn.horizontal_scroll);
163 ImGui::SameLine();
164 changed |= gui::InputHexWord("Vertical Scroll", &spawn.vertical_scroll);
165
166 changed |= gui::InputHexWord("Overworld Door Tilemap",
167 &spawn.overworld_door_tilemap, 70.f, true);
168
169 ImGui::Separator();
170 changed |= gui::InputHexByte("Layer", &spawn.layer, 50.f, true);
171 ImGui::SameLine();
172 changed |= gui::InputHexByte("Spawn Quadrant", &spawn.quadrant, 50.f, true);
173 ImGui::SameLine();
174 changed |= gui::InputHexByte("Scroll Controller",
175 &spawn.camera_scroll_controller, 50.f, true);
176
177 ImGui::Separator();
178 ImGui::Text(tr("Camera Boundaries"));
179 ImGui::Separator();
180 ImGui::Text(tr("\t\t\t\t\tNorth East South West"));
181
182 changed |=
183 gui::InputHexByte("Quadrant##SpawnBoundaryQN",
184 &spawn.camera_scroll_boundaries[0], 50.f, true);
185 ImGui::SameLine();
186 changed |= gui::InputHexByte(
187 "##SpawnQE", &spawn.camera_scroll_boundaries[6], 50.f, true);
188 ImGui::SameLine();
189 changed |= gui::InputHexByte(
190 "##SpawnQS", &spawn.camera_scroll_boundaries[2], 50.f, true);
191 ImGui::SameLine();
192 changed |= gui::InputHexByte(
193 "##SpawnQW", &spawn.camera_scroll_boundaries[4], 50.f, true);
194
195 changed |= gui::InputHexByte(
196 "Full room", &spawn.camera_scroll_boundaries[1], 50.f, true);
197 ImGui::SameLine();
198 changed |= gui::InputHexByte(
199 "##SpawnFE", &spawn.camera_scroll_boundaries[7], 50.f, true);
200 ImGui::SameLine();
201 changed |= gui::InputHexByte(
202 "##SpawnFS", &spawn.camera_scroll_boundaries[3], 50.f, true);
203 ImGui::SameLine();
204 changed |= gui::InputHexByte(
205 "##SpawnFW", &spawn.camera_scroll_boundaries[5], 50.f, true);
206 ImGui::EndDisabled();
207
208 MarkDungeonSpawnPointDirtyIfEditable(slot_index, spawn, changed);
209 }
210
211 void DrawRegularEntranceProperties(int slot_index) {
212 auto& entrance = (*entrances_)[slot_index];
213 const bool properties_editable =
214 CanEditDungeonEntrance(slot_index, entrance);
215 bool changed = false;
216
217 ImGui::Text(tr("Entrance ID: %04X"), entrance.entrance_id_);
218 ImGui::BeginDisabled(!properties_editable);
219 changed |= gui::InputHexWord("Room ID", &entrance.room_);
220 ImGui::SameLine();
221 changed |=
222 gui::InputHexByte("Dungeon ID", &entrance.dungeon_id_, 50.f, true);
223
224 changed |= gui::InputHexByte("Blockset", &entrance.blockset_, 50.f, true);
225 ImGui::SameLine();
226 changed |= gui::InputHexByte("Music", &entrance.music_, 50.f, true);
227 ImGui::SameLine();
228 changed |= gui::InputHexByte("Floor", &entrance.floor_);
229
230 ImGui::Separator();
231
232 changed |= gui::InputHexWord("Player X ", &entrance.x_position_);
233 ImGui::SameLine();
234 changed |= gui::InputHexWord("Player Y ", &entrance.y_position_);
235
236 changed |= gui::InputHexWord("Camera X", &entrance.camera_trigger_x_);
237 ImGui::SameLine();
238 changed |= gui::InputHexWord("Camera Y", &entrance.camera_trigger_y_);
239
240 changed |= gui::InputHexWord("Scroll X ", &entrance.camera_x_);
241 ImGui::SameLine();
242 changed |= gui::InputHexWord("Scroll Y ", &entrance.camera_y_);
243
244 changed |= gui::InputHexWord("Exit", &entrance.exit_, 50.f, true);
245
246 ImGui::Separator();
247 ImGui::Text(tr("Camera Boundaries"));
248 ImGui::Separator();
249 ImGui::Text(tr("\t\t\t\t\tNorth East South West"));
250
251 changed |= gui::InputHexByte("Quadrant", &entrance.camera_boundary_qn_,
252 50.f, true);
253 ImGui::SameLine();
254 changed |=
255 gui::InputHexByte("##QE", &entrance.camera_boundary_qe_, 50.f, true);
256 ImGui::SameLine();
257 changed |=
258 gui::InputHexByte("##QS", &entrance.camera_boundary_qs_, 50.f, true);
259 ImGui::SameLine();
260 changed |=
261 gui::InputHexByte("##QW", &entrance.camera_boundary_qw_, 50.f, true);
262
263 changed |= gui::InputHexByte("Full room", &entrance.camera_boundary_fn_,
264 50.f, true);
265 ImGui::SameLine();
266 changed |=
267 gui::InputHexByte("##FE", &entrance.camera_boundary_fe_, 50.f, true);
268 ImGui::SameLine();
269 changed |=
270 gui::InputHexByte("##FS", &entrance.camera_boundary_fs_, 50.f, true);
271 ImGui::SameLine();
272 changed |=
273 gui::InputHexByte("##FW", &entrance.camera_boundary_fw_, 50.f, true);
274 ImGui::EndDisabled();
275
276 MarkDungeonEntranceDirtyIfEditable(slot_index, entrance, changed);
277 }
278
279 std::array<zelda3::RoomEntrance, zelda3::kNumDungeonEntranceSlots>*
280 entrances_ = nullptr;
281 std::array<zelda3::DungeonSpawnPoint, zelda3::kNumDungeonSpawnPoints>*
282 spawn_points_ = nullptr;
283 int* current_entrance_id_ = nullptr;
284 std::function<void(int)> on_entrance_selected_;
285};
286
287} // namespace editor
288} // namespace yaze
289
290#endif // YAZE_APP_EDITOR_DUNGEON_PANELS_DUNGEON_ENTRANCES_PANEL_H_
WindowContent for displaying and editing dungeon entrances.
DungeonEntrancesPanel(std::array< zelda3::RoomEntrance, zelda3::kNumDungeonEntranceSlots > *entrances, std::array< zelda3::DungeonSpawnPoint, zelda3::kNumDungeonSpawnPoints > *spawn_points, int *current_entrance_id, std::function< void(int)> on_entrance_selected)
void Draw(bool *p_open) override
Draw the panel content.
std::function< void(int)> on_entrance_selected_
int GetPriority() const override
Get display priority for menu ordering.
std::array< zelda3::DungeonSpawnPoint, zelda3::kNumDungeonSpawnPoints > * spawn_points_
std::string GetDisplayName() const override
Human-readable name shown in menus and title bars.
std::string GetWorkflowGroup() const override
Optional workflow group for hack-centric actions.
std::array< zelda3::RoomEntrance, zelda3::kNumDungeonEntranceSlots > * entrances_
std::string GetEditorCategory() const override
Editor category this panel belongs to.
std::string GetId() const override
Unique identifier for this panel.
std::string GetIcon() const override
Material Design icon for this panel.
Base interface for all logical window content components.
#define ICON_MD_TUNE
Definition icons.h:2022
bool CanEditDungeonEntrance(int slot_index, const zelda3::RoomEntrance &entrance)
bool CanEditDungeonSpawnPoint(int slot_index, const zelda3::DungeonSpawnPoint &spawn)
bool MarkDungeonEntranceDirtyIfEditable(int slot_index, zelda3::RoomEntrance &entrance, bool properties_changed)
bool MarkDungeonSpawnPointDirtyIfEditable(int slot_index, zelda3::DungeonSpawnPoint &spawn, bool properties_changed)
bool InputHexWord(const char *label, uint16_t *data, float input_width, bool no_step)
Definition input.cc:489
bool InputHexByte(const char *label, uint8_t *data, float input_width, bool no_step)
Definition input.cc:510
std::string GetEntranceLabel(int id)
Convenience function to get an entrance label.
std::string GetRoomLabel(int id)
Convenience function to get a room label.
constexpr int kNumRegularDungeonEntrances
constexpr int kNumDungeonSpawnPoints
constexpr int kNumDungeonEntranceSlots