UI Component Hierarchy
The UI Component Hierarchy defines how visual elements are structured, rendered, and managed in McRogueFace.
Quick Reference
Related Issues:
- #122 - Parent-Child UI System (Tier 2)
- #118 - Scene as Drawable (Tier 2)
- #102 - Add global_position Property (Tier 1)
- #10 - Visibility System with AABB
Key Files:
src/UIDrawable.h- Base class for all UI componentssrc/UIFrame.h/.cpp- Container with childrensrc/UICaption.h/.cpp- Text renderingsrc/UISprite.h/.cpp- Image/sprite renderingsrc/UIGrid.h/.cpp- Tilemap grid (see Grid-System)src/UIEntity.h/.cpp- Grid entities (see Entity-Management)
API Reference:
- See mcrfpy UI Classes 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 positionw,h,size- Dimensionsvisible- Show/hide flagopacity- 0.0-1.0 transparencyz_index- Render order (higher = front)
Common Methods:
move(dx, dy)- Relative movementresize(w, h)- Resizeget_bounds()- Returns (x, y, w, h)
Lifetime:
- All UI objects use
std::shared_ptrfor 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 drawablesfill_color,outline_color- Rectangle colorsoutline_thickness- Border widthclip_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 displayfont- Font objectfont_size- Text sizefill_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 objectsprite_index- Index in sprite sheetscale_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:
- Scene sorts UI elements by z_index (lower = back)
- Elements rendered in sorted order
- Children rendered after parents (relative to parent z_index)
Optimization: Dirty flag prevents re-sorting static scenes
Implementation: src/Scene.cpp::render(), issue #63 (Closed)
Parent-Child Relationships
Current State: No automatic parent tracking
Planned: #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:
# 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 - Object splitting bug
Common Tasks
Creating UI Elements
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:
# 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
# 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 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: Parent-Child UI System
- Add
parentfield to UIDrawable - Automatic coordinate transformation
- Recursive visibility and opacity
#118: Scene as Drawable
- Make Scene inherit from UIDrawable
- Enable scene composition and transitions as animations
- Scenes become first-class UI elements
#102: Global Position
- Calculate absolute screen position for nested elements
- Useful for click detection, tooltips
- Depends on parent-child system
See Also:
- UIDrawable API
- Python-Binding-Layer for implementation details
- Adding-Python-Bindings to add new UI components