Game Development Community

dev|Pro Game Development Curriculum

Customizable tab control

by Geom · 12/07/2007 (1:24 pm) · 18 comments

Download Code File

redbrickgames.com/pix/071205/tabDemo.jpg

YouTube video here.

Features:

o text labels in the tabs (obviously)
o icons in the tabs
o optional custom bitmaps for the (entire) tabs
o unique appearances for each tab state (unselected, selected, hovered, pressed)
o settable fill colors
o settable border colors
o settable border thickness (or none)
o settable margins on either side of the tabs
o tab widths may be fixed, or resize with the control width
o sound effects on mouse-over and mouse-down

It's a pretty basic tab ctrl. It doesn't cover every possible use case, but it should be more than adequate for most needs.

Note, TGE 1.4 and later already have a native tab control built-in (GuiTabBook / GuiTabPage). The control in this resource is a different tab control, and has some different features.

Adding the tab control to the Torque SDK

First, make a backup of the file "example/starter.fps/client/ui/mainMenuGui.gui". It'll get overwritten. Then download tabctrl.zip and unzip it to your Torque directory.

Next, add the new files

- engine/gui/containers/guiTabCtrl.h
- engine/gui/containers/guiTabCtrl.cc

to your build system. (In Visual Studio 2005, you do this by clicking on a Solution folder, choosing "Add", "Existing Item...", then browsing to the files). Recompile. You shouldn't get any compile errors with Torque 1.5.2, but for other versions of Torque you may need to tweak some #include paths.

Run the starter.fps example. You should see two tab ctrls on the main menu screen!

To see sample script for those two ctrls, diff the old and new mainMenuGui.gui files.

GUI Profile

The tab control is pretty easy to script. To create your own control, start by making a new GUI profile:

new GuiControlProfile(GuiTabProfile)
{
   bitmap         = "";             // unless you want custom bitmapped tabs, set this to "".  see below.
   opaque         = true;
   borderThickness = 2;             // or if you want no border, set this to 0
   borderColor    = "20 20 20";     // color of border that faces lower right
   borderColorHL  = "240 240 240";  // color of border that faces upper left
   fillColor      = "200 180 150";  // color of selected tab and of the interior pane
   fillColorNA    = "180 170 140";  // color of unselected tabs
   fillColorHL    = "230 220 150";  // color of hovered-over tab
   fontColor      = "0 0 0";
   justify        = "center";       // justification of tab labels
};

The comments above show how the tab ctrl uses each profile field. Note, be sure to set the bitmap field to the empty string (unless you want custom tab bitmaps - see below).

GuiTabCtrl

Next, declare a GuiTabCtrl object somewhere in your GUI script.

new GuiTabCtrl() {
   profile     = GuiTabProfile;
   position    = "510 385";
   extent      = "270 100";
   tabSize     = "0 24";     // the width & height of each tab.  width = 0 means tabs should resize.
   iconSize    = "0 0";      // size at which to render icons.  If "0 0", icons render at their natural size.
   margins     = "0 0";      // left & right margins on either side of the tab row.  See below.
   bevel       = 3;          // beveling of the tab corners, in pixels.  0 = square corners.
   labelOffset = "0 0";      // optional offset to add to the icon & label (usually zero).

   new GuiTextCtrl() {
      profile  = "GuiTextProfile";
      position = "60 40";
      text     = "This is tab pane #1.";
      tabLabel = "Tab #1";			 // text label to appear in the tab.
      tabIcon  = "starter.fps/client/ui/icon1";	 // icon to appear in the tab.  Must be a full path!
   };
};

The GuiTabCtrl creates one tab for each of its child GUI ctrls. In the example above, there's only one child (the text ctrl), so there will be only one tab. To create more tabs, just add more child GUI ctrls.

Child ctrls may be any kind of GUI ctrls - there's no requirement about their type. The GuiTabCtrl knows how to draw their tabs by looking for the dynamic fields "tabLabel" and "tabIcon" on each child.

Notes:

* If you specify tab icons, the icon files must be specified using a full path (as in "starter.fps/client/ui/icon1"). Path abbreviations won't work (e.g. "~/client/ui/icon1", "./icon1").

* Margin values are normally interpreted as pixel widths, but if you specify a fraction between 0-1 (like 0.5), it'll be interpreted as a percentage of the tab control's width.

* You can specify asymmetrical margins for a funky look.

* All GuiTabCtrl fields have default values, so you only need to specify the ones you care about.

That's about it! Run your game and try it out.

It's not super well tested, so if you do unusual things with it, you may find bugs. For example, if you dynamically add & remove children while the tab ctrl is in-use, I'm not sure how it will behave.

Custom tab bitmaps

If you don't like the default look of the tabs, you can supply your own bitmaps. To do this, set the bitmap field of the GUI profile to a file containing a bitmap array. (you need to understand Torque's bitmap arrays to use this feature) The array can have up six bitmaps. The six bitmaps represent the different states that a tab can be in, which are:

1. an unselected tab
2. a selected tab
3. an unselected hovered-over tab
4. a selected hovered-over tab
5. an unselected pressed-down tab
6. a selected pressed-down tab

Here's an example bitmap array:

redbrickgames.com/pix/071205/customTabs.png
Once you specify your bitmaps, the tab control will draw them for the tabs instead of the usual renderings.

Note, the height of your bitmaps should be the tab height plus the border thickness. Tab height is defined in the GuiTabCtrl's tabSize field. So if your tab height is 24 and your border thickness is 2, your bitmaps should be 24 + 2 = 26 pixels tall.

If you supply less than six bitmaps, the tab control will improvise with however many you give it.


Just to be clear, this feature (custom tab bitmaps) and the tab "icons" are two different features. Tab bitmaps are the backgrounds, and tab icons are the small images that appear next to the text labels. You can use both features at the same time, or one, or neither.


If you create some slick custom jobs, feel free to post screenshots!

About the author

My email address is my GG handle, at redbrickgames.com.


#1
12/10/2007 (2:46 am)
Very nice!
I was used to set up something similar using bitmap buttons and panel but this is more immediate and flexible... :)
The only addition I would like to see is the possibility to have the tabs disposed vertically.
But wonderful resource! :)
#2
12/10/2007 (5:52 am)
Excelent Geom!! I have to say the final resource is much more elaborated than I expected!!
Awesome job, thanks for it.
#3
12/10/2007 (4:45 pm)
Awesome!
Thank you for sharing!
#4
12/10/2007 (5:04 pm)
Thanks guys! I hope it gets lots of use! Hey Novack, that's good to hear, that was one reason it took me awhile to get it out, I was trying to make it flexible!
#5
12/10/2007 (10:10 pm)
WOW this is one fo the big things that was lost when they got TGE from Tribes 2! Thanks a ton.
#6
12/22/2007 (9:38 pm)
Anyone try to add this to TGEA yet?
#7
12/23/2007 (3:00 pm)
I haven't, don't own it.
I woulda thought the gui system was the same in TGEA...
#8
12/24/2007 (10:52 pm)
Awesome. 5/5.
#9
12/25/2007 (1:21 am)
Geom - Man I wish. No since TGEA is DirectX based instead of OpenGl it is significantly different. I have been trying to get this converted. So far it just crashes the game. But at least I got the darned thing to compile, that just means I made a mistake somewhere.

If there is another TGEA owner better versed in programming in DirectX in TGEA, let me know I would love to collaborate with you on this.
#10
12/28/2007 (8:03 pm)
Well I actually managed to muddle my way through it and made a TGEA version of this. I posted it up as a resource here. All credit goes to you Geom, this resource is wonderful.

www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=14063
#11
12/28/2007 (8:37 pm)
Thanks, Ron! Awesome! You definitely deserve some credit... I don't know any DirectX myself.
#12
12/28/2007 (8:44 pm)
Thanks Geom, to be honest I really did for myself initially. I really like your work and it has become an important part of my project.
#13
01/15/2008 (10:20 pm)
Occasionally I get stuck on a particular tab and am unable to switch between the different tabs - has anyone else come across this issue? and suggestions?
#14
01/16/2008 (7:13 am)
Andrew, is it reproducible?
#15
01/16/2008 (1:22 pm)
not that I have been able to find which is the most frustrating part!
#16
01/16/2008 (7:30 pm)
I did a quick look over the code and don't see anything obvious. If you want to email me the .gui file, I'll check it out. geom at redbrickgames nospaam dot nospaam com

One thing, the tab ctrl doesn't switch panes until mouse-up, so if the cursor drifts off its original tab it won't switch
#17
03/05/2008 (6:35 am)
I am having problems putting other controls inside a tab page. I tried to put guiSliderCtrl into a tab page and it won't show it. Any ideas???
#18
03/06/2008 (2:35 pm)
So the tab shows up, it just doesn't contain anything?

No idea, other than the regular things... make sure the ctrls don't have "visible" set to 0, make sure their positions fit within the tab pane, check that your .gui or .cs file compiled ok w/o errors in console.log...