GUIs: Templates

From Mod Wiki

Templates can be used for reducing the size of GUIs and improving the readability of them.

Templates

Templates are very useful and the use of them is essential in creating some of the more complex GUIs like the main menu, server browser and the limbo menu. It increases the readability of the scripts a lot since often used script code can be hidden away in the templates and it can guarantee that for example buttons in the main menu all behave and look the same way.

Basic example of a GUI template:

$template simpleTemplate
	[put text here]
$endtemplate

All occurrences of simpleTemplate in any GUIs will be replaced with the [put text here] keywords when parsing the GUIs.

Naming convention

Templates that are generic and could/is being used several places should have one underscore. Templates or "helper templates" that are only used in a GUI should have two underscores.

Both these templates are from guis/common/utility.include. __right is only used as a helper template for _right and should have two underscores:

$template __right( windowName, padding )
	( ( gui.windowName.rect.width - rect.width ) - padding )
$endtemplate

$template _right( windowName )
	__right( windowName, PADDING )
$endtemplate

There are hundreds of places where _right is used since you just about always want to have padding between windows, while __right is not used outside the include file (except for one case).

Simple Templates

The simplest templates have no parameters and replaces the parameter name throughout the GUIs with the contents of the template during parsing:

Found in guis/common/utility.include and used in the main menu:

$template _monitor_music_volume
	events {
		onCVarChanged "s_volumeMusic_dB" {
			gui.fadeSoundClass( 1, gui.getCVarFloat( "s_volumeMusic_dB" ), 500 );
		}
	}
$endtemplate

Main Menu line ~85:

...
_menu_icons
_crosshair_materials
_monitor_music_volume

// init window classes
_btn_init
_dlg_init
...

Templates With Parameters

Often templates have arguments, for example the _bottom and _center templates found in guis/common/utility.include, useful for placing a windows in relation to other windows:

$template _bottom( windowName )
	( ( gui.windowName.rect.height - rect.h ) - PADDING )
$endtemplate
$template _center( windowName, orientation )
	( ( gui.windowName.rect.orientation * 0.5 ) - ( rect.orientation * 0.5 ) )
$endtemplate

A window at this position:

rect rect = ( ( gui.desktop.rect.orientation * 0.5 ) - ( rect.width * 0.5 ) ), ( ( gui.desktop.rect.height - rect.h ) - PADDING ), SCREEN_WIDTH/2, 32;

is equal to a window at this position using templates:

rect rect = _center( desktop, width ), _bottom( desktop ), SCREEN_WIDTH/2, 32;

The example will place the window at the center of the screen, just above the bottom edge of the GUI. The second version is much easier to read and you can be sure that no spelling mistakes have been made for it since the template is most likely being used in several other places.

A more commpliated template with the use of multiple parameters:

$template _horizontal_line( NameParm, XPos, YPos, WidthParm, HeightParm )
	windowDef div##NameParm {
		properties {
			rect 	rect 		= XPos, YPos, WidthParm, HeightParm;
			color	backColor 	= COLOR_MED;
			string	material	= "window_line_t";
		}
$endtemplate

For many templates like buttons/edit boxes/lists/sliders/etc. there is a closing template which allows you to include the start template then add some additional scripting if needed before closing the window with a _end_<template name>:

$template _end_horizontal_line
	}
$endtemplate

Notice the two ## which means it will concatenate div and the name NameParm. If you create a horizontal line like this for example:

_horizontal_line( Horizontal1, 0, 0, SREEN_WIDTH, 4 )
_end_horizontal_line

After parsing it will expand to:

windowDef divHorizontal1 {
	properties {
		rect 	rect 		= 0, 0, SREEN_WIDTH, 4;
		color	backColor 	= COLOR_MED;
		string	material	= "window_line_t";
	}
}

Names can be made literal with a single # as a prefix. If a template parameter is MaterialName and the value of MaterialName is window_line_t then using #MaterialName will expand to "window_line_t" after parsing.

Game Settings Template

The Game Settings dialog in the main menu is actually a template itself so only a single line needs to be included in guis/mainmenu/mainmenu.gui to include the dialog. It heavily uses templates itself which makes it a lot more readable.

Here's the advanced vehicles section of the game settings, found in guis/mainmenu/dialogs/gamesettings.include:

_label_localized( GameSettings_AdvVehicles, localize( "guis/mainmenu/vehicles" ), PADDING, PADDING, 100, BUTTON_HEIGHT, COLOR_WHITE )
	properties {
		vec2 textAlignment = TA_LEFT, TA_VCENTER;
	}
_end_label
_check( GameSettings_AdvFlight, localize( "guis/mainmenu/advflight" ), $evalfloat( 2 * PADDING ), 0, 120 )
	_cvar_bool( ui_advancedFlightControls )
_end_check

To really understand this you just have to look up the template and see what the parameters do.

guis/mainmenu/components/label.include:

$template _label_localized( NameParm, TextParm, XPos, YPos, Width, Height, ColorParm )

NameParm is the name of the window. Draw a localized label at XPos/YPos with the Width/Height where TextParm is the text handle with a color of ColorParm.

guis/mainmenu/components/lines.include:

$template _check( NameParm, TextParm, xPos, yPos, WidthParm )

NameParm is the name of the window. Draw a check box with the localized text handle TextParm at xPos/yPos with the specified width.

guis/mainmenu/cvars.include:

$template _cvar_bool( CVarParm )

This template ties the value of the checkbox with the CVar specified.

Now it is really easy to add another checkbox here if we would want to, here's an example that adds an advanced driving controls checkbox:

_check( GameSettings_AdvDriving, localize( "guis/mainmenu/advdriving" ), $evalfloat( 2 * PADDING ), 0, 120 )
	_cvar_bool( ui_advancedDrivingControls )
_end_check