3 UI Component Hierarchy
John McCardle edited this page 2026-02-07 23:50:46 +00:00

UI Component Hierarchy

The UI Component Hierarchy defines how visual elements are structured, rendered, and managed in McRogueFace.

Quick Reference

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)
  • src/UIArc.h, src/UICircle.h, src/UILine.h - Geometry primitives

Class Hierarchy

UIDrawable (base class)
+-- UIFrame    - Rectangle container with children
+-- UICaption  - Text labels
+-- UISprite   - Images and sprite sheets
+-- UIGrid     - Tilemap rendering
+-- UIEntity   - Grid-based game entities
+-- UIArc      - Arc/partial circle outline
+-- UICircle   - Filled/outlined circle
+-- UILine     - Line segment

UIDrawable (Base Class)

All UI components inherit from UIDrawable, providing a consistent interface for positioning, visibility, hierarchy, and interaction.

Position and Geometry

Property Type Description
pos (x, y) Position as tuple
x, y float Position components
w, h float Dimensions (Frame, Grid)
bounds (x, y, w, h) Bounding rectangle
global_bounds (x, y, w, h) Bounds in screen coordinates
global_position (x, y) Position in screen coordinates (accounts for parent chain)

Methods:

  • move(dx, dy) - Relative movement
  • resize(w, h) - Change dimensions

Hierarchy

Property Type Description
parent UIDrawable Parent element (read-only, set automatically)
z_index int Render order (higher = front)

Children are positioned relative to their parent. When a child is added to a Frame's children collection, its parent property is set automatically.

Visibility

Property Type Description
visible bool Show/hide element
opacity float Transparency (0.0 = invisible, 1.0 = opaque)

Interaction Callbacks

All UIDrawable types support mouse event callbacks:

Property Signature Description
on_click (pos: Vector, button: MouseButton, action: InputState) -> None Mouse click
on_enter (pos: Vector) -> None Mouse enters element bounds
on_exit (pos: Vector) -> None Mouse leaves element bounds
on_move (pos: Vector) -> None Mouse moves within element
frame = mcrfpy.Frame(pos=(100, 100), size=(200, 150))

def on_click(pos, button, action):
    if button == mcrfpy.MouseButton.LEFT and action == mcrfpy.InputState.PRESSED:
        print(f"Clicked at ({pos.x}, {pos.y})")

frame.on_click = on_click
frame.on_enter = lambda pos: print("Mouse entered")
frame.on_exit = lambda pos: print("Mouse left")
frame.on_move = lambda pos: print(f"Mouse at ({pos.x}, {pos.y})")

Animation

All UIDrawable types support the .animate() method:

obj.animate("property", target_value, duration_secs, easing, callback=None)

See Animation-System for details on animatable properties per type.

Utility

Property Type Description
name str Optional identifier for debugging/lookup

Concrete Types

UIFrame

Rectangle container that can hold child elements. Primary building block for UI layouts.

frame = mcrfpy.Frame(pos=(50, 50), size=(200, 150),
                      fill_color=mcrfpy.Color(40, 40, 50))
frame.outline_color = mcrfpy.Color(100, 100, 120)
frame.outline = 2

# Child elements are positioned relative to parent
label = mcrfpy.Caption(text="Title", pos=(10, 5))
frame.children.append(label)

Unique properties: children (UICollection), fill_color, outline_color, outline, clip_children

Animatable: x, y, w, h, opacity, outline, fill_color, outline_color

UICaption

Text rendering with font support.

text = mcrfpy.Caption(text="Hello World!", pos=(10, 10))
text.font_size = 24
text.fill_color = mcrfpy.Color(255, 255, 255)

Unique properties: text, font, font_size, fill_color

Animatable: x, y, opacity, outline, fill_color, outline_color

UISprite

Image and sprite sheet rendering.

texture = mcrfpy.Texture("assets/sprites/tileset.png", 16, 16)
sprite = mcrfpy.Sprite(x=100, y=100)
sprite.texture = texture
sprite.sprite_index = 5

Unique properties: texture, sprite_index, scale

Animatable: x, y, scale, sprite_index, opacity

UIGrid

Tilemap container for roguelike game maps. See Grid-System for complete documentation.

terrain = mcrfpy.TileLayer(name="terrain", z_index=-1, texture=texture)
grid = mcrfpy.Grid(grid_size=(50, 50), pos=(100, 100), size=(400, 300),
                    layers=[terrain])

Unique properties: grid_size, center, zoom, layers, entities, fill_color, perspective

Animatable: x, y, w, h, center_x, center_y, zoom

UIEntity

Game entities that live on grids. See Entity-Management for complete documentation.

entity = mcrfpy.Entity(grid_pos=(10, 10), sprite_index=0, name="player")
grid.entities.append(entity)

Unique properties: grid_x, grid_y, sprite_index, grid (parent reference)

Animatable: x, y, draw_x, draw_y, sprite_index, sprite_scale

UIArc, UICircle, UILine

Geometry primitives for shapes and decorations.

arc = mcrfpy.Arc(radius=50, start_angle=0, end_angle=90)
circle = mcrfpy.Circle(radius=30)
line = mcrfpy.Line(start=(0, 0), end=(100, 100))

Collections

UICollection

Container for Frame, Caption, Sprite, Grid, and geometry primitives. Used by Frame.children and Scene.children.

scene = mcrfpy.Scene("test")
ui = scene.children  # UICollection

ui.append(frame)
ui.extend([caption, sprite])
ui.remove(frame)

# Sequence protocol
for item in ui:
    print(type(item).__name__)
obj = ui[0]
count = len(ui)

UIEntityCollection

Container for Entity objects on a Grid.

grid.entities.append(entity)
grid.entities.extend([e1, e2, e3])
grid.entities.remove(entity)

for e in grid.entities:
    print(f"{e.name} at ({e.grid_x}, {e.grid_y})")

Rendering

Z-Index Order

  1. Scene sorts UI elements by z_index (lower = back)
  2. Elements rendered in sorted order
  3. Children rendered after parents

Parent-Child Coordinates

Children use coordinates relative to their parent's position:

frame = mcrfpy.Frame(pos=(100, 100), size=(200, 150))
label = mcrfpy.Caption(text="Hello", pos=(10, 10))
frame.children.append(label)

print(label.x, label.y)               # 10, 10 (relative)
print(label.global_position)           # (110, 110) (absolute)

Type Preservation

When retrieving from collections, the correct Python type is preserved:

scene.children.append(mcrfpy.Sprite(x=0, y=0, sprite_index=0))
obj = scene.children[0]
print(type(obj).__name__)  # "Sprite" (not "UIDrawable")

Implementation: RET_PY_INSTANCE macro in UIDrawable.h handles type dispatch.



Last updated: 2026-02-07