Add "UI-Component-Hierarchy"

John McCardle 2025-10-25 21:00:02 +00:00
parent 1f06157855
commit b8af2bd821
1 changed files with 299 additions and 0 deletions

299
UI-Component-Hierarchy.-.md Normal file

@ -0,0 +1,299 @@
# UI Component Hierarchy
The UI Component Hierarchy defines how visual elements are structured, rendered, and managed in McRogueFace.
## Quick Reference
**Related Issues:**
- [#122](../../issues/122) - Parent-Child UI System (Tier 2)
- [#118](../../issues/118) - Scene as Drawable (Tier 2)
- [#102](../../issues/102) - Add global_position Property (Tier 1)
- [#10](../../issues/10) - Visibility System with AABB
**Key Files:**
- `src/UIDrawable.h` - Base class for all UI components
- `src/UIFrame.h` / `.cpp` - Container with children
- `src/UICaption.h` / `.cpp` - Text rendering
- `src/UISprite.h` / `.cpp` - Image/sprite rendering
- `src/UIGrid.h` / `.cpp` - Tilemap grid (see [[Grid-System]])
- `src/UIEntity.h` / `.cpp` - Grid entities (see [[Entity-Management]])
**API Reference:**
- See [mcrfpy UI Classes](../../docs/api_reference_dynamic.html) in generated API docs
## Class Hierarchy
```
UIDrawable (base class)
├── UIFrame - Rectangle container with children
├── UICaption - Text labels
├── UISprite - Images and sprite sheets
├── UIGrid - Tilemap rendering (see [[Grid-System]])
└── UIEntity - Grid-based game entities
```
**Base Class:** `src/UIDrawable.h::UIDrawable`
### UIDrawable (Base)
**Common Properties:**
- `x`, `y`, `pos` - Screen position
- `w`, `h`, `size` - Dimensions
- `visible` - Show/hide flag
- `opacity` - 0.0-1.0 transparency
- `z_index` - Render order (higher = front)
**Common Methods:**
- `move(dx, dy)` - Relative movement
- `resize(w, h)` - Resize
- `get_bounds()` - Returns (x, y, w, h)
**Lifetime:**
- All UI objects use `std::shared_ptr` for automatic memory management
- Collections (UICollection, UIEntityCollection) hold shared_ptrs
- Removal from collection doesn't destroy object if Python still references it
**Implementation:** `src/UIDrawable.h`, exposed via [[Python-Binding-Layer]]
### UIFrame
**Purpose:** Container for grouping UI elements
**Unique Properties:**
- `children` - UICollection of child drawables
- `fill_color`, `outline_color` - Rectangle colors
- `outline_thickness` - Border width
- `clip_children` - Clipping support (opt-in)
**Use Cases:**
- GUI panels and windows
- Button groups
- Layout containers
**File:** `src/UIFrame.h` / `src/UIFrame.cpp`
### UICaption
**Purpose:** Text rendering with fonts
**Unique Properties:**
- `text` - String to display
- `font` - Font object
- `font_size` - Text size
- `fill_color` - Text color
**Use Cases:**
- Labels
- HUD text
- Dialogue
**File:** `src/UICaption.h` / `src/UICaption.cpp`
### UISprite
**Purpose:** Image and sprite sheet rendering
**Unique Properties:**
- `texture` - Texture object
- `sprite_index` - Index in sprite sheet
- `scale_x`, `scale_y` - Independent scaling
**Use Cases:**
- Character sprites
- UI icons
- Backgrounds
**File:** `src/UISprite.h` / `src/UISprite.cpp`
### UIGrid
**Purpose:** Tilemap rendering for roguelikes
See [[Grid-System]] for complete documentation.
### UIEntity
**Purpose:** Game entities that live on grids
See [[Entity-Management]] for complete documentation.
## Collections
### UICollection
**Purpose:** Container for Frame, Caption, Sprite, Grid
**Type:** `std::vector<std::shared_ptr<UIDrawable>>`
**Features:**
- Python sequence protocol (indexing, slicing, iteration)
- Append, remove, extend operations
- Preserves z_index order for rendering
**File:** `src/UICollection.h` / `.cpp`
### UIEntityCollection
**Purpose:** Container specifically for Entity objects
**Type:** `std::list<std::shared_ptr<UIEntity>>`
**Why std::list?** Allows stable iteration during entity removal
**Features:**
- Python sequence protocol
- Entity-specific operations
**File:** `src/UIEntityCollection.h` / `.cpp`
## Rendering Pipeline
### Z-Index Rendering
**Order:**
1. Scene sorts UI elements by z_index (lower = back)
2. Elements rendered in sorted order
3. Children rendered after parents (relative to parent z_index)
**Optimization:** Dirty flag prevents re-sorting static scenes
**Implementation:** `src/Scene.cpp::render()`, issue [#63](../../issues/63) (Closed)
### Parent-Child Relationships
**Current State:** No automatic parent tracking
**Planned:** [#122](../../issues/122) - Add parent field
- Children positioned relative to parent
- Parent movement affects children
- Automatic removal from old parent when added to new
**Workaround:** Manual coordinate management
## Type Preservation
### Challenge: Shared Pointer Type Loss
When retrieving from collections, C++ shared_ptr may lose Python type info:
```python
# Adding derived type
frame.children.append(my_sprite) # my_sprite is Sprite
# Retrieving
obj = frame.children[0] # Returns as UIDrawable, not Sprite!
```
**Solution:** `RET_PY_INSTANCE` macro (see [[Python-Binding-Layer]])
**Issue:** [#112](../../issues/112) - Object splitting bug
## Common Tasks
### Creating UI Elements
```python
import mcrfpy
# Frame (container)
frame = mcrfpy.Frame(100, 100, 200, 150)
frame.fill_color = mcrfpy.Color(50, 50, 50)
# Caption (text)
label = mcrfpy.Caption((10, 10), "Hello!")
label.font_size = 24
# Sprite (image)
sprite = mcrfpy.Sprite("player.png", 50, 50)
sprite.sprite_index = 0 # If using sprite sheet
# Add to scene
mcrfpy.sceneUI("game").append(frame)
frame.children.append(label)
```
### Animating Properties
All UIDrawable properties are animatable:
```python
# Animate position
mcrfpy.animate(sprite, "x", 300, 1000, "ease_in_out_cubic")
# Animate color
mcrfpy.animate(frame, "fill_color", mcrfpy.Color(255, 0, 0), 500, "linear")
# Animate opacity
mcrfpy.animate(label, "opacity", 0.0, 800, "ease_out_quad")
```
See [[Animation-System]] for complete animation documentation.
### Z-Index Layering
```python
# Background
background = mcrfpy.Sprite("bg.png", 0, 0)
background.z_index = 0
# Middleground
entities_grid = mcrfpy.Grid(50, 50, 16, 16)
entities_grid.z_index = 10
# Foreground UI
hud_frame = mcrfpy.Frame(0, 0, 800, 50)
hud_frame.z_index = 100
# Add to scene (order doesn't matter, z_index controls rendering)
scene_ui = mcrfpy.sceneUI("game")
scene_ui.append(hud_frame)
scene_ui.append(background)
scene_ui.append(entities_grid)
```
## Design Decisions
**Why Shared Pointers?**
- Automatic memory management
- Python can hold references independently of C++ collections
- Safe removal from collections
**Why Vector for UICollection vs List for EntityCollection?**
- Vector: Better cache locality, random access for UI
- List: Stable iterators during removal for entities
**Why No Automatic Parent Tracking?**
- Performance: Avoids overhead for simple use cases
- Flexibility: Manual control when needed
- Planned: [#122](../../issues/122) will add optional parent tracking
## Related Systems
- [[Animation-System]] - All UIDrawable properties are animatable
- [[Python-Binding-Layer]] - How UI classes exposed to Python
- [[Grid-System]] - UIGrid specifics
- [[Performance-and-Profiling]] - Rendering performance metrics
## Planned Improvements
**[#122](../../issues/122): Parent-Child UI System**
- Add `parent` field to UIDrawable
- Automatic coordinate transformation
- Recursive visibility and opacity
**[#118](../../issues/118): Scene as Drawable**
- Make Scene inherit from UIDrawable
- Enable scene composition and transitions as animations
- Scenes become first-class UI elements
**[#102](../../issues/102): Global Position**
- Calculate absolute screen position for nested elements
- Useful for click detection, tooltips
- Depends on parent-child system
---
**See Also:**
- [UIDrawable API](../../docs/api_reference_dynamic.html#UIDrawable)
- [[Python-Binding-Layer]] for implementation details
- [[Adding-Python-Bindings]] to add new UI components