GUI Scripting: If Statements

From The DarkMod Wiki
Revision as of 16:21, 4 November 2022 by Geep (talk | contribs) (Add category tag)
Jump to navigationJump to search

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

Introduction

The term "if statement" here is an abbreviated name for "if ... else if ... else ... statement". Its nature in GUI scripting is just enough like that of C-family languages to get you into trouble. In a nutshell, here’s guidance on problem areas:

  • Curly brackets are not optional.
  • A closing curly bracket is never followed by ";"
  • Each commands within curly brackets should be terminated by ";"
  • In if-conditions, within the parentheses:
    • wrap variables in double-quotes.
    • preferably surround any #defined macros with spaces.
    • be aware that non-numeric string comparison has an odd syntax.

Overall Structure and Syntax

GUI scripting "if statements" are found in an event block (i.e., body of an event handler like onTime). The general form is:

if (boolean condition)
{
  1 or more valid statements terminated by ";" and executed only if condition was true.
}
else if (boolean conditionN)
{
  1 or more valid statements, each terminated by ";" and executed if all preceding conditions were false and conditionN is true.
}
else
{
  1 or more valid statements, each terminated by ";" and executed if all conditions were false.
}

where the "else if" and "else" substructures are optional, and the "else if" substructure can be repeated any number of times.

The curly brackets can be on the same line as the "if", "else if", and "else", or separate. The degree of white space indentation doesn’t matter. It is a convention to use whitespace (i.e., space or newline) to separate the keywords ("if", "else if", "else) from the punctuation (parentheses and curly brackets).

There is NO semi-colon after any closing bracket "}".

CURLY BRACKETS ARE REQUIRED! So this is NOT OK:

if (boolean condition)
  command1;
else
  command2;

If-Condition

This must resolve to a boolean value. This could come directly from a variable that only has 0 or non-zero (interpreted as 1) as values, or by a comparison, or by a conjunction of these separated by "&&" (i.e., logical AND) or "||" (i.e., logical OR) as in C.

Common Cases

All variables names MUST be in double quotes, e.g.:

if ("gui::lang_danish") {....
if ("gui::lang_spanish" == 0) {....
if ("gui::av_screenshot_download_in_progress" == "0" && "exit" == 0) {....

Most if-conditions in TDM are used to test gui:: parameters, as shown. The last example, from mainmenu_download.gui, also tests a user variable defined locally in the guiDef.

Tested variables are routinely of type float (representing boolean as above, or integer or real), and comparisons use numeric operators, e.g.:

if ("gui::curPage" < "gui::numPages") {

By convention, numeric literal values are UNQUOTED, although quotes are tolerated. Unquoted examples with various operators:

if ("gui::diffSelect" != 2) {....
if ("gui::numPages" > 1) {....
if ("gui::flashbomb_halfblind_enum" >= 0.8) {....
if ("gui::player_health"  <= 0) {....

String Comparison

Text comparisons are generally avoided, but you can check with a special QUOTED form of not-equal operator, e.g., here for the empty string:

if ("LSGSaveGameNameEntry::text" "!=" "") {

This also shows a rare example of an if-condition referring to a property declared in a different guiDef from that of the if statement.

With #Defined Values

If you don’t see double quotes, e.g.,

if ( MM_BRIEFING_VIDEO_LENGTH_1 > 0 && MM_BRIEFING_VIDEO_LENGTH_2 == 0 )

...it means a #define statement either incorporates the quotes around a variable name, or uses a numeric literal, where quotes are optional, e.g.:

#define MM_BRIEFING_VIDEO_LENGTH_1 10000 // In mainmenu_custom_defaults.gui & mainmenu_custom_defs.gui

Also, if you have a #defined item in your condition, the preprocessor parser will probably thank you if you surround it with spaces, e.g.:

if ( MM_BRIEFING_VIDEO_LENGTH_1 > 0 && MM_BRIEFING_VIDEO_LENGTH_2 == 0 )

NOT:

if (MM_BRIEFING_VIDEO_LENGTH_1>0&&MM_BRIEFING_VIDEO_LENGTH_2==0)

Precedence & Arithmetic Operations?

No example of an if-condition in TDM using parenthetical grouping or simple arithmetic operators {+,-,*,/} was seen. It is presumed those are possible; such arithmetic is deployed elsewhere.

For example, arithmetic is used to initialize vector values of the "rect" property, to position a button. First, in tdm_gui01.pk4\guis\mainmenu_defs.gui, boolean MM_POS_HASMOD_SHIFT is #defined:

#define MM_POS_HASMOD_SHIFT ("gui::hasCurrentMod" || "gui::inGame")

This in turn affects where the "New Mission" button is positioned vertically, by calculation:

#define MM_POS_NEW_MISSION_BUTTON 	MM_POS_X, MM_POS_Y + MM_POS_Y_STEP*(0+2*MM_POS_HASMOD_SHIFT), MM_POS_W, MM_POS_H

Then in tdm_gui01\guis\mainmenu_main.gui:

rect MM_POS_NEW_MISSION_BUTTON

Multiple If Statements

Within an event block, it is perfectly fine to have multiple if statements sequentially, perhaps interspersed with commands.

Can if statements be nested? You would think so, given that's the case with most C-style languages. However, no example of that was seen with TDM. Perhaps the need simply didn't arise?