GUI Scripting: TDM vs Doom 3, Quake 4

From The DarkMod Wiki
Jump to navigationJump to search

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:

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 Differences
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


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


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

HMart recalls:

  • 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";

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.


Ends the game. In multiplayer Doom 3, causes disconnect. Unused in TDM.


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.


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.


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.