GUI Scripting Language: Difference between revisions

From The DarkMod Wiki
Jump to navigationJump to search
Geep (talk | contribs)
add link
 
(61 intermediate revisions by 3 users not shown)
Line 1: Line 1:
[LOTS COMING SOON]
''Overview and hub of the "GUI Scripting" series by Geep, 2022''


[Links so far:]
''Comments to: [https://forums.thedarkmod.com/index.php?/topic/21642-feedback-on-wiki-gui-scripting-language-series/ Feedback on Wiki GUI Scripting Language Series].


[[GUI Scripting: Parsing of Set 'Cmd']]
==Introduction==
Inherited from Doom 3, TDM has a specialized GUI ("Graphical User Interface") layout language within .gui text files to define:
* Full-screen dialogs, such as menus
* Screen overlays, such as popup messages, HUD items and underwater murk.
* Active game-world surfaces like readables or custom video effects.


[[GUI Scripting: Tools]]
This language differs from that of .script files. It describes the visual appearance and (to some extent) behavior – including text display - of nested rectangular areas. For mappers, these areas can be manipulated through .script files. Beyond that, for menu developers interfacing to C++ code, it allows defining what MS Windows traditionally called "dialog controls", for selection from lists or multiple choices, setting values from sliders, and entry of text.


[[GUI Scripting: EditGuis Editor]]
==The Basics for Mappers==
===Need I Learn GUI Scripting?===
Often not! For the mapper, much can be accomplished without much GUI wrangling.
 
====FM Customizing Using Only #defines in a Standard GUI====
The TDM main menu hierarchy is set up to allow you to customize it without really knowing GUI scripting, just by commenting/uncommenting particular #defines. Such customizations include:
* Main menu background art or music
* Aspects of pre-mission briefing (text or video)
* Aspects of post-mission debriefing (text or video)
 
You do this by overriding the core "guis/mainmenu_custom_defs.gui" file with your own altered copy. See the comments in that file for details.
 
'''Note:''' If you create custom "menu music", a silent leadin in the sound shader can produce random audio issues. See '''[https://forums.thedarkmod.com/index.php?/topic/9082-newbie-darkradiant-questions/&do=findComment&comment=494383 thread]'''
 
====Deploying Stock GUIs or the Entities that Use Them====
For many things you want to do, there’s already a provided gui-using entity and/or stock or sample .gui files. For particular guidance, see:
* [[Briefing]] and [[Video Briefing]]
* [[Full-Screen Video Cutscenes]]
* [[A Full-Screen Slide in Mid-Game]]
* [[Subtitles]]
* [[Popup messages]]
* [[Readables]]
* [[Text Decals for Signs etc.]]
* [[Swimmable Water#Coloured, Murky Water]]
* [[Creating Automaps]]
* [[Xrays in GUIs]]
 
===Tools & Tricks for GUI Scripting===
Occasionally, you may need to craft a .gui from scratch, or as a novel customization. You can do this in a text editor, but be aware that the .gui language is quirky, and the existing parsing system unhelpful in detecting errors.
====Names & Case Sensitivity====
* [[GUI Scripting: Names & Case Sensitivity]]. A gloss on when keywords and other names of things in the GUI are case-sensitive or insensitive, and related naming conventions and styles. Case issues can cause parser fails!
====Syntax, Semantics, & Usage====
* [[GUI Scripting: Syntax, Semantics, & Usage]]. A comprehensive list of "rules of thumb", with some highlighted, to help cope with the "syntax from hell".
====Tools====
* [[GUI Scripting: Tools]]. How to edit and test GUIs. Because GUI scripts are in separate files (with the .gui extension), they can be developed independently from the rest of the game code. A change in a GUI does not require a DMAP (unless an associated entity changes). Furthermore, GUI scripts can be reloaded on real time, which makes for easy debugging and testing.
====Debugging====
* [[GUI Scripting: Debugging]]. Ways to display or log info during GUI activity.
 
===A Basic "windowDef" Template===
''With nomenclature used in this series.''
 
Every .gui file (unless designed just to be #included) must have a top-level "windowDef" structure, typically named "Desktop". Nested within, there may be more windowDefs (and other members of the "guiDef" family described further below), each with a locally-unique <name>. The basic template outline, with the terminology used in this series, is:
windowDef <Name> {
<Property List>
<User Variable List>
<Nested Child windowDefs or other guiDefs>
<Event Handlers>
}
 
Nesting of child guiDefs can be as deep as you need.
====Property List====
This is zero or more "Properies", by convention each on its own line. A Property has a predefined name, type (Boolean, float, vec2, vec4, string) and default value. If a property is not listed, it still exists, with its default value.
* [[GUI Scripting: Properties in Common]] to all guiDefs, and the only properties of windowDefs.
 
====User Variable List====
This is zero or more "User Variables", by convention each on its own line. Unlike Properties, a User Variable is not predefined. This is a float typically used as a bool. It has a default value of 0; as of TDM 2.11, you can specify a non-zero initial value too.
* [[GUI Scripting: User Variables]], likewise applicable to all guiDefs.
 
====Event Handlers====
An "Event Handler" catches user actions, .script requests, or elapsed time occurrences, and has general syntax:
<onHandler> [handler_param] {
  <If-Statements> and <GUI Script Commands>
}
 
The two most widely used event handlers are:
* '''onTime''' ''time'' - fires when ''time'' in milliseconds is reached, for the specific guiDef’s timer.
* '''onNamedEvent''' ''event'' - Catches a custom event, generated by your entity’s script function (e.g., in a script object). Or catches an engine-generated event. See [[GUI Scripting: Named Events]].
 
For a full list, with syntax and usage examples, see [[GUI Scripting: Event Handlers]].
 
====If Statements====
Within the body of an Event Handler, if-clauses read or compare properties and user variables, then alter program flow accordingly. Basic syntax is:
* '''if''' (''condition'') {...} '''else if''' (''another_condition'') {...} '''else''' {...}
 
For details, see [[GUI Scripting: If Statements]]
 
====GUI Script Commands====
In the body of an Event Handler, including within arms of if-clauses, GUI script commands read and change properties, user variables, GUI: parameters, and timer functions. Most widely used are:
* '''set''' ''variable'' ''value_or_source'';
* '''transition''' ''property'' ''start_value'' ''end_value'' ''time_duration'' [''accel'' ''decel''];
* '''resetTime''' ''time'';
For a full list, with syntax and usage examples, see [[GUI Scripting: Commands]].
 
====Evaluating Expressions - Special Rules====
The GUI scripting language differs from most scripting languages, regarding when expressions are evaluated and how values of properties and user variables can change. These rules affect:
* auto-updating of a property, due to deactivation by "set" and "transition".
* "early evaluation" of expressions within event handlers, impacting how if-statements can be written.
 
For more, see [[GUI Scripting: Evaluating Expressions & Variables]]
 
===Data Passing & Manipulation===
====Scope of Properties and User Variables====
Unlike some other languages, properties and user variables in one guiDef (e.g., a parent) are not immediately visible to another (e.g., a child). Instead, to access the property or variable of a different guiDef, use that guiDef name followed by "::" (two colons):
windowDef Desktop {
  visible 1
  ...
  windowDef Child1 {
      visible "Desktop::visible"
      ....
  }
}
====GUI:: Parameters====
* [[GUI Scripting: GUI:: Parameters]]. These are used to pass data values between an entity's .gui (where a "gui::" prefix must be used) and .script. In addition, they provide ways to get values of an entity's spawnargs into its GUI. In particular, spawnargs with a "gui_parm" prefix are available to a GUI at entity spawn.
====Handles====
* [[GUI Scripting: Handles]]. Inside an entity's script function, a handle is needed to access a particular GUI and its GUI:: parameters.
====GUI Overlays====
* [[GUI Overlays]]. This circa-2007 page hits highlights of interacting with existing or new overlays from your .script file, including using callGui(...) to call an overlay GUI's named event. See also [[GUI Scripting: Named Events]].
 
====Preprocessor Directives====
* [[GUI Scripting: Preprocessor Directives]]. As is common in C-style languages, #define can be used to give symbolic names to literal elements for static substitutions, including basic math expressions. Other directives are also surveyed.
 
===Examples===
The first two examples could serve as beginner tutorials.
 
* [[GUI Scripting: Mission Start Example]]. If you are new to GUI scripting, this example considers the rather simple GUI code of the familiar popup dialog that TDM shows on FM start. The commentary introduces how essential GUI elements are composed, and how timers and transitions create visual effects.
* [[GUI Scripting: Popup Message Example]]. Consider this a follow-on to the Mission Start example, covering more of what an FM author should know. It sketches how an entity, GUI, and script object collaborate to get results. That includes onNamedEvent handling and the use of GUI:: parameters for data passing. The entity is an abstract one, represented by a colored cube in-game.
 
Like the previous examples, the next three involve a "Desktop" overlay, associated with the player, that represents the real-estate of the full screen. But they also involve an in-world 3D entity.
 
* [[GUI Scripting: Flashbomb Example]]. A standard flashbomb thrown at an AI can momentarily blind it. But if not careful, the player can also be briefly blinded, to various degrees. This example reviews the GUI for that player blinding. The implementation uses a "gui" spawnarg to specify the GUI file and create its player-associated overlay. Then in the GUI, named events, and a GUI:: parameter about blinding, together manage a nest of "if...else" statements with the desired visual transitions.
* [[GUI Scripting: Number Wheel Example]]. TDM number wheels make up combination locks. You frob a particular wheel to indicate interest in it, then use certain mouse or key actions to rotate it. Those actions - noticed by the SDK and turned into standard named events - are detected in an overlay's onNamedEvent handlers, which forwards them to the awaiting script object via GUI:: parameters. The script object drives the wheel rotation and unlocking.
* [[GUI Scripting: Inventory Icon Example]]. The [[Inventory]] wiki article includes an example explaining how to make an inventory item (a skull) interact with a world object (a pedestal that if frobbed gets the skull placed atop it). Here, that example is extended, to color-pulse the skull's inventory icon, using a custom GUI and a generally-useful template for an inventory script object. More about GUI:: parameters too.
 
==GUIs on an In-World Entity Surface==
Rather than applied to a full-screen overlay, a custom GUIs can be applied - as an "Entity GUI" texture - to an in-world entity surface.
* [[GUI Scripting: On Entity's Surface]] explains the basics, plus some simple examples of transitions of colors or images on a surface.
* [[GUI Scripting: Limitations of On-Surface GUIs]] extends the discussion of what is and isn't possible.
* [[GUI Scripting: Sign Text Example]]. This considers a standard model-based wall plaque with an embedded "Entity GUI" surface. There's a stock entityDef that uses it, retrieving the sign text from an .xd file. The treatment here instead gets the sign text from a spawnarg, and centers the results.
* [[GUI Scripting: In-World Menu Examples]]. You can offer the player a choice of some option by presenting a menu on an in-world surface, such as a wall plaque (in this case, brush-based). Three different implementations ("Firepit", "Spiders", and "Fumes") are shown to emulate or deploy a choiceDef.
 
==More Advanced Topics==
Developers working on improvements to TDM core systems - the main menus, briefings, HUD, or entities with active surfaces - must be conversant with additional aspects of GUI scripting. Mappers too will want to understand such aspects if they are developing analogous but novel visual items.
 
===Main Menu Tool Tips===
Near the bottom of a guiDef for the main menu system, you may see something like:
toolTip("#str_menu_fov_tooltip")
See [[GUI Scripting:Tooltip Macro]] for more.
 
===Other "GuiDef" Types===
The term "guiDef" has been coined here to describe the main layout structure shown in the template above, but generalized beyond just windowDef. (Other tutorial authors use "Window", "Item", or "Def" for this; see [[GUI Scripting: TDM vs Doom 3, Quake 4]].)
 
Follow the links below for details about each type, including their additional Properties.
 
''Used throughout the core main menu hierarchy:''
====EditDef====
See [[GUI Scripting: EditDef]]  - text input, e.g., the name of a game save file, and for specifying certain video options.
====ChoiceDef====
See [[GUI Scripting: ChoiceDef]] – widely used for making choices among settings.
 
====SliderDef====
See [[GUI Scripting: SliderDef]] – widely used as a horizontal slider to control a setting value.
====ListDef====
See [[GUI Scripting: ListDef]] – provides a scrollable multi-column list control. Examples include mission downloads, mission select, and saved game select.
 
''Rarely used:''
====BindDef====
See [[GUI Scripting: BindDef]] – used just In the Controls submenu, to bind particular keys to particular functions.
====RenderDef====
See [[GUI Scripting: RenderDef]] – used to show a 3D model in an guiDef, typically an overlay. This is not a static snapshot or sprite, but an object that could be oriented, e.g., by code. In the game HUD, used for the compass playertool.
 
===Additional Event Handler Commands===
====Set 'Cmd'====
For a way for a main-menu GUI to invoke C++ engine functions, see [[GUI Scripting: Parsing of Set 'Cmd']].
====Fetching CVars====
See [[GUI Scripting: Getting System CVars]].
 
==Arcana==
===Formal Syntax Definition===
See [[GUI Scripting: BNF]].
===TDM vs Doom 3 or Quake 4===
For usage and nomenclature differences, see [[GUI Scripting: TDM vs Doom 3, Quake 4]].
===References and Resources===
For sources used in this series, including other early GUI scripting tutorials, see [[GUI Scripting: References & Resources]].
===The idTech4 Built-in EditGuis Editor===
See [[GUI Scripting: EditGuis Editor]]
 
{{GUI|name=GUI Scripting Language - START HERE}}

Latest revision as of 19:26, 7 May 2024

Overview and hub of the "GUI Scripting" series by Geep, 2022

Comments to: Feedback on Wiki GUI Scripting Language Series.

Introduction

Inherited from Doom 3, TDM has a specialized GUI ("Graphical User Interface") layout language within .gui text files to define:

  • Full-screen dialogs, such as menus
  • Screen overlays, such as popup messages, HUD items and underwater murk.
  • Active game-world surfaces like readables or custom video effects.

This language differs from that of .script files. It describes the visual appearance and (to some extent) behavior – including text display - of nested rectangular areas. For mappers, these areas can be manipulated through .script files. Beyond that, for menu developers interfacing to C++ code, it allows defining what MS Windows traditionally called "dialog controls", for selection from lists or multiple choices, setting values from sliders, and entry of text.

The Basics for Mappers

Need I Learn GUI Scripting?

Often not! For the mapper, much can be accomplished without much GUI wrangling.

FM Customizing Using Only #defines in a Standard GUI

The TDM main menu hierarchy is set up to allow you to customize it without really knowing GUI scripting, just by commenting/uncommenting particular #defines. Such customizations include:

  • Main menu background art or music
  • Aspects of pre-mission briefing (text or video)
  • Aspects of post-mission debriefing (text or video)

You do this by overriding the core "guis/mainmenu_custom_defs.gui" file with your own altered copy. See the comments in that file for details.

Note: If you create custom "menu music", a silent leadin in the sound shader can produce random audio issues. See thread

Deploying Stock GUIs or the Entities that Use Them

For many things you want to do, there’s already a provided gui-using entity and/or stock or sample .gui files. For particular guidance, see:

Tools & Tricks for GUI Scripting

Occasionally, you may need to craft a .gui from scratch, or as a novel customization. You can do this in a text editor, but be aware that the .gui language is quirky, and the existing parsing system unhelpful in detecting errors.

Names & Case Sensitivity

  • GUI Scripting: Names & Case Sensitivity. A gloss on when keywords and other names of things in the GUI are case-sensitive or insensitive, and related naming conventions and styles. Case issues can cause parser fails!

Syntax, Semantics, & Usage

Tools

  • GUI Scripting: Tools. How to edit and test GUIs. Because GUI scripts are in separate files (with the .gui extension), they can be developed independently from the rest of the game code. A change in a GUI does not require a DMAP (unless an associated entity changes). Furthermore, GUI scripts can be reloaded on real time, which makes for easy debugging and testing.

Debugging

A Basic "windowDef" Template

With nomenclature used in this series.

Every .gui file (unless designed just to be #included) must have a top-level "windowDef" structure, typically named "Desktop". Nested within, there may be more windowDefs (and other members of the "guiDef" family described further below), each with a locally-unique <name>. The basic template outline, with the terminology used in this series, is:

windowDef <Name> {
<Property List>
<User Variable List>

<Nested Child windowDefs or other guiDefs>

<Event Handlers>
}

Nesting of child guiDefs can be as deep as you need.

Property List

This is zero or more "Properies", by convention each on its own line. A Property has a predefined name, type (Boolean, float, vec2, vec4, string) and default value. If a property is not listed, it still exists, with its default value.

User Variable List

This is zero or more "User Variables", by convention each on its own line. Unlike Properties, a User Variable is not predefined. This is a float typically used as a bool. It has a default value of 0; as of TDM 2.11, you can specify a non-zero initial value too.

Event Handlers

An "Event Handler" catches user actions, .script requests, or elapsed time occurrences, and has general syntax:

<onHandler> [handler_param] {
  <If-Statements> and <GUI Script Commands>
}

The two most widely used event handlers are:

  • onTime time - fires when time in milliseconds is reached, for the specific guiDef’s timer.
  • onNamedEvent event - Catches a custom event, generated by your entity’s script function (e.g., in a script object). Or catches an engine-generated event. See GUI Scripting: Named Events.

For a full list, with syntax and usage examples, see GUI Scripting: Event Handlers.

If Statements

Within the body of an Event Handler, if-clauses read or compare properties and user variables, then alter program flow accordingly. Basic syntax is:

  • if (condition) {...} else if (another_condition) {...} else {...}

For details, see GUI Scripting: If Statements

GUI Script Commands

In the body of an Event Handler, including within arms of if-clauses, GUI script commands read and change properties, user variables, GUI: parameters, and timer functions. Most widely used are:

  • set variable value_or_source;
  • transition property start_value end_value time_duration [accel decel];
  • resetTime time;

For a full list, with syntax and usage examples, see GUI Scripting: Commands.

Evaluating Expressions - Special Rules

The GUI scripting language differs from most scripting languages, regarding when expressions are evaluated and how values of properties and user variables can change. These rules affect:

  • auto-updating of a property, due to deactivation by "set" and "transition".
  • "early evaluation" of expressions within event handlers, impacting how if-statements can be written.

For more, see GUI Scripting: Evaluating Expressions & Variables

Data Passing & Manipulation

Scope of Properties and User Variables

Unlike some other languages, properties and user variables in one guiDef (e.g., a parent) are not immediately visible to another (e.g., a child). Instead, to access the property or variable of a different guiDef, use that guiDef name followed by "::" (two colons):

windowDef Desktop {
  visible 1
  ...
  windowDef Child1 {
      visible "Desktop::visible"
      ....
  }
}

GUI:: Parameters

  • GUI Scripting: GUI:: Parameters. These are used to pass data values between an entity's .gui (where a "gui::" prefix must be used) and .script. In addition, they provide ways to get values of an entity's spawnargs into its GUI. In particular, spawnargs with a "gui_parm" prefix are available to a GUI at entity spawn.

Handles

  • GUI Scripting: Handles. Inside an entity's script function, a handle is needed to access a particular GUI and its GUI:: parameters.

GUI Overlays

  • GUI Overlays. This circa-2007 page hits highlights of interacting with existing or new overlays from your .script file, including using callGui(...) to call an overlay GUI's named event. See also GUI Scripting: Named Events.

Preprocessor Directives

  • GUI Scripting: Preprocessor Directives. As is common in C-style languages, #define can be used to give symbolic names to literal elements for static substitutions, including basic math expressions. Other directives are also surveyed.

Examples

The first two examples could serve as beginner tutorials.

  • GUI Scripting: Mission Start Example. If you are new to GUI scripting, this example considers the rather simple GUI code of the familiar popup dialog that TDM shows on FM start. The commentary introduces how essential GUI elements are composed, and how timers and transitions create visual effects.
  • GUI Scripting: Popup Message Example. Consider this a follow-on to the Mission Start example, covering more of what an FM author should know. It sketches how an entity, GUI, and script object collaborate to get results. That includes onNamedEvent handling and the use of GUI:: parameters for data passing. The entity is an abstract one, represented by a colored cube in-game.

Like the previous examples, the next three involve a "Desktop" overlay, associated with the player, that represents the real-estate of the full screen. But they also involve an in-world 3D entity.

  • GUI Scripting: Flashbomb Example. A standard flashbomb thrown at an AI can momentarily blind it. But if not careful, the player can also be briefly blinded, to various degrees. This example reviews the GUI for that player blinding. The implementation uses a "gui" spawnarg to specify the GUI file and create its player-associated overlay. Then in the GUI, named events, and a GUI:: parameter about blinding, together manage a nest of "if...else" statements with the desired visual transitions.
  • GUI Scripting: Number Wheel Example. TDM number wheels make up combination locks. You frob a particular wheel to indicate interest in it, then use certain mouse or key actions to rotate it. Those actions - noticed by the SDK and turned into standard named events - are detected in an overlay's onNamedEvent handlers, which forwards them to the awaiting script object via GUI:: parameters. The script object drives the wheel rotation and unlocking.
  • GUI Scripting: Inventory Icon Example. The Inventory wiki article includes an example explaining how to make an inventory item (a skull) interact with a world object (a pedestal that if frobbed gets the skull placed atop it). Here, that example is extended, to color-pulse the skull's inventory icon, using a custom GUI and a generally-useful template for an inventory script object. More about GUI:: parameters too.

GUIs on an In-World Entity Surface

Rather than applied to a full-screen overlay, a custom GUIs can be applied - as an "Entity GUI" texture - to an in-world entity surface.

  • GUI Scripting: On Entity's Surface explains the basics, plus some simple examples of transitions of colors or images on a surface.
  • GUI Scripting: Limitations of On-Surface GUIs extends the discussion of what is and isn't possible.
  • GUI Scripting: Sign Text Example. This considers a standard model-based wall plaque with an embedded "Entity GUI" surface. There's a stock entityDef that uses it, retrieving the sign text from an .xd file. The treatment here instead gets the sign text from a spawnarg, and centers the results.
  • GUI Scripting: In-World Menu Examples. You can offer the player a choice of some option by presenting a menu on an in-world surface, such as a wall plaque (in this case, brush-based). Three different implementations ("Firepit", "Spiders", and "Fumes") are shown to emulate or deploy a choiceDef.

More Advanced Topics

Developers working on improvements to TDM core systems - the main menus, briefings, HUD, or entities with active surfaces - must be conversant with additional aspects of GUI scripting. Mappers too will want to understand such aspects if they are developing analogous but novel visual items.

Main Menu Tool Tips

Near the bottom of a guiDef for the main menu system, you may see something like:

toolTip("#str_menu_fov_tooltip")

See GUI Scripting:Tooltip Macro for more.

Other "GuiDef" Types

The term "guiDef" has been coined here to describe the main layout structure shown in the template above, but generalized beyond just windowDef. (Other tutorial authors use "Window", "Item", or "Def" for this; see GUI Scripting: TDM vs Doom 3, Quake 4.)

Follow the links below for details about each type, including their additional Properties.

Used throughout the core main menu hierarchy:

EditDef

See GUI Scripting: EditDef - text input, e.g., the name of a game save file, and for specifying certain video options.

ChoiceDef

See GUI Scripting: ChoiceDef – widely used for making choices among settings.

SliderDef

See GUI Scripting: SliderDef – widely used as a horizontal slider to control a setting value.

ListDef

See GUI Scripting: ListDef – provides a scrollable multi-column list control. Examples include mission downloads, mission select, and saved game select.

Rarely used:

BindDef

See GUI Scripting: BindDef – used just In the Controls submenu, to bind particular keys to particular functions.

RenderDef

See GUI Scripting: RenderDef – used to show a 3D model in an guiDef, typically an overlay. This is not a static snapshot or sprite, but an object that could be oriented, e.g., by code. In the game HUD, used for the compass playertool.

Additional Event Handler Commands

Set 'Cmd'

For a way for a main-menu GUI to invoke C++ engine functions, see GUI Scripting: Parsing of Set 'Cmd'.

Fetching CVars

See GUI Scripting: Getting System CVars.

Arcana

Formal Syntax Definition

See GUI Scripting: BNF.

TDM vs Doom 3 or Quake 4

For usage and nomenclature differences, see GUI Scripting: TDM vs Doom 3, Quake 4.

References and Resources

For sources used in this series, including other early GUI scripting tutorials, see GUI Scripting: References & Resources.

The idTech4 Built-in EditGuis Editor

See GUI Scripting: EditGuis Editor