GUI API

This page documents the AngelScript GUI API used to build and interact with the Perception.cx UI.

❗ All GUI types are owned and cleaned up by the engine. You never delete or free them from AngelScript.


Overview

Typical usage flow:

  1. Create a subtab under one of the fixed top-level tabs.

  2. Create a panel inside that subtab.

  3. Add UI elements (checkboxes, keybinds, sliders, inputs, color pickers, lists, multi/single-select, buttons) to that panel.

  4. Read/update values in your main() or on_frame() loop.

  5. Optionally, attach a callback to a button.

Example:

subtab_t st = create_subtab(0, "My Script");
if (!st.is_valid())
{
    log("[GUI] failed to create subtab");
    return -1;
}

panel_t p = st.add_panel("Main Panel", false); // false = large panel

checkbox_t cb = p.add_checkbox("Enable Feature", false);
slider_double_t dist = p.add_slider_double("Distance", "m", 100.0, 0.0, 500.0, 1.0);

// Each frame:
void on_frame(int cb_index, int data_index)
{
    bool enabled = cb.get();
    double d = dist.get();
    // ... use enabled + d ...
}

Subtabs & Panels

subtab_t

A subtab_t represents a subtab under one of the fixed top-level tabs.

Create

  • parent_tab: 0–(FIXED_TAB_COUNT-1) – which main tab to attach to.

  • name: label shown in the UI subtab bar.

Methods

  • add_panel – creates a new panel inside this subtab.

    • is_small = true → small panel layout; false → normal/large.

  • is_valid()true if the handle is non-null. Only needed for error-checking in main().

panel_t

Represents a panel inside a subtab. All other UI elements are added to a panel.

You don’t manually free panels; they’re destroyed when the owning subtab is destroyed (usually when the script unloads).


Checkbox

Create

  • name: label.

  • initial: initial on/off state.

  • draw_title: whether to render the title text.

  • find_protect: if true, protects the element from naive find/replace patterns (internal anti-scan behavior).

  • draw_just_label: When enabled, the checkbox is non-interactive and functions purely as a label. This is useful when you only want to attach a color picker or keybind without toggle behavior.

❗ Design rule:

  • A checkbox can act as a parent for either:

    • up to two color pickers, or

    • up to two keybinds or

    • one colorpicker + one keybind

  • Color pickers / keybind must be added immediately after the checkbox on the panel.

Methods

Example:


Keybind

Keybinds let you bind a virtual-key and mode to a checkbox-controlled feature.

Create

  • Must appear right after its parent checkbox.

  • key: a Win32 virtual-key code (e.g. 0x2E for Delete, 0x2C for PrintScreen).

  • mode: "off", "on", "single", "toggle", or "always_on".

Methods

Example:


Color Picker

Color pickers store RGBA as 0–255 floats.

Create

  • Must follow a checkbox or keybind within that chain (according to your UI layout rules).

  • rgbaarray<float> of size 4: {R, G, B, A}, each in [0–255].

Methods

Example:


Sliders

Double slider

Methods

Example:

Int slider

Methods


Input Text Box

Example:


List

Lists are 2-column rows (info1, info2).

Create

Each dictionary is expected to have:

  • "info1" – string

  • "info2" – string

Methods

Example:


Multi-Select

A multi-select lets you toggle multiple options.

Create

Each dictionary in options should contain:

  • "label" – string

  • "selected" – bool (optional; defaults to false)

Methods

Example:


Single-Select

Single-select is a dropdown/radio list with a single active index.

Create

Methods

Example:


Buttons & Callbacks

Buttons are clickable UI elements with an AngelScript callback.

Funcdef

Create

  • cb is a function with signature void f().

Methods

Example

When you click the button in the UI, OnTestButton will be executed.


bool gui_active()

Checks if the gui is currently visible or not


Finding Existing Elements (find_*)

If your script needs to attach to UI created elsewhere (or from config), use the find_* helpers.

Each find_* searches by:

  • tab – top-level tab index (0..FIXED_TAB_COUNT-1)

  • subtab – subtab name (string)

  • panel – panel name(string)

  • name – element label (string)

  • element type (encoded in the function name)

Signatures

These return handle 0 if no element is found.

Example:

❗ Internally, find_* marks elements as "referenced" for cleanup when the script unloads. You don’t need (and must not try) to free them manually.


Config Helpers

These are global functions for saving/loading the UI configuration (all tabs, subtabs, elements).

  • construct_config() – builds a serialized config string of the current UI state.

  • apply_config(cfg) – applies a serialized config string.

Example:


Name Prefixing for Elements (##prefix_)

Multiple UI elements with the same visible name are supported, but the configuration system cannot uniquely identify them unless you explicitly assign a prefix.

The ##prefix_ syntax allows you to attach an internal unique ID to an element while keeping the visible label unchanged.


✔ What Prefixing Does

  • The part after ##prefox_ is the visible label shown in the UI and the rest is Unique ID.

  • Prefixing is optional, but required if you want your elements to save/load uniquely in configs.

  • find_ functions completely ignore the prefix* and search only by the visible label.


✔ Example

Both inputs look identical to the user, but internally:

  • Internal IDs: elem1_Player Name, elem2_Player Name

  • Visible name: Player Name

  • Config system will save/load each one correctly.


Behavior Summary

System / Functionality
Prefix Used?
Notes

UI Rendering

❌ No — prefix hidden

Only the text after ## is shown.

Internal ID / Config

✅ Yes — full prefixed name used

Required for unique config entries.

find_ API*

❌ No — prefix ignored

Searches only by visible name.

Duplicate visible names

✔ Allowed, even without prefix

But: config will not differentiate them unless prefixed.


⚠ Important Notes

1. Duplicate names without prefix

These work in the UI, but the configuration system will treat them as the same element, causing:

  • overwritten values

  • incorrect load order

  • mismatched element states

2. Duplicate names with prefix

These behave perfectly:

  • visible name is the same

  • internal ID is unique

  • config system saves & loads correctly

  • find_* still searches by visible name only

3. find_* and duplicates

Because find_* searches by visible name, if you have two labels both named "Player Name", then:

…it will always return the first one created, regardless of prefixes.


When Should You Use Prefixing?

Use ##prefix_ whenever:

  • You create multiple repeated UI blocks (e.g. per-player, per-item, per-weapon).

  • You have identical element names inside the same panel or subtab.

  • You want your configuration to properly remember each element’s value.


Quick Example

Last updated