Buttons are an important part of any menu since they allow you to perform an action when you click on them. This action could be opening another menu or playing the game. There are several different methods of creating buttons that we will look at, as well as some graphical and audio enhancements to jazz up your menu.
Text Buttons
The simplest button consists of just some text. Quake 3 uses this type of button in most of its menus so we'll use the Quake 3 menu script from Backgrounds, Graphics, Text and Models as our template.
menuDef
{
name "main"
fullScreen MENU_TRUE
focusColor 1 .75 0 1
background "textures/sfx/logo512.tga"
onOpen { playlooped "music/sonic1.wav" }
onESC { uiScript "quit" }
itemDef
{
name logomodel
type ITEM_TYPE_MODEL
rect 0 -15 640 150
asset_model "models/mapobjects/banner/banner5.md3"
model_angle 180
model_fovx 75
model_fovy 30
visible MENU_TRUE
decoration
}
itemDef
{
name copyright
style WINDOW_STYLE_EMPTY
rect 0 450 640 30
text "Quake III Arena(c) 1999-2000, Id Software, Inc. All Rights Reserved"
forecolor 0.5 0 0 1
textstyle ITEM_TEXTSTYLE_NORMAL
textalign ITEM_ALIGN_CENTER
textalignx 320
textaligny 24
textscale 0.33
visible MENU_TRUE
decoration
}
}
Our text button will be an item that displays text but with a type of ITEM_TYPE_BUTTON.
itemDef
{
name new
rect 192 134 256 34
style WINDOW_STYLE_EMPTY
type ITEM_TYPE_BUTTON
visible MENU_TRUE
forecolor 1 0 0 1
text "SINGLE PLAYER"
textstyle ITEM_TEXTSTYLE_SHADOWEDMORE
textalign ITEM_ALIGN_CENTER
textalignx 128
textaligny 28
textscale .5
action { play "sound/misc/kcaction.wav" ;
close main ; open skirmish }
}
This item has a window size of 256x34 and the horizontal origin (X=192) is set to center the box. The text is defined to be centered horizontally in the box and the vertical offset is such that the text is also centered vertically in the box. Since the type is set to ITEM_TYPE_BUTTON the action command is run when the window area is clicked on. This plays a sound, closes the main menu and opens the skirmish menu.
This is a simple but effective button. However, it is rather plain and may not match the rest of the menu for looks. The next step we can take is to color the window area and place borders around it.
itemDef
{
name new
rect 192 134 256 34
style WINDOW_STYLE_FILLED
backcolor 0 0 .75 .25
border WINDOW_BORDER_FULL
bordercolor 0.5 0.5 0.5 1
bordersize 1
type ITEM_TYPE_BUTTON
visible MENU_TRUE
forecolor 1 0 0 1
text "SINGLE PLAYER"
textstyle ITEM_TEXTSTYLE_SHADOWEDMORE
textalign ITEM_ALIGN_CENTER
textalignx 128
textaligny 27
textscale .5
action { play "sound/misc/kcaction.wav" ;
close main ; open skirmish }
}
To color the window area we needed to change the window style to WINDOW_STYLE_FILLED and define the background color, a light, very transparent blue. We also added a 1 pixel wide border around the entire window, colored a medium grey. Because of the border we had to adjust the vertical text alignment (from 28 to 27) to keep the text centered. By playing with different window styles (WINDOW_STYLE_GRADIENT for example) and changing the border type and color we can create an interesting background for the text.
The current text button can still be jazzed up a little in the looks department. As it currently stands, moving the mouse over the button causes the text to change to the focus color and pulse. What we can do is also make the color of the window area change when the mouse moves over the button and change back when it leaves. For this we'll use the mouseEnter and mouseExit script commands.
itemDef
{
name new
rect 192 134 256 34
style WINDOW_STYLE_FILLED
backcolor 0 0 .75 .25
border WINDOW_BORDER_FULL
bordercolor 0.5 0.5 0.5 1
bordersize 1
type ITEM_TYPE_BUTTON
visible MENU_TRUE
forecolor 1 0 0 1
text "SINGLE PLAYER"
textstyle ITEM_TEXTSTYLE_SHADOWEDMORE
textalign ITEM_ALIGN_CENTER
textalignx 128
textaligny 27
textscale .5
mouseEnter { setitemcolor new backcolor .75 0 0 .25 }
mouseExit { setitemcolor new backcolor 0 0 .75 .25 }
action { play "sound/misc/kcaction.wav" ;
close main ; open skirmish }
}
What we have done is this - when the mouse moves over the item's window area the mouseEnter action script is executed. When this happens the setitemcolor command is run. This command changes the background color of the item named new to a red color. Since this item is named new, its background color changes to red when the mouse is moved over it. When the mouse leaves this item the mouseExit command is run. Again, the background color of the item named new (this item) is changed, this time to blue. So what we end up with is an item whose background color changes to red when the mouse is over it and to blue when it isn't.
It is also possible to use a graphic for a background by changing the window type to WINDOW_STYLE_SHADER and using the background command but there is an unfortunate side effect - the graphic will be tinted to the same color as the text (the foreground color). This, in general, will not look good and probably should be avoided. Instead what has to be done is you create another item, before the button item, that displays the graphic you want for the background.
itemDef
{
name newbar
rect 192 134 256 34
style WINDOW_STYLE_SHADER
background "textures/sfx/proto_zzztblu.jpg"
forecolor 1 1 1 1
border WINDOW_BORDER_FULL
bordercolor 0.5 0.5 0.5 1
bordersize 1
visible MENU_TRUE
decoration
}
This is just a decorative item that displays a graphic with borders. We now define our button.
itemDef
{
name new
rect 192 134 256 34
style WINDOW_STYLE_EMPTY
type ITEM_TYPE_BUTTON
visible MENU_TRUE
forecolor 1 0 0 1
text "SINGLE PLAYER"
textstyle ITEM_TEXTSTYLE_SHADOWEDMORE
textalign ITEM_ALIGN_CENTER
textalignx 128
textaligny 27
action { play "sound/misc/kcaction.wav" ;
close main ; open skirmish }
}
In the button item we removed all the background color and border commands and changed the window style back to default. This gives us a graphic background and a button whose text changes to the focus color when the mouse is over it. Again we can use the mouseEnter and mouseExit commands to change the foreground color of the newbar item so it tints when the mouse is over the button.
itemDef
{
name new
rect 192 134 256 34
style WINDOW_STYLE_EMPTY
type ITEM_TYPE_BUTTON
visible MENU_TRUE
forecolor 1 0 0 1
text "SINGLE PLAYER"
textstyle ITEM_TEXTSTYLE_SHADOWEDMORE
textalign ITEM_ALIGN_CENTER
textalignx 128
textaligny 27
mouseEnter { setitemcolor newbar forecolor 0 0 1 .5 }
mouseExit { setitemcolor newbar forecolor 1 1 1 1 }
action { play "sound/misc/kcaction.wav" ;
close main ; open skirmish }
}
These changes causes the foreground color of the item named newbar (our graphic background item) to change to blue when the mouse is over the button and revert back to white when it leaves. This is an example of an action in one item affecting another item, in this case, the mouse moving over item new changes the color of item newbar.
Another button style that looks very good is the one used by Jedi Knight II. These are text buttons with a graphic background that appears when the mouse moves over the button. By using a shader for the graphic background they get a nice effect on the graphic that compliments the rest of the menu. Let's look at this in more detail.
 |
 |
menu_buttonback.jpg |
static_menu.jpg |
These are the two graphics used by the following shader :
ui/assets/menu_buttonback
{
nopicmip
nomipmaps
{
map ui/assets/menu_buttonback.jpg
blendFunc GL_ONE GL_ONE
}
{
map ui/assets/static_menu.jpg
blendFunc GL_DST_COLOR GL_ONE
tcMod scroll -1 0
}
{
map ui/assets/static_menu.jpg
blendFunc GL_DST_COLOR GL_ONE
tcMod scroll 1 0
}
{
map ui/assets/static_menu.jpg
blendFunc GL_DST_COLOR GL_ONE
tcMod scroll -1.3 0
}
{
map ui/assets/static_menu.jpg
blendFunc GL_DST_COLOR GL_ONE
tcMod scroll 1.3 0
}
}
As with the previous text button, you must use a seperate item to display the graphic background to avoid tinting with the foreground color.
itemDef
{
name newgamebutton_glow
style WINDOW_STYLE_SHADER
rect 115 115 130 24
background "ui/assets/menu_buttonback"
forecolor 1 1 1 1
visible MENU_FALSE
decoration
}
The noteworthy point about this item is that it is not visible when the menu is loaded. Since it only appears when the mouse is over the button this makes perfect sense. The actual button item is thus :
itemDef
{
name newgamebutton
style WINDOW_STYLE_EMPTY
type ITEM_TYPE_BUTTON
rect 115 115 130 24
text "NEW"
textscale 0.33
textaligny 20
textalign ITEM_ALIGN_CENTER
textstyle ITEM_TEXTSTYLE_SHADOWEDMORE
textalignx 65
forecolor 0.65 0.65 1 1
visible MENU_TRUE
mouseEnter { show newgamebutton_glow }
mouseExit { hide newgamebutton_glow }
action { play "sound/misc/kcaction.wav" ;
close main ; open skirmish }
}
Just a regular text button with the text centered both ways in the box. Notice that its window area is identical to the newgamebutton_glow item window area. The magical part is done with the mouseEnter and mouseExit commands. When the mouse moves over the button the visibility of the newgamebutton_glow item is set to MENU_TRUE by the show command. The graphic is then drawn. When the mouse leaves the button the visiblity of the newgamebutton_glow item is set to MENU_FALSE by the hide command, making it not be drawn.
Graphic Buttons
Using graphics is the other way of creating buttons. FAKK 2 uses graphic buttons with special effects when the mouse is over them. We'll start with a simple graphic button and work our way up to more complex creations as we go. We'll use the FAKK 2 menu script from Backgrounds, Graphics, Text and Models as our template.
menuDef
{
name "main"
fullScreen MENU_TRUE
background "ui/assets/fakkback.tga"
style WINDOW_STYLE_SHADER
focusColor 0 .75 0 1
onOpen { playlooped "music/sonic1.wav" }
itemDef
{
name menusmoke
style WINDOW_STYLE_SHADER
rect 0 0 640 480
background "ui/assets/smoke"
visible MENU_TRUE
decoration
}
itemDef
{
name julie1
style WINDOW_STYLE_SHADER
rect 54 0 256 256
background "ui/assets/julie_1.tga"
visible MENU_TRUE
decoration
}
itemDef
{
name julie2
style WINDOW_STYLE_SHADER
rect 0 256 256 256
background "ui/assets/julie_2.tga"
visible MENU_TRUE
decoration
}
itemDef
{
name julie3
style WINDOW_STYLE_SHADER
rect 256 256 128 256
background "ui/assets/julie_3.tga"
visible MENU_TRUE
decoration
}
}
Our graphic button is just an item with a graphic background whose type is set to ITEM_TYPE_BUTTON.
itemDef
{
name newgame
style WINDOW_STYLE_SHADER
type ITEM_TYPE_BUTTON
rect 349 46 256 64
forecolor 1 1 1 1
background "ui/assets/b_newgame.tga"
visible MENU_TRUE
action { play "sound/misc/kcaction.wav" ;
close main ; open skirmish }
}
Since the type is set to ITEM_TYPE_BUTTON the action command is run when the window area is clicked on. This plays a sound, closes the main menu and opens the skirmish menu. A simple button but it doesn't give you any indication of when the button has recieved the focus since the focus color only applies to text. You can use the mouseEnter and mouseExit commands, like we did with text buttons, to change the tinting of the graphic to indicate focus being recieved and lost.
itemDef
{
name newgame
style WINDOW_STYLE_SHADER
type ITEM_TYPE_BUTTON
rect 349 46 256 64
forecolor 1 1 1 1
background "ui/assets/b_newgame.tga"
visible MENU_TRUE
mouseEnter { setitemcolor newgame forecolor 0 0 1 .5 }
mouseExit { setitemcolor newgame forecolor 1 1 1 1 }
action { play "sound/misc/kcaction.wav" ;
close main ; open skirmish }
}
Now we have a button that tints blue when the mouse is over it and shows normally when it isn't.
The next thing we can do is to make the graphic change when the mouse is over the button. We can use a shader with some special effects in it to replace the orginal graphic when the mouse is over it so we know when it has the focus. This what FAKK 2 does with its buttons to give the glow effect for buttons that have the focus. We'll look at an actual button graphic and the shader used by FAKK 2 for its New Game button.
 |
 |
b_newgame.tga |
b_newgame2.tga |
and the shader used is :
ui/assets/b_newgame_selected
{
nomipmaps
nopicmip
cull none
{
blendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
clampMap ui/assets/b_newgame.tga
}
{
blendFunc GL_ONE GL_ONE
clampMap ui/assets/b_newgame2.tga
rgbGen wave sin .5 .5 0 1
}
}
Our button item would be like this :
itemDef
{
name newgame
style WINDOW_STYLE_SHADER
type ITEM_TYPE_BUTTON
rect 349 46 256 64
forecolor 1 1 1 1
background "ui/assets/b_newgame.tga"
visible MENU_TRUE
mouseEnter { setbackground "ui/assets/b_newgame_selected" }
mouseExit { setbackground "ui/assets/b_newgame.tga" }
action { play "sound/misc/kcaction.wav" ;
close main ; open skirmish }
}
What we have here is this - when the mouse is over the button the item background changes to the shader shown above. This produces a glow around the graphic. When the mouse leaves the button the background is restored to the original graphic.
Special Button Effects
We can add to the basic text and graphic buttons some special effects that will make a menu look more professional. These effects can be added to any button, either text or graphic.
Focus Sound
One of the features of FAKK 2 main menu buttons is a voice telling you what the button does when it recieves the focus. This quite simple to implement by adding the following command to the item definition :
onFocus { play "sound/menu/newgame.wav" }
substituting the appropriate sound file directory and name for "sound/menu/newgame.wav". This will play only when the button recieves the focus and will not play again until the button loses the focus and then regains it.
Focus Text
Another type of focus effect is displaying some text describing the button when it receives the focus. The Jedi Knight II menus do this very nicely. This technique requires that you define another item for each button that will display the text when the button recieves the focus. This is very similar to the way we needed another item to display the background graphic for Jedi Knight II buttons. To display the text the item would be :
itemDef
{
name newgametext
style WINDOW_STYLE_EMPTY
rect 0 425 640 24
text "Start a New Game"
textscale 0.33
textaligny 20
textalign ITEM_ALIGN_CENTER
textstyle ITEM_TEXTSTYLE_SHADOWEDMORE
textalignx 320
forecolor .235 .882 .847 1
visible MENU_FALSE
decoration
}
Just a simple text item that places its text centered near the bottom of the screen. It's visibility is false so it normally won't be drawn. Every text item associated with a button will have the same window area so they are all shown in the same place. Since only one will be visible at any given time sharing the same screen area is no problem. In the button item definition you place the following commands :
onFocus { show newgametext }
leaveFocus { hide newgametext }
These commands make the newgametext item visible when the button receives the focus and invisible when it loses it.