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:
Create a subtab under one of the fixed top-level tabs.
Create a panel inside that subtab.
Add UI elements (checkboxes, keybinds, sliders, inputs, color pickers, lists, multi/single-select, buttons) to that panel.
Read/update values in your main() or on_frame() loop.
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 panelcheckbox_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:voidon_frame(intcb_index,intdata_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).
rgba – array<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.
// Both show "Player Name" on screen
p.add_input("##elem1_Player Name", "Alex");
p.add_input("##elem2_Player Name", "Alex");
auto inp = find_input(0, "Tab", "Panel", "Player Name");
panel_t p = st.add_panel("Players", false);
// These two will look identical to the user
p.add_slider_double("##p1_Speed", 0.0, 100.0, 50.0);
p.add_slider_double("##p2_Speed", 0.0, 100.0, 60.0);
// Without prefixes, the config system would conflict them
// With prefixes, each one saves/loads separately