yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
dungeon_map_panel.h
Go to the documentation of this file.
1#ifndef YAZE_APP_EDITOR_DUNGEON_PANELS_DUNGEON_MAP_PANEL_H_
2#define YAZE_APP_EDITOR_DUNGEON_PANELS_DUNGEON_MAP_PANEL_H_
3
4#include <algorithm>
5#include <array>
6#include <cmath>
7#include <functional>
8#include <map>
9#include <memory>
10#include <string>
11#include <vector>
12#include "util/i18n/tr.h"
13
21#include "app/gui/core/icons.h"
22#include "core/hack_manifest.h"
23#include "imgui/imgui.h"
24#include "zelda3/dungeon/room.h"
27
28namespace yaze {
29namespace editor {
30
50 public:
58 DungeonMapPanel(int* current_room_id, ImVector<int>* active_rooms,
59 std::function<void(int)> on_room_selected,
60 DungeonRoomStore* rooms = nullptr)
61 : current_room_id_(current_room_id),
62 active_rooms_(active_rooms),
63 rooms_(rooms),
64 on_room_selected_(std::move(on_room_selected)) {}
65
66 // ==========================================================================
67 // WindowContent Identity
68 // ==========================================================================
69
70 std::string GetId() const override { return "dungeon.dungeon_map"; }
71 std::string GetDisplayName() const override { return "Dungeon Map"; }
72 std::string GetIcon() const override { return ICON_MD_MAP; }
73 std::string GetEditorCategory() const override { return "Dungeon"; }
74 int GetPriority() const override { return 35; }
75 std::string GetWorkflowGroup() const override { return "Editors"; }
76
78 std::function<void(int, RoomSelectionIntent)> callback) {
79 on_room_intent_ = std::move(callback);
80 }
81
82 // ==========================================================================
83 // Configuration
84 // ==========================================================================
85
90 void SetDungeonRooms(const std::vector<int>& room_ids) {
92 dungeon_room_ids_ = room_ids;
94 }
95
99 void AddRoom(int room_id) {
100 // Avoid duplicates
101 for (int id : dungeon_room_ids_) {
102 if (id == room_id)
103 return;
104 }
105 dungeon_room_ids_.push_back(room_id);
107 }
108
112 void ClearRooms() {
114 dungeon_room_ids_.clear();
115 room_positions_.clear();
116 room_types_.clear();
117 stair_connections_.clear();
118 holewarp_connections_.clear();
119 }
120
124 void SetRoomPosition(int room_id, int grid_x, int grid_y) {
125 room_positions_[room_id] =
126 ImVec2(static_cast<float>(grid_x), static_cast<float>(grid_y));
127 }
128
129 void SetRenderContextCallback(std::function<void(int)> callback) {
130 prepare_render_context_ = std::move(callback);
131 }
132
134 if (rooms_ != rooms) {
136 rooms_ = rooms;
137 }
138 }
139
143 void SetHackManifest(const core::HackManifest* manifest) {
144 hack_manifest_ = manifest;
145 }
146
151 ClearRooms();
152 current_dungeon_name_ = dungeon.name;
153 for (const auto& room : dungeon.rooms) {
154 dungeon_room_ids_.push_back(room.id);
155 room_positions_[room.id] = ImVec2(static_cast<float>(room.grid_col),
156 static_cast<float>(room.grid_row));
157 room_types_[room.id] = room.type;
158 }
159 stair_connections_ = dungeon.stairs;
161 }
162
163 // ==========================================================================
164 // WindowContent Drawing
165 // ==========================================================================
166
167 void Draw(bool* p_open) override {
169 return;
170
171 const auto& theme = AgentUI::GetTheme();
172
173 // Show dungeon selection/quick presets
175
176 ImGui::Separator();
177
178 // Room size in the map
179 constexpr float kRoomWidth = 64.0f;
180 constexpr float kRoomHeight = 64.0f;
181 constexpr float kRoomSpacing = 8.0f;
182
183 // Calculate canvas size based on room positions
184 float max_x = 0, max_y = 0;
185 for (const auto& [room_id, pos] : room_positions_) {
186 max_x = std::max(max_x, pos.x);
187 max_y = std::max(max_y, pos.y);
188 }
189 float canvas_width =
190 (max_x + 1) * (kRoomWidth + kRoomSpacing) + kRoomSpacing;
191 float canvas_height =
192 (max_y + 1) * (kRoomHeight + kRoomSpacing) + kRoomSpacing;
193
194 // Minimum size
195 canvas_width = std::max(canvas_width, 200.0f);
196 canvas_height = std::max(canvas_height, 200.0f);
197
198 const ImVec2 available = ImGui::GetContentRegionAvail();
199 const float footer = ImGui::GetTextLineHeightWithSpacing();
200 if (!ImGui::BeginChild("##DungeonMapCanvas",
201 ImVec2(0, std::max(1.0f, available.y - footer)),
202 false, ImGuiWindowFlags_HorizontalScrollbar)) {
203 ImGui::EndChild();
204 return;
205 }
206 const ImVec2 canvas_size(canvas_width, canvas_height);
207
208 // Begin canvas area
209 ImVec2 canvas_pos = ImGui::GetCursorScreenPos();
210 ImDrawList* draw_list = ImGui::GetWindowDrawList();
211
212 // Background
213 ImU32 bg_color = ImGui::ColorConvertFloat4ToU32(theme.panel_bg_darker);
214 draw_list->AddRectFilled(
215 canvas_pos,
216 ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y),
217 bg_color);
218
219 // Helper lambda: compute the center pixel position for a room on the canvas
220 auto RoomCenter = [&](int room_id) -> ImVec2 {
221 auto it = room_positions_.find(room_id);
222 if (it == room_positions_.end())
223 return ImVec2(0, 0);
224 ImVec2 pos = it->second;
225 return ImVec2(canvas_pos.x + kRoomSpacing +
226 pos.x * (kRoomWidth + kRoomSpacing) + kRoomWidth * 0.5f,
227 canvas_pos.y + kRoomSpacing +
228 pos.y * (kRoomHeight + kRoomSpacing) +
229 kRoomHeight * 0.5f);
230 };
231
232 // Draw connections between adjacent rooms (gray lines — doors)
233 ImVec4 connection_color = theme.dungeon_room_border_dark;
234 connection_color.w = 0.45f;
235 for (size_t i = 0; i < dungeon_room_ids_.size(); i++) {
236 for (size_t j = i + 1; j < dungeon_room_ids_.size(); j++) {
237 int room_a = dungeon_room_ids_[i];
238 int room_b = dungeon_room_ids_[j];
239
240 bool adjacent = false;
241 if (std::abs(room_a - room_b) == 16) {
242 adjacent = true;
243 } else if (std::abs(room_a - room_b) == 1) {
244 int col_a = room_a % 16;
245 int col_b = room_b % 16;
246 if (std::abs(col_a - col_b) == 1) {
247 adjacent = true;
248 }
249 }
250
251 if (adjacent) {
252 draw_list->AddLine(RoomCenter(room_a), RoomCenter(room_b),
253 ImGui::ColorConvertFloat4ToU32(connection_color),
254 1.5f);
255 }
256 }
257 }
258
259 // Draw stair connections (blue dashed lines — bidirectional)
260 for (const auto& conn : stair_connections_) {
261 if (room_positions_.count(conn.from_room) &&
262 room_positions_.count(conn.to_room)) {
263 ImVec2 from = RoomCenter(conn.from_room);
264 ImVec2 to = RoomCenter(conn.to_room);
265 DrawDashedLine(draw_list, from, to, IM_COL32(100, 149, 237, 200), 1.5f,
266 6.0f);
267 }
268 }
269
270 // Draw holewarp connections (red lines with arrow — one-way falls)
271 for (const auto& conn : holewarp_connections_) {
272 if (room_positions_.count(conn.from_room) &&
273 room_positions_.count(conn.to_room)) {
274 ImVec2 from = RoomCenter(conn.from_room);
275 ImVec2 to = RoomCenter(conn.to_room);
276 ImU32 red = IM_COL32(220, 60, 60, 200);
277 draw_list->AddLine(from, to, red, 2.0f);
278 // Arrowhead at destination
279 DrawArrowhead(draw_list, from, to, red, 6.0f);
280 }
281 }
282
283 // Draw each room
284 for (int room_id : dungeon_room_ids_) {
285 auto pos_it = room_positions_.find(room_id);
286 if (pos_it == room_positions_.end())
287 continue;
288
289 ImVec2 grid_pos = pos_it->second;
290 ImVec2 room_min(canvas_pos.x + kRoomSpacing +
291 grid_pos.x * (kRoomWidth + kRoomSpacing),
292 canvas_pos.y + kRoomSpacing +
293 grid_pos.y * (kRoomHeight + kRoomSpacing));
294 ImVec2 room_max(room_min.x + kRoomWidth, room_min.y + kRoomHeight);
295
296 // Check if room is valid
297 if (room_id < 0 || room_id >= 0x128)
298 continue;
299
300 bool is_current = (*current_room_id_ == room_id);
301 bool is_open = false;
302 for (int i = 0; i < active_rooms_->Size; i++) {
303 if ((*active_rooms_)[i] == room_id) {
304 is_open = true;
305 break;
306 }
307 }
308
309 // Draw room thumbnail or placeholder
310 if (rooms_) {
311 auto* loaded_room = rooms_->GetIfLoaded(room_id);
312 if (loaded_room != nullptr) {
315 auto& output = room_composite_outputs_[room_id];
316 if (!output) {
317 output = std::make_unique<RoomCompositeOutput>();
318 }
319 auto& preview_bitmap =
320 PrepareCanonicalRoomComposite(*loaded_room, *output);
323 if (preview_bitmap.is_active() && preview_bitmap.texture() != 0) {
324 // Draw room thumbnail
325 draw_list->AddImage((ImTextureID)(intptr_t)preview_bitmap.texture(),
326 room_min, room_max, ImVec2(0, 0), ImVec2(1, 1),
327 ImGui::GetColorU32(ImVec4(1, 1, 1, 1)));
328 } else {
329 // Placeholder for loaded but no texture
330 draw_list->AddRectFilled(
331 room_min, room_max,
332 ImGui::ColorConvertFloat4ToU32(theme.panel_bg_color));
333 }
334 } else {
335 // Not loaded - gray placeholder
336 draw_list->AddRectFilled(
337 room_min, room_max,
338 ImGui::ColorConvertFloat4ToU32(theme.panel_bg_darker));
339
340 // Show room ID
341 char label[8];
342 snprintf(label, sizeof(label), "%02X", room_id);
343 ImVec2 text_size = ImGui::CalcTextSize(label);
344 ImVec2 text_pos(room_min.x + (kRoomWidth - text_size.x) * 0.5f,
345 room_min.y + (kRoomHeight - text_size.y) * 0.5f);
346 draw_list->AddText(
347 text_pos,
348 ImGui::ColorConvertFloat4ToU32(theme.text_secondary_gray), label);
349 }
350 } else {
351 // Not loaded - gray placeholder
352 draw_list->AddRectFilled(
353 room_min, room_max,
354 ImGui::ColorConvertFloat4ToU32(theme.panel_bg_darker));
355
356 // Show room ID
357 char label[8];
358 snprintf(label, sizeof(label), "%02X", room_id);
359 ImVec2 text_size = ImGui::CalcTextSize(label);
360 ImVec2 text_pos(room_min.x + (kRoomWidth - text_size.x) * 0.5f,
361 room_min.y + (kRoomHeight - text_size.y) * 0.5f);
362 draw_list->AddText(
363 text_pos, ImGui::ColorConvertFloat4ToU32(theme.text_secondary_gray),
364 label);
365 }
366
367 // Draw border based on state
368 if (is_current) {
369 // Glow effect
370 ImVec4 glow = theme.dungeon_selection_primary;
371 glow.w = 0.4f;
372 ImVec2 glow_min(room_min.x - 2, room_min.y - 2);
373 ImVec2 glow_max(room_max.x + 2, room_max.y + 2);
374 draw_list->AddRect(glow_min, glow_max,
375 ImGui::ColorConvertFloat4ToU32(glow), 0.0f, 0, 4.0f);
376 // Inner border
377 draw_list->AddRect(
378 room_min, room_max,
379 ImGui::ColorConvertFloat4ToU32(theme.dungeon_selection_primary),
380 0.0f, 0, 2.0f);
381 } else if (is_open) {
382 draw_list->AddRect(
383 room_min, room_max,
384 ImGui::ColorConvertFloat4ToU32(theme.dungeon_grid_cell_selected),
385 0.0f, 0, 2.0f);
386 } else {
387 draw_list->AddRect(
388 room_min, room_max,
389 ImGui::ColorConvertFloat4ToU32(theme.dungeon_grid_cell_border),
390 0.0f, 0, 1.0f);
391 }
392
393 // Room type badge (small colored dot in top-left corner)
394 auto type_it = room_types_.find(room_id);
395 if (type_it != room_types_.end()) {
396 ImU32 badge_color = 0;
397 if (type_it->second == "entrance") {
398 badge_color = IM_COL32(76, 175, 80, 220); // Green
399 } else if (type_it->second == "boss") {
400 badge_color = IM_COL32(244, 67, 54, 220); // Red
401 } else if (type_it->second == "mini_boss") {
402 badge_color = IM_COL32(255, 152, 0, 220); // Orange
403 }
404 if (badge_color != 0) {
405 ImVec2 badge_center(room_min.x + 6.0f, room_min.y + 6.0f);
406 draw_list->AddCircleFilled(badge_center, 4.0f, badge_color);
407 }
408 }
409
410 // Handle clicks
411 ImGui::SetCursorScreenPos(room_min);
412 char btn_id[32];
413 snprintf(btn_id, sizeof(btn_id), "##map_room%d", room_id);
414 ImGui::InvisibleButton(btn_id, ImVec2(kRoomWidth, kRoomHeight));
415
416 if (ImGui::IsItemClicked()) {
417 if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
418 if (on_room_intent_) {
420 } else if (on_room_selected_) {
421 on_room_selected_(room_id);
422 }
423 } else if (on_room_selected_) {
424 on_room_selected_(room_id);
425 }
426 }
427
428 // Tooltip
429 if (ImGui::IsItemHovered()) {
430 ImGui::BeginTooltip();
431 ImGui::Text("[%03X] %s", room_id,
432 zelda3::GetRoomLabel(room_id).c_str());
433 if (rooms_) {
434 if (auto* loaded_room = rooms_->GetIfLoaded(room_id)) {
435 ImGui::TextDisabled(tr("Palette: %d"), loaded_room->palette());
436 }
437 }
438 ImGui::TextDisabled(tr("Click to select"));
439 ImGui::EndTooltip();
440 }
441 }
442
443 // Invisible room buttons moved the cursor. Reserve the grid from its
444 // original origin, rather than adding its extent after the last room.
445 ImGui::SetCursorScreenPos(canvas_pos);
446 ImGui::Dummy(canvas_size);
447 ImGui::EndChild();
448
449 // Status bar
450 ImGui::TextDisabled(tr("%zu rooms in view"), dungeon_room_ids_.size());
451 }
452
453 private:
455
460 room_positions_.clear();
461
462 int cols = static_cast<int>(
463 std::ceil(std::sqrt(static_cast<double>(dungeon_room_ids_.size()))));
464 cols = std::max(1, cols);
465
466 for (size_t i = 0; i < dungeon_room_ids_.size(); i++) {
467 int room_id = dungeon_room_ids_[i];
468 int grid_x = static_cast<int>(i % cols);
469 int grid_y = static_cast<int>(i / cols);
470 room_positions_[room_id] =
471 ImVec2(static_cast<float>(grid_x), static_cast<float>(grid_y));
472 }
473 }
474
480 bool has_registry = hack_manifest_ && hack_manifest_->HasProjectRegistry();
481
482 if (has_registry) {
484 } else {
486 }
487
488 ImGui::SameLine();
489 if (ImGui::Button(ICON_MD_ADD " Add Current")) {
490 if (current_room_id_ && *current_room_id_ >= 0) {
492 }
493 }
494 if (ImGui::IsItemHovered()) {
495 ImGui::SetTooltip(tr("Add currently selected room to the map"));
496 }
497
498 ImGui::SameLine();
499 if (ImGui::Button(ICON_MD_CLEAR " Clear")) {
500 ClearRooms();
501 current_dungeon_name_ = "Select Dungeon...";
502 selected_preset_ = -1;
503 }
504 }
505
510 const auto& dungeons = hack_manifest_->project_registry().dungeons;
511
512 ImGui::SetNextItemWidth(
513 std::max(100.0f, ImGui::GetContentRegionAvail().x - 220.0f));
514 if (ImGui::BeginCombo("##DungeonRegistry", current_dungeon_name_.c_str())) {
515 for (size_t i = 0; i < dungeons.size(); i++) {
516 const auto& dungeon = dungeons[i];
517 char label[128];
518 if (!dungeon.vanilla_name.empty()) {
519 snprintf(label, sizeof(label), "%s: %s (%s)", dungeon.id.c_str(),
520 dungeon.name.c_str(), dungeon.vanilla_name.c_str());
521 } else {
522 snprintf(label, sizeof(label), "%s: %s", dungeon.id.c_str(),
523 dungeon.name.c_str());
524 }
525 bool selected = (current_dungeon_name_ == dungeon.name);
526 if (ImGui::Selectable(label, selected)) {
527 LoadFromDungeonEntry(dungeon);
528 selected_preset_ = static_cast<int>(i);
529 }
530 }
531 ImGui::EndCombo();
532 }
533 }
534
539 struct DungeonPreset {
540 const char* name;
541 int start_room;
542 int count;
543 };
544
545 static const DungeonPreset kPresets[] = {
546 {"Eastern Palace", 0xC8, 8}, {"Desert Palace", 0x33, 8},
547 {"Tower of Hera", 0x07, 8}, {"Palace of Darkness", 0x09, 12},
548 {"Swamp Palace", 0x28, 10}, {"Skull Woods", 0x29, 10},
549 {"Thieves' Town", 0x44, 8}, {"Ice Palace", 0x0E, 12},
550 {"Misery Mire", 0x61, 10}, {"Turtle Rock", 0x04, 12},
551 {"Ganon's Tower", 0x0C, 16}, {"Hyrule Castle", 0x01, 12},
552 };
553
554 ImGui::SetNextItemWidth(
555 std::max(100.0f, ImGui::GetContentRegionAvail().x - 220.0f));
556 if (ImGui::BeginCombo(
557 "##DungeonPreset",
558 selected_preset_ >= 0 && selected_preset_ < IM_ARRAYSIZE(kPresets)
559 ? kPresets[selected_preset_].name
560 : "Select Dungeon...")) {
561 for (int i = 0; i < IM_ARRAYSIZE(kPresets); i++) {
562 if (ImGui::Selectable(kPresets[i].name, selected_preset_ == i)) {
564 ClearRooms();
565 for (int j = 0; j < kPresets[i].count; j++) {
566 int room_id = kPresets[i].start_room + j;
567 if (room_id < 0x128) {
568 dungeon_room_ids_.push_back(room_id);
569 }
570 }
572 }
573 }
574 ImGui::EndCombo();
575 }
576 }
577
581 static void DrawDashedLine(ImDrawList* dl, ImVec2 from, ImVec2 to,
582 ImU32 color, float thickness, float dash_len) {
583 float dx = to.x - from.x;
584 float dy = to.y - from.y;
585 float length = std::sqrt(dx * dx + dy * dy);
586 if (length < 1.0f)
587 return;
588 float nx = dx / length;
589 float ny = dy / length;
590
591 float drawn = 0.0f;
592 bool visible = true;
593 while (drawn < length) {
594 float seg = std::min(dash_len, length - drawn);
595 ImVec2 seg_start(from.x + nx * drawn, from.y + ny * drawn);
596 ImVec2 seg_end(from.x + nx * (drawn + seg), from.y + ny * (drawn + seg));
597 if (visible) {
598 dl->AddLine(seg_start, seg_end, color, thickness);
599 }
600 drawn += seg;
601 visible = !visible;
602 }
603 }
604
608 static void DrawArrowhead(ImDrawList* dl, ImVec2 from, ImVec2 to, ImU32 color,
609 float size) {
610 float dx = to.x - from.x;
611 float dy = to.y - from.y;
612 float length = std::sqrt(dx * dx + dy * dy);
613 if (length < 1.0f)
614 return;
615 float nx = dx / length;
616 float ny = dy / length;
617 // Perpendicular
618 float px = -ny;
619 float py = nx;
620
621 ImVec2 tip = to;
622 ImVec2 left(to.x - nx * size + px * size * 0.5f,
623 to.y - ny * size + py * size * 0.5f);
624 ImVec2 right(to.x - nx * size - px * size * 0.5f,
625 to.y - ny * size - py * size * 0.5f);
626 dl->AddTriangleFilled(tip, left, right, color);
627 }
628
629 int* current_room_id_ = nullptr;
630 ImVector<int>* active_rooms_ = nullptr;
632 std::function<void(int)> prepare_render_context_;
633 std::function<void(int)> on_room_selected_;
634 std::function<void(int, RoomSelectionIntent)> on_room_intent_;
635
636 // Room data
637 std::vector<int> dungeon_room_ids_;
638 std::map<int, ImVec2> room_positions_;
639 std::map<int, std::string> room_types_;
640 // Each configured room needs stable texture identity through ImGui's
641 // deferred frame render. Clear the set when switching dungeon contexts.
642 std::map<int, std::unique_ptr<RoomCompositeOutput>> room_composite_outputs_;
644
645 // Project registry integration
647 std::vector<core::DungeonConnection> stair_connections_;
648 std::vector<core::DungeonConnection> holewarp_connections_;
649 std::string current_dungeon_name_ = "Select Dungeon...";
650};
651
652} // namespace editor
653} // namespace yaze
654
655#endif // YAZE_APP_EDITOR_DUNGEON_PANELS_DUNGEON_MAP_PANEL_H_
Loads and queries the hack manifest JSON for yaze-ASM integration.
const ProjectRegistry & project_registry() const
bool HasProjectRegistry() const
WindowContent for displaying multiple rooms in a spatial dungeon layout.
std::string GetDisplayName() const override
Human-readable name shown in menus and title bars.
std::string GetEditorCategory() const override
Editor category this panel belongs to.
std::map< int, ImVec2 > room_positions_
void ClearRooms()
Clear all rooms from the dungeon map.
void SetRoomIntentCallback(std::function< void(int, RoomSelectionIntent)> callback)
void LoadFromDungeonEntry(const core::DungeonEntry &dungeon)
Load rooms and connections from a project registry dungeon entry.
const core::HackManifest * hack_manifest_
void SetRooms(DungeonRoomStore *rooms)
std::vector< core::DungeonConnection > stair_connections_
std::function< void(int, RoomSelectionIntent)> on_room_intent_
std::map< int, std::unique_ptr< RoomCompositeOutput > > room_composite_outputs_
void SetDungeonRooms(const std::vector< int > &room_ids)
Set which rooms to display in this dungeon map.
void DrawVanillaPresetSelector()
Fallback selector using vanilla ALTTP dungeon presets.
void AutoLayoutRooms()
Auto-layout rooms in a grid based on their IDs.
static void DrawDashedLine(ImDrawList *dl, ImVec2 from, ImVec2 to, ImU32 color, float thickness, float dash_len)
Draw a dashed line between two points.
std::function< void(int)> on_room_selected_
void AddRoom(int room_id)
Add a single room to the dungeon map.
std::function< void(int)> prepare_render_context_
void DrawDungeonSelector()
Draw dungeon preset selector — uses project registry if available, falls back to vanilla ALTTP preset...
std::map< int, std::string > room_types_
static void DrawArrowhead(ImDrawList *dl, ImVec2 from, ImVec2 to, ImU32 color, float size)
Draw a small triangle arrowhead at the 'to' end of a line.
void DrawRegistrySelector()
Selector using project registry area overviews.
int GetPriority() const override
Get display priority for menu ordering.
DungeonMapPanel(int *current_room_id, ImVector< int > *active_rooms, std::function< void(int)> on_room_selected, DungeonRoomStore *rooms=nullptr)
Construct a dungeon map panel.
void SetRenderContextCallback(std::function< void(int)> callback)
std::string GetIcon() const override
Material Design icon for this panel.
void SetHackManifest(const core::HackManifest *manifest)
Set the hack manifest for project registry access.
std::string GetWorkflowGroup() const override
Optional workflow group for hack-centric actions.
void Draw(bool *p_open) override
Draw the panel content.
std::vector< core::DungeonConnection > holewarp_connections_
std::string GetId() const override
Unique identifier for this panel.
void SetRoomPosition(int room_id, int grid_x, int grid_y)
Manually set a room's position in the grid.
zelda3::Room * GetIfLoaded(int room_id)
Base interface for all logical window content components.
void ProcessTextureQueue(IRenderer *renderer)
Definition arena.cc:211
static Arena & Get()
Definition arena.cc:24
#define ICON_MD_MAP
Definition icons.h:1173
#define ICON_MD_ADD
Definition icons.h:86
#define ICON_MD_CLEAR
Definition icons.h:416
const AgentUITheme & GetTheme()
gfx::Bitmap & PrepareCanonicalRoomComposite(zelda3::Room &room, RoomCompositeOutput &output)
RoomSelectionIntent
Intent for room selection in the dungeon editor.
void EnsureCompositeBitmapTextureQueued(Bitmap &composite)
std::string GetRoomLabel(int id)
Convenience function to get a room label.
A complete dungeon entry with rooms and connections.
std::vector< DungeonConnection > holewarps
std::vector< DungeonRoom > rooms
std::vector< DungeonConnection > stairs
std::vector< DungeonEntry > dungeons