# Widget Layout — WidgetTree, Panels, Slots, Anchors

Detailed reference for widget positioning and layout. For the complete UMG workflow (creation → layout → variables → graphs → save), see `umg_widgets` module first.

## Core Concept: WidgetTree

Every WidgetBlueprint has a `WidgetTree` that owns all child widgets. The workflow is always:

1. **Get the WidgetTree** from the WidgetBlueprint asset
2. **Construct widgets** — use the WidgetTree's construct method (never regular constructors). Each widget needs a unique name within the tree.
3. **Set the root widget** — required before anything else. Usually a CanvasPanel for absolute positioning, or a layout panel (VerticalBox, etc.) if the entire UI is flow-based.
4. **Add children to panels** — `panel.add_child(child)` returns a **slot** object for positioning
5. **Configure the slot** — anchors, size, position, alignment, padding (properties depend on which panel type owns the slot)
6. **Compile and save** the WidgetBlueprint when done

If unsure about exact method names, use `query_ue_api('WidgetTree')` to discover available methods.

## Panel Types and Their Slots

Each panel type produces a different slot type when you call `add_child()`. Discover slot properties via `query_ue_api` for the specific slot class.

| Panel | Slot Type | Layout Model |
|-------|-----------|-------------|
| CanvasPanel | CanvasPanelSlot | Absolute positioning — anchors, position, size |
| VerticalBox | VerticalBoxSlot | Top-to-bottom stacking — auto/fill sizing, padding |
| HorizontalBox | HorizontalBoxSlot | Left-to-right stacking — auto/fill sizing, padding |
| Overlay | OverlaySlot | Z-ordered stacking — alignment controls |
| GridPanel | GridPanelSlot | Row/column grid layout |
| SizeBox | (single child) | Wraps one child with size overrides (width, height) |
| Border | (single child) | Wraps one child with background brush + padding |
| ScaleBox | (single child) | Wraps one child with scaling rules |

**To discover slot properties:** use `query_ue_api` on the slot class name (e.g., search for "CanvasPanelSlot" properties). You can also use `dir()` on the slot object filtering for "set" methods.

**Single-child panels** (SizeBox, Border, ScaleBox) accept only ONE child via `add_child()`.

## Layout Pattern: CanvasPanel Root (Absolute Positioning)

Most HUD widgets use a CanvasPanel as the root. Children are placed at absolute positions using anchors:

1. Create a CanvasPanel and set it as the WidgetTree root
2. Create child widgets (images, text blocks, progress bars, etc.) via the WidgetTree's construct method
3. Add each child to the CanvasPanel — the returned slot is a CanvasPanelSlot
4. On the CanvasPanelSlot, configure:
   - **Anchors** — where the widget attaches (see Anchor Reference below)
   - **Position** — offset from the anchor point (when using point anchors)
   - **Size** — explicit width/height (when using point anchors)
   - **Alignment** — pivot point for the widget (0,0 = top-left, 0.5,0.5 = center)
   - **Z-Order** — stacking order for overlapping widgets

## Layout Pattern: Linear Stacking (VerticalBox / HorizontalBox)

For menus, lists, or any sequential layout:

1. Create a CanvasPanel root (for screen-level anchoring), then place a SizeBox inside it to constrain dimensions
2. Create a VerticalBox or HorizontalBox inside the SizeBox
3. Add children to the box — each returned slot controls sizing behavior:
   - **Auto size** — widget uses its natural/desired size
   - **Fill size** — widget fills remaining space; the value acts as fill weight (1.0 = equal share among siblings)
4. Set horizontal/vertical alignment and padding on each slot

**Typical menu structure:** CanvasPanel root → SizeBox (centered via anchors + alignment) → VerticalBox → buttons/text blocks as children.

## Layout Pattern: Overlay (Stacked Layers)

For dialog boxes, loading screens, or any "content over background" layout:

1. Create an Overlay widget and anchor it to fill the parent (stretch anchors with zero offsets)
2. First child = background layer (e.g., a dimming Image with reduced opacity)
3. Subsequent children = foreground content (e.g., a SizeBox with dialog content, centered via alignment)
4. Each OverlaySlot has horizontal and vertical alignment — use these to position layers relative to the overlay bounds

## Anchor Reference

Anchors define how a widget attaches to its parent CanvasPanel. An anchor has a minimum and maximum point (both are 2D vectors with values 0.0–1.0). To discover anchor/slot struct construction, use `query_ue_api('Anchors CanvasPanel slot')`. For vector construction, use `query_ue_api('FVector2D')`.

| Layout | Minimum | Maximum | Description |
|--------|---------|---------|-------------|
| Top-Left | (0,0) | (0,0) | Fixed position from top-left |
| Top-Right | (1,0) | (1,0) | Fixed position from top-right |
| Bottom-Left | (0,1) | (0,1) | Fixed from bottom-left |
| Bottom-Right | (1,1) | (1,1) | Fixed from bottom-right |
| Center | (0.5,0.5) | (0.5,0.5) | Fixed at center |
| Top-Stretch | (0,0) | (1,0) | Horizontal stretch at top |
| Left-Stretch | (0,0) | (0,1) | Vertical stretch at left |
| Full-Stretch | (0,0) | (1,1) | Fill entire parent (use offsets, not position/size) |

**Key rule:** When min == max (point anchor), use position and size to place the widget. When min != max (stretch anchor), use offsets (left, top, right, bottom margins) instead — position/size don't apply.

## Alignment (Pivot Point)

Alignment controls the widget's pivot point: (0,0) = top-left, (0.5,0.5) = center, (1,1) = bottom-right.

To center a widget at a point anchor: set alignment to (0.5, 0.5) and position to (0, 0) with the anchor at (0.5, 0.5).

## Size Rules (for VBox/HBox Slots)

Box slots use a size rule with two modes:
- **Auto** — the widget uses its desired/natural size (the value is ignored)
- **Fill** — the widget fills remaining space; the value is a weight (1.0 = equal share, 2.0 = double share)

Discover the exact property names and enum values via `query_ue_api('VerticalBoxSlot')` or `query_ue_api('HorizontalBoxSlot')` for the relevant slot class.

## Margin / Padding

Margins use four values: left, top, right, bottom (in pixels). A single value applies uniformly to all sides. To discover margin struct construction, use `query_ue_api('FMargin')`.

Padding is set on **slots**, not on widgets directly. Each slot type exposes a padding property — discover it via `query_ue_api('CanvasPanelSlot')` (or the relevant slot class name).

## Slot Casting

`panel.add_child(widget)` returns the base PanelSlot type. In most cases Python auto-resolves the correct slot subclass (UE 5.4+). If you need specific slot methods, cast the slot to the panel's slot type. Use `dir()` on the slot to verify available methods.

## Modifying Existing Widgets

To modify widgets in an existing WidgetBlueprint:
1. Load the WidgetBlueprint asset
2. Access its WidgetTree
3. Find the widget by name using the WidgetTree's find method
4. Modify properties via `set_editor_property()` or direct attribute access
5. Compile and save

To inspect the tree, get the root widget and walk children, or list all widgets. Print widget names and classes to understand the structure.

## Runtime API Discovery

When unsure about exact property names, method signatures, or available slot types:

- **Use `query_ue_api`** with a specific keyword — e.g., `query_ue_api('CanvasPanelSlot')`, `query_ue_api('Anchors CanvasPanel slot')`, `query_ue_api('FVector2D')`, `query_ue_api('FMargin')`, `query_ue_api('OverlaySlot')`.
- **Use `get_editor_property()` / `set_editor_property()`** as a fallback if direct Python attribute access fails for a property.
- **Use `find_class()`** to verify a widget class exists before trying to use it.

## CRITICAL RULES

- **NEVER call `open_editor_for_asset()`** — crashes the editor in automated context. All widget layout is done via the WidgetTree API.
- ALWAYS set the root widget before adding children — without a root, the widget blueprint is empty.
- ALWAYS compile and save the WidgetBlueprint after modifying the WidgetTree.
- Use the WidgetTree's construct method for ALL widget creation — never instantiate widget classes directly.
- Widget names must be unique within the tree.
- Single-child panels (SizeBox, Border, ScaleBox) accept only ONE child.
- When anchors stretch (min != max), use offsets — NOT position/size.
- If a property or method doesn't work, use `query_ue_api` with the class name (e.g., `query_ue_api('CanvasPanelSlot')`) to discover the correct API.
- Print layout results to confirm success — silent failures are common in UMG scripting.
