# F2: Dungeon Editor v2 - Complete Guide

**Last Updated**: October 10, 2025  
**Related**: [E2-development-guide.md](E2-development-guide.md), [E5-debugging-guide.md](E5-debugging-guide.md)

---

## Overview

The Dungeon Editor uses a modern card-based architecture (DungeonEditorV2) with self-contained room rendering. This guide covers the architecture, recent refactoring work, and next development steps.

### Key Features
- ✅ **Visual room editing** with 512x512 canvas per room
- ✅ **Object position visualization** - Colored outlines by layer (Red/Green/Blue)
- ✅ **Per-room settings** - Independent BG1/BG2 visibility and layer types
- ✅ **Flexible docking** - EditorCard system for custom workspace layouts
- ✅ **Self-contained rooms** - Each room owns its bitmaps and palettes
- ✅ **Overworld integration** - Double-click entrances to open dungeon rooms

---

### Architecture Improvements ✅
1. **Room Buffers Decoupled** - No dependency on Arena graphics sheets
2. **ObjectRenderer Removed** - Standardized on ObjectDrawer (~1000 lines deleted)
3. **LoadGraphicsSheetsIntoArena Removed** - Using per-room graphics (~66 lines)
4. **Old Tab System Removed** - EditorCard is the standard
5. **Texture Atlas Infrastructure** - Future-proof stub created
6. **Test Suite Cleaned** - Deleted 1270 lines of redundant tests

### UI Improvements ✅
- Room ID in card title: `[003] Room Name`
- Properties reorganized into clean 4-column table
- Compact layer controls (1 row instead of 3)
- Room graphics canvas height fixed (1025px → 257px)
- Object count in status bar

---

## Architecture

### Component Overview

```
DungeonEditorV2 (UI Layer)
├─ Card-based UI system
├─ Room window management  
├─ Component coordination
└─ Lazy loading

DungeonEditorSystem (Backend Layer)
├─ Sprite/Item/Entrance/Door/Chest management
├─ Undo/Redo functionality
├─ Room properties management
└─ Dungeon-wide operations

Room (Data Layer)
├─ Self-contained buffers (bg1_buffer_, bg2_buffer_)
├─ Object storage (tile_objects_)
├─ Graphics loading
└─ Rendering pipeline
```

### Room Rendering Pipeline

TODO: Update this to latest code.

```
1. LoadRoomGraphics(blockset)
   └─> Reads blocks[] from ROM
   └─> Loads blockset data → current_gfx16_

2. LoadObjects()
   └─> Parses object data from ROM
   └─> Creates tile_objects_[]
   └─> SETS floor1_graphics_, floor2_graphics_ ← CRITICAL!

3. RenderRoomGraphics() [SELF-CONTAINED]
   ├─> DrawFloor(floor1_graphics_, floor2_graphics_)
   ├─> DrawBackground(current_gfx16_)
   ├─> SetPalette(full_90_color_dungeon_palette)
   ├─> RenderObjectsToBackground()
   │   └─> ObjectDrawer::DrawObjectList()
   └─> QueueTextureCommand(UPDATE/CREATE)

4. DrawRoomBackgroundLayers(room_id)
   └─> ProcessTextureQueue() → GPU textures
   └─> canvas_.DrawBitmap(bg1, bg2)

5. DrawObjectPositionOutlines(room)
   └─> Colored rectangles by layer
   └─> Object ID labels
```

### Room Structure (Bottom to Top)

Understanding ALTTP dungeon composition is critical:

```
Room Composition:
├─ Room Layout (BASE LAYER - immovable)
│  ├─ Walls (structural boundaries, 7 configurations of squares in 2x2 grid)
│  ├─ Floors (walkable areas, repeated tile pattern set to BG1/BG2)
├─ Layer 0 Objects (floor decorations, some walls)
├─ Layer 1 Objects (chests, decorations)
└─ Layer 2 Objects (stairs, transitions)

Doors: Positioned at room edges to connect rooms
```

**Key Insight**: Layouts are immovable base structure. Objects are placed ON TOP and can be moved/edited. This allows for large rooms, 4-quadrant rooms, tall/wide rooms, etc.

---

## Next Development Steps

### High Priority (Must Do)

#### 1. Door Rendering at Room Edges
**What**: Render doors with proper patterns at room connections

**Pattern Reference**: ZScream's door drawing patterns

**Implementation**:
```cpp
void DungeonCanvasViewer::DrawDoors(const zelda3::Room& room) {
  // Doors stored in room data
  // Position at room edges (North/South/East/West)
  // Use current_gfx16_ graphics data
  
  // TODO: Get door data from room.GetDoors() or similar
  // TODO: Use ObjectDrawer patterns for door graphics
  // TODO: Draw at interpolation points between rooms
}
```

---

#### 2. Object Name Labels from String Array
**File**: `dungeon_canvas_viewer.cc:416` (DrawObjectPositionOutlines)

**What**: Show real object names instead of just IDs

**Implementation**:
```cpp
// Instead of:
std::string label = absl::StrFormat("0x%02X", obj.id_);

// Use:
std::string object_name = GetObjectName(obj.id_);
std::string label = absl::StrFormat("%s\n0x%02X", object_name.c_str(), obj.id_);

// Helper function:
std::string GetObjectName(int16_t object_id) {
  // TODO: Reference ZScream's object name arrays
  // TODO: Map object ID → name string
  // Example: 0x10 → "Wall (North)"
  return "Object";
}
```

---

#### 4. Fix Plus Button to Select Any Room
**File**: `dungeon_editor_v2.cc:228` (DrawToolset)

**Current Issue**: Opens Room 0x00 (Ganon) always

**Fix**:
```cpp
if (toolbar.AddAction(ICON_MD_ADD, "Open Room")) {
  // Show room selector dialog instead of opening room 0
  show_room_selector_ = true;
  // Or: show room picker popup
  ImGui::OpenPopup("SelectRoomToOpen");
}

// Add popup:
if (ImGui::BeginPopup("SelectRoomToOpen")) {
  static int selected_room = 0;
  ImGui::InputInt("Room ID", &selected_room);
  if (ImGui::Button("Open")) {
    OnRoomSelected(selected_room);
    ImGui::CloseCurrentPopup();
  }
  ImGui::EndPopup();
}
```

---

### Medium Priority (Should Do)

#### 6. Fix InputHexByte +/- Button Events
**File**: `src/app/gui/input.cc` (likely)

**Issue**: Buttons don't respond to clicks

**Investigation Needed**:
- Check if button click events are being captured
- Verify event logic matches working examples
- Keep existing event style if it works elsewhere


### Lower Priority (Nice to Have)

#### 9. Move Backend Logic to DungeonEditorSystem
**What**: Separate UI (V2) from data operations (System)

**Migration**:
- Sprite management → DungeonEditorSystem
- Item management → DungeonEditorSystem
- Entrance/Door/Chest → DungeonEditorSystem
- Undo/Redo → DungeonEditorSystem

**Result**: DungeonEditorV2 becomes pure UI coordinator

---

## Quick Start

### Build & Run
```bash
cd /Users/scawful/Code/yaze
cmake --preset mac-ai -B build_ai
cmake --build build_ai --target yaze -j12

# Run dungeon editor
./build_ai/bin/yaze.app/Contents/MacOS/yaze --rom_file=zelda3.sfc --editor=Dungeon

# Open specific room
./build_ai/bin/yaze.app/Contents/MacOS/yaze --rom_file=zelda3.sfc --editor=Dungeon --cards="Room 0x00"
```

---

## Testing & Verification

### Debug Commands
```bash
# Verify floor values load correctly
./build_ai/bin/yaze.app/Contents/MacOS/yaze --rom_file=zelda3.sfc --editor=Dungeon 2>&1 | grep "floor1="

# Expected: floor1=4, floor2=8 (NOT 0!)

# Check object rendering
./build_ai/bin/yaze.app/Contents/MacOS/yaze --rom_file=zelda3.sfc --editor=Dungeon 2>&1 | grep "Drawing.*objects"

# Check object drawing details
./build_ai/bin/yaze.app/Contents/MacOS/yaze --rom_file=zelda3.sfc --editor=Dungeon 2>&1 | grep "Writing Tile16"
```

## Related Documentation

- **E2-development-guide.md** - Core architectural patterns
- **E5-debugging-guide.md** - Debugging workflows
- **F1-dungeon-editor-guide.md** - Original dungeon guide (may be outdated)

---

**Last Updated**: October 10, 2025  
**Contributors**: Dungeon Editor Refactoring Session


