GUI Scripting: TDM vs Doom 3, Quake 4
This page is part of a series. See GUI Scripting Language for overview.
TDM's GUI scripting usage has evolved from the original open-sourced idTech 4 engine and Doom 3. It is thus quite similar but not identical to Doom 3, as well as Quake 4 or other id-family games. This may need to be kept if mind if you are using a tutorial or GUI editing tool for these other games.
GUI Evolution within TDM
Doom GUI scripting has historically been buggy and programmer-hostile, but seen as very complex to fix, so relatively unaddressed by TDM until recently. TDM has of course changed over the years, and a search of the bugtracker using text-search "GUI" and Resolution=fixed shows hundreds of hits, within the "GUI" Category and others. But almost all of these involve GUI design or implementation aspects unrelated to GUI scripting.
So TDM-version-specific indications will be restricted to stgatilov's major GUI scripting refresh for TDM 2.11. Specific improvements are noted in context throughout this series, but for even more, see these reports:
- 0005869: Better diagnostic for syntax errors in GUI code. Many parsing problems now are reported to the console for the first time!
- 0006026: Wrong order of evaluation in expressions
- 0006028: GUI: support expressions on right side of Set command
Nomenclature Differences Among Tutorial Sources
The rather odd naming of GUI elements by id Software in Ref 1, reflecting class names in the engine .cpp code, was not a big hit with subsequent documentation authors, who chose other nomenclatures:
Nomenclature Used Here | Ref 1. Making Doom 3 Mods: GUIS | Ref 2. GUI scripting [Note 1] | Ref 3. GUIEditor (Quake 4 version) |
---|---|---|---|
GuiDef (Type, Name) | Window {Type, Name} | Item {Type, Name} | Def {Type, Name} |
Property (Type, Name, Value) | Either Window Register or Window Variable. [Note 2] Both with {Type, Variable, Value} | Property {Type, Name, Value} | Def Flag |
User Variable | User Variable {DefineType Command, Variable, Value} | Variable {Type, Name, Value} | Float Variable & Definevec4 (aka Vec4) Variable {Name, Value} |
GUI:: Parameter | ??? | GUI Variable aka GUI Parameter | GUI Variable |
Event Handler {Parameter} | Event Handler {Parameter} | Event Type {Parameter} | Item Scripts (multiple) |
Event Block (body of Event Handler) | ??? | Event Block | (script code; free text) |
Event Handler Command | Script Command | GUI Command or Command Statement | (script code; free text) |
Set “cmd” Command | ??? | Engine or Game GUI Command | (script code; free text) |
[Note 1] This nomenclature is what's generally used in the "Quake 4 editguis" editor, including the version included with Doom 3.
[Note 2] Window Registers can be changed with 'set' or 'transition'. Window Variables cannot, so constant.
"Window Types" are analogous to Microsoft Dialog Controls. The id nomenclature reflects the C++ code; thus .h and .cpp files with names like Windows and WinVar (and references to Registers) comprise part of the implementation. Also important are OverlaySys, UserInterface, and the system to post and dispatch events.
"Flags" as a category name in Ref 3 is no doubt due to a number of the boolean Properties being represented as bits within the "flags" variable of Windows.h/cpp, seen below. Additional bits (shown as "--") have no explicit Property representation.
guiDef Property ..h/.cpp bit within "flags" -- WIN_CHILD = 0x00000001; -- WIN_CAPTION = 0x00000002; -- WIN_BORDER = 0x00000004; -- WIN_SIZABLE = 0x00000008; -- WIN_MOVABLE = 0x00000010; -- WIN_FOCUS = 0x00000020; -- WIN_CAPTURE = 0x00000040; hcenter WIN_HCENTER = 0x00000080; [missing:vcenter] WIN_VCENTER = 0x00000100; modal WIN_MODAL = 0x00000200; -- WIN_INTRANSITION = 0x00000400; -- WIN_CANFOCUS = 0x00000800; -- WIN_SELECTED = 0x00001000; -- WIN_TRANSFORM = 0x00002000; -- WIN_HOLDCAPTURE = 0x00004000; nowrap WIN_NOWRAP = 0x00008000; noclip WIN_NOCLIP = 0x00010000; invertrect WIN_INVERTRECT = 0x00020000; naturalmatscale WIN_NATURALMAT = 0x00040000; nocursor WIN_NOCURSOR = 0x00080000; menugui WIN_MENUGUI = 0x00100000; -- WIN_ACTIVE = 0x00200000; showcoords WIN_SHOWCOORDS = 0x00400000; showtime WIN_SHOWTIME = 0x00800000; wantenter WIN_WANTENTER = 0x01000000; forcescreenaspect WIN_SCREENASPECT = 0x02000000; -- WIN_DESKTOP = 0x10000000;
Usage Differences
This analysis is based on a "reasonable effort"; it should not be taken as definitive or complete.
In-Game Active Surfaces
Doom 3 has interactive GUIs to show a 2D mouse cursor on an in-game 2D surface, e.g., an in-game computer screen, with active buttons and text input areas. There were stock models designed for this (e.g., flatmonitor.lwo).
This purpose is far less important for TDM, due to its different historical period. And TDM has other ways to provide in-world buttons, either flat (e.g., simple frobbable surface) or 3D. Consequently, the SDK code to support this form of interactive GUI was removed in TDM, as unlikely to be useful and complicating frob highlighting. See post by ishvan (Ref 11).
Still, TDM uses GUIs applied to in-game surfaces for some purposes, e.g., readables or custom video effects. Anf for full-screen overlays, supports the mouse cursor.
guiDef Types
Fully Supported in TDM, Doom 3, Quake 4
bindDef, choiceDef, editDef, listDef, renderDef, sliderDef, windowDef
Types for which Support Varies
Key:
Y = Supported, used
N = Probably or definitely no code for this
n = Some leftover C++ code for this, but probably either skips over or breaks
guiDef TDM Doom 3 Quake 4 animationDef n n N fieldDef n n N gameBearShootDef N Y N gameBustOutDef N Y N gameSSDDef N Y N graphDef N N Y htmlDef N N Y markerDef n n N popupDef N N Y
Chief source for Doom 3: Ref 9
Chief source for Quake 4: Ref 3
Properties
Fonts in GUI Text
TDM fonts are entirely different from Doom 3 and other id fonts (presumably for legal and licensing reasons). See Fonts_Screenshots for TDM choices.
Shortcut to Components of Vectors such as Colors
For 4Vect properties (e.g., RGBA properties like backcolor, bordercolor, matcolor, forecolor), individual R, G, B, Alpha values can be referenced by notation like backcolor_x, backcolor_y, backcolor_z, backcolor_w. This is available in Quake 4, as described in Ref 3, but not in Doom 3 or TDM (Ref 10; 2020).
In TDM 2.11, access to components has been added using [0] ... [3] notation, but only in certain contexts.
Properties Specific to ListDefs
TDM has a number of Properties for handling icons in listDefs. These may be TDM exhancements, since they are not mentioned for Doom 3 in Ref 1.
Also, Ref 3 claims that for Quake 4, there is this property:
Scrollbar bool
that indicates if the listDef’s scrollbars are enabled. Default: 0 (false).
However, this conflicts with sliderDef's meaning of "scrollbar" from the same source; nor does Ref 1 mention it for Doom 3. Probably just a documentation mistake.
Other Properties Specific to Quake 4
From Ref 3:
descriptions string Sets the text to be displayed alongside each choice in a popupDef. Descriptions are separated by semicolons.
dpadgui bool When set to 1 on a world GUI, this marks it as having navigable elements via the D-pad.
User Variables
- In the old Doom3World forum, an idSoftware dev said that the "definefloat" keyword came early, during script and gui language development. Later they added "float", doing the same thing. Because many in-world GUI's were already made with the older keyword, it was kept for expedience.
- Why did id Software not add "vec4" to similarly supplement "definevec4"? A mystery. Quake4 removed definefloat (or at least didn't discuss it in their wiki). In QuakeWars, "definefloat" and "definevec4" were removed entirely, in favor of "float" and "vec4", plus "vec2" and "vec3".
Event Handlers
onTime time
Then you have a sequence of onTime event handlers inside a guiDef, Quake 4, but not TDM or Doom 3, allows time in milliseconds to be specified relative to that of the preceding onTime, with a plus-sign prefix. Example syntax:
onTime +100 {
Event Handler Commands
Commands for which Parsing Code Exists in TDM
As of 2.10 in GuiScript.cpp. But not necessarily functional! Commands seemingly not pertinent to TDM are in parentheses. See discussion about individual commands further below.
- resetCinematics;
- resetTime [guiDef_name] time;
- set parameters;
- setFocus bool;
- showCursor bool;
- transition 4-6 parameters;
- (endGame;)
- (evalRegs;)
- (localSound sound;)
- runScript function;
Also, there are additional parenthetical commands discussed below, that have no parsing code in TDM.
resetCinematics; – additional parameters?
Note: Prior to 2.11, TDM's code in GuiScript.cpp seems to show that this can take 2 optional parameters, but what are they? No use of additional parameters was seen in TDM, but maybe in Doom 3 or Quake 4? Speculatively:
resetCinematics [guiDef_name] [time]; // ???
In 2.11, those extra parameter slots were dropped.
resetTime [guiDef_name] time;
In some idTech4 documentation, time itself is also optional and assumed zero. TDM can crash if the time parameter is omitted. In 2.11, a warning is emitted if arguments are wrong.
(set "cmd" runscript function;)
Runs the specified function in the game script. Like "runScript function", this form is believed to be quietly parsed but ignored in TDM.
The RunScript page of Ref 2 – Doom 3 GUI Scripting indicates that this command was widely used in id Software's code.
set "cmd" command_keyword command_parameter;
In a GUI event block, this special form of the "set" statement issues a GUI command to the engine code. On a multiplayer game, it's to the local client. This distinction is of no importance to single-player TDM. Similarly, some calls to the engine code were forwarded to game code when those were separate code bases. They are merged in modern TDM, but internal call patterns can reflect this history. Also, in TDM, only the core developers, not mappers, can take direct advantage of this form. The evolving collection of cmd command keywords for TDM is now quite different than for Doom 3. For example [[GUI Scripting: References & Resources | Ref 10 - HMart 2020], in Doom 3, the main menu starts up a map automatically with a set "cmd" "startgame..." inside an onTime handler. The mapper could do this more generally, for example:
onTime 12000 // after 12 seconds { set "cmd" "startgame test.map"; }
whereas TDM has no startgame keyword. For more about what TDM supports, see GUI Scripting: Parsing of Set 'Cmd'.
transition 4-6 parameters
Often, transition statements have a pair of 4-value color vectors as their 2nd & 3rd parameters. As the discussion in Ref 10 indicates, each vector is traditionally represented by a double-quoted literal:
transition "matcolor" "1, 1, 1, 0" "1, 1, 1, 0.8" "300"
This was id Studio's preferred method, but using a definevec4 user variable was a possible alternative. In addition, TDM can #define colors for transitions. Unfortunately, due to syntax differences, for a particular color, it is not possible to create a single #define that would work with both properties and transitions; thus:
#define INACTIVE_COLOR 0,0,0,0.50 #define SINACTIVE_COLOR "0 0 0 0.50"
See GUI Scripting: Preprocessor Directives for further examples. (Possible future improvement: Changing TDM's parsing to let a transition also accept color vectors with commas.)
See also the discussion above about 4vect properties and _x, _y, _z, _w suffixes.
(endGame;)
Ends the game. In multiplayer Doom 3, causes disconnect. Unused in TDM.
(evalRegs;)
Re-evaluates window registers (variables). [[GUI Scripting: References & Resources | Ref 1] says: should not be needed anymore in Doom 3. Unused in TDM core.
(localSound <sound>;)
Plays a sound given by a sound shader or a file path. Used in Doom 3, but not functional in TDM. If working with the main menu, consider alternatives like:
set "cmd" "play sound/meta/menu/mnu_select;";
Mappers can control sounds by other means, e.g., with .script files.
(runScript function;)
Runs the specified function in the game script. Believed to be quietly parsed but ignored in TDM. According to [[GUI Scripting: References & Resources | HMart (Ref 10)], the function can be specified either of two ways:
- As the name of a particular function in a map script:
runScript "map_name::functionName";
- As the name of a placeholder spawnarg (like gui::gui_parm6) on the attached entity, that has the function name, e.g.:
runScript "gui::gui_parm6";
The RunScript page of Ref 2 indicates that runScript could be used by mappers in Doom 3. This would seem to be confirmed by the line
RunScript "gui::gui_parm"
seen in a GUI of Ref 8's Doom 3-style test project. However, Ref 1 reported "runScript" as unused in Doom 3; maybe just unused by id developers, who can use the "set 'cmd' runscript alternative?
In any case, as noted, TDM seems to quietly parse but otherwise ignore any effort to call a user .script function from a GUI. See also "set 'cmd' runscript function" above.
Resurrecting "runScript" is a possibility for TDM 2.12; See New features in GUI engine.
(namedEvent <eventName>;)
Available in Quake 4 but not Doom 3 or (to date) TDM (Ref 10 - HMart 2020). Within an event handler, a named event can be raised, which would then be handled elsewhere in the GUI, using an onNamedEvent handler of the same name.
HMart in 2019 (Ref 10) reported adding this functionality to a custom version of the idtech4 engine ("fhDoom") and suggested C++ code to add it to TDM.
Adding this capability has been proposed as a possibility for TDM 2.12; See New features in GUI engine.
(onInit;)
Quake 4 calls this when GUI is loaded. Doom3 and TDM would presumably use onActivate or onTime 0.
.Script Commands Related to GUIs
SetGuiParm Commands In Doom3, if an entity had multiple GUIs, the SetGui... commands in .script would broadcast values to all of them. If this was not wanted, the GUIs would have to be undesirably edited to make keynames unique. In TDM, the handle to a particular GUI (namely, 1, 2, or 3) is given, so the value propagation is individualized.
CVars
Suffice it to say, lots of differences here too, with plentiful new CVars added to TDM. For access to CVars by .gui and .script, see GUI Scripting: Getting System CVars.
The editGUIS Tool
The specialized "editGUIS" editor is [add ref to bugtracker] broken under TDM (probably since 2.0). Alternatives are discussed in GUI Scripting: Tools and GUI Scripting: EditGuis Editor.