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
22#include "app/gui/core/icons.h"
23#include "core/hack_manifest.h"
24#include "imgui/imgui.h"
25#include "zelda3/dungeon/room.h"
29
30namespace yaze {
31namespace editor {
32
52 public:
60 DungeonMapPanel(int* current_room_id, ImVector<int>* active_rooms,
61 std::function<void(int)> on_room_selected,
62 DungeonRoomStore* rooms = nullptr)
63 : current_room_id_(current_room_id),
64 active_rooms_(active_rooms),
65 rooms_(rooms),
66 on_room_selected_(std::move(on_room_selected)) {}
67
68 // ==========================================================================
69 // WindowContent Identity
70 // ==========================================================================
71
72 std::string GetId() const override { return "dungeon.dungeon_map"; }
73 std::string GetDisplayName() const override { return "Dungeon Map"; }
74 std::string GetIcon() const override { return ICON_MD_MAP; }
75 std::string GetEditorCategory() const override { return "Dungeon"; }
76 int GetPriority() const override { return 35; }
77 std::string GetWorkflowGroup() const override { return "Editors"; }
78
80 std::function<void(int, RoomSelectionIntent)> callback) {
81 on_room_intent_ = std::move(callback);
82 }
83
84 // ==========================================================================
85 // Configuration
86 // ==========================================================================
87
92 void SetDungeonRooms(const std::vector<int>& room_ids) {
94 dungeon_room_ids_ = room_ids;
96 }
97
101 void AddRoom(int room_id) {
102 // Avoid duplicates
103 for (int id : dungeon_room_ids_) {
104 if (id == room_id)
105 return;
106 }
107 dungeon_room_ids_.push_back(room_id);
109 }
110
114 void ClearRooms() {
116 dungeon_room_ids_.clear();
117 room_positions_.clear();
118 room_types_.clear();
119 stair_connections_.clear();
120 holewarp_connections_.clear();
121 }
122
126 void SetRoomPosition(int room_id, int grid_x, int grid_y) {
127 room_positions_[room_id] =
128 ImVec2(static_cast<float>(grid_x), static_cast<float>(grid_y));
129 }
130
131 void SetRenderContextCallback(std::function<void(int)> callback) {
132 prepare_render_context_ = std::move(callback);
133 }
134
136 if (rooms_ != rooms) {
138 rooms_ = rooms;
139 }
140 }
141
145 void SetHackManifest(const core::HackManifest* manifest) {
146 hack_manifest_ = manifest;
147 }
148
153 ClearRooms();
154 current_dungeon_name_ = dungeon.name;
155 for (const auto& room : dungeon.rooms) {
156 dungeon_room_ids_.push_back(room.id);
157 room_positions_[room.id] = ImVec2(static_cast<float>(room.grid_col),
158 static_cast<float>(room.grid_row));
159 room_types_[room.id] = room.type;
160 }
161 stair_connections_ = dungeon.stairs;
163 }
164
165 // ==========================================================================
166 // WindowContent Drawing
167 // ==========================================================================
168
169 void Draw(bool* p_open) override {
171 return;
172
173 const auto& theme = AgentUI::GetTheme();
174
175 // Show dungeon selection/quick presets
177
178 ImGui::Separator();
179
180 // Room size in the map
181 constexpr float kRoomWidth = 64.0f;
182 constexpr float kRoomHeight = 64.0f;
183 constexpr float kRoomSpacing = 8.0f;
184
185 // Calculate canvas size based on room positions
186 float max_x = 0, max_y = 0;
187 for (const auto& [room_id, pos] : room_positions_) {
188 max_x = std::max(max_x, pos.x);
189 max_y = std::max(max_y, pos.y);
190 }
191 float canvas_width =
192 (max_x + 1) * (kRoomWidth + kRoomSpacing) + kRoomSpacing;
193 float canvas_height =
194 (max_y + 1) * (kRoomHeight + kRoomSpacing) + kRoomSpacing;
195
196 // Minimum size
197 canvas_width = std::max(canvas_width, 200.0f);
198 canvas_height = std::max(canvas_height, 200.0f);
199
200 const ImVec2 available = ImGui::GetContentRegionAvail();
201 const float footer = ImGui::GetTextLineHeightWithSpacing();
202 if (!ImGui::BeginChild("##DungeonMapCanvas",
203 ImVec2(0, std::max(1.0f, available.y - footer)),
204 false, ImGuiWindowFlags_HorizontalScrollbar)) {
205 ImGui::EndChild();
206 return;
207 }
208 const ImVec2 canvas_size(canvas_width, canvas_height);
209
210 // Begin canvas area
211 ImVec2 canvas_pos = ImGui::GetCursorScreenPos();
212 ImDrawList* draw_list = ImGui::GetWindowDrawList();
213
214 // Background
215 ImU32 bg_color = ImGui::ColorConvertFloat4ToU32(theme.panel_bg_darker);
216 draw_list->AddRectFilled(
217 canvas_pos,
218 ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y),
219 bg_color);
220
221 // Helper lambda: compute the center pixel position for a room on the canvas
222 auto RoomCenter = [&](int room_id) -> ImVec2 {
223 auto it = room_positions_.find(room_id);
224 if (it == room_positions_.end())
225 return ImVec2(0, 0);
226 ImVec2 pos = it->second;
227 return ImVec2(canvas_pos.x + kRoomSpacing +
228 pos.x * (kRoomWidth + kRoomSpacing) + kRoomWidth * 0.5f,
229 canvas_pos.y + kRoomSpacing +
230 pos.y * (kRoomHeight + kRoomSpacing) +
231 kRoomHeight * 0.5f);
232 };
233
234 // Registry edges may be historical adjacency guesses or raw header
235 // bytes. Draw only connections supported by current editable rooms.
236 ImVec4 connection_color = theme.dungeon_room_border_dark;
237 connection_color.w = 0.45f;
238 for (const auto& link : CollectConnections()) {
239 const ImVec2 from = RoomCenter(link.from_room_id);
240 const ImVec2 to = RoomCenter(link.to_room_id);
241 switch (link.type) {
243 draw_list->AddLine(
244 from, to, ImGui::ColorConvertFloat4ToU32(connection_color), 1.5f);
245 break;
247 DrawDashedLine(draw_list, from, to, IM_COL32(100, 149, 237, 200),
248 1.5f, 6.0f);
249 break;
251 const ImU32 red = IM_COL32(220, 60, 60, 200);
252 draw_list->AddLine(from, to, red, 2.0f);
253 DrawArrowhead(draw_list, from, to, red, 6.0f);
254 break;
255 }
256 }
257 }
258
259 // Draw each room
260 for (int room_id : dungeon_room_ids_) {
261 auto pos_it = room_positions_.find(room_id);
262 if (pos_it == room_positions_.end())
263 continue;
264
265 ImVec2 grid_pos = pos_it->second;
266 ImVec2 room_min(canvas_pos.x + kRoomSpacing +
267 grid_pos.x * (kRoomWidth + kRoomSpacing),
268 canvas_pos.y + kRoomSpacing +
269 grid_pos.y * (kRoomHeight + kRoomSpacing));
270 ImVec2 room_max(room_min.x + kRoomWidth, room_min.y + kRoomHeight);
271
272 // Check if room is valid
273 if (room_id < 0 || room_id >= 0x128)
274 continue;
275
276 bool is_current = (*current_room_id_ == room_id);
277 bool is_open = false;
278 for (int i = 0; i < active_rooms_->Size; i++) {
279 if ((*active_rooms_)[i] == room_id) {
280 is_open = true;
281 break;
282 }
283 }
284
285 // Draw room thumbnail or placeholder
286 if (rooms_) {
287 auto* loaded_room = rooms_->GetIfLoaded(room_id);
288 if (loaded_room != nullptr) {
291 auto& output = room_composite_outputs_[room_id];
292 if (!output) {
293 output = std::make_unique<RoomCompositeOutput>();
294 }
295 auto& preview_bitmap =
296 PrepareCanonicalRoomComposite(*loaded_room, *output);
299 if (preview_bitmap.is_active() && preview_bitmap.texture() != 0) {
300 // Draw room thumbnail
301 draw_list->AddImage((ImTextureID)(intptr_t)preview_bitmap.texture(),
302 room_min, room_max, ImVec2(0, 0), ImVec2(1, 1),
303 ImGui::GetColorU32(ImVec4(1, 1, 1, 1)));
304 } else {
305 // Placeholder for loaded but no texture
306 draw_list->AddRectFilled(
307 room_min, room_max,
308 ImGui::ColorConvertFloat4ToU32(theme.panel_bg_color));
309 }
310 } else {
311 // Not loaded - gray placeholder
312 draw_list->AddRectFilled(
313 room_min, room_max,
314 ImGui::ColorConvertFloat4ToU32(theme.panel_bg_darker));
315
316 // Show room ID
317 char label[8];
318 snprintf(label, sizeof(label), "%02X", room_id);
319 ImVec2 text_size = ImGui::CalcTextSize(label);
320 ImVec2 text_pos(room_min.x + (kRoomWidth - text_size.x) * 0.5f,
321 room_min.y + (kRoomHeight - text_size.y) * 0.5f);
322 draw_list->AddText(
323 text_pos,
324 ImGui::ColorConvertFloat4ToU32(theme.text_secondary_gray), label);
325 }
326 } else {
327 // Not loaded - gray placeholder
328 draw_list->AddRectFilled(
329 room_min, room_max,
330 ImGui::ColorConvertFloat4ToU32(theme.panel_bg_darker));
331
332 // Show room ID
333 char label[8];
334 snprintf(label, sizeof(label), "%02X", room_id);
335 ImVec2 text_size = ImGui::CalcTextSize(label);
336 ImVec2 text_pos(room_min.x + (kRoomWidth - text_size.x) * 0.5f,
337 room_min.y + (kRoomHeight - text_size.y) * 0.5f);
338 draw_list->AddText(
339 text_pos, ImGui::ColorConvertFloat4ToU32(theme.text_secondary_gray),
340 label);
341 }
342
343 // Draw border based on state
344 if (is_current) {
345 // Glow effect
346 ImVec4 glow = theme.dungeon_selection_primary;
347 glow.w = 0.4f;
348 ImVec2 glow_min(room_min.x - 2, room_min.y - 2);
349 ImVec2 glow_max(room_max.x + 2, room_max.y + 2);
350 draw_list->AddRect(glow_min, glow_max,
351 ImGui::ColorConvertFloat4ToU32(glow), 0.0f, 4.0f);
352 // Inner border
353 draw_list->AddRect(
354 room_min, room_max,
355 ImGui::ColorConvertFloat4ToU32(theme.dungeon_selection_primary),
356 0.0f, 2.0f);
357 } else if (is_open) {
358 draw_list->AddRect(
359 room_min, room_max,
360 ImGui::ColorConvertFloat4ToU32(theme.dungeon_grid_cell_selected),
361 0.0f, 2.0f);
362 } else {
363 draw_list->AddRect(
364 room_min, room_max,
365 ImGui::ColorConvertFloat4ToU32(theme.dungeon_grid_cell_border),
366 0.0f, 1.0f);
367 }
368
369 // Room type badge (small colored dot in top-left corner)
370 auto type_it = room_types_.find(room_id);
371 if (type_it != room_types_.end()) {
372 ImU32 badge_color = 0;
373 if (type_it->second == "entrance") {
374 badge_color = IM_COL32(76, 175, 80, 220); // Green
375 } else if (type_it->second == "boss") {
376 badge_color = IM_COL32(244, 67, 54, 220); // Red
377 } else if (type_it->second == "mini_boss") {
378 badge_color = IM_COL32(255, 152, 0, 220); // Orange
379 }
380 if (badge_color != 0) {
381 ImVec2 badge_center(room_min.x + 6.0f, room_min.y + 6.0f);
382 draw_list->AddCircleFilled(badge_center, 4.0f, badge_color);
383 }
384 }
385
386 // Handle clicks
387 ImGui::SetCursorScreenPos(room_min);
388 char btn_id[32];
389 snprintf(btn_id, sizeof(btn_id), "##map_room%d", room_id);
390 ImGui::InvisibleButton(btn_id, ImVec2(kRoomWidth, kRoomHeight));
391
392 if (ImGui::IsItemClicked()) {
393 if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
394 if (on_room_intent_) {
396 } else if (on_room_selected_) {
397 on_room_selected_(room_id);
398 }
399 } else if (on_room_selected_) {
400 on_room_selected_(room_id);
401 }
402 }
403
404 // Tooltip
405 if (ImGui::IsItemHovered()) {
406 ImGui::BeginTooltip();
407 ImGui::Text("[%03X] %s", room_id,
408 zelda3::GetRoomLabel(room_id).c_str());
409 if (rooms_) {
410 if (auto* loaded_room = rooms_->GetIfLoaded(room_id)) {
411 ImGui::TextDisabled(tr("Palette: %d"), loaded_room->palette());
412 }
413 }
414 ImGui::TextDisabled(tr("Click to select"));
415 ImGui::EndTooltip();
416 }
417 }
418
419 // Invisible room buttons moved the cursor. Reserve the grid from its
420 // original origin, rather than adding its extent after the last room.
421 ImGui::SetCursorScreenPos(canvas_pos);
422 ImGui::Dummy(canvas_size);
423 ImGui::EndChild();
424
425 // Status bar
426 ImGui::TextDisabled(tr("%zu rooms in view"), dungeon_room_ids_.size());
427 }
428
429 private:
430 std::vector<DungeonConnectedRoomLink> CollectConnections() const {
431 std::vector<DungeonConnectedRoomLink> links;
432 if (!rooms_) {
433 return links;
434 }
435 const auto warp_tags =
437 : std::set<uint8_t>{};
438 for (int room_id : dungeon_room_ids_) {
439 const auto* room = rooms_->GetIfMaterialized(room_id);
440 if (!room || !room->IsLoaded()) {
441 continue;
442 }
443 const auto outgoing = CollectDungeonConnectedRoomLinks(
444 room_id, *room,
445 [this](int neighbor_id, zelda3::DoorDirection direction) {
446 const auto* neighbor = rooms_->GetIfMaterialized(neighbor_id);
447 if (!neighbor || !neighbor->IsLoaded()) {
448 return false;
449 }
450 return std::any_of(
451 neighbor->GetDoors().begin(), neighbor->GetDoors().end(),
452 [direction](const auto& door) {
453 return door.direction == direction &&
454 zelda3::IsRoomConnectionDoorType(door.type);
455 });
456 },
457 nullptr, warp_tags);
458 for (const auto& link : outgoing) {
459 if (room_positions_.contains(link.to_room_id) &&
460 (link.type != DungeonConnectedLinkType::Door ||
461 link.from_room_id < link.to_room_id)) {
462 links.push_back(link);
463 }
464 }
465 }
466 return links;
467 }
468
470
475 room_positions_.clear();
476
477 int cols = static_cast<int>(
478 std::ceil(std::sqrt(static_cast<double>(dungeon_room_ids_.size()))));
479 cols = std::max(1, cols);
480
481 for (size_t i = 0; i < dungeon_room_ids_.size(); i++) {
482 int room_id = dungeon_room_ids_[i];
483 int grid_x = static_cast<int>(i % cols);
484 int grid_y = static_cast<int>(i / cols);
485 room_positions_[room_id] =
486 ImVec2(static_cast<float>(grid_x), static_cast<float>(grid_y));
487 }
488 }
489
495 bool has_registry = hack_manifest_ && hack_manifest_->HasProjectRegistry();
496
497 if (has_registry) {
499 } else {
501 }
502
503 ImGui::SameLine();
504 if (ImGui::Button(ICON_MD_ADD " Add Current")) {
505 if (current_room_id_ && *current_room_id_ >= 0) {
507 }
508 }
509 if (ImGui::IsItemHovered()) {
510 ImGui::SetTooltip(tr("Add currently selected room to the map"));
511 }
512
513 ImGui::SameLine();
514 if (ImGui::Button(ICON_MD_CLEAR " Clear")) {
515 ClearRooms();
516 current_dungeon_name_ = "Select Dungeon...";
517 selected_preset_ = -1;
518 }
519 }
520
525 const auto& dungeons = hack_manifest_->project_registry().dungeons;
526
527 ImGui::SetNextItemWidth(
528 std::max(100.0f, ImGui::GetContentRegionAvail().x - 220.0f));
529 if (ImGui::BeginCombo("##DungeonRegistry", current_dungeon_name_.c_str())) {
530 for (size_t i = 0; i < dungeons.size(); i++) {
531 const auto& dungeon = dungeons[i];
532 char label[128];
533 if (!dungeon.vanilla_name.empty()) {
534 snprintf(label, sizeof(label), "%s: %s (%s)", dungeon.id.c_str(),
535 dungeon.name.c_str(), dungeon.vanilla_name.c_str());
536 } else {
537 snprintf(label, sizeof(label), "%s: %s", dungeon.id.c_str(),
538 dungeon.name.c_str());
539 }
540 bool selected = (current_dungeon_name_ == dungeon.name);
541 if (ImGui::Selectable(label, selected)) {
542 LoadFromDungeonEntry(dungeon);
543 selected_preset_ = static_cast<int>(i);
544 }
545 }
546 ImGui::EndCombo();
547 }
548 }
549
554 struct DungeonPreset {
555 const char* name;
556 int start_room;
557 int count;
558 };
559
560 static const DungeonPreset kPresets[] = {
561 {"Eastern Palace", 0xC8, 8}, {"Desert Palace", 0x33, 8},
562 {"Tower of Hera", 0x07, 8}, {"Palace of Darkness", 0x09, 12},
563 {"Swamp Palace", 0x28, 10}, {"Skull Woods", 0x29, 10},
564 {"Thieves' Town", 0x44, 8}, {"Ice Palace", 0x0E, 12},
565 {"Misery Mire", 0x61, 10}, {"Turtle Rock", 0x04, 12},
566 {"Ganon's Tower", 0x0C, 16}, {"Hyrule Castle", 0x01, 12},
567 };
568
569 ImGui::SetNextItemWidth(
570 std::max(100.0f, ImGui::GetContentRegionAvail().x - 220.0f));
571 if (ImGui::BeginCombo(
572 "##DungeonPreset",
573 selected_preset_ >= 0 && selected_preset_ < IM_ARRAYSIZE(kPresets)
574 ? kPresets[selected_preset_].name
575 : "Select Dungeon...")) {
576 for (int i = 0; i < IM_ARRAYSIZE(kPresets); i++) {
577 if (ImGui::Selectable(kPresets[i].name, selected_preset_ == i)) {
579 ClearRooms();
580 for (int j = 0; j < kPresets[i].count; j++) {
581 int room_id = kPresets[i].start_room + j;
582 if (room_id < 0x128) {
583 dungeon_room_ids_.push_back(room_id);
584 }
585 }
587 }
588 }
589 ImGui::EndCombo();
590 }
591 }
592
596 static void DrawDashedLine(ImDrawList* dl, ImVec2 from, ImVec2 to,
597 ImU32 color, float thickness, float dash_len) {
598 float dx = to.x - from.x;
599 float dy = to.y - from.y;
600 float length = std::sqrt(dx * dx + dy * dy);
601 if (length < 1.0f)
602 return;
603 float nx = dx / length;
604 float ny = dy / length;
605
606 float drawn = 0.0f;
607 bool visible = true;
608 while (drawn < length) {
609 float seg = std::min(dash_len, length - drawn);
610 ImVec2 seg_start(from.x + nx * drawn, from.y + ny * drawn);
611 ImVec2 seg_end(from.x + nx * (drawn + seg), from.y + ny * (drawn + seg));
612 if (visible) {
613 dl->AddLine(seg_start, seg_end, color, thickness);
614 }
615 drawn += seg;
616 visible = !visible;
617 }
618 }
619
623 static void DrawArrowhead(ImDrawList* dl, ImVec2 from, ImVec2 to, ImU32 color,
624 float size) {
625 float dx = to.x - from.x;
626 float dy = to.y - from.y;
627 float length = std::sqrt(dx * dx + dy * dy);
628 if (length < 1.0f)
629 return;
630 float nx = dx / length;
631 float ny = dy / length;
632 // Perpendicular
633 float px = -ny;
634 float py = nx;
635
636 ImVec2 tip = to;
637 ImVec2 left(to.x - nx * size + px * size * 0.5f,
638 to.y - ny * size + py * size * 0.5f);
639 ImVec2 right(to.x - nx * size - px * size * 0.5f,
640 to.y - ny * size - py * size * 0.5f);
641 dl->AddTriangleFilled(tip, left, right, color);
642 }
643
644 int* current_room_id_ = nullptr;
645 ImVector<int>* active_rooms_ = nullptr;
647 std::function<void(int)> prepare_render_context_;
648 std::function<void(int)> on_room_selected_;
649 std::function<void(int, RoomSelectionIntent)> on_room_intent_;
650
651 // Room data
652 std::vector<int> dungeon_room_ids_;
653 std::map<int, ImVec2> room_positions_;
654 std::map<int, std::string> room_types_;
655 // Each configured room needs stable texture identity through ImGui's
656 // deferred frame render. Clear the set when switching dungeon contexts.
657 std::map<int, std::unique_ptr<RoomCompositeOutput>> room_composite_outputs_;
659
660 // Project registry integration
662 std::vector<core::DungeonConnection> stair_connections_;
663 std::vector<core::DungeonConnection> holewarp_connections_;
664 std::string current_dungeon_name_ = "Select Dungeon...";
665};
666
667} // namespace editor
668} // namespace yaze
669
670#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.
std::vector< DungeonConnectedRoomLink > CollectConnections() const
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 * GetIfMaterialized(int room_id)
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.
std::vector< DungeonConnectedRoomLink > CollectDungeonConnectedRoomLinks(int room_id, const zelda3::Room &room, const std::function< bool(int, zelda3::DoorDirection)> &has_reciprocal_door, const zelda3::RoomLinkFacts *link_facts, const std::set< uint8_t > &warp_tag_ids)
void EnsureCompositeBitmapTextureQueued(Bitmap &composite)
std::set< uint8_t > RoomCensusWarpTagsFromManifest(const core::HackManifest &manifest)
std::string GetRoomLabel(int id)
Convenience function to get a room label.
DoorDirection
Door direction on room walls.
Definition door_types.h:18
A complete dungeon entry with rooms and connections.
std::vector< DungeonConnection > holewarps
std::vector< DungeonRoom > rooms
std::vector< DungeonConnection > stairs
std::vector< DungeonEntry > dungeons