Add Comprehensive Dungeon Editor Design Plan
- Introduced a detailed design plan document for the Yaze Dungeon Editor, outlining the current architecture, main components, and core systems. - Documented identified issues and applied fixes, including crash prevention and UI simplification, along with a roadmap for future development phases. - Enhanced clarity on the implementation guidelines, testing strategies, and performance considerations to support ongoing development efforts. - Established a structured approach for new developers to understand the codebase and contribute effectively to the project.
This commit is contained in:
430
docs/dungeon-editor-design-plan.md
Normal file
430
docs/dungeon-editor-design-plan.md
Normal file
@@ -0,0 +1,430 @@
|
||||
# Dungeon Editor Design Plan & Future Development Guide
|
||||
|
||||
## Overview
|
||||
This document provides a comprehensive design plan for the Yaze Dungeon Editor, including current architecture, identified issues, and a roadmap for future developers to continue development effectively.
|
||||
|
||||
## Current Architecture
|
||||
|
||||
### Main Components
|
||||
|
||||
#### 1. **DungeonEditor** (Main Controller)
|
||||
- **File**: `src/app/editor/dungeon/dungeon_editor.h/cc`
|
||||
- **Purpose**: Main UI controller and coordinator
|
||||
- **Responsibilities**:
|
||||
- Managing the 3-column UI layout
|
||||
- Coordinating between different editor components
|
||||
- Handling ROM loading and initialization
|
||||
- Managing editor state and undo/redo
|
||||
|
||||
#### 2. **DungeonRoomSelector** (Room/Entrance Selection)
|
||||
- **File**: `src/app/editor/dungeon/dungeon_room_selector.h/cc`
|
||||
- **Purpose**: Handles room and entrance selection UI
|
||||
- **Responsibilities**:
|
||||
- Room list display and selection
|
||||
- Entrance configuration and selection
|
||||
- Room properties editing
|
||||
|
||||
#### 3. **DungeonCanvasViewer** (Main Canvas)
|
||||
- **File**: `src/app/editor/dungeon/dungeon_canvas_viewer.h/cc`
|
||||
- **Purpose**: Main canvas rendering and interaction
|
||||
- **Responsibilities**:
|
||||
- Room graphics rendering
|
||||
- Object rendering and positioning
|
||||
- Canvas interaction (pan, zoom, select)
|
||||
- Coordinate system management
|
||||
|
||||
#### 4. **DungeonObjectSelector** (Object Management)
|
||||
- **File**: `src/app/editor/dungeon/dungeon_object_selector.h/cc`
|
||||
- **Purpose**: Object selection, preview, and editing
|
||||
- **Responsibilities**:
|
||||
- Object preview rendering
|
||||
- Object editing controls
|
||||
- Graphics sheet display
|
||||
- Integrated editing panels
|
||||
|
||||
### Core Systems
|
||||
|
||||
#### 1. **ObjectRenderer**
|
||||
- **File**: `src/app/zelda3/dungeon/object_renderer.h/cc`
|
||||
- **Purpose**: Renders dungeon objects to bitmaps
|
||||
- **Features**: Caching, performance monitoring, memory management
|
||||
|
||||
#### 2. **DungeonEditorSystem**
|
||||
- **File**: `src/app/zelda3/dungeon/dungeon_editor_system.h/cc`
|
||||
- **Purpose**: High-level dungeon editing operations
|
||||
- **Features**: Undo/redo, room management, object operations
|
||||
|
||||
#### 3. **DungeonObjectEditor**
|
||||
- **File**: `src/app/zelda3/dungeon/dungeon_object_editor.h/cc`
|
||||
- **Purpose**: Interactive object editing
|
||||
- **Features**: Object placement, editing modes, validation
|
||||
|
||||
## Current Issues & Fixes Applied
|
||||
|
||||
### 1. **Crash Prevention** ✅ FIXED
|
||||
- **Issue**: Multiple crashes when ROM not loaded or invalid data accessed
|
||||
- **Fixes Applied**:
|
||||
- Added comprehensive null checks in `DrawSpriteTile`
|
||||
- Added ROM validation in `LoadAnimatedGraphics` and `CopyRoomGraphicsToBuffer`
|
||||
- Added bounds checking for all array/vector accesses
|
||||
- Added graceful error handling with early returns
|
||||
|
||||
### 2. **UI Simplification** ✅ FIXED
|
||||
- **Issue**: 4-column layout was too crowded
|
||||
- **Fixes Applied**:
|
||||
- Reduced to 3-column layout: Room/Entrance Selector | Canvas | Object Selector/Editor
|
||||
- Fixed column widths for better space utilization
|
||||
- Separated logical components into dedicated classes
|
||||
|
||||
### 3. **Coordinate System Issues** ✅ PARTIALLY FIXED
|
||||
- **Issue**: Object previews and coordinates were incorrect
|
||||
- **Fixes Applied**:
|
||||
- Fixed object preview centering in canvas
|
||||
- Added coordinate conversion helper functions
|
||||
- Improved bounds checking for object rendering
|
||||
|
||||
## Remaining Issues
|
||||
|
||||
### 1. **Object Preview Not Showing**
|
||||
- **Current Status**: Objects may not render in preview due to:
|
||||
- ROM data not properly loaded
|
||||
- Palette issues
|
||||
- Object parsing failures
|
||||
- **Recommended Fix**: Add debug logging and fallback rendering
|
||||
|
||||
### 2. **Graphics Loading Issues**
|
||||
- **Current Status**: Room graphics may not load properly
|
||||
- **Recommended Fix**: Implement proper error handling and user feedback
|
||||
|
||||
### 3. **Memory Management**
|
||||
- **Current Status**: Potential memory leaks in graphics caching
|
||||
- **Recommended Fix**: Implement proper cleanup and memory monitoring
|
||||
|
||||
## Future Development Roadmap
|
||||
|
||||
### Phase 1: Stability & Bug Fixes (Priority: High)
|
||||
|
||||
#### 1.1 Object Preview System
|
||||
```cpp
|
||||
// In DungeonObjectSelector::DrawObjectRenderer()
|
||||
void DungeonObjectSelector::DrawObjectRenderer() {
|
||||
// Add debug information
|
||||
if (ImGui::Button("Debug Object Preview")) {
|
||||
// Log object data, ROM state, palette info
|
||||
LogObjectPreviewDebugInfo();
|
||||
}
|
||||
|
||||
// Add fallback rendering
|
||||
if (!object_loaded_) {
|
||||
ImGui::Text("No object preview available");
|
||||
if (ImGui::Button("Force Load Preview")) {
|
||||
ForceLoadObjectPreview();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 1.2 Error Handling & User Feedback
|
||||
```cpp
|
||||
// Add to all major operations
|
||||
absl::Status LoadRoomGraphics(int room_id) {
|
||||
auto result = DoLoadRoomGraphics(room_id);
|
||||
if (!result.ok()) {
|
||||
ShowErrorMessage("Failed to load room graphics", result.message());
|
||||
return result;
|
||||
}
|
||||
ShowSuccessMessage("Room graphics loaded successfully");
|
||||
return absl::OkStatus();
|
||||
}
|
||||
```
|
||||
|
||||
#### 1.3 Memory Management
|
||||
```cpp
|
||||
// Add memory monitoring
|
||||
class DungeonEditor {
|
||||
private:
|
||||
void MonitorMemoryUsage() {
|
||||
auto stats = object_renderer_.GetPerformanceStats();
|
||||
if (stats.memory_usage > kMaxMemoryUsage) {
|
||||
ClearObjectCache();
|
||||
ShowWarningMessage("Memory usage high, cleared cache");
|
||||
}
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### Phase 2: Feature Enhancement (Priority: Medium)
|
||||
|
||||
#### 2.1 Advanced Object Editing
|
||||
- Multi-object selection
|
||||
- Object grouping
|
||||
- Copy/paste operations
|
||||
- Object templates
|
||||
|
||||
#### 2.2 Enhanced Canvas Features
|
||||
- Zoom controls
|
||||
- Grid snapping
|
||||
- Layer management
|
||||
- Real-time preview
|
||||
|
||||
#### 2.3 Room Management
|
||||
- Room duplication
|
||||
- Room templates
|
||||
- Bulk operations
|
||||
- Room validation
|
||||
|
||||
### Phase 3: Advanced Features (Priority: Low)
|
||||
|
||||
#### 3.1 Scripting Support
|
||||
- Lua scripting for custom operations
|
||||
- Automation tools
|
||||
- Batch processing
|
||||
|
||||
#### 3.2 Plugin System
|
||||
- Modular architecture
|
||||
- Third-party plugins
|
||||
- Custom object types
|
||||
|
||||
## Implementation Guidelines
|
||||
|
||||
### 1. **Error Handling Pattern**
|
||||
```cpp
|
||||
absl::Status DoOperation() {
|
||||
// Validate inputs
|
||||
if (!IsValidInput()) {
|
||||
return absl::InvalidArgumentError("Invalid input");
|
||||
}
|
||||
|
||||
// Perform operation with error checking
|
||||
auto result = PerformOperation();
|
||||
if (!result.ok()) {
|
||||
LogError("Operation failed", result.status());
|
||||
return result.status();
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
```
|
||||
|
||||
### 2. **UI Component Pattern**
|
||||
```cpp
|
||||
class ComponentName {
|
||||
public:
|
||||
void Draw() {
|
||||
if (!IsValid()) {
|
||||
ImGui::Text("Component not ready");
|
||||
return;
|
||||
}
|
||||
|
||||
// Draw component UI
|
||||
DrawMainUI();
|
||||
|
||||
// Handle interactions
|
||||
HandleInteractions();
|
||||
}
|
||||
|
||||
private:
|
||||
bool IsValid() const {
|
||||
return rom_ != nullptr && rom_->is_loaded();
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### 3. **Memory Management Pattern**
|
||||
```cpp
|
||||
class GraphicsManager {
|
||||
public:
|
||||
void ClearCache() {
|
||||
object_cache_.clear();
|
||||
texture_cache_.clear();
|
||||
memory_pool_.Reset();
|
||||
}
|
||||
|
||||
size_t GetMemoryUsage() const {
|
||||
return object_cache_.size() * sizeof(CachedObject) +
|
||||
texture_cache_.size() * sizeof(Texture);
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<CachedObject> object_cache_;
|
||||
std::unordered_map<int, Texture> texture_cache_;
|
||||
MemoryPool memory_pool_;
|
||||
};
|
||||
```
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
### 1. **Unit Tests**
|
||||
- Test each component in isolation
|
||||
- Mock ROM data for consistent testing
|
||||
- Test error conditions and edge cases
|
||||
|
||||
### 2. **Integration Tests**
|
||||
- Test component interactions
|
||||
- Test with real ROM data
|
||||
- Test performance under load
|
||||
|
||||
### 3. **UI Tests**
|
||||
- Test user interactions
|
||||
- Test layout responsiveness
|
||||
- Test accessibility
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
### 1. **Rendering Optimization**
|
||||
- Implement object culling
|
||||
- Use texture atlases
|
||||
- Implement level-of-detail (LOD)
|
||||
|
||||
### 2. **Memory Optimization**
|
||||
- Implement smart caching
|
||||
- Use memory pools
|
||||
- Monitor memory usage
|
||||
|
||||
### 3. **UI Responsiveness**
|
||||
- Use async operations for heavy tasks
|
||||
- Implement progress indicators
|
||||
- Minimize UI blocking operations
|
||||
|
||||
## Debugging Tools
|
||||
|
||||
### 1. **Debug Console**
|
||||
```cpp
|
||||
class DebugConsole {
|
||||
public:
|
||||
void LogObjectState(const RoomObject& obj) {
|
||||
ImGui::Text("Object ID: %d", obj.id_);
|
||||
ImGui::Text("Position: (%d, %d)", obj.x_, obj.y_);
|
||||
ImGui::Text("Size: %d", obj.size_);
|
||||
ImGui::Text("Layer: %d", static_cast<int>(obj.layer_));
|
||||
ImGui::Text("Tiles Loaded: %s", obj.tiles().empty() ? "No" : "Yes");
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### 2. **Performance Monitor**
|
||||
```cpp
|
||||
class PerformanceMonitor {
|
||||
public:
|
||||
void DrawPerformanceStats() {
|
||||
auto stats = GetStats();
|
||||
ImGui::Text("Render Time: %.2f ms", stats.render_time.count());
|
||||
ImGui::Text("Memory Usage: %.2f MB", stats.memory_usage / 1024.0 / 1024.0);
|
||||
ImGui::Text("Cache Hit Rate: %.2f%%", stats.cache_hit_rate * 100);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## Current Implementation Status
|
||||
|
||||
### ✅ Completed (Phase 1)
|
||||
- **UI Component Separation**: Successfully separated DungeonEditor into 3 main components:
|
||||
- `DungeonRoomSelector`: Room and entrance selection UI
|
||||
- `DungeonCanvasViewer`: Main canvas rendering and interaction
|
||||
- `DungeonObjectSelector`: Object management and editing panels
|
||||
- **3-Column Layout**: Implemented clean 3-column layout as requested
|
||||
- **Debug Elements Popup**: Moved debug controls into modal popup for cleaner UI
|
||||
- **Crash Prevention**: Added comprehensive null checks and bounds validation
|
||||
- **Component Architecture**: Established proper separation of concerns
|
||||
|
||||
### 🔄 In Progress (Phase 2)
|
||||
- **Component Integration**: Currently integrating UI components into main DungeonEditor
|
||||
- **Method Implementation**: Adding missing SetRom, SetRooms, SetCurrentPaletteGroup methods
|
||||
- **Data Flow**: Establishing proper data flow between components
|
||||
|
||||
### ⏳ Next Steps (Phase 3)
|
||||
1. **Complete Method Implementation**: Add all missing methods to UI components
|
||||
2. **Test Integration**: Verify all components work together correctly
|
||||
3. **Error Handling**: Add proper error handling and user feedback
|
||||
4. **Performance Optimization**: Implement caching and memory management
|
||||
|
||||
## Implementation Notes for Future Developers
|
||||
|
||||
### Component Integration Pattern
|
||||
```cpp
|
||||
// Main DungeonEditor coordinates components
|
||||
class DungeonEditor {
|
||||
private:
|
||||
DungeonRoomSelector room_selector_;
|
||||
DungeonCanvasViewer canvas_viewer_;
|
||||
DungeonObjectSelector object_selector_;
|
||||
|
||||
public:
|
||||
void Load() {
|
||||
// Initialize components with data
|
||||
room_selector_.set_rom(rom_);
|
||||
room_selector_.set_rooms(&rooms_);
|
||||
room_selector_.set_entrances(&entrances_);
|
||||
|
||||
canvas_viewer_.SetRom(rom_);
|
||||
canvas_viewer_.SetRooms(rooms_);
|
||||
canvas_viewer_.SetCurrentPaletteGroup(current_palette_group_);
|
||||
|
||||
object_selector_.SetRom(rom_);
|
||||
object_selector_.SetCurrentPaletteGroup(current_palette_group_);
|
||||
}
|
||||
|
||||
void UpdateDungeonRoomView() {
|
||||
// 3-column layout
|
||||
if (BeginTable("#DungeonEditTable", 3, kDungeonTableFlags)) {
|
||||
TableNextColumn();
|
||||
room_selector_.Draw(); // Column 1: Room/Entrance Selector
|
||||
|
||||
TableNextColumn();
|
||||
canvas_viewer_.Draw(current_room_id_); // Column 2: Canvas
|
||||
|
||||
TableNextColumn();
|
||||
object_selector_.Draw(); // Column 3: Object Selector/Editor
|
||||
|
||||
EndTable();
|
||||
}
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### Required Methods for UI Components
|
||||
Each UI component needs these methods for proper integration:
|
||||
|
||||
```cpp
|
||||
// DungeonRoomSelector
|
||||
void SetRom(Rom* rom);
|
||||
void SetRooms(std::array<Room, 0x128>* rooms);
|
||||
void SetEntrances(std::array<RoomEntrance, 0x8C>* entrances);
|
||||
void Draw();
|
||||
|
||||
// DungeonCanvasViewer
|
||||
void SetRom(Rom* rom);
|
||||
void SetRooms(std::array<Room, 0x128>& rooms);
|
||||
void SetCurrentPaletteGroup(const gfx::PaletteGroup& palette_group);
|
||||
void SetCurrentPaletteId(uint64_t palette_id);
|
||||
void Draw(int room_id);
|
||||
|
||||
// DungeonObjectSelector
|
||||
void SetRom(Rom* rom);
|
||||
void SetCurrentPaletteGroup(const gfx::PaletteGroup& palette_group);
|
||||
void SetCurrentPaletteId(uint64_t palette_id);
|
||||
void Draw();
|
||||
```
|
||||
|
||||
## Conclusion
|
||||
|
||||
The Dungeon Editor has a solid foundation with proper separation of concerns and crash prevention measures in place. The main areas for improvement are:
|
||||
|
||||
1. **Component Integration**: Complete the integration of UI components (IN PROGRESS)
|
||||
2. **Object Preview System**: Needs debugging and fallback mechanisms
|
||||
3. **Error Handling**: Needs better user feedback and recovery
|
||||
4. **Memory Management**: Needs monitoring and cleanup
|
||||
5. **UI Polish**: Needs better visual feedback and responsiveness
|
||||
|
||||
Following this design plan will ensure the Dungeon Editor becomes a robust, user-friendly tool for Zelda 3 ROM editing.
|
||||
|
||||
## Quick Start for New Developers
|
||||
|
||||
1. **Read the Architecture**: Understand the component separation
|
||||
2. **Study the Crash Fixes**: Learn the error handling patterns
|
||||
3. **Start with Debugging**: Add logging to understand current issues
|
||||
4. **Implement Incrementally**: Make small, testable changes
|
||||
5. **Test Thoroughly**: Always test with real ROM data
|
||||
6. **Document Changes**: Update this document as you make improvements
|
||||
|
||||
The codebase is well-structured and ready for continued development. Focus on stability first, then features.
|
||||
@@ -65,6 +65,10 @@ void DungeonCanvasViewer::DrawDungeonTabView() {
|
||||
Separator();
|
||||
}
|
||||
|
||||
void DungeonCanvasViewer::Draw(int room_id) {
|
||||
DrawDungeonCanvas(room_id);
|
||||
}
|
||||
|
||||
void DungeonCanvasViewer::DrawDungeonCanvas(int room_id) {
|
||||
// Validate room_id and ROM
|
||||
if (room_id < 0 || room_id >= 128) {
|
||||
|
||||
@@ -20,22 +20,23 @@ class DungeonCanvasViewer {
|
||||
|
||||
void DrawDungeonTabView();
|
||||
void DrawDungeonCanvas(int room_id);
|
||||
void Draw(int room_id);
|
||||
|
||||
void set_rom(Rom* rom) {
|
||||
void SetRom(Rom* rom) {
|
||||
rom_ = rom;
|
||||
object_renderer_.SetROM(rom);
|
||||
}
|
||||
Rom* rom() const { return rom_; }
|
||||
|
||||
// Room data access
|
||||
void set_rooms(std::array<zelda3::Room, 0x128>* rooms) { rooms_ = rooms; }
|
||||
void SetRooms(std::array<zelda3::Room, 0x128>* rooms) { rooms_ = rooms; }
|
||||
void set_active_rooms(const ImVector<int>& rooms) { active_rooms_ = rooms; }
|
||||
void set_current_active_room_tab(int tab) { current_active_room_tab_ = tab; }
|
||||
|
||||
// Palette access
|
||||
void set_current_palette_group_id(uint64_t id) { current_palette_group_id_ = id; }
|
||||
void set_current_palette_id(uint64_t id) { current_palette_id_ = id; }
|
||||
void set_current_palette_group(const gfx::PaletteGroup& group) { current_palette_group_ = group; }
|
||||
void SetCurrentPaletteId(uint64_t id) { current_palette_id_ = id; }
|
||||
void SetCurrentPaletteGroup(const gfx::PaletteGroup& group) { current_palette_group_ = group; }
|
||||
|
||||
// Canvas access
|
||||
gui::Canvas& canvas() { return canvas_; }
|
||||
|
||||
@@ -100,6 +100,21 @@ absl::Status DungeonEditor::Load() {
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the new UI components with loaded data
|
||||
room_selector_.set_rom(rom_);
|
||||
room_selector_.set_rooms(&rooms_);
|
||||
room_selector_.set_entrances(&entrances_);
|
||||
room_selector_.set_active_rooms(active_rooms_);
|
||||
|
||||
canvas_viewer_.SetRom(rom_);
|
||||
canvas_viewer_.SetRooms(&rooms_);
|
||||
canvas_viewer_.SetCurrentPaletteGroup(current_palette_group_);
|
||||
canvas_viewer_.SetCurrentPaletteId(current_palette_id_);
|
||||
|
||||
object_selector_.SetRom(rom_);
|
||||
object_selector_.SetCurrentPaletteGroup(current_palette_group_);
|
||||
object_selector_.SetCurrentPaletteId(current_palette_id_);
|
||||
|
||||
is_loaded_ = true;
|
||||
return absl::OkStatus();
|
||||
}
|
||||
@@ -230,33 +245,21 @@ absl::Status DungeonEditor::UpdateDungeonRoomView() {
|
||||
TableHeadersRow();
|
||||
TableNextRow();
|
||||
|
||||
// Column 1: Room and Entrance Selector
|
||||
// Column 1: Room and Entrance Selector (using new component)
|
||||
TableNextColumn();
|
||||
if (ImGui::BeginTabBar("##DungeonRoomTabBar")) {
|
||||
TAB_ITEM("Rooms");
|
||||
DrawRoomSelector();
|
||||
END_TAB_ITEM();
|
||||
TAB_ITEM("Entrances");
|
||||
DrawEntranceSelector();
|
||||
END_TAB_ITEM();
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
room_selector_.Draw();
|
||||
|
||||
// Column 2: Main Canvas
|
||||
// Column 2: Main Canvas (using new component)
|
||||
TableNextColumn();
|
||||
DrawDungeonTabView();
|
||||
|
||||
// Column 3: Object Selector and Editor
|
||||
TableNextColumn();
|
||||
if (ImGui::BeginTabBar("##ObjectEditorTabBar")) {
|
||||
TAB_ITEM("Graphics");
|
||||
DrawTileSelector();
|
||||
END_TAB_ITEM();
|
||||
TAB_ITEM("Editor");
|
||||
DrawIntegratedEditingPanels();
|
||||
END_TAB_ITEM();
|
||||
ImGui::EndTabBar();
|
||||
int current_room = current_room_id_;
|
||||
if (!active_rooms_.empty() && current_active_room_tab_ < active_rooms_.Size) {
|
||||
current_room = active_rooms_[current_active_room_tab_];
|
||||
}
|
||||
canvas_viewer_.Draw(current_room);
|
||||
|
||||
// Column 3: Object Selector and Editor (using new component)
|
||||
TableNextColumn();
|
||||
object_selector_.Draw();
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
@@ -45,7 +45,8 @@ constexpr ImGuiTableFlags kDungeonTableFlags =
|
||||
class DungeonEditor : public Editor {
|
||||
public:
|
||||
explicit DungeonEditor(Rom* rom = nullptr)
|
||||
: rom_(rom), object_renderer_(rom), preview_object_(0, 0, 0, 0, 0) {
|
||||
: rom_(rom), object_renderer_(rom), preview_object_(0, 0, 0, 0, 0),
|
||||
room_selector_(rom), canvas_viewer_(rom), object_selector_(rom) {
|
||||
type_ = EditorType::kDungeon;
|
||||
// Initialize the new dungeon editor system
|
||||
if (rom) {
|
||||
@@ -67,7 +68,13 @@ class DungeonEditor : public Editor {
|
||||
|
||||
void add_room(int i) { active_rooms_.push_back(i); }
|
||||
|
||||
void set_rom(Rom* rom) { rom_ = rom; }
|
||||
void set_rom(Rom* rom) {
|
||||
rom_ = rom;
|
||||
// Update the new UI components with the new ROM
|
||||
room_selector_.set_rom(rom_);
|
||||
canvas_viewer_.SetRom(rom_);
|
||||
object_selector_.SetRom(rom_);
|
||||
}
|
||||
Rom* rom() const { return rom_; }
|
||||
|
||||
private:
|
||||
@@ -212,6 +219,11 @@ class DungeonEditor : public Editor {
|
||||
std::array<zelda3::RoomEntrance, 0x8C> entrances_ = {};
|
||||
zelda3::ObjectRenderer object_renderer_;
|
||||
|
||||
// New UI components
|
||||
DungeonRoomSelector room_selector_;
|
||||
DungeonCanvasViewer canvas_viewer_;
|
||||
DungeonObjectSelector object_selector_;
|
||||
|
||||
absl::flat_hash_map<uint16_t, int> spriteset_usage_;
|
||||
absl::flat_hash_map<uint16_t, int> blockset_usage_;
|
||||
absl::flat_hash_map<uint16_t, int> palette_usage_;
|
||||
|
||||
@@ -127,6 +127,20 @@ void DungeonObjectSelector::DrawObjectRenderer() {
|
||||
}
|
||||
}
|
||||
|
||||
void DungeonObjectSelector::Draw() {
|
||||
if (ImGui::BeginTabBar("##ObjectEditorTabBar")) {
|
||||
if (ImGui::BeginTabItem("Graphics")) {
|
||||
DrawRoomGraphics();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem("Editor")) {
|
||||
DrawIntegratedEditingPanels();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
}
|
||||
|
||||
void DungeonObjectSelector::DrawRoomGraphics() {
|
||||
const auto height = 0x40;
|
||||
room_gfx_canvas_.DrawBackground();
|
||||
|
||||
@@ -22,11 +22,16 @@ class DungeonObjectSelector {
|
||||
void DrawTileSelector();
|
||||
void DrawObjectRenderer();
|
||||
void DrawIntegratedEditingPanels();
|
||||
void Draw();
|
||||
|
||||
void set_rom(Rom* rom) {
|
||||
rom_ = rom;
|
||||
object_renderer_.SetROM(rom);
|
||||
}
|
||||
void SetRom(Rom* rom) {
|
||||
rom_ = rom;
|
||||
object_renderer_.SetROM(rom);
|
||||
}
|
||||
Rom* rom() const { return rom_; }
|
||||
|
||||
// Editor system access
|
||||
@@ -43,6 +48,8 @@ class DungeonObjectSelector {
|
||||
|
||||
// Palette access
|
||||
void set_current_palette_group_id(uint64_t id) { current_palette_group_id_ = id; }
|
||||
void SetCurrentPaletteGroup(const gfx::PaletteGroup& palette_group) { current_palette_group_ = palette_group; }
|
||||
void SetCurrentPaletteId(uint64_t palette_id) { current_palette_id_ = palette_id; }
|
||||
|
||||
private:
|
||||
void DrawRoomGraphics();
|
||||
@@ -69,6 +76,8 @@ class DungeonObjectSelector {
|
||||
|
||||
// Palette data
|
||||
uint64_t current_palette_group_id_ = 0;
|
||||
uint64_t current_palette_id_ = 0;
|
||||
gfx::PaletteGroup current_palette_group_;
|
||||
|
||||
// Object preview system
|
||||
zelda3::RoomObject preview_object_{0, 0, 0, 0, 0};
|
||||
|
||||
@@ -10,9 +10,28 @@
|
||||
namespace yaze::editor {
|
||||
|
||||
using ImGui::BeginChild;
|
||||
using ImGui::BeginTabBar;
|
||||
using ImGui::BeginTabItem;
|
||||
using ImGui::EndChild;
|
||||
using ImGui::EndTabBar;
|
||||
using ImGui::EndTabItem;
|
||||
using ImGui::Separator;
|
||||
using ImGui::SameLine;
|
||||
using ImGui::Text;
|
||||
|
||||
void DungeonRoomSelector::Draw() {
|
||||
if (ImGui::BeginTabBar("##DungeonRoomTabBar")) {
|
||||
if (ImGui::BeginTabItem("Rooms")) {
|
||||
DrawRoomSelector();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem("Entrances")) {
|
||||
DrawEntranceSelector();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
}
|
||||
|
||||
void DungeonRoomSelector::DrawRoomSelector() {
|
||||
if (!rom_ || !rom_->is_loaded()) {
|
||||
|
||||
@@ -17,6 +17,7 @@ class DungeonRoomSelector {
|
||||
public:
|
||||
explicit DungeonRoomSelector(Rom* rom = nullptr) : rom_(rom) {}
|
||||
|
||||
void Draw();
|
||||
void DrawRoomSelector();
|
||||
void DrawEntranceSelector();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user