yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
dungeon_canvas_viewer.h
Go to the documentation of this file.
1#ifndef YAZE_APP_EDITOR_DUNGEON_DUNGEON_CANVAS_VIEWER_H
2#define YAZE_APP_EDITOR_DUNGEON_DUNGEON_CANVAS_VIEWER_H
3
4#include <array>
5#include <cstdint>
6#include <functional>
7#include <map>
8#include <memory>
9#include <optional>
10#include <set>
11#include <string>
12#include <tuple>
13#include <unordered_map>
14#include <vector>
15
23#include "app/editor/editor.h"
28#include "core/project.h"
31#include "dungeon_room_store.h"
32#include "imgui/imgui.h"
33#include "rom/rom.h"
34#include "util/lru_cache.h"
37#include "zelda3/dungeon/room.h"
40#include "zelda3/game_data.h"
42
43// Room-based plans and tools must follow canvas.h's ImGui math configuration.
49
50namespace yaze {
51namespace editor {
52
53class MinecartTrackEditorPanel;
54class DungeonCanvasViewerTestPeer;
55
56enum class DungeonConnectedLinkType : uint8_t {
57 Door,
60};
61
63 int from_room_id = -1;
64 int to_room_id = -1;
67 // Provenance fields populated by CollectDungeonConnectedRoomLinkDiagnostics
68 // for hover tooltips and issue reports. Defaults represent "not applicable".
69 int slot_index = -1; // Staircase slot 0..3, -1 otherwise.
70 int16_t object_id = -1; // Placed staircase tile-object id, -1 otherwise.
71 int door_index = -1; // Index in room.GetDoors() for Door links.
73};
74
75// Discriminator for staircase configuration anomalies surfaced through
76// CollectDungeonConnectedRoomLinkDiagnostics. Each kind explains a different
77// failure mode the runtime silently ignores.
78enum class DungeonStaircaseIssueKind : uint8_t {
79 // Header destination is non-zero but no placed interroom-stair object
80 // consumes that slot. Runtime never traverses the link.
82 // Placed interroom-stair object exists but its resolved destination is out
83 // of range. A consumed zero byte is valid room $000 or $100.
85 // Placed interroom-stair object beyond the 4 header slots. The runtime
86 // can only consume four; extras can never be reached.
88};
89
90// Captures one anomaly found while resolving a room's staircase connectivity.
91// Field meaning depends on `kind`; defaults represent "not applicable".
93 int from_room_id = -1;
95 int slot_index = -1; // 0..3 for UnusedHeader/MissingDestination.
96 int header_room_id = -1; // Header destination value (raw, may be invalid).
97 int16_t object_id = -1; // Placed object id (MissingDestination/Extra).
98};
99
101 std::vector<DungeonConnectedRoomLink> links;
102 std::vector<DungeonStaircaseIssue> staircase_issues;
103};
104
113
114inline constexpr std::array<const char*, 6> kDungeonIssueCategoryLabels = {{
115 "Palette mismatch",
116 "Object draw mismatch",
117 "Door render mismatch",
118 "Entity mismatch",
119 "Overlay or collision mismatch",
120 "General room render mismatch",
121}};
122
124 return static_cast<int>(category);
125}
126
127inline const char* GetIssueCategoryLabel(int index) {
128 if (index < 0 ||
129 index >= static_cast<int>(kDungeonIssueCategoryLabels.size())) {
130 return kDungeonIssueCategoryLabels.back();
131 }
132 return kDungeonIssueCategoryLabels[static_cast<size_t>(index)];
133}
134
136 const DungeonObjectInteraction& object_interaction) {
137 if (!object_interaction.GetSelectedObjectIndices().empty()) {
139 }
140 if (object_interaction.HasEntitySelection()) {
141 switch (object_interaction.GetSelectedEntity().type) {
142 case EntityType::Door:
144 case EntityType::Sprite:
145 case EntityType::Item:
147 default:
148 break;
149 }
150 }
152}
153
154std::vector<DungeonConnectedRoomLink> CollectDungeonConnectedRoomLinks(
155 int room_id, const zelda3::Room& room,
156 const std::function<bool(int, zelda3::DoorDirection)>& has_reciprocal_door,
157 const zelda3::RoomLinkFacts* link_facts = nullptr,
158 const std::set<uint8_t>& warp_tag_ids = {});
159
160// Returns the same set of links as CollectDungeonConnectedRoomLinks plus any
161// stale staircase header slots — i.e. header destinations with no placed
162// interroom-stair object consuming them. Provenance fields on each returned
163// link are populated for tooltip/issue-report surfacing.
164DungeonConnectedRoomLinkDiagnostics CollectDungeonConnectedRoomLinkDiagnostics(
165 int room_id, const zelda3::Room& room,
166 const std::function<bool(int, zelda3::DoorDirection)>& has_reciprocal_door,
167 const zelda3::RoomLinkFacts* link_facts = nullptr,
168 const std::set<uint8_t>& warp_tag_ids = {});
169
170// Renders a single connectivity link as a one-line human-readable description
171// for tooltips and issue reports. Caller decides separator/heading.
173 const DungeonConnectedRoomLink& link);
174
175// Renders a staircase issue entry as a one-line warning for tooltips and
176// issue reports.
178 const DungeonStaircaseIssue& issue);
179
180// Returns the room id adjacent to `room_id` in the given direction, or -1 if
181// no such neighbor exists (out of the 16x16 room matrix).
182inline int NeighborRoomId(int room_id, zelda3::DoorDirection dir) {
183 if (room_id < 0 || room_id >= zelda3::kNumberOfRooms) {
184 return -1;
185 }
186
187 constexpr int kCols = 16;
188 const int row = room_id / kCols;
189 const int col = room_id % kCols;
190
191 int candidate = -1;
192 switch (dir) {
194 candidate = row > 0 ? room_id - kCols : -1;
195 break;
197 candidate = room_id + kCols;
198 break;
200 candidate = col > 0 ? room_id - 1 : -1;
201 break;
203 candidate = col < kCols - 1 ? room_id + 1 : -1;
204 break;
205 }
206
207 return (candidate >= 0 && candidate < zelda3::kNumberOfRooms) ? candidate
208 : -1;
209}
210
211// Returns the opposite cardinal direction (N<->S, E<->W).
226
231 Manual, // Use ObjectDrawer routines
232 Emulator, // Use SNES emulator
233 Hybrid // Emulator with manual fallback
234};
235
238
239 public:
240 explicit DungeonCanvasViewer(Rom* rom = nullptr)
244 [this](int target_room, std::optional<size_t> target_door_index,
245 int target_tile_x, int target_tile_y) {
246 if (target_door_index &&
247 NavigateToDoorConnectionTarget(target_room, *target_door_index)) {
248 return;
249 }
250 NavigateToRoom(target_room);
251 bool focused_target_door = false;
252 if (target_door_index.has_value() && rooms_ != nullptr) {
253 auto* target = rooms_->TryEnsureRoom(target_room);
254 if (target != nullptr &&
255 *target_door_index < target->GetDoors().size()) {
256 const auto [x, y, width, height] =
257 target->GetDoors()[*target_door_index].GetEditorBounds();
258 ScrollToTile((x + width / 2) / 8, (y + height / 2) / 8);
259 TriggerCanvasPingRect(x, y, width, height);
260 object_interaction_.SelectEntity(EntityType::Door,
261 *target_door_index);
262 focused_target_door = true;
263 }
264 }
265 if (!focused_target_door && target_tile_x >= 0 &&
266 target_tile_y >= 0) {
267 ScrollToTile(target_tile_x, target_tile_y);
268 TriggerCanvasPingRect(target_tile_x * 8, target_tile_y * 8, 24, 24);
269 } else if (!focused_target_door) {
271 }
272 });
274 [this](int room_id, const zelda3::RoomObject& object) {
275 const auto semantics =
277 auto is_visible = [this, room_id](zelda3::LayerType layer) {
278 return IsLayerVisible(room_id, layer) &&
279 GetLayerBlendMode(room_id, layer) !=
281 };
282 switch (semantics.effective_bg_layer) {
284 return is_visible(zelda3::LayerType::BG1_Objects);
286 return is_visible(zelda3::LayerType::BG2_Objects);
288 return is_visible(zelda3::LayerType::BG1_Objects) ||
290 }
291 return true;
292 });
293 }
295
296 void DrawDungeonCanvas(int room_id);
297 std::optional<int> DrawConnectedRoomMatrix(int center_room_id);
298 // Read-only direct-neighbor thumbnails within the caller's spare height,
299 // including captions. Does not change the room view; clicks use normal room
300 // navigation after drawing. Empty connections consume no layout space.
301 void DrawNearbyRoomPreviews(int room_id, float height);
302 // Read-only proposal preview: overlay.rooms rendered left to right with the
303 // visible layers drawn on top. Never edits room data.
305 const std::vector<char>& layer_visible,
306 bool show_overlay, float scale);
308 float scale) const;
309 void DrawConnectedToolbarControls(int center_room_id);
310 void Draw(int room_id);
316 void TriggerChangePing();
318 std::function<absl::Status(int, const RoomMetadataEdit&)>;
320 std::function<absl::Status(const std::vector<RoomMetadataRequest>&)>;
322 std::function<absl::Status(int, size_t, uint8_t, bool)>;
323 using ChestDeleteCallback = std::function<absl::Status(int, size_t)>;
325 std::function<absl::StatusOr<DungeonConnectionPlan>(
328 std::function<absl::Status(const DungeonConnectionPlan&)>;
330 metadata_edit_callback_ = std::move(callback);
331 }
336 chest_edit_callback_ = std::move(callback);
337 }
339 chest_delete_callback_ = std::move(callback);
340 }
346 absl::StatusOr<DungeonConnectionPlan> PreviewDoorConnection(
347 const DungeonConnectionRequest& request);
348 absl::Status ApplyDoorConnection(const DungeonConnectionPlan& plan);
350 std::function<void(int, size_t)> callback) {
351 door_connection_navigation_callback_ = std::move(callback);
352 }
354 return static_cast<bool>(door_connection_navigation_callback_);
355 }
356 bool NavigateToDoorConnectionTarget(int room_id, size_t door_index) {
358 return false;
359 }
360 door_connection_navigation_callback_(room_id, door_index);
361 return true;
362 }
367 std::function<absl::StatusOr<std::string>(int)>;
369 std::function<absl::StatusOr<DungeonRoomTransferPlan>(
370 int, int, const std::string&, const DungeonRoomTransferOptions&)>;
372 std::function<absl::Status(const DungeonRoomTransferPlan&)>;
376 room_document_export_callback_ = std::move(export_document);
377 room_transfer_preview_callback_ = std::move(preview);
378 room_transfer_apply_callback_ = std::move(apply);
379 }
380 absl::StatusOr<std::string> ExportRoomDocument(int room_id);
381 absl::StatusOr<DungeonRoomTransferPlan> PreviewRoomTransfer(
382 int source_room_id, const std::string& json,
383 const DungeonRoomTransferOptions& options);
384 absl::Status ApplyRoomTransfer(const DungeonRoomTransferPlan& plan);
388 absl::Status EditRoomMetadata(int room_id, const RoomMetadataEdit& edit);
389 absl::Status EditRoomMetadataBatch(
390 const std::vector<RoomMetadataRequest>& requests);
391 absl::Status EditChest(int room_id, size_t index, uint8_t item_id,
392 bool big_chest);
393 absl::Status DeleteChest(int room_id, size_t index);
394 absl::Status OpenChestEditor(int room_id, size_t index);
401 void TriggerCanvasPingRect(int pixel_x, int pixel_y, int pixel_w,
402 int pixel_h);
404 const std::vector<zelda3::RoomObject>& previous_objects,
405 const std::vector<zelda3::RoomObject>& next_objects);
406
407 // Unscaled content size of the connected-room graph centered on
408 // `center_room_id`. Used by the workbench to reserve scroll space for the
409 // body child before DrawConnectedRoomMatrix runs, so the matrix doesn't need
410 // to open its own BeginChild scroll wrapper.
411 ImVec2 GetConnectedContentSize(int center_room_id);
412 // Clamped connected-canvas zoom scale that matches the one used by
413 // DrawConnectedRoomMatrix when it next runs.
414 float ConnectedCanvasScale() const;
415 void SetConnectedControlsInline(bool inline_controls) {
416 connected_controls_inline_ = inline_controls;
417 }
418
430 EditorContext context() const { return {rom_, game_data_}; }
441 Rom* rom() const { return rom_; }
449 void SetRenderer(gfx::IRenderer* renderer) { renderer_ = renderer; }
450
451 // Room data access
460 // Rebind ROM-backed context without replacing this viewer. This preserves
461 // panel aliases into viewer state while discarding selections and caches
462 // that may refer to data decoded from the previous ROM bytes.
464 DungeonRoomStore* rooms, int room_id);
465 DungeonRoomStore* rooms() const { return rooms_; }
466 bool HasRooms() const { return rooms_ != nullptr; }
467
468 // Best-effort "current room" context for auxiliary panels that are driven by
469 // whichever room the viewer is currently drawing.
470 int current_room_id() const { return current_room_id_; }
471
472 // Workbench/Inspector integration.
473 void SetCompactHeaderMode(bool compact) { compact_header_mode_ = compact; }
475 void SetRoomDetailsExpanded(bool expanded) { show_room_details_ = expanded; }
476
477 // Used by overworld editor when double-clicking entrances
478 void set_active_rooms(const ImVector<int>& rooms) { active_rooms_ = rooms; }
480
481 // Palette access
484 }
485 void SetCurrentPaletteId(uint64_t id) { current_palette_id_ = id; }
487 bool force_refresh = false) {
488 bool palette_changed = current_palette_group_.name() != group.name() ||
489 current_palette_group_.size() != group.size();
490 for (int i = 0; !palette_changed && i < static_cast<int>(group.size());
491 ++i) {
492 palette_changed =
494 }
495 if (!palette_changed && !force_refresh) {
496 return;
497 }
498
500 object_interaction_.SetCurrentPaletteGroup(group, force_refresh);
501 }
502 void SetEntranceRenderContext(int entrance_id, uint8_t entrance_blockset) {
503 current_entrance_id_ = entrance_id;
504 current_entrance_blockset_ = entrance_blockset;
505 }
513 }
514 // Auto may assign different graphics to rooms in a connected preview.
515 // The editor owns inference; standalone viewers retain their fixed context.
516 void SetEntranceBlocksetResolver(std::function<uint8_t(int)> resolver) {
517 entrance_blockset_resolver_ = std::move(resolver);
518 }
519 void SetEntranceCameraOverlay(int entrance_slot,
520 const DungeonEntranceCameraState& state) {
521 camera_overlay_entrance_slot_ = entrance_slot;
523 }
528 const std::optional<DungeonEntranceCameraState>& entrance_camera_overlay()
529 const {
531 }
532 void SetRoomNavigationCallback(std::function<void(int)> callback) {
533 room_navigation_callback_ = std::move(callback);
534 }
535 // Callback to swap the current room in-place (for arrow navigation)
536 void SetRoomSwapCallback(std::function<void(int, int)> callback) {
537 room_swap_callback_ = std::move(callback);
538 }
539
540 bool CanNavigateRooms() const {
541 return room_swap_callback_ != nullptr ||
542 room_navigation_callback_ != nullptr;
543 }
544
545 // Navigate to another dungeon room using the same semantics as the header
546 // arrow buttons:
547 // - If a swap callback exists (workbench mode), swap in-place.
548 // - Otherwise, use the navigation callback (opens/switches room view).
549 void NavigateToRoom(int target_room) {
550 if (target_room < 0 || target_room >= zelda3::kNumberOfRooms) {
551 return;
552 }
555 } else if (room_navigation_callback_) {
556 room_navigation_callback_(target_room);
557 }
558 }
559 void SetShowObjectPanelCallback(std::function<void()> callback) {
560 show_object_panel_callback_ = std::move(callback);
561 }
562 void SetShowSpritePanelCallback(std::function<void()> callback) {
563 show_sprite_panel_callback_ = std::move(callback);
564 }
565 void SetShowItemPanelCallback(std::function<void()> callback) {
566 show_item_panel_callback_ = std::move(callback);
567 }
568 void SetShowRoomListCallback(std::function<void()> callback) {
569 show_room_list_callback_ = std::move(callback);
570 }
571 void SetShowRoomMatrixCallback(std::function<void()> callback) {
572 show_room_matrix_callback_ = std::move(callback);
573 }
574 void SetShowEntranceListCallback(std::function<void()> callback) {
575 show_entrance_list_callback_ = std::move(callback);
576 }
577
584
587 }
589
590 // Overlay toggles (used by settings panels / workbench UI).
614 }
621
622 bool show_grid() const { return show_grid_; }
623 void set_show_grid(bool show) { show_grid_ = show; }
624 int custom_grid_size() const { return custom_grid_size_; }
625 void set_custom_grid_size(int size) {
626 custom_grid_size_ = size > 0 ? size : 1;
627 }
629 void set_show_object_bounds(bool show) { show_object_bounds_ = show; }
633 }
637 void set_show_texture_debug(bool show) { show_texture_debug_ = show; }
638 bool show_layer_info() const { return show_layer_info_; }
639 void set_show_layer_info(bool show) { show_layer_info_ = show; }
641 void set_show_crumble_floor(bool show) {
642 show_crumble_floor_ = show;
643 if (!show)
645 }
654
655 // Mutable pointer accessors for OverlayManagerPanel binding.
656 bool* mutable_show_grid() { return &show_grid_; }
678 void SetShowRoomGraphicsCallback(std::function<void()> callback) {
679 show_room_graphics_callback_ = std::move(callback);
680 }
681 void SetShowDoorEditorCallback(std::function<void()> callback) {
682 show_door_editor_callback_ = std::move(callback);
683 }
684 void SetShowDungeonSettingsCallback(std::function<void()> callback) {
685 show_dungeon_settings_callback_ = std::move(callback);
686 }
687 void SetSaveRoomCallback(std::function<void(int)> callback) {
688 save_room_callback_ = std::move(callback);
689 }
691 std::function<void(int, const zelda3::RoomObject&)> callback) {
692 edit_graphics_callback_ = std::move(callback);
693 }
695 std::function<void(int, const zelda3::RoomObject&)> callback) {
696 edit_object_tiles_callback_ = std::move(callback);
697 }
698 // Opens Object Coverage on the selected object's ID.
700 std::function<void(int, const zelda3::RoomObject&)> callback) {
701 check_object_coverage_callback_ = std::move(callback);
702 }
706 void SetPinned(bool pinned) { is_pinned_ = pinned; }
707 void SetPinCallback(std::function<void(bool)> callback) {
708 pin_callback_ = std::move(callback);
709 }
711 // Refresh external previews without replacing room data or editing state.
713 const project::YazeProject* project() const { return project_; }
714
715 // Canvas access
717 const gui::Canvas& canvas() const { return canvas_; }
718
719 // Object interaction access
721
725
726 // Enable/disable object interaction mode
727 void SetObjectInteractionEnabled(bool enabled) {
728 if (object_interaction_enabled_ && !enabled)
731 }
735
736 // Make the room header controls non-interactive while retaining centered
737 // canvas zoom (useful for split/compare views).
738 void SetHeaderReadOnly(bool read_only) {
739 if (!header_read_only_ && read_only)
741 header_read_only_ = read_only;
742 }
743 bool header_read_only() const { return header_read_only_; }
744
745 // Hide the header chrome entirely (useful for stitched/split layouts where a
746 // parent container provides its own metadata/controls).
747 void SetHeaderVisible(bool visible) { header_visible_ = visible; }
748 bool header_visible() const { return header_visible_; }
755
756 // Set and get the object render mode
761
762 // Layer visibility controls (per-room) using RoomLayerManager
763 void SetLayerVisible(int room_id, zelda3::LayerType layer, bool visible) {
764 GetRoomLayerManager(room_id).SetLayerVisible(layer, visible);
765 }
766 bool IsLayerVisible(int room_id, zelda3::LayerType layer) const {
767 auto it = room_layer_managers_.find(room_id);
768 return it != room_layer_managers_.end()
769 ? it->second.manager.IsLayerVisible(layer)
770 : true;
771 }
772
773 // Legacy compatibility - BG1 visibility (combines layout + objects)
774 void SetBG1Visible(int room_id, bool visible) {
775 auto& mgr = GetRoomLayerManager(room_id);
776 mgr.SetLayerVisible(zelda3::LayerType::BG1_Layout, visible);
777 mgr.SetLayerVisible(zelda3::LayerType::BG1_Objects, visible);
778 }
779 void SetBG2Visible(int room_id, bool visible) {
780 auto& mgr = GetRoomLayerManager(room_id);
781 mgr.SetLayerVisible(zelda3::LayerType::BG2_Layout, visible);
782 mgr.SetLayerVisible(zelda3::LayerType::BG2_Objects, visible);
783 }
784 bool IsBG1Visible(int room_id) const {
785 auto it = room_layer_managers_.find(room_id);
786 if (it == room_layer_managers_.end())
787 return true;
788 return it->second.manager.IsLayerVisible(zelda3::LayerType::BG1_Layout) ||
789 it->second.manager.IsLayerVisible(zelda3::LayerType::BG1_Objects);
790 }
791 bool IsBG2Visible(int room_id) const {
792 auto it = room_layer_managers_.find(room_id);
793 if (it == room_layer_managers_.end())
794 return true;
795 return it->second.manager.IsLayerVisible(zelda3::LayerType::BG2_Layout) ||
796 it->second.manager.IsLayerVisible(zelda3::LayerType::BG2_Objects);
797 }
798
799 // Layer blend mode controls
800 void SetLayerBlendMode(int room_id, zelda3::LayerType layer,
802 GetRoomLayerManager(room_id).SetLayerBlendMode(layer, mode);
803 }
805 zelda3::LayerType layer) const {
806 auto it = room_layer_managers_.find(room_id);
807 return it != room_layer_managers_.end()
808 ? it->second.manager.GetLayerBlendMode(layer)
810 }
811
812 // Per-object translucency
813 void SetObjectTranslucent(int room_id, size_t object_index, bool translucent,
814 uint8_t alpha = 128) {
815 GetRoomLayerManager(room_id).SetObjectTranslucency(object_index,
816 translucent, alpha);
817 }
818
819 // Layer manager access
822 static zelda3::RoomLayerManager default_manager;
823 auto it = room_layer_managers_.find(room_id);
824 return it != room_layer_managers_.end() ? it->second.manager
825 : default_manager;
826 }
827
828 // Legacy BG2 layer type (mapped to blend mode)
829 void SetBG2LayerType(int room_id, int type) {
830 auto& mgr = GetRoomLayerManager(room_id);
832 switch (type) {
833 case 0:
835 break;
836 case 1:
838 break;
839 case 2:
841 break;
842 case 3:
844 break;
845 case 4:
847 break;
848 default:
850 break;
851 }
852 mgr.SetLayerBlendMode(zelda3::LayerType::BG2_Layout, mode);
853 mgr.SetLayerBlendMode(zelda3::LayerType::BG2_Objects, mode);
854 }
855 int GetBG2LayerType(int room_id) const {
857 switch (mode) {
859 return 0;
861 return 1;
863 return 2;
865 return 3;
867 return 4;
868 }
869 return 0;
870 }
871
872 // Set the object to be placed
874 // Pass palette group first so ghost preview can render correctly
877 }
880 false);
881 }
882
883 // Scroll the canvas to center on the given tile coordinates.
884 // The pending target is consumed by Draw() on the next frame.
885 void ScrollToTile(int tile_x, int tile_y) {
886 pending_scroll_target_ = {tile_x, tile_y};
887 }
889 return pending_scroll_target_.has_value();
890 }
891 std::optional<std::pair<int, int>> GetPendingScrollTarget() const {
893 }
894
895 // Object manipulation
900 return ImGui::GetCurrentContext() != nullptr &&
901 HasRoomCanvasShortcutFocusForFrame(ImGui::GetFrameCount());
902 }
904 return ImGui::GetCurrentContext() != nullptr &&
906 room_canvas_last_draw_frame_ >= ImGui::GetFrameCount() - 1;
907 }
908
909 // Entity visibility controls
910 void SetSpritesVisible(bool visible) {
912 }
914 void SetPotItemsVisible(bool visible) {
916 }
918 void SetChestContentsVisible(bool visible) {
920 }
924
927 int col = 0;
928 int row = 0;
929 bool placed = false;
930 bool connected_to_start = false;
931 };
932
933 std::array<bool, zelda3::kNumberOfRooms> room_mask{};
934 std::array<RoomPlacement, zelda3::kNumberOfRooms> room_positions{};
935 std::array<std::string, zelda3::kNumberOfRooms> room_floor_labels{};
936 std::vector<std::string> floor_order;
937 std::vector<DungeonConnectedRoomLink> links;
938 std::map<int, DungeonConnectedRoomLinkDiagnostics> room_diagnostics;
939 // Staircase configuration anomalies aggregated across the whole
940 // connected component. Order is "first-encountered during BFS".
941 std::vector<DungeonStaircaseIssue> staircase_issues;
942 // Resolved links whose destination room falls outside the project's
943 // current dungeon registry scope (only populated when scoping is active).
944 // The runtime would still traverse these; the matrix omits the target
945 // rooms by default but surfaces the link as a diagnostic so the user can
946 // see "current dungeon connects out to room X via staircase".
947 std::vector<DungeonConnectedRoomLink> out_of_scope_links;
948 // True when BFS is restricted to a project-registry dungeon group.
950 int room_count = 0;
952 int min_col = 0;
953 int max_col = 0;
954 int min_row = 0;
955 int max_row = 0;
956 };
957
958 private:
964 friend class
966 friend class
968 friend class
970 friend class
972
974 int x = 0;
975 int y = 0;
976 int w = 0;
977 int h = 0;
978 };
979
981 const zelda3::RoomObject& object, int canvas_x,
982 int canvas_y);
983 void DrawRoomHeader(zelda3::Room& room, int room_id);
984 void DrawRoomNavigation(int room_id);
985 void DrawRoomPropertyTable(zelda3::Room& room, int room_id);
986 void DrawRecentRoomBreadcrumbs(int room_id);
987 void DrawLayerControls(zelda3::Room& room, int room_id);
988 void DrawCompactLayerToggles(int room_id);
989 void PopulateCanvasContextMenu(int room_id);
990 void AddInteractionContextMenuItems(int room_id);
991 void AddLoadedRoomContextMenuItems(int room_id);
993 std::vector<gui::CanvasMenuItem> BuildSelectionContextMenuItems(int room_id);
994 std::vector<gui::CanvasMenuItem> BuildSelectionContextMenuItems(
995 int room_id, std::optional<zelda3::RoomObject> context_object);
996 std::optional<zelda3::RoomObject> GetObjectUnderContextCursor(int room_id);
997 std::optional<size_t> GetObjectIndexUnderContextCursor(int room_id);
1000 std::optional<gui::CanvasMenuItem> BuildOpenContextMenu();
1005 std::string BuildRoomMetadataSummary(const zelda3::Room& room,
1006 int room_id) const;
1007 std::string BuildDrawIssueReport(const zelda3::Room& room, int room_id);
1008 std::string BuildSelectionIssueReport(const zelda3::Room& room,
1009 int room_id) const;
1010 void OpenIssueReportPopup(const std::string& title,
1011 const std::string& summary,
1012 const std::string& kind_label,
1013 const std::string& diagnostics, int room_id,
1014 int default_category_index);
1015 absl::Status PrepareIssueReportPopup(const std::string& title,
1016 const std::string& summary,
1017 const std::string& kind_label,
1018 const std::string& diagnostics,
1019 int room_id, int default_category_index);
1020 std::string BuildIssueReportClipboardText() const;
1021 absl::Status CaptureIssueReportScreenshot();
1022 absl::Status AppendIssueReportToLog();
1023 absl::Status EnsureIssueReportPersisted();
1024 void MarkIssueReportDirty();
1026 void SetIssueReportPopupStatus(std::string message, bool is_error);
1027 void DrawIssueReportStorageSummary() const;
1028 void DrawIssueReportStatusMessage() const;
1029 void RenderSprites(const gui::CanvasRuntime& rt, const zelda3::Room& room);
1030 void RenderPotItems(const gui::CanvasRuntime& rt, const zelda3::Room& room);
1032 const zelda3::Room& room);
1034 const zelda3::Room& room);
1035
1036 // Touch interaction: long-press context menu for entities
1038 const zelda3::Room& room);
1039
1040 // Visualization
1042 const zelda3::Room& room);
1045 GetCollisionOverlayCache(int room_id);
1046
1047 // Draw semi-transparent overlay on stored value 1 / BG2 overlay objects when
1048 // mask mode is active.
1050 const zelda3::Room& room);
1051 void DrawPersistentDebugWindows(int room_id);
1052 void DrawRoomDebugWindow(zelda3::Room& room, int room_id);
1053 void DrawTextureDebugWindow(zelda3::Room& room, int room_id);
1054 void DrawLayerInfoWindow(int room_id);
1056 int room_id);
1057 void DrawCoordinateOverlayHud(int room_id);
1058 bool ValidateRoomCanvasRequest(int room_id);
1060 void UpdateRoomCanvasViewport(ImVec2 viewport_size);
1064 void RefreshActiveRoomCanvasState(zelda3::Room& room, int room_id);
1066 void SyncCanvasCaptureRegion(const gui::CanvasRuntime& canvas_rt);
1067 void ConsumePendingCanvasScroll(const gui::CanvasRuntime& canvas_rt);
1068 void DrawHeaderHiddenMetadataHud(int room_id);
1069 void PrepareRoomStateForCanvas(zelda3::Room& room, int room_id);
1070 void DrawRoomCanvasContent(const gui::CanvasRuntime& canvas_rt,
1071 zelda3::Room& room, int room_id);
1072 void HandleRoomCanvasDropTargets(zelda3::Room& room, int room_id);
1073 void DrawChangePingOverlay(const gui::CanvasRuntime& canvas_rt,
1074 const zelda3::Room& room);
1075 void RecordVisitedRoom(int room_id);
1077 RoomCompositeOutput& output);
1080 void UpdateRoomCanvasShortcutFocus(bool hovered, bool pointer_pressed,
1081 int frame_index);
1082 bool HasRoomCanvasShortcutFocusForFrame(int frame_index) const;
1083
1084 // Room graphics management
1085 // Load: Read from ROM, Render: Process pixels, Draw: Display on canvas
1086 absl::Status LoadAndRenderRoomGraphics(int room_id);
1092 int ApplyConnectedStaircaseIssueAutoFixes(int center_room_id);
1093 bool DrawRoomBackgroundLayers(int room_id); // Draw room buffers to canvas
1094
1095 Rom* rom_ = nullptr;
1097 gui::Canvas canvas_{"##DungeonCanvas", ImVec2(0x200, 0x200)};
1100 gui::Canvas connected_canvas_{"##DungeonConnectedCanvas",
1101 ImVec2(0x200, 0x200)};
1102 // ObjectRenderer removed - use ObjectDrawer for rendering (production system)
1104
1105 // Touch gesture handler for long-press context menus on touch devices
1107
1108 // Scroll target
1109 std::optional<std::pair<int, int>> pending_scroll_target_;
1110
1111 // Room data
1114 std::vector<int> recently_visited_rooms_;
1117 std::function<uint8_t(int)> entrance_blockset_resolver_;
1119 std::optional<DungeonEntranceCameraState> entrance_camera_overlay_;
1120 // Used by overworld editor for double-click entrance → open dungeon room
1121 ImVector<int> active_rooms_;
1130 // Last-frame visibility of the connected-mode side panel (overview /
1131 // preview). Used to apply hysteresis when the viewport width crosses the
1132 // panel's min-size threshold, so dragging the pane splitter past the
1133 // threshold doesn't cause a sudden ~220 px horizontal snap.
1141
1142 // Object interaction state
1146
1147 // Per-room layer managers (4-way visibility, blend modes, per-object translucency)
1150 std::optional<std::pair<zelda3::LayerMergeType, zelda3::EffectKey>>
1152 };
1153 std::map<int, RoomLayerState> room_layer_managers_;
1154
1155 // The primary output is pinned because Canvas retains its Bitmap pointer.
1156 // Connected previews keep stable outputs for rooms visible this frame.
1159 std::unique_ptr<RoomCompositeOutput> output;
1161 };
1162 std::map<int, ConnectedRoomCompositeEntry> connected_composite_outputs_;
1164
1165 // Palette data
1169 std::function<void(int)> room_navigation_callback_;
1170 std::function<void(int, int)>
1171 room_swap_callback_; // (old_room_id, new_room_id)
1172 std::function<void()> show_object_panel_callback_;
1173 std::function<void()> show_sprite_panel_callback_;
1174 std::function<void()> show_item_panel_callback_;
1175 std::function<void()> show_room_list_callback_;
1176 std::function<void()> show_room_matrix_callback_;
1177 std::function<void()> show_entrance_list_callback_;
1178 std::function<void()> show_room_graphics_callback_;
1179 std::function<void()> show_door_editor_callback_;
1180 std::function<void()> show_dungeon_settings_callback_;
1181 std::function<void(int)> save_room_callback_;
1182 std::function<void(int, const zelda3::RoomObject&)> edit_graphics_callback_;
1188 bool DrawCrumbleCanvas(const gui::CanvasRuntime& rt);
1190 int room_id);
1192 zelda3::Room& room, int room_id);
1196 bool is_pinned_ = false;
1197 std::function<void(bool)> pin_callback_;
1200 // Room graphics revisions are globally unique. Retain indexed pixels across
1201 // connected-room draws; presentation (palette, position, zoom) stays live.
1202 using SpritePreviewKey = std::tuple<uint64_t, uint8_t, int, bool>;
1203 using ItemPreviewKey = std::pair<uint64_t, uint8_t>;
1205 std::vector<uint8_t> pixels;
1206 SDL_Rect bounds{};
1207 };
1211
1230 std::function<void(int, size_t)> door_connection_navigation_callback_;
1237 bool header_read_only_ = false;
1238 bool header_visible_ = true;
1240
1242 std::vector<uint16_t> track_tile_order_;
1243 std::vector<uint16_t> switch_tile_order_;
1245 std::unordered_map<int, DungeonRenderingHelpers::CollisionOverlayCache>
1247 std::bitset<256> minecart_sprite_ids_{};
1248
1249 // Object rendering cache
1257 std::vector<ObjectRenderCache> object_render_cache_;
1259
1260 // Debug state flags
1264 bool show_layer_info_ = false;
1265 bool show_grid_ = false; // Grid off by default for dungeon editor
1267 false; // Show camera coordinates on hover (toggle via Debug menu)
1268 int layout_override_ = -1; // -1 for no override
1271 ObjectRenderMode::Emulator; // Default to emulator rendering
1272
1273 // Object outline filtering toggles
1275 bool show_type1_objects = true; // Standard objects (0x00-0xFF)
1276 bool show_type2_objects = true; // Extended objects (0x100-0x1FF)
1277 bool show_type3_objects = true; // Special objects (0xF00-0xFFF)
1278 bool show_layer0_objects = true; // Primary / upper layer (BG1)
1279 bool show_layer1_objects = true; // BG2 overlay / lower layer (BG2)
1280 bool show_layer2_objects = true; // BG1 overlay room stream
1281 };
1283
1284 // Entity overlay visibility toggles
1286 bool show_sprites = true; // Show sprite entities
1287 bool show_pot_items = true; // Show pot item entities
1288 bool show_chests = true; // Show chest receipt labels above chest objects
1289 };
1291
1293
1294 // Previous room state for change detection (per-viewer)
1299
1309 "Report Dungeon Issue##DungeonIssueReportPopup";
1321 std::vector<ChangePingRect> change_ping_rects_;
1323 std::function<void(int, const zelda3::RoomObject&)>
1325 std::function<void(int, const zelda3::RoomObject&)>
1327};
1328
1329} // namespace editor
1330} // namespace yaze
1331
1332#endif
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
Definition rom.h:52
bool DrawMinecartNodePlacement(const gui::CanvasRuntime &rt, zelda3::Room &room, int room_id)
std::function< absl::StatusOr< DungeonConnectionPlan >( const DungeonConnectionRequest &)> DoorConnectionPreviewCallback
RoomTransferPreviewCallback room_transfer_preview_callback_
std::optional< zelda3::RoomObject > GetObjectUnderContextCursor(int room_id)
void SetCheckObjectCoverageCallback(std::function< void(int, const zelda3::RoomObject &)> callback)
gui::CanvasMenuItem BuildLayerVisibilityContextMenu(int room_id)
void SetChestEditCallback(ChestEditCallback callback)
void HandleRoomCanvasDropTargets(zelda3::Room &room, int room_id)
bool RoomHasNonExitDoorInDirection(int room_id, zelda3::DoorDirection dir)
const zelda3::RoomLayerManager & GetRoomLayerManager(int room_id) const
std::function< absl::Status(int, size_t)> ChestDeleteCallback
void DrawChangePingOverlay(const gui::CanvasRuntime &canvas_rt, const zelda3::Room &room)
void SetShowEntranceListCallback(std::function< void()> callback)
DungeonRoomTransferEditorState room_transfer_state_
void SetMetadataBatchEditCallback(MetadataBatchEditCallback callback)
std::function< absl::Status(const std::vector< RoomMetadataRequest > &)> MetadataBatchEditCallback
void RefreshActiveRoomCanvasState(zelda3::Room &room, int room_id)
gfx::Bitmap * PrepareConnectedRoomCompositeBitmap(int room_id)
std::function< void(int, size_t)> door_connection_navigation_callback_
DungeonChestEditDialogState chest_edit_dialog_state_
gui::CanvasMenuItem BuildRoomContextMenu(int room_id)
gui::CanvasMenuItem BuildDebugContextMenu(int room_id)
friend class DungeonEditorPaletteRefreshTest_CachedRoomRefreshesThroughViewerCompositePreparation_Test
void SetDoorConnectionCallbacks(DoorConnectionPreviewCallback preview, DoorConnectionApplyCallback apply)
std::string BuildDrawIssueReport(const zelda3::Room &room, int room_id)
std::optional< std::pair< int, int > > pending_scroll_target_
std::function< void(int, const zelda3::RoomObject &) check_object_coverage_callback_)
void SetLayerBlendMode(int room_id, zelda3::LayerType layer, zelda3::LayerBlendMode mode)
void SyncCanvasCaptureRegion(const gui::CanvasRuntime &canvas_rt)
std::vector< gui::CanvasMenuItem > BuildSelectionContextMenuItems(int room_id)
void SetEditorSystem(zelda3::DungeonEditorSystem *system)
absl::Status ApplyRoomTransfer(const DungeonRoomTransferPlan &plan)
int ApplyConnectedStaircaseIssueAutoFixes(int center_room_id)
absl::StatusOr< std::string > ExportRoomDocument(int room_id)
void RenderPotItems(const gui::CanvasRuntime &rt, const zelda3::Room &room)
RoomTransferApplyCallback room_transfer_apply_callback_
std::optional< int > DrawConnectedRoomMatrix(int center_room_id)
absl::Status LoadAndRenderRoomGraphics(int room_id)
gfx::Bitmap * PrepareRoomCompositeWithOutput(int room_id, RoomCompositeOutput &output)
DungeonChestEditorState & chest_editor_state()
DoorConnectionPreviewCallback door_connection_preview_callback_
absl::Status OpenChestEditor(int room_id, size_t index)
void UpdateRoomCanvasShortcutFocus(bool hovered, bool pointer_pressed, int frame_index)
std::function< absl::Status(int, size_t, uint8_t, bool)> ChestEditCallback
friend class DungeonEditorPaletteRefreshTest_DungeonMainNotificationSkipsUnrelatedCachedViewerWork_Test
std::optional< size_t > GetObjectIndexUnderContextCursor(int room_id)
void SetMinecartTrackPanel(MinecartTrackEditorPanel *panel)
absl::Status ApplyDoorConnection(const DungeonConnectionPlan &plan)
void SetObjectTranslucent(int room_id, size_t object_index, bool translucent, uint8_t alpha=128)
RoomDocumentExportCallback room_document_export_callback_
absl::Status EditRoomMetadataBatch(const std::vector< RoomMetadataRequest > &requests)
void SetRoomTransferCallbacks(RoomDocumentExportCallback export_document, RoomTransferPreviewCallback preview, RoomTransferApplyCallback apply)
void SetShowItemPanelCallback(std::function< void()> callback)
std::function< void()> show_door_editor_callback_
void SetShowRoomGraphicsCallback(std::function< void()> callback)
void SetConnectedControlsInline(bool inline_controls)
std::function< void(int, const zelda3::RoomObject &) edit_object_tiles_callback_)
zelda3::SpritePreviewResourceCache sprite_preview_resources_
void SetProject(const project::YazeProject *project)
std::function< void(int, const zelda3::RoomObject &) edit_graphics_callback_)
const DungeonRenderingHelpers::CollisionOverlayCache & GetCollisionOverlayCache(int room_id)
std::map< int, ConnectedRoomCompositeEntry > connected_composite_outputs_
void SetIssueReportPopupStatus(std::string message, bool is_error)
void set_active_rooms(const ImVector< int > &rooms)
void SetRenderer(gfx::IRenderer *renderer)
void SetEditGraphicsCallback(std::function< void(int, const zelda3::RoomObject &)> callback)
void SetBG2LayerType(int room_id, int type)
std::optional< DungeonEntranceCameraState > entrance_camera_overlay_
friend class DungeonEditorPaletteRefreshTest_CachedPanelPaletteRefreshSurvivesWorkbenchModeAndPreservesRoomPalette_Test
DungeonConnectionEditorState & connection_editor_state()
std::function< void()> show_entrance_list_callback_
bool DrawCrumbleCanvas(const gui::CanvasRuntime &rt)
const std::optional< DungeonEntranceCameraState > & entrance_camera_overlay() const
void DrawTextureDebugWindow(zelda3::Room &room, int room_id)
zelda3::Room * EnsureRoomLoadedForConnectedView(int room_id)
void SetShowRoomListCallback(std::function< void()> callback)
absl::Status EditRoomMetadata(int room_id, const RoomMetadataEdit &edit)
absl::StatusOr< DungeonConnectionPlan > PreviewDoorConnection(const DungeonConnectionRequest &request)
bool DrawMinecartCanvas(const gui::CanvasRuntime &rt, zelda3::Room &room, int room_id)
void SetEntranceBlocksetResolver(std::function< uint8_t(int)> resolver)
zelda3::Room * PrepareActiveRoomForCanvasFrame(int room_id)
void RefreshRomBackedState(Rom *rom, zelda3::GameData *game_data, DungeonRoomStore *rooms, int room_id)
DungeonObjectInteraction object_interaction_
void SetObjectRenderMode(ObjectRenderMode mode)
void PrepareRoomStateForCanvas(zelda3::Room &room, int room_id)
void OpenIssueReportPopup(const std::string &title, const std::string &summary, const std::string &kind_label, const std::string &diagnostics, int room_id, int default_category_index)
void DrawRoomCanvasContent(const gui::CanvasRuntime &canvas_rt, zelda3::Room &room, int room_id)
DungeonObjectInteraction & object_interaction()
void DrawRoomDebugWindow(zelda3::Room &room, int room_id)
ConnectedRoomGraphData BuildConnectedRoomGraph(int start_room_id)
friend class DungeonEditorPaletteRefreshTest_CachedCompositePreparationPreservesTargetEntranceContext_Test
std::string BuildRoomMetadataSummary(const zelda3::Room &room, int room_id) const
std::function< void()> show_room_list_callback_
void SetChestDeleteCallback(ChestDeleteCallback callback)
void TriggerCanvasPingRect(int pixel_x, int pixel_y, int pixel_w, int pixel_h)
absl::Status EditChest(int room_id, size_t index, uint8_t item_id, bool big_chest)
void SetShowRoomMatrixCallback(std::function< void()> callback)
const project::YazeProject * project_
std::function< uint8_t(int)> entrance_blockset_resolver_
bool NavigateToDoorConnectionTarget(int room_id, size_t door_index)
DoorConnectionApplyCallback door_connection_apply_callback_
void SetRoomNavigationCallback(std::function< void(int)> callback)
absl::StatusOr< DungeonRoomTransferPlan > PreviewRoomTransfer(int source_room_id, const std::string &json, const DungeonRoomTransferOptions &options)
gui::CanvasMenuItem BuildReportContextMenu(int room_id)
void SetShowSpritePanelCallback(std::function< void()> callback)
void SetPreviewObject(const zelda3::RoomObject &object)
std::function< void()> show_object_panel_callback_
std::function< void(bool)> pin_callback_
std::optional< std::pair< int, int > > GetPendingScrollTarget() const
void UpdateRoomCanvasViewport(ImVec2 viewport_size)
void SetBG1Visible(int room_id, bool visible)
void SetBG2Visible(int room_id, bool visible)
bool IsLayerVisible(int room_id, zelda3::LayerType layer) const
std::unordered_map< int, DungeonRenderingHelpers::CollisionOverlayCache > collision_overlay_cache_
void DrawLayerControls(zelda3::Room &room, int room_id)
std::function< absl::Status(const DungeonConnectionPlan &)> DoorConnectionApplyCallback
void SetShowObjectPanelCallback(std::function< void()> callback)
void RenderSprites(const gui::CanvasRuntime &rt, const zelda3::Room &room)
gfx::Bitmap * PrepareRoomCompositeBitmap(int room_id)
zelda3::RoomLayerManager & GetRoomLayerManager(int room_id)
ObjectRenderMode GetObjectRenderMode() const
std::function< absl::Status(int, const RoomMetadataEdit &)> MetadataEditCallback
std::function< absl::StatusOr< DungeonRoomTransferPlan >( int, int, const std::string &, const DungeonRoomTransferOptions &)> RoomTransferPreviewCallback
void DrawMaskHighlights(const gui::CanvasRuntime &rt, const zelda3::Room &room)
void TriggerObjectChangePing(const std::vector< zelda3::RoomObject > &previous_objects, const std::vector< zelda3::RoomObject > &next_objects)
gui::CanvasFrameOptions BuildRoomCanvasFrameOptions() const
void SetMetadataEditCallback(MetadataEditCallback callback)
void SetEntranceRenderContext(int entrance_id, uint8_t entrance_blockset)
absl::Status PrepareIssueReportPopup(const std::string &title, const std::string &summary, const std::string &kind_label, const std::string &diagnostics, int room_id, int default_category_index)
util::LruCache< SpritePreviewKey, CachedSpritePreview > sprite_preview_cache_
void RenderChestContents(const gui::CanvasRuntime &rt, const zelda3::Room &room)
bool HasRoomCanvasShortcutFocusForFrame(int frame_index) const
absl::Status DeleteChest(int room_id, size_t index)
std::function< void()> show_dungeon_settings_callback_
void SetRoomSwapCallback(std::function< void(int, int)> callback)
MetadataBatchEditCallback metadata_batch_edit_callback_
DungeonRoomTransferEditorState & room_transfer_state()
const project::YazeProject * project() const
void SetEditObjectTilesCallback(std::function< void(int, const zelda3::RoomObject &)> callback)
std::function< void()> show_room_matrix_callback_
std::pair< uint64_t, uint8_t > ItemPreviewKey
void ScrollToTile(int tile_x, int tile_y)
void SetDoorConnectionNavigationCallback(std::function< void(int, size_t)> callback)
std::function< absl::Status(const DungeonRoomTransferPlan &)> RoomTransferApplyCallback
DungeonConnectionEditorState connection_editor_state_
std::function< absl::StatusOr< std::string >(int)> RoomDocumentExportCallback
zelda3::LayerBlendMode GetLayerBlendMode(int room_id, zelda3::LayerType layer) const
std::function< void()> show_room_graphics_callback_
void ConsumePendingCanvasScroll(const gui::CanvasRuntime &canvas_rt)
util::LruCache< ItemPreviewKey, CachedSpritePreview > item_preview_cache_
void SetSaveRoomCallback(std::function< void(int)> callback)
ImVec2 GetProposalPreviewContentSize(const DungeonProposalOverlay &overlay, float scale) const
void SetCurrentPaletteGroup(const gfx::PaletteGroup &group, bool force_refresh=false)
void DrawProposalPreview(const DungeonProposalOverlay &overlay, const std::vector< char > &layer_visible, bool show_overlay, float scale)
void DrawRoomHeader(zelda3::Room &room, int room_id)
std::function< void(int)> room_navigation_callback_
void RenderEntityOverlay(const gui::CanvasRuntime &rt, const zelda3::Room &room)
std::function< void()> show_item_panel_callback_
std::vector< ObjectRenderCache > object_render_cache_
void DisplayObjectInfo(const gui::CanvasRuntime &rt, const zelda3::RoomObject &object, int canvas_x, int canvas_y)
std::tuple< uint64_t, uint8_t, int, bool > SpritePreviewKey
std::function< void()> show_sprite_panel_callback_
std::function< void(int, int)> room_swap_callback_
DungeonRenderingHelpers::TrackCollisionConfig track_collision_config_
void SetLayerVisible(int room_id, zelda3::LayerType layer, bool visible)
void DrawNearbyRoomPreviews(int room_id, float height)
void DrawObjectPositionOutlines(const gui::CanvasRuntime &rt, const zelda3::Room &room)
std::optional< gui::CanvasMenuItem > BuildOpenContextMenu()
void DrawRoomPropertyTable(zelda3::Room &room, int room_id)
void HandleTouchLongPressContextMenu(const gui::CanvasRuntime &rt, const zelda3::Room &room)
void SetShowDungeonSettingsCallback(std::function< void()> callback)
void SetEntranceCameraOverlay(int entrance_slot, const DungeonEntranceCameraState &state)
void SetRooms(DungeonRoomStore *rooms)
MinecartTrackEditorPanel * minecart_track_panel_
void HandleRoomCanvasNavigation(gui::CanvasRuntime &canvas_rt)
std::vector< ChangePingRect > change_ping_rects_
std::map< int, RoomLayerState > room_layer_managers_
void DrawRoomCanvasOverlays(const gui::CanvasRuntime &rt, zelda3::Room &room, int room_id)
std::string BuildSelectionIssueReport(const zelda3::Room &room, int room_id) const
gui::CanvasMenuItem BuildCopyExportContextMenu(int room_id)
void SetGameData(zelda3::GameData *game_data)
void SetShowDoorEditorCallback(std::function< void()> callback)
void SetPinCallback(std::function< void(bool)> callback)
std::function< void(int)> save_room_callback_
Handles object selection, placement, and interaction within the dungeon canvas.
void SetObjectSelectionVisibilityPredicate(std::function< bool(int, const zelda3::RoomObject &)> predicate)
void SetDoorPairNavigationCallback(std::function< void(int, std::optional< size_t >, int, int)> callback)
void SetEditorSystem(zelda3::DungeonEditorSystem *system)
std::vector< size_t > GetSelectedObjectIndices() const
void SetCurrentPaletteGroup(const gfx::PaletteGroup &group, bool force_refresh=false)
void SelectEntity(EntityType type, size_t index)
void SetPreviewObject(const zelda3::RoomObject &object, bool loaded)
zelda3::Room * TryEnsureRoom(int room_id)
Represents a bitmap image optimized for SNES ROM hacking.
Definition bitmap.h:70
Defines an abstract interface for all rendering operations.
Definition irenderer.h:60
Handles touch input integration for Canvas.
Modern, robust canvas for drawing and manipulating graphics.
Definition canvas.h:64
RoomLayerManager - Manages layer visibility and compositing.
void SetLayerBlendMode(LayerType layer, LayerBlendMode mode)
void SetLayerVisible(LayerType layer, bool visible)
void SetObjectTranslucency(size_t object_index, bool translucent, uint8_t alpha=128)
const std::vector< Door > & GetDoors() const
Definition room.h:413
std::string FormatDungeonConnectedLinkDescription(const DungeonConnectedRoomLink &link)
int NeighborRoomId(int room_id, zelda3::DoorDirection dir)
DungeonConnectedRoomLinkDiagnostics CollectDungeonConnectedRoomLinkDiagnostics(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)
const char * GetIssueCategoryLabel(int index)
constexpr std::array< const char *, 6 > kDungeonIssueCategoryLabels
zelda3::DoorDirection OppositeDir(zelda3::DoorDirection dir)
DungeonIssueCategory GetDefaultSelectionIssueCategory(const DungeonObjectInteraction &object_interaction)
ObjectRenderMode
Handles the main dungeon canvas rendering and interaction.
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)
constexpr int ToIssueCategoryIndex(DungeonIssueCategory category)
std::string FormatDungeonStaircaseIssueDescription(const DungeonStaircaseIssue &issue)
DoorType
Door types from ALTTP.
Definition door_types.h:33
@ NormalDoor
Normal door (upper layer)
LayerBlendMode
Layer blend modes for compositing.
ObjectLayerSemantics GetEffectiveObjectLayerSemantics(const RoomObject &object)
LayerType
Layer types for the 4-way visibility system.
constexpr int kNumberOfRooms
DoorDirection
Door direction on room walls.
Definition door_types.h:18
@ South
Bottom wall (horizontal door, 4x3 tiles)
@ North
Top wall (horizontal door, 4x3 tiles)
@ East
Right wall (vertical door, 3x4 tiles)
@ West
Left wall (vertical door, 3x4 tiles)
std::array< RoomPlacement, zelda3::kNumberOfRooms > room_positions
std::array< std::string, zelda3::kNumberOfRooms > room_floor_labels
std::map< int, DungeonConnectedRoomLinkDiagnostics > room_diagnostics
std::optional< std::pair< zelda3::LayerMergeType, zelda3::EffectKey > > room_settings
std::vector< DungeonConnectedRoomLink > links
std::vector< DungeonStaircaseIssue > staircase_issues
Lightweight view into the essential runtime context (Rom + GameData)
Definition editor.h:73
zelda3::GameData * game_data
Definition editor.h:75
Represents a group of palettes.
const SnesPalette & palette_ref(int i) const
Declarative menu item definition.
Definition canvas_menu.h:64
Modern project structure with comprehensive settings consolidation.
Definition project.h:290