From d85974be60652a83761de0650b3d45f2a7696673 Mon Sep 17 00:00:00 2001 From: scawful Date: Sat, 4 Oct 2025 01:23:43 -0400 Subject: [PATCH] feat: Refactor dungeon object selection and editing interfaces for improved usability --- src/app/editor/dungeon/dungeon_editor.cc | 113 +++++++++++++++++- src/app/editor/dungeon/dungeon_editor.h | 18 ++- .../editor/dungeon/dungeon_object_selector.cc | 6 +- .../editor/dungeon/dungeon_object_selector.h | 6 +- 4 files changed, 132 insertions(+), 11 deletions(-) diff --git a/src/app/editor/dungeon/dungeon_editor.cc b/src/app/editor/dungeon/dungeon_editor.cc index 0585eb5a..9c8829fd 100644 --- a/src/app/editor/dungeon/dungeon_editor.cc +++ b/src/app/editor/dungeon/dungeon_editor.cc @@ -42,7 +42,20 @@ void DungeonEditor::Initialize() { if (rom_ && !dungeon_editor_system_) { dungeon_editor_system_ = std::make_unique(rom_); - object_editor_ = std::make_shared(rom_); + } + + // Phase 5: Initialize integrated object editor + if (rom_ && !object_editor_) { + object_editor_ = std::make_unique(rom_); + + // Configure editor for dungeon editing + auto config = object_editor_->GetConfig(); + config.show_selection_highlight = enable_selection_highlight_; + config.show_layer_colors = enable_layer_visualization_; + config.show_property_panel = show_object_property_panel_; + config.snap_to_grid = true; + config.grid_size = 16; // 16x16 tiles + object_editor_->SetConfig(config); } } @@ -224,6 +237,10 @@ absl::Status DungeonEditor::UpdateDungeonRoomView() { // Column 3: Object selector, room graphics, and object editor TableNextColumn(); object_selector_.Draw(); + + // Phase 5: Draw integrated object editor panels below object selector + ImGui::Separator(); + DrawObjectEditorPanels(); ImGui::EndTable(); } @@ -667,6 +684,9 @@ void DungeonEditor::DrawDungeonCanvas(int room_id) { } } + // Phase 5: Render with integrated object editor + RenderRoomWithObjects(room_id); + // Draw selection box and drag preview using component object_interaction_.DrawSelectBox(); object_interaction_.DrawDragPreview(); @@ -675,6 +695,97 @@ void DungeonEditor::DrawDungeonCanvas(int room_id) { canvas_.DrawOverlay(); } +// ============================================================================ +// Phase 5: Integrated Object Editor Methods +// ============================================================================ + +void DungeonEditor::UpdateObjectEditor() { + if (!object_editor_ || !rom_ || !rom_->is_loaded()) { + return; + } + + // Get current room ID + int room_id = current_room_id_; + if (!active_rooms_.empty() && current_active_room_tab_ < active_rooms_.Size) { + room_id = active_rooms_[current_active_room_tab_]; + } + + if (room_id < 0 || room_id >= rooms_.size()) { + return; + } + + // Ensure room graphics and objects are loaded + auto& room = rooms_[room_id]; + + // Load room graphics if not already loaded (this populates arena buffers) + if (room.blocks().empty()) { + auto status = LoadAndRenderRoomGraphics(room_id); + if (!status.ok()) { + // Log error but continue + return; + } + } + + // Load room objects if not already loaded + if (room.GetTileObjects().empty()) { + room.LoadObjects(); + } + + // Sync object editor with current room's objects + // The object editor should work with the room's tile_objects_ directly + // rather than maintaining its own copy +} + +void DungeonEditor::RenderRoomWithObjects(int room_id) { + if (!object_editor_ || room_id < 0 || room_id >= rooms_.size()) { + return; + } + + // Ensure room graphics are loaded and rendered to arena buffers first + if (rooms_[room_id].blocks().empty()) { + // Room graphics not loaded yet, will be loaded by LoadAndRenderRoomGraphics + return; + } + + // Get the arena buffers for rendering - these should already be populated + // by Room::RenderRoomGraphics() which was called in LoadAndRenderRoomGraphics + auto& bg1_bitmap = gfx::Arena::Get().bg1().bitmap(); + auto& bg2_bitmap = gfx::Arena::Get().bg2().bitmap(); + + if (!bg1_bitmap.is_active() || !bg2_bitmap.is_active()) { + // Arena bitmaps not initialized, this means RenderRoomGraphics wasn't called + return; + } + + // Render layer visualization if enabled (draws on top of existing bitmap) + if (enable_layer_visualization_) { + object_editor_->RenderLayerVisualization(bg1_bitmap); + } + + // Render selection highlights if enabled (draws on top of existing bitmap) + if (enable_selection_highlight_) { + object_editor_->RenderSelectionHighlight(bg1_bitmap); + } +} + +void DungeonEditor::DrawObjectEditorPanels() { + if (!object_editor_) { + return; + } + + // Update editor state + UpdateObjectEditor(); + + // Render ImGui panels + if (show_object_property_panel_) { + object_editor_->RenderObjectPropertyPanel(); + } + + if (show_layer_controls_) { + object_editor_->RenderLayerControls(); + } +} + // Legacy method implementations that delegate to components absl::Status DungeonEditor::LoadAndRenderRoomGraphics(int room_id) { if (room_id < 0 || room_id >= rooms_.size()) { diff --git a/src/app/editor/dungeon/dungeon_editor.h b/src/app/editor/dungeon/dungeon_editor.h index 2e31edac..c77b5ecc 100644 --- a/src/app/editor/dungeon/dungeon_editor.h +++ b/src/app/editor/dungeon/dungeon_editor.h @@ -57,7 +57,7 @@ class DungeonEditor : public Editor { // Initialize the new dungeon editor system if (rom) { dungeon_editor_system_ = std::make_unique(rom); - object_editor_ = std::make_shared(rom); + object_editor_ = std::make_unique(rom); } } @@ -105,6 +105,11 @@ class DungeonEditor : public Editor { void DrawCanvasAndPropertiesPanel(); void DrawRoomPropertiesDebugPopup(); + // Phase 5: Integrated editor panels + void DrawObjectEditorPanels(); + void RenderRoomWithObjects(int room_id); + void UpdateObjectEditor(); + // Room selection management void OnRoomSelected(int room_id); @@ -126,10 +131,15 @@ class DungeonEditor : public Editor { bool palette_showing_ = false; bool refresh_graphics_ = false; - // New editor system integration + // Phase 5: Integrated object editor system + std::unique_ptr object_editor_; + bool show_object_property_panel_ = true; + bool show_layer_controls_ = true; + bool enable_selection_highlight_ = true; + bool enable_layer_visualization_ = true; + + // Legacy editor system (deprecated) std::unique_ptr dungeon_editor_system_; - std::shared_ptr object_editor_; - bool show_object_editor_ = false; bool show_sprite_editor_ = false; bool show_item_editor_ = false; bool show_entrance_editor_ = false; diff --git a/src/app/editor/dungeon/dungeon_object_selector.cc b/src/app/editor/dungeon/dungeon_object_selector.cc index 6358d054..bc351da4 100644 --- a/src/app/editor/dungeon/dungeon_object_selector.cc +++ b/src/app/editor/dungeon/dungeon_object_selector.cc @@ -374,7 +374,7 @@ void DungeonObjectSelector::DrawRoomGraphics() { } void DungeonObjectSelector::DrawIntegratedEditingPanels() { - if (!dungeon_editor_system_ || !object_editor_ || !*dungeon_editor_system_ || !*object_editor_) { + if (!dungeon_editor_system_ || !*dungeon_editor_system_ || !object_editor_) { ImGui::Text("Editor systems not initialized"); return; } @@ -428,12 +428,12 @@ void DungeonObjectSelector::DrawIntegratedEditingPanels() { } void DungeonObjectSelector::DrawCompactObjectEditor() { - if (!object_editor_ || !*object_editor_) { + if (!object_editor_) { ImGui::Text("Object editor not initialized"); return; } - auto& editor = **object_editor_; + auto& editor = *object_editor_; ImGui::Text("Object Editor"); Separator(); diff --git a/src/app/editor/dungeon/dungeon_object_selector.h b/src/app/editor/dungeon/dungeon_object_selector.h index e542a1fc..0a9d307d 100644 --- a/src/app/editor/dungeon/dungeon_object_selector.h +++ b/src/app/editor/dungeon/dungeon_object_selector.h @@ -38,8 +38,8 @@ class DungeonObjectSelector { void set_dungeon_editor_system(std::unique_ptr* system) { dungeon_editor_system_ = system; } - void set_object_editor(std::shared_ptr* editor) { - object_editor_ = editor; + void set_object_editor(std::unique_ptr* editor) { + object_editor_ = editor ? editor->get() : nullptr; } // Room data access @@ -93,7 +93,7 @@ class DungeonObjectSelector { // Editor systems std::unique_ptr* dungeon_editor_system_ = nullptr; - std::shared_ptr* object_editor_ = nullptr; + zelda3::DungeonObjectEditor* object_editor_ = nullptr; // Room data std::array* rooms_ = nullptr;