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 <string>
11#include <tuple>
12#include <unordered_map>
13#include <vector>
14
22#include "app/editor/editor.h"
27#include "core/project.h"
30#include "dungeon_room_store.h"
31#include "imgui/imgui.h"
32#include "rom/rom.h"
33#include "util/lru_cache.h"
36#include "zelda3/dungeon/room.h"
38#include "zelda3/game_data.h"
40
41// Room-based plans and tools must follow canvas.h's ImGui math configuration.
47
48namespace yaze {
49namespace editor {
50
51class MinecartTrackEditorPanel;
52class DungeonCanvasViewerTestPeer;
53
54enum class DungeonConnectedLinkType : uint8_t {
55 Door,
58};
59
61 int from_room_id = -1;
62 int to_room_id = -1;
65 // Provenance fields populated by CollectDungeonConnectedRoomLinkDiagnostics
66 // for hover tooltips and issue reports. Defaults represent "not applicable".
67 int slot_index = -1; // Staircase slot 0..3, -1 otherwise.
68 int16_t object_id = -1; // Placed staircase tile-object id, -1 otherwise.
69 int door_index = -1; // Index in room.GetDoors() for Door links.
71};
72
73// Discriminator for staircase configuration anomalies surfaced through
74// CollectDungeonConnectedRoomLinkDiagnostics. Each kind explains a different
75// failure mode the runtime silently ignores.
76enum class DungeonStaircaseIssueKind : uint8_t {
77 // Header destination is non-zero but no placed interroom-stair object
78 // consumes that slot. Runtime never traverses the link.
80 // Placed interroom-stair object exists but the matched header slot is 0
81 // (unset) or out of range — the runtime would jump to an invalid room.
83 // Placed interroom-stair object beyond the 4 header slots. The runtime
84 // can only consume four; extras can never be reached.
86};
87
88// Captures one anomaly found while resolving a room's staircase connectivity.
89// Field meaning depends on `kind`; defaults represent "not applicable".
91 int from_room_id = -1;
93 int slot_index = -1; // 0..3 for UnusedHeader/MissingDestination.
94 int header_room_id = -1; // Header destination value (raw, may be invalid).
95 int16_t object_id = -1; // Placed object id (MissingDestination/Extra).
96};
97
99 std::vector<DungeonConnectedRoomLink> links;
100 std::vector<DungeonStaircaseIssue> staircase_issues;
101};
102
111
112inline constexpr std::array<const char*, 6> kDungeonIssueCategoryLabels = {{
113 "Palette mismatch",
114 "Object draw mismatch",
115 "Door render mismatch",
116 "Entity mismatch",
117 "Overlay or collision mismatch",
118 "General room render mismatch",
119}};
120
122 return static_cast<int>(category);
123}
124
125inline const char* GetIssueCategoryLabel(int index) {
126 if (index < 0 ||
127 index >= static_cast<int>(kDungeonIssueCategoryLabels.size())) {
128 return kDungeonIssueCategoryLabels.back();
129 }
130 return kDungeonIssueCategoryLabels[static_cast<size_t>(index)];
131}
132
134 const DungeonObjectInteraction& object_interaction) {
135 if (!object_interaction.GetSelectedObjectIndices().empty()) {
137 }
138 if (object_interaction.HasEntitySelection()) {
139 switch (object_interaction.GetSelectedEntity().type) {
140 case EntityType::Door:
142 case EntityType::Sprite:
143 case EntityType::Item:
145 default:
146 break;
147 }
148 }
150}
151
152std::vector<DungeonConnectedRoomLink> CollectDungeonConnectedRoomLinks(
153 int room_id, const zelda3::Room& room,
154 const std::function<bool(int, zelda3::DoorDirection)>& has_reciprocal_door);
155
156// Returns the same set of links as CollectDungeonConnectedRoomLinks plus any
157// stale staircase header slots — i.e. header destinations with no placed
158// interroom-stair object consuming them. Provenance fields on each returned
159// link are populated for tooltip/issue-report surfacing.
160DungeonConnectedRoomLinkDiagnostics CollectDungeonConnectedRoomLinkDiagnostics(
161 int room_id, const zelda3::Room& room,
162 const std::function<bool(int, zelda3::DoorDirection)>& has_reciprocal_door);
163
164// Renders a single connectivity link as a one-line human-readable description
165// for tooltips and issue reports. Caller decides separator/heading.
167 const DungeonConnectedRoomLink& link);
168
169// Renders a staircase issue entry as a one-line warning for tooltips and
170// issue reports.
172 const DungeonStaircaseIssue& issue);
173
174// Returns the room id adjacent to `room_id` in the given direction, or -1 if
175// no such neighbor exists (out of the 16x16 room matrix).
176inline int NeighborRoomId(int room_id, zelda3::DoorDirection dir) {
177 if (room_id < 0 || room_id >= zelda3::kNumberOfRooms) {
178 return -1;
179 }
180
181 constexpr int kCols = 16;
182 const int row = room_id / kCols;
183 const int col = room_id % kCols;
184
185 int candidate = -1;
186 switch (dir) {
188 candidate = row > 0 ? room_id - kCols : -1;
189 break;
191 candidate = room_id + kCols;
192 break;
194 candidate = col > 0 ? room_id - 1 : -1;
195 break;
197 candidate = col < kCols - 1 ? room_id + 1 : -1;
198 break;
199 }
200
201 return (candidate >= 0 && candidate < zelda3::kNumberOfRooms) ? candidate
202 : -1;
203}
204
205// Returns the opposite cardinal direction (N<->S, E<->W).
220
225 Manual, // Use ObjectDrawer routines
226 Emulator, // Use SNES emulator
227 Hybrid // Emulator with manual fallback
228};
229
231 public:
232 explicit DungeonCanvasViewer(Rom* rom = nullptr)
236 [this](int target_room, std::optional<size_t> target_door_index,
237 int target_tile_x, int target_tile_y) {
238 if (target_door_index &&
239 NavigateToDoorConnectionTarget(target_room, *target_door_index)) {
240 return;
241 }
242 NavigateToRoom(target_room);
243 bool focused_target_door = false;
244 if (target_door_index.has_value() && rooms_ != nullptr) {
245 auto* target = rooms_->TryEnsureRoom(target_room);
246 if (target != nullptr &&
247 *target_door_index < target->GetDoors().size()) {
248 const auto [x, y, width, height] =
249 target->GetDoors()[*target_door_index].GetEditorBounds();
250 ScrollToTile((x + width / 2) / 8, (y + height / 2) / 8);
251 TriggerCanvasPingRect(x, y, width, height);
252 object_interaction_.SelectEntity(EntityType::Door,
253 *target_door_index);
254 focused_target_door = true;
255 }
256 }
257 if (!focused_target_door && target_tile_x >= 0 &&
258 target_tile_y >= 0) {
259 ScrollToTile(target_tile_x, target_tile_y);
260 TriggerCanvasPingRect(target_tile_x * 8, target_tile_y * 8, 24, 24);
261 } else if (!focused_target_door) {
263 }
264 });
266 [this](int room_id, const zelda3::RoomObject& object) {
267 const auto semantics =
269 auto is_visible = [this, room_id](zelda3::LayerType layer) {
270 return IsLayerVisible(room_id, layer) &&
271 GetLayerBlendMode(room_id, layer) !=
273 };
274 switch (semantics.effective_bg_layer) {
276 return is_visible(zelda3::LayerType::BG1_Objects);
278 return is_visible(zelda3::LayerType::BG2_Objects);
280 return is_visible(zelda3::LayerType::BG1_Objects) ||
282 }
283 return true;
284 });
285 }
287
288 void DrawDungeonCanvas(int room_id);
289 std::optional<int> DrawConnectedRoomMatrix(int center_room_id);
290 // Read-only proposal preview: overlay.rooms rendered left to right with the
291 // visible layers drawn on top. Never edits room data.
293 const std::vector<char>& layer_visible,
294 bool show_overlay, float scale);
296 float scale) const;
297 void DrawConnectedToolbarControls(int center_room_id);
298 void Draw(int room_id);
300 void TriggerChangePing();
302 std::function<absl::Status(int, const RoomMetadataEdit&)>;
304 std::function<absl::Status(const std::vector<RoomMetadataRequest>&)>;
306 std::function<absl::Status(int, size_t, uint8_t, bool)>;
307 using ChestDeleteCallback = std::function<absl::Status(int, size_t)>;
309 std::function<absl::StatusOr<DungeonConnectionPlan>(
312 std::function<absl::Status(const DungeonConnectionPlan&)>;
314 metadata_edit_callback_ = std::move(callback);
315 }
320 chest_edit_callback_ = std::move(callback);
321 }
323 chest_delete_callback_ = std::move(callback);
324 }
330 absl::StatusOr<DungeonConnectionPlan> PreviewDoorConnection(
331 const DungeonConnectionRequest& request);
332 absl::Status ApplyDoorConnection(const DungeonConnectionPlan& plan);
334 std::function<void(int, size_t)> callback) {
335 door_connection_navigation_callback_ = std::move(callback);
336 }
338 return static_cast<bool>(door_connection_navigation_callback_);
339 }
340 bool NavigateToDoorConnectionTarget(int room_id, size_t door_index) {
342 return false;
343 }
344 door_connection_navigation_callback_(room_id, door_index);
345 return true;
346 }
351 std::function<absl::StatusOr<std::string>(int)>;
353 std::function<absl::StatusOr<DungeonRoomTransferPlan>(
354 int, int, const std::string&, const DungeonRoomTransferOptions&)>;
356 std::function<absl::Status(const DungeonRoomTransferPlan&)>;
360 room_document_export_callback_ = std::move(export_document);
361 room_transfer_preview_callback_ = std::move(preview);
362 room_transfer_apply_callback_ = std::move(apply);
363 }
364 absl::StatusOr<std::string> ExportRoomDocument(int room_id);
365 absl::StatusOr<DungeonRoomTransferPlan> PreviewRoomTransfer(
366 int source_room_id, const std::string& json,
367 const DungeonRoomTransferOptions& options);
368 absl::Status ApplyRoomTransfer(const DungeonRoomTransferPlan& plan);
372 absl::Status EditRoomMetadata(int room_id, const RoomMetadataEdit& edit);
373 absl::Status EditRoomMetadataBatch(
374 const std::vector<RoomMetadataRequest>& requests);
375 absl::Status EditChest(int room_id, size_t index, uint8_t item_id,
376 bool big_chest);
377 absl::Status DeleteChest(int room_id, size_t index);
383 void TriggerCanvasPingRect(int pixel_x, int pixel_y, int pixel_w,
384 int pixel_h);
386 const std::vector<zelda3::RoomObject>& previous_objects,
387 const std::vector<zelda3::RoomObject>& next_objects);
388
389 // Unscaled content size of the connected-room graph centered on
390 // `center_room_id`. Used by the workbench to reserve scroll space for the
391 // body child before DrawConnectedRoomMatrix runs, so the matrix doesn't need
392 // to open its own BeginChild scroll wrapper.
393 ImVec2 GetConnectedContentSize(int center_room_id);
394 // Clamped connected-canvas zoom scale that matches the one used by
395 // DrawConnectedRoomMatrix when it next runs.
396 float ConnectedCanvasScale() const;
397 void SetConnectedControlsInline(bool inline_controls) {
398 connected_controls_inline_ = inline_controls;
399 }
400
412 EditorContext context() const { return {rom_, game_data_}; }
423 Rom* rom() const { return rom_; }
431 void SetRenderer(gfx::IRenderer* renderer) { renderer_ = renderer; }
432
433 // Room data access
442 // Rebind ROM-backed context without replacing this viewer. This preserves
443 // panel aliases into viewer state while discarding selections and caches
444 // that may refer to data decoded from the previous ROM bytes.
446 DungeonRoomStore* rooms, int room_id);
447 DungeonRoomStore* rooms() const { return rooms_; }
448 bool HasRooms() const { return rooms_ != nullptr; }
449
450 // Best-effort "current room" context for auxiliary panels that are driven by
451 // whichever room the viewer is currently drawing.
452 int current_room_id() const { return current_room_id_; }
453
454 // Workbench/Inspector integration.
455 void SetCompactHeaderMode(bool compact) { compact_header_mode_ = compact; }
457 void SetRoomDetailsExpanded(bool expanded) { show_room_details_ = expanded; }
458
459 // Used by overworld editor when double-clicking entrances
460 void set_active_rooms(const ImVector<int>& rooms) { active_rooms_ = rooms; }
462
463 // Palette access
466 }
467 void SetCurrentPaletteId(uint64_t id) { current_palette_id_ = id; }
469 bool force_refresh = false) {
470 bool palette_changed = current_palette_group_.name() != group.name() ||
471 current_palette_group_.size() != group.size();
472 for (int i = 0; !palette_changed && i < static_cast<int>(group.size());
473 ++i) {
474 palette_changed =
476 }
477 if (!palette_changed && !force_refresh) {
478 return;
479 }
480
482 object_interaction_.SetCurrentPaletteGroup(group, force_refresh);
483 }
484 void SetEntranceRenderContext(int entrance_id, uint8_t entrance_blockset) {
485 current_entrance_id_ = entrance_id;
486 current_entrance_blockset_ = entrance_blockset;
487 }
495 }
496 // Auto may assign different graphics to rooms in a connected preview.
497 // The editor owns inference; standalone viewers retain their fixed context.
498 void SetEntranceBlocksetResolver(std::function<uint8_t(int)> resolver) {
499 entrance_blockset_resolver_ = std::move(resolver);
500 }
501 void SetEntranceCameraOverlay(int entrance_slot,
502 const DungeonEntranceCameraState& state) {
503 camera_overlay_entrance_slot_ = entrance_slot;
505 }
510 const std::optional<DungeonEntranceCameraState>& entrance_camera_overlay()
511 const {
513 }
514 void SetRoomNavigationCallback(std::function<void(int)> callback) {
515 room_navigation_callback_ = std::move(callback);
516 }
517 // Callback to swap the current room in-place (for arrow navigation)
518 void SetRoomSwapCallback(std::function<void(int, int)> callback) {
519 room_swap_callback_ = std::move(callback);
520 }
521
522 bool CanNavigateRooms() const {
523 return room_swap_callback_ != nullptr ||
524 room_navigation_callback_ != nullptr;
525 }
526
527 // Navigate to another dungeon room using the same semantics as the header
528 // arrow buttons:
529 // - If a swap callback exists (workbench mode), swap in-place.
530 // - Otherwise, use the navigation callback (opens/switches room view).
531 void NavigateToRoom(int target_room) {
532 if (target_room < 0 || target_room >= zelda3::kNumberOfRooms) {
533 return;
534 }
537 } else if (room_navigation_callback_) {
538 room_navigation_callback_(target_room);
539 }
540 }
541 void SetShowObjectPanelCallback(std::function<void()> callback) {
542 show_object_panel_callback_ = std::move(callback);
543 }
544 void SetShowSpritePanelCallback(std::function<void()> callback) {
545 show_sprite_panel_callback_ = std::move(callback);
546 }
547 void SetShowItemPanelCallback(std::function<void()> callback) {
548 show_item_panel_callback_ = std::move(callback);
549 }
550 void SetShowRoomListCallback(std::function<void()> callback) {
551 show_room_list_callback_ = std::move(callback);
552 }
553 void SetShowRoomMatrixCallback(std::function<void()> callback) {
554 show_room_matrix_callback_ = std::move(callback);
555 }
556 void SetShowEntranceListCallback(std::function<void()> callback) {
557 show_entrance_list_callback_ = std::move(callback);
558 }
559
566
569 }
571
572 // Overlay toggles (used by settings panels / workbench UI).
596 }
603
604 bool show_grid() const { return show_grid_; }
605 void set_show_grid(bool show) { show_grid_ = show; }
606 int custom_grid_size() const { return custom_grid_size_; }
607 void set_custom_grid_size(int size) {
608 custom_grid_size_ = size > 0 ? size : 1;
609 }
611 void set_show_object_bounds(bool show) { show_object_bounds_ = show; }
615 }
619 void set_show_texture_debug(bool show) { show_texture_debug_ = show; }
620 bool show_layer_info() const { return show_layer_info_; }
621 void set_show_layer_info(bool show) { show_layer_info_ = show; }
623 void set_show_crumble_floor(bool show) {
624 show_crumble_floor_ = show;
625 if (!show)
627 }
636
637 // Mutable pointer accessors for OverlayManagerPanel binding.
638 bool* mutable_show_grid() { return &show_grid_; }
660 void SetShowRoomGraphicsCallback(std::function<void()> callback) {
661 show_room_graphics_callback_ = std::move(callback);
662 }
663 void SetShowDoorEditorCallback(std::function<void()> callback) {
664 show_door_editor_callback_ = std::move(callback);
665 }
666 void SetShowDungeonSettingsCallback(std::function<void()> callback) {
667 show_dungeon_settings_callback_ = std::move(callback);
668 }
669 void SetSaveRoomCallback(std::function<void(int)> callback) {
670 save_room_callback_ = std::move(callback);
671 }
673 std::function<void(int, const zelda3::RoomObject&)> callback) {
674 edit_graphics_callback_ = std::move(callback);
675 }
677 std::function<void(int, const zelda3::RoomObject&)> callback) {
678 edit_object_tiles_callback_ = std::move(callback);
679 }
680 // Opens Object Coverage on the selected object's ID.
682 std::function<void(int, const zelda3::RoomObject&)> callback) {
683 check_object_coverage_callback_ = std::move(callback);
684 }
688 void SetPinned(bool pinned) { is_pinned_ = pinned; }
689 void SetPinCallback(std::function<void(bool)> callback) {
690 pin_callback_ = std::move(callback);
691 }
693 // Refresh external previews without replacing room data or editing state.
695 const project::YazeProject* project() const { return project_; }
696
697 // Canvas access
699 const gui::Canvas& canvas() const { return canvas_; }
700
701 // Object interaction access
703
707
708 // Enable/disable object interaction mode
709 void SetObjectInteractionEnabled(bool enabled) {
711 }
715
716 // Make the room header controls non-interactive while retaining centered
717 // canvas zoom (useful for split/compare views).
718 void SetHeaderReadOnly(bool read_only) { header_read_only_ = read_only; }
719 bool header_read_only() const { return header_read_only_; }
720
721 // Hide the header chrome entirely (useful for stitched/split layouts where a
722 // parent container provides its own metadata/controls).
723 void SetHeaderVisible(bool visible) { header_visible_ = visible; }
724 bool header_visible() const { return header_visible_; }
731
732 // Set and get the object render mode
737
738 // Layer visibility controls (per-room) using RoomLayerManager
739 void SetLayerVisible(int room_id, zelda3::LayerType layer, bool visible) {
740 GetRoomLayerManager(room_id).SetLayerVisible(layer, visible);
741 }
742 bool IsLayerVisible(int room_id, zelda3::LayerType layer) const {
743 auto it = room_layer_managers_.find(room_id);
744 return it != room_layer_managers_.end()
745 ? it->second.manager.IsLayerVisible(layer)
746 : true;
747 }
748
749 // Legacy compatibility - BG1 visibility (combines layout + objects)
750 void SetBG1Visible(int room_id, bool visible) {
751 auto& mgr = GetRoomLayerManager(room_id);
752 mgr.SetLayerVisible(zelda3::LayerType::BG1_Layout, visible);
753 mgr.SetLayerVisible(zelda3::LayerType::BG1_Objects, visible);
754 }
755 void SetBG2Visible(int room_id, bool visible) {
756 auto& mgr = GetRoomLayerManager(room_id);
757 mgr.SetLayerVisible(zelda3::LayerType::BG2_Layout, visible);
758 mgr.SetLayerVisible(zelda3::LayerType::BG2_Objects, visible);
759 }
760 bool IsBG1Visible(int room_id) const {
761 auto it = room_layer_managers_.find(room_id);
762 if (it == room_layer_managers_.end())
763 return true;
764 return it->second.manager.IsLayerVisible(zelda3::LayerType::BG1_Layout) ||
765 it->second.manager.IsLayerVisible(zelda3::LayerType::BG1_Objects);
766 }
767 bool IsBG2Visible(int room_id) const {
768 auto it = room_layer_managers_.find(room_id);
769 if (it == room_layer_managers_.end())
770 return true;
771 return it->second.manager.IsLayerVisible(zelda3::LayerType::BG2_Layout) ||
772 it->second.manager.IsLayerVisible(zelda3::LayerType::BG2_Objects);
773 }
774
775 // Layer blend mode controls
776 void SetLayerBlendMode(int room_id, zelda3::LayerType layer,
778 GetRoomLayerManager(room_id).SetLayerBlendMode(layer, mode);
779 }
781 zelda3::LayerType layer) const {
782 auto it = room_layer_managers_.find(room_id);
783 return it != room_layer_managers_.end()
784 ? it->second.manager.GetLayerBlendMode(layer)
786 }
787
788 // Per-object translucency
789 void SetObjectTranslucent(int room_id, size_t object_index, bool translucent,
790 uint8_t alpha = 128) {
791 GetRoomLayerManager(room_id).SetObjectTranslucency(object_index,
792 translucent, alpha);
793 }
794
795 // Layer manager access
798 static zelda3::RoomLayerManager default_manager;
799 auto it = room_layer_managers_.find(room_id);
800 return it != room_layer_managers_.end() ? it->second.manager
801 : default_manager;
802 }
803
804 // Legacy BG2 layer type (mapped to blend mode)
805 void SetBG2LayerType(int room_id, int type) {
806 auto& mgr = GetRoomLayerManager(room_id);
808 switch (type) {
809 case 0:
811 break;
812 case 1:
814 break;
815 case 2:
817 break;
818 case 3:
820 break;
821 case 4:
823 break;
824 default:
826 break;
827 }
828 mgr.SetLayerBlendMode(zelda3::LayerType::BG2_Layout, mode);
829 mgr.SetLayerBlendMode(zelda3::LayerType::BG2_Objects, mode);
830 }
831 int GetBG2LayerType(int room_id) const {
833 switch (mode) {
835 return 0;
837 return 1;
839 return 2;
841 return 3;
843 return 4;
844 }
845 return 0;
846 }
847
848 // Set the object to be placed
850 // Pass palette group first so ghost preview can render correctly
853 }
856 false);
857 }
858
859 // Scroll the canvas to center on the given tile coordinates.
860 // The pending target is consumed by Draw() on the next frame.
861 void ScrollToTile(int tile_x, int tile_y) {
862 pending_scroll_target_ = {tile_x, tile_y};
863 }
865 return pending_scroll_target_.has_value();
866 }
867 std::optional<std::pair<int, int>> GetPendingScrollTarget() const {
869 }
870
871 // Object manipulation
876 return ImGui::GetCurrentContext() != nullptr &&
877 HasRoomCanvasShortcutFocusForFrame(ImGui::GetFrameCount());
878 }
880 return ImGui::GetCurrentContext() != nullptr &&
882 room_canvas_last_draw_frame_ >= ImGui::GetFrameCount() - 1;
883 }
884
885 // Entity visibility controls
886 void SetSpritesVisible(bool visible) {
888 }
890 void SetPotItemsVisible(bool visible) {
892 }
894 void SetChestContentsVisible(bool visible) {
896 }
900
903 int col = 0;
904 int row = 0;
905 bool placed = false;
906 bool connected_to_start = false;
907 };
908
909 std::array<bool, zelda3::kNumberOfRooms> room_mask{};
910 std::array<RoomPlacement, zelda3::kNumberOfRooms> room_positions{};
911 std::array<std::string, zelda3::kNumberOfRooms> room_floor_labels{};
912 std::vector<std::string> floor_order;
913 std::vector<DungeonConnectedRoomLink> links;
914 // Staircase configuration anomalies aggregated across the whole
915 // connected component. Order is "first-encountered during BFS".
916 std::vector<DungeonStaircaseIssue> staircase_issues;
917 // Resolved links whose destination room falls outside the project's
918 // current dungeon registry scope (only populated when scoping is active).
919 // The runtime would still traverse these; the matrix omits the target
920 // rooms by default but surfaces the link as a diagnostic so the user can
921 // see "current dungeon connects out to room X via staircase".
922 std::vector<DungeonConnectedRoomLink> out_of_scope_links;
923 // True when BFS is restricted to a project-registry dungeon group.
925 int room_count = 0;
927 int min_col = 0;
928 int max_col = 0;
929 int min_row = 0;
930 int max_row = 0;
931 };
932
933 private:
939 friend class
941 friend class
943 friend class
945 friend class
947
949 int x = 0;
950 int y = 0;
951 int w = 0;
952 int h = 0;
953 };
954
956 const zelda3::RoomObject& object, int canvas_x,
957 int canvas_y);
958 void DrawRoomHeader(zelda3::Room& room, int room_id);
959 void DrawRoomNavigation(int room_id);
960 void DrawRoomPropertyTable(zelda3::Room& room, int room_id);
961 void DrawRecentRoomBreadcrumbs(int room_id);
962 void DrawLayerControls(zelda3::Room& room, int room_id);
963 void DrawCompactLayerToggles(int room_id);
964 void PopulateCanvasContextMenu(int room_id);
965 void AddInteractionContextMenuItems(int room_id);
966 void AddLoadedRoomContextMenuItems(int room_id);
968 std::vector<gui::CanvasMenuItem> BuildSelectionContextMenuItems(int room_id);
969 std::vector<gui::CanvasMenuItem> BuildSelectionContextMenuItems(
970 int room_id, std::optional<zelda3::RoomObject> context_object);
971 std::optional<zelda3::RoomObject> GetObjectUnderContextCursor(int room_id);
974 std::optional<gui::CanvasMenuItem> BuildOpenContextMenu();
979 std::string BuildRoomMetadataSummary(const zelda3::Room& room,
980 int room_id) const;
981 std::string BuildDrawIssueReport(const zelda3::Room& room, int room_id);
982 std::string BuildSelectionIssueReport(const zelda3::Room& room,
983 int room_id) const;
984 void OpenIssueReportPopup(const std::string& title,
985 const std::string& summary,
986 const std::string& kind_label,
987 const std::string& diagnostics, int room_id,
988 int default_category_index);
989 absl::Status PrepareIssueReportPopup(const std::string& title,
990 const std::string& summary,
991 const std::string& kind_label,
992 const std::string& diagnostics,
993 int room_id, int default_category_index);
994 std::string BuildIssueReportClipboardText() const;
995 absl::Status CaptureIssueReportScreenshot();
996 absl::Status AppendIssueReportToLog();
997 absl::Status EnsureIssueReportPersisted();
1000 void SetIssueReportPopupStatus(std::string message, bool is_error);
1001 void DrawIssueReportStorageSummary() const;
1002 void DrawIssueReportStatusMessage() const;
1003 void RenderSprites(const gui::CanvasRuntime& rt, const zelda3::Room& room);
1004 void RenderPotItems(const gui::CanvasRuntime& rt, const zelda3::Room& room);
1006 const zelda3::Room& room);
1008 const zelda3::Room& room);
1009
1010 // Touch interaction: long-press context menu for entities
1012 const zelda3::Room& room);
1013
1014 // Visualization
1016 const zelda3::Room& room);
1019 GetCollisionOverlayCache(int room_id);
1020
1021 // Draw semi-transparent overlay on stored value 1 / BG2 overlay objects when
1022 // mask mode is active.
1024 const zelda3::Room& room);
1025 void DrawPersistentDebugWindows(int room_id);
1026 void DrawRoomDebugWindow(zelda3::Room& room, int room_id);
1027 void DrawTextureDebugWindow(zelda3::Room& room, int room_id);
1028 void DrawLayerInfoWindow(int room_id);
1030 int room_id);
1031 void DrawCoordinateOverlayHud(int room_id);
1032 bool ValidateRoomCanvasRequest(int room_id);
1034 void UpdateRoomCanvasViewport(ImVec2 viewport_size);
1038 void RefreshActiveRoomCanvasState(zelda3::Room& room, int room_id);
1040 void SyncCanvasCaptureRegion(const gui::CanvasRuntime& canvas_rt);
1041 void ConsumePendingCanvasScroll(const gui::CanvasRuntime& canvas_rt);
1042 void DrawHeaderHiddenMetadataHud(int room_id);
1043 void PrepareRoomStateForCanvas(zelda3::Room& room, int room_id);
1044 void DrawRoomCanvasContent(const gui::CanvasRuntime& canvas_rt,
1045 zelda3::Room& room, int room_id);
1046 void HandleRoomCanvasDropTargets(zelda3::Room& room, int room_id);
1047 void DrawChangePingOverlay(const gui::CanvasRuntime& canvas_rt,
1048 const zelda3::Room& room);
1049 void RecordVisitedRoom(int room_id);
1051 RoomCompositeOutput& output);
1054 void UpdateRoomCanvasShortcutFocus(bool hovered, bool pointer_pressed,
1055 int frame_index);
1056 bool HasRoomCanvasShortcutFocusForFrame(int frame_index) const;
1057
1058 // Room graphics management
1059 // Load: Read from ROM, Render: Process pixels, Draw: Display on canvas
1060 absl::Status LoadAndRenderRoomGraphics(int room_id);
1066 int ApplyConnectedStaircaseIssueAutoFixes(int center_room_id);
1067 bool DrawRoomBackgroundLayers(int room_id); // Draw room buffers to canvas
1068
1069 Rom* rom_ = nullptr;
1071 gui::Canvas canvas_{"##DungeonCanvas", ImVec2(0x200, 0x200)};
1074 gui::Canvas connected_canvas_{"##DungeonConnectedCanvas",
1075 ImVec2(0x200, 0x200)};
1076 // ObjectRenderer removed - use ObjectDrawer for rendering (production system)
1078
1079 // Touch gesture handler for long-press context menus on touch devices
1081
1082 // Scroll target
1083 std::optional<std::pair<int, int>> pending_scroll_target_;
1084
1085 // Room data
1088 std::vector<int> recently_visited_rooms_;
1091 std::function<uint8_t(int)> entrance_blockset_resolver_;
1093 std::optional<DungeonEntranceCameraState> entrance_camera_overlay_;
1094 // Used by overworld editor for double-click entrance → open dungeon room
1095 ImVector<int> active_rooms_;
1104 // Last-frame visibility of the connected-mode side panel (overview /
1105 // preview). Used to apply hysteresis when the viewport width crosses the
1106 // panel's min-size threshold, so dragging the pane splitter past the
1107 // threshold doesn't cause a sudden ~220 px horizontal snap.
1115
1116 // Object interaction state
1120
1121 // Per-room layer managers (4-way visibility, blend modes, per-object translucency)
1124 std::optional<std::pair<zelda3::LayerMergeType, zelda3::EffectKey>>
1126 };
1127 std::map<int, RoomLayerState> room_layer_managers_;
1128
1129 // The primary output is pinned because Canvas retains its Bitmap pointer.
1130 // Connected previews keep stable outputs for rooms visible this frame.
1133 std::unique_ptr<RoomCompositeOutput> output;
1135 };
1136 std::map<int, ConnectedRoomCompositeEntry> connected_composite_outputs_;
1138
1139 // Palette data
1143 std::function<void(int)> room_navigation_callback_;
1144 std::function<void(int, int)>
1145 room_swap_callback_; // (old_room_id, new_room_id)
1146 std::function<void()> show_object_panel_callback_;
1147 std::function<void()> show_sprite_panel_callback_;
1148 std::function<void()> show_item_panel_callback_;
1149 std::function<void()> show_room_list_callback_;
1150 std::function<void()> show_room_matrix_callback_;
1151 std::function<void()> show_entrance_list_callback_;
1152 std::function<void()> show_room_graphics_callback_;
1153 std::function<void()> show_door_editor_callback_;
1154 std::function<void()> show_dungeon_settings_callback_;
1155 std::function<void(int)> save_room_callback_;
1156 std::function<void(int, const zelda3::RoomObject&)> edit_graphics_callback_;
1162 bool DrawCrumbleCanvas(const gui::CanvasRuntime& rt);
1164 int room_id);
1168 bool is_pinned_ = false;
1169 std::function<void(bool)> pin_callback_;
1172 // Room graphics revisions are globally unique. Retain indexed pixels across
1173 // connected-room draws; presentation (palette, position, zoom) stays live.
1174 using SpritePreviewKey = std::tuple<uint64_t, uint8_t, int, bool>;
1176 std::vector<uint8_t> pixels;
1177 SDL_Rect bounds{};
1178 };
1181
1199 std::function<void(int, size_t)> door_connection_navigation_callback_;
1206 bool header_read_only_ = false;
1207 bool header_visible_ = true;
1209
1211 std::vector<uint16_t> track_tile_order_;
1212 std::vector<uint16_t> switch_tile_order_;
1214 std::unordered_map<int, DungeonRenderingHelpers::CollisionOverlayCache>
1216 std::bitset<256> minecart_sprite_ids_{};
1217
1218 // Object rendering cache
1226 std::vector<ObjectRenderCache> object_render_cache_;
1228
1229 // Debug state flags
1233 bool show_layer_info_ = false;
1234 bool show_grid_ = false; // Grid off by default for dungeon editor
1236 false; // Show camera coordinates on hover (toggle via Debug menu)
1237 int layout_override_ = -1; // -1 for no override
1240 ObjectRenderMode::Emulator; // Default to emulator rendering
1241
1242 // Object outline filtering toggles
1244 bool show_type1_objects = true; // Standard objects (0x00-0xFF)
1245 bool show_type2_objects = true; // Extended objects (0x100-0x1FF)
1246 bool show_type3_objects = true; // Special objects (0xF00-0xFFF)
1247 bool show_layer0_objects = true; // Primary / upper layer (BG1)
1248 bool show_layer1_objects = true; // BG2 overlay / lower layer (BG2)
1249 bool show_layer2_objects = true; // BG1 overlay room stream
1250 };
1252
1253 // Entity overlay visibility toggles
1255 bool show_sprites = true; // Show sprite entities
1256 bool show_pot_items = true; // Show pot item entities
1257 bool show_chests = true; // Show chest receipt labels above chest objects
1258 };
1260
1262
1263 // Previous room state for change detection (per-viewer)
1268
1278 "Report Dungeon Issue##DungeonIssueReportPopup";
1290 std::vector<ChangePingRect> change_ping_rects_;
1292 std::function<void(int, const zelda3::RoomObject&)>
1294 std::function<void(int, const zelda3::RoomObject&)>
1296};
1297
1298} // namespace editor
1299} // namespace yaze
1300
1301#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:49
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_
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_
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
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_
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)
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 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 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.
constexpr int ToIssueCategoryIndex(DungeonIssueCategory category)
std::vector< DungeonConnectedRoomLink > CollectDungeonConnectedRoomLinks(int room_id, const zelda3::Room &room, const std::function< bool(int, zelda3::DoorDirection)> &has_reciprocal_door)
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::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:287