- 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.
13 KiB
13 KiB
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
LoadAnimatedGraphicsandCopyRoomGraphicsToBuffer - Added bounds checking for all array/vector accesses
- Added graceful error handling with early returns
- Added comprehensive null checks in
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
// 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
// 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
// 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
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
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
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
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
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 UIDungeonCanvasViewer: Main canvas rendering and interactionDungeonObjectSelector: 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)
- Complete Method Implementation: Add all missing methods to UI components
- Test Integration: Verify all components work together correctly
- Error Handling: Add proper error handling and user feedback
- Performance Optimization: Implement caching and memory management
Implementation Notes for Future Developers
Component Integration Pattern
// 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:
// 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:
- Component Integration: Complete the integration of UI components (IN PROGRESS)
- Object Preview System: Needs debugging and fallback mechanisms
- Error Handling: Needs better user feedback and recovery
- Memory Management: Needs monitoring and cleanup
- 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
- Read the Architecture: Understand the component separation
- Study the Crash Fixes: Learn the error handling patterns
- Start with Debugging: Add logging to understand current issues
- Implement Incrementally: Make small, testable changes
- Test Thoroughly: Always test with real ROM data
- 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.