-
Notifications
You must be signed in to change notification settings - Fork 113
database
title: Database, Links and Expressions description: The interface database, reactive elements and the interface expression language published: true editor: markdown
The interface database is the reactive state store of the UI: a tree of named 64-bit values. Widgets bind to leaves, sliders and pickers write them, <link> elements watch them and push computed results into element properties. Most "logic" in a NeL interface is this triangle, with no code involved.

- Paths are colon-separated:
UI:TEMP:SLIDERH,SERVER:USER:HP. Nodes are created on demand. - A leaf stores one sint64. Everything else is a view of those bits: booleans, RGBA packed as
R | G<<8 | B<<16 | A<<24, doubles bit-cast. Expressions read leaves as integers, so don't@-read a double-typed leaf. - The root branches are conventions, not magic:
UI:is interface state (UI:SAVE:the persisted part), and in the clientSERVER:is the network-synchronized tree andLOCAL:the prediction layer. Writes toSERVER:/LOCAL:from interface data are refused hard (both by thesethandler and@link targets).
Declare and seed your state with <variable>:
<variable entry="UI:TEMP:SLIDERH" type="sint32" value="220" />A fresh database is all zeros. Values nothing declared read 0, and several engine bindings are alpha values, so the classic failure is a fully transparent interface: declare
UI:SAVE:CONTENT_ALPHA,UI:SAVE:CONTAINER_ALPHA(255) and friends in your config XML. The*_ROLLOVER_FACTORentries are inverted: 255 = no fade when the mouse is elsewhere, 0 = invisible. {.is-warning}
Widgets that display leaves directly (text_number, bar, …) poll with a change cache; they're cheap and always current. Two-way widgets (scroll sliders, colpick, combo_box, select_number) write leaves and follow external writes.
<link expr="gt(@UI:TEMP:SLIDERH, 200)"
target="ui:sample:sliders:content:warn:active" />A <link> evaluates expr whenever any database leaf it reads changes, and writes the result to its targets. Attributes:
| attribute | meaning |
|---|---|
expr |
the expression; its @ reads define the trigger set |
target |
comma-separated targets: an element property (path:property, where the last segment is the reflected property, e.g. :active, :w, :color), or @db:path to write a database leaf |
action / params
|
an action handler to run on trigger (instead of or besides targets) |
cond |
expression gating the action |
Target paths resolve relative to the enclosing group first, then as absolute ids. Writable properties are the reflected properties, the same set Lua sees: active, x, y, w, h, color, hardtext, texture, and per-widget extras.
Links evaluate lazily: a leaf change only marks the link; evaluation happens on the widget manager's observer flush each frame. Two embedding-level requirements make this pipeline run at all: a link updater instance and one updateAllLinks() after parsing. If links only fire at startup and never again, read Embedding.
addOnDbChange is the Lua-side equivalent (run a script when leaves change); see Lua scripting.
Interface expressions appear in <link expr>, cond= attributes, the set handler's value=, <define value_from_code>, and menu/proc conditions.
The grammar is minimal: there are no infix operators; everything is a function call.
add(mul(@UI:TEMP:A, 2), 1) arithmetic
eq(@UI:TEMP:MODE, 3) comparison
ifthenelse(cond, a, b) selection
'a string' single quotes only, C escapes
@UI:PATH:LEAF database read (and trigger registration)
@UI:VAL[UI:INDEX] indirection: value of UI:INDEX spliced into the path
Literals: integers, decimals (float precision), true/false, 'strings'. Function names are case-sensitive. %name inside an expression attribute is define substitution, resolved before the expression parser runs.
Arithmetic and logic: add, sub, mul, div, mod, abs, min, max, eq, ne, lt, le, gt, ge, and, or, not, ifthenelse(cond,a[,b]), switch(index,v0,v1,…), int (force integer), identity, rand([lo,hi]), ilinear(i,start,end).
Bits: band, bor, bxor, bnot, shl, shr, sal, sar, getbit, extSign8To64, extSign11To64.
Strings and colors: str(...) (concatenate), localize(id) (translation lookup), makeRGB(r,g,b[,a]), intToColor, getRed/getGreen/getBlue/getAlpha, secondsToTimeString/secondsToTimeStringShort.
Database and UI: getprop('ui:abs:path:prop') (read a reflected property; absolute ids only), oldvalue('UI:PATH') (a leaf's previous value), dbcount('UI:LIST:$:X') (count consecutive entries), depends(...) (evaluate args only to register triggers, i.e. subscribe a link to leaves it doesn't otherwise read).
The Ryzom client registers ~100 more game-side functions (item names, skill values, …) that are not available in a bare-library interface. Notably lua('...') and the lua: expression prefix are client extensions: in a standalone embedding they work only if the application registers a lua expression function alongside its lua action handler.
The set action handler is the workhorse counterpart to links: evaluate once, write now.
onclick_l="set" params_l="dblink=UI:TEMP:HELLO|value=add(@UI:TEMP:HELLO,1)"
onclick_l="set" params_l="target_property=ui:sample:views:active|value=not(getprop('ui:sample:views:active'))"value= is the expression; dblink= writes a leaf, target_property= a reflected property (relative targets resolve against the caller's window), target= an expression evaluating to a target name. See Action handlers.