# UI Fundamentals

***

Adding UI to your game requires writing code, but once you learn a few patterns you can build clean, scalable interfaces quickly. This guide walks you through a step-by-step tutorial that ends with a complete dialog example.

{% hint style="info" %}
All UI for a player must be drawn inside that player's `ao_late_update` call stack and wrapped with `is_local_or_server()`. This prevents UI from appearing for the wrong client.
{% endhint %}

At any time, you can jump to [UI Reference](/ui/ui-reference.md) for more patterns and deeper details.

### Step 1: Create a UI Entry Point

All interactive UI should be drawn from the local player's `ao_late_update`:

```csl
Player :: class : Player_Base {
    ao_late_update :: method(dt: float) {
        if this.is_local_or_server() {
            draw_ui(this);
        }
    }
}
```

### Step 2: Start From a Screen Rect

Screen UI should always be derived from `UI.get_safe_screen_rect()` or `UI.get_screen_rect()`. Remember: (0, 0) is the bottom-left and Y grows upward.

```csl
draw_ui :: proc(player: Player) {
    screen := UI.get_safe_screen_rect();

    // A simple centered panel
    panel := screen.center_rect().grow(120, 200, 120, 200);
    UI.quad(panel, core_globals.white_sprite, {0, 0, 0, 0.7});
}
```

### Step 3: Use Cut For Layout

When laying out multiple elements, cut space out of a rect instead of positioning everything from the same origin.

```csl
draw_panel_layout :: proc() {
    panel := UI.get_safe_screen_rect().center_rect().grow(140, 220, 140, 220);

    header := panel.cut_top(80);
    footer := panel.cut_bottom(70);
    body := panel;

    UI.quad(header, core_globals.white_sprite, {0.1, 0.1, 0.1, 0.8});
    UI.quad(body, core_globals.white_sprite, {0.05, 0.05, 0.05, 0.8});
    UI.quad(footer, core_globals.white_sprite, {0.1, 0.1, 0.1, 0.8});
}
```

### Step 4: Add Text

Use text settings to control size, color, and alignment.

```csl
draw_header_text :: proc(rect: Rect) {
    ts := UI.default_text_settings();
    ts.size = 52;
    ts.color = {1, 1, 1, 1};
    ts.halign = .CENTER;
    ts.valign = .CENTER;

    UI.text(rect, ts, "New Quest!");
}
```

### Step 5: Add Buttons

Buttons combine layout and interaction. Use a button sprite from the engine supplied assets (see [UI Reference](/ui/ui-reference.md) for more).

```csl
draw_button :: proc(rect: Rect) {
    bs := UI.default_button_settings();
    ts := UI.default_text_settings();

    bs.sprite = get_asset(Texture_Asset, "$AO/new/modal/buttons_2/button_2.png");
    bs.press_scaling = 0.35;

    if UI.button(rect, bs, ts, "Accept").clicked {
        log_info("Accepted!");
    }
}
```

### Step 6: Build a Dialog

Now combine all of the steps into a reusable dialog layout.

```csl
draw_dialog :: proc(title: string, body: string) {
    screen := UI.get_safe_screen_rect();
    dialog := screen.center_rect().grow(200, 300, 200, 300);

    UI.quad(dialog, core_globals.white_sprite, {0, 0, 0, 0.85});

    content := dialog.inset(30);
    header := content.cut_top(80);
    buttons := content.cut_bottom(90);
    body_rect := content;

    ts := UI.default_text_settings();
    ts.halign = .CENTER;
    ts.valign = .CENTER;

    ts.size = 52;
    UI.text(header, ts, title);

    ts.size = 36;
    UI.text(body_rect, ts, body);

    bs := UI.default_button_settings();
    bs.sprite = get_asset(Texture_Asset, "$AO/new/modal/buttons_2/button_2.png");
    bs.press_scaling = 0.35;

    left := buttons.cut_left(210);
    buttons.cut_left(20);
    right := buttons.cut_left(210);

    if UI.button(left, bs, ts, "Cancel").clicked {
        log_info("Cancelled");
    }
    if UI.button(right, bs, ts, "Confirm").clicked {
        log_info("Confirmed");
    }
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.allout.game/ui/fundamentals.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
