GUI Scripting: GUI:: Parameters

From The DarkMod Wiki
Revision as of 03:40, 6 July 2022 by Geep (talk | contribs) (→‎What and Why of GUI:: Parameters: soften comment about vectors)
Jump to navigationJump to search

This page is part of a series. See GUI Scripting Language for overview.

What and Why of GUI:: Parameters

"GUI:: Parameters" are different from standard GUI properties and GUI user variables. But just like user variables, you invent their names. They can easily take on float values (including representing boolean and integer values) or string values. Vector values such as color can be more problematic.

If you have an entity with both a .gui and .script, a GUI:: Parameter provides a channel to pass a value in either direction. This will be potentially "instantaneous", in that values could be re-evaluated on every frame. In the GUI file, the GUI:: Parameter is always prefixed with "gui::". That prefix is NOT used in the .script file.

The Magic Prefix "Gui_Parm"

If you have an entity with:

  • a "gui" spawnarg of valid value, and
  • one or more spawnargs with name prefix "gui_parm".

then when the entity and its GUI are spawned, gui:: parameters with the gui_parm names will be created and initialized from the spawnargs values, and can be used immediately in the GUI. The usual naming convention is "gui_parm" alone or followed by a digit, but any suffix string will do.

This is most useful for entities that don't need a .script file. If the overlay is created (or replaced) in a script, then spawnargs will NOT be consulted for gui:: parameter creation and initialization. Also, if an updatable spawnarg value is so updated by a script, that change is not automatically propagated to the gui:: parameter. However, in both those cases, script code can be written as needed to get the spawnarg value and send it to the gui:: parameter, as indicated next.

Important Use: Spawnarg -> .Script -> .Gui

Except for the magic prefix initialization, a .gui attached to an entity cannot read or access the entity’s spawnargs directly. Instead, a .script function acts as the intermediary. The usual dance is:

  • The mapper sets a key/value spawnarg on the entity (with key and default value often predefined in an entityDef).
  • An attached script (say, specified in a "scriptobject" spawnarg) fetches the spawnarg value, with:
    • GetKey(spawnarg_name); // gets value in string form
    • GetIntKey(spawnarg_name);
    • GetFloatKey(spawnarg_name);
  • The script can then pass that on the GUI in a desired form, as discussed next.

As mentioned above, gui:: parameters do not involve or affect entity spawnargs (other than magic prefix initialization). Internally, gui:: parameters are stored in separate "dictionary" data structures. You create them by referencing them in your .gui and .script.

In a GUI File – Syntax and Use

In the GUI file, use a "gui::" prefix, followed by a name, all in double quotes. A gui:: parameter can appear multiple times within a file and at any level of "guiDef" nesting.

Bound In a Property List

A gui:: parameter can be "bound" to a standard float property (not a user variable or vector). For example, in the property list of a "windowDef SignText":

text	"gui::gui_parm1"

Another string example, from the mainmenu_briefing.gui:

background	"gui::BriefingVideoMaterial"

For a more dynamic use, see GUI Scripting: On Entity’s Surface, where it is important that the boolean value of the bound property...

visible "gui::is_visible"

... is automatically re-evaluated every frame.

In Event Block’s Set Command

Usages are either sources or sinks for "set" commands (involving floats, not vectors).

Consider this readable example. In one of the onTime handlers, strings are copied from two gui:: parameters to the text property of the two other windowDefs named "title" and "body":

set "title::text" "$gui::title";
set "body::text" "$gui::body";

As usual with "set", a "$" on the source indicates that the value is to be copied, not a literal string such as "gui::title". See the example at this article’s end for more.

In Event Block’s "If" Statement

A gui:: parameter can be tested in a "if" conditional clauses. For example, when a readable fades out its background, it uses an onTime event handler containing:

if ("gui::numPages" > 1) {
  transition "backgroundmulti::matcolor" "1 1 1 1" "1 1 1 0" READABLE_FADE_TIME;
}
if ("gui::numPages" == 1) {
  transition "backgroundsingle::matcolor" "1 1 1 1" "1 1 1 0" READABLE_FADE_TIME;
}

In a SCRIPT File – Syntax, and Available Functions for GUI:: Parameters

In the body of a SCRIPT function, use a double-quoted parameter name that matches that in the GUI file, but without the "gui::" prefix. Pass that name in a SetGui… or GetGui… function call whose type (bool, int, string) matches the usage in the GUI file. You must specify a handle with these functions, as discussed in GUI Scripting: Handles.

GetGui… Functions

Each of these functions returns the value of the GUI:: Parameter given by "key":

  • getGuiFloat(float handle, string key); // returns a float
  • getGuiInt(float handle, string key); // returns a float with int value
  • getGuiString(float handle, string key); // returns a string

Don’t confuse that last one with this function:

  • getGui(float handle); // returns a string with the file currently loaded by the GUI.

SetGui… Functions

Similarly:

  • setGuiFloat(float handle, string key, float val);
  • setGuiInt(float handle, string key, float val);
  • setGuiString(float handle, string key, string val);

There is a 127 character size limit on script strings that can impede that last function. An alternative function gets around that, by copying a string value directly from an entity spawnarg to a gui:: parameter:

  • setGuiStringFromKey(float handle, string key, entity src, string srcKey);

So, for example, in the body of a script object function, it would typically take the form:

$player1.setGuiStringFromKey(myhandle, "myGuiParamName", self, "mySpawnArgName");

An Example: Number Wheel

TDM number wheels are used for combination locks. A typical lock has 3 wheels, each with edge digits 0 to 9. The gamer frobs a particular wheel to indicate interest in it, then uses mouse actions or keystrokes to rotate it.

Turning to the implementation, in tdm_numberwheel.script, a "numberwheel" script object is defined. Its main function body is called (via Stim/Response) when frobbed. In the function body, a custom overlay is first created (about which see GUI Scripting: Handles). Then the code enters an "eachFrame" loop to do processing, where it remains until the gamer frobs something else.

The overlay (instantiated from "guis/numberwheel_handler.gui" and shown next) catches the events raised by the standard player actions to go to previous or next thing (i.e., weapon, inventory item, or inventory group). It then uses those events to (also) manipulate the number wheel. Note that this overlay has no visual aspect:

windowDef Desktop {
  rect      0, 0, 640, 480
  nocursor 1

  onNamedEvent prevWeapon {
    set "gui::nextPos" "1";
  }

  onNamedEvent nextWeapon {
    set "gui::prevPos" "1";
  }

  onNamedEvent inventoryPrevItem {
    set "gui::nextPos" "1";
  }

  onNamedEvent inventoryNextItem {
    set "gui::prevPos" "1";
  }

  onNamedEvent inventoryPrevGroup {
    set "gui::nextPos" "1";
  }

  onNamedEvent inventoryNextGroup {
    set "gui::prevPos" "1";
  }
}

Clearly, "prevPos" and "nextPos" are booleans, set to 1 when the user makes a request to go to the previous or next position on the number wheel. The .script then manages what digit is shown on the wheel. For gui:: parameters, the salient portions in the script are:

Did we get a request?

float prevPos = $player1.getGuiFloat(overlayHandle,"prevPos");
float nextPos = $player1.getGuiFloat(overlayHandle,"nextPos");

If so, process it and rotate the wheel (code not shown), then reset and wait for next request:

$player1.setGuiFloat(overlayHandle,"prevPos",0);
$player1.setGuiFloat(overlayHandle,"nextPos",0);

(There is a separate script that combines the values of each number wheel to determine if the lock should open. This is beyond the scope here.)

For More

GUI Scripting: Flashbomb Example also is relevant. In particular, it shows how to use a gui:: parameter to control color transitions, even though the GUI language parser will not accept a gui:: parameter embedded into a color vector.