Bork3D Games

Personal tools
From Bork3D
Jump to: navigation, search

Contents

User Interface Files

The Bork3D Game Engine has the ability to load multiple user interface controls from a single configuration file. This allows you to decouple UI layout from your game code, so that you (or an artist) can iterate on the look and feel of your game without repeatedly recompiling it.


UI File Format

In a nutshell:

  • UI files must end with the ".ui" extension.
  • The file format defines one UI element per line.
  • UI element specifications are delimited with the tab character.
  • Lines beginning with a '#' are interpreted as comments.

The first word in a UI element line is the class name. The engine declares four UI classes that can be used in UI files: RudeControl, RudeButtonControl, RudeButtonAnimControl, and RudeTextControl. You're free to define your own classes too (see below).

Each class has it's own declaration format.

RudeTextControl

Parameters:

  • RudeTextControl (required). Begins the declaration.
  • Name (required). Name of control.
  • Text (required). The text value of the control.
  • Alignment (required). The alignment of text within the control. Must be one of: center, right, left, or justify.
  • Position (required). The position of the text. Meaning depends upon alignment. Specify in the form {x, y}.
  • Font (required). Font name. One of: default, big.
  • Style (required). Font style. One of: none, outline.
  • Animation (required). Animation attribute. One of: none, popslide, constant.
  • Color0 (optional).
  • Color1 (optional).
  • Color2 (optional).
  • Color3 (optional).

Example:

RudeTextControl	scoreText	+1	right	{310, 36}	default	outline	none	0xFF666666	0xFF000000	0xFFFFFFFF	0xFFFFFFFF


Working with UI Files

To load a UI file, create a RudeControl and call the Load() method on it. Pass it the name of the file without the ".ui" extension. Loading a UI file into a RudeControl creates child RudeControl's for each control defined in the file. You can access these children with the GetChildControl() method. For example:

RBUITitle::RBUITitle()
{
  ...
  // Load the "title.ui" UI file
  m_ui.Load("title");

  // Obtain references to the child controls
  m_logo = m_ui.GetChildControl<RudeButtonControl>("logo");
  m_rangeMedallion = m_ui.GetChildControl<RudeButtonControl>("rangeMedallion");
  m_courseMedallion = m_ui.GetChildControl<RudeButtonControl>("courseMedallion");
  m_courseSplash = m_ui.GetChildControl<RudeButtonControl>("courseSplash");
  ...
}

The usefulness of this system becomes most apparent when you conditionally load a different UI file depending upon the dimensions or orientation of the device you're working with. You may have a UI file for iPhone and another for iPad, one for portrait and one for landscape, etc. For example:

  if(RUDE_IPAD)
     m_ui.Load("title_ipad");
  else
     m_ui.Load("title_iphone");

Extending the UI File Format

The engine ships with the ability to load three types of controls from these configuration files, but the system is easily extensible so that you can give it the ability to load your own custom control types. To add your own control type, you'll need to create a factory function that provide RudeControl the ability to generate a new control of your type, and then register this function with the RudeControlRegistration system.

For example, here's the factory for the "RBWindControl" class, which is the UI control that displays the little wind indicator in the bottom-right corner of the screen in Anytime Golf. The factory takes a list of tokens provided by the configuration file parser and parses out the rectangle that defines the control's position on the screen. It then returns a pointer to the new control. The declaration of the RudeControlRegistration object below the function definition is what actually binds the factory function with the configuration file parser at init-time.

#include "RudeControl.h"
...

/**
 * ConstructRBWindControl factory assistant for RudeControl.  This is called by RudeControl::Load()
 */
RudeControl * ConstructRBWindControl(std::list<std::string> &tokens, const std::string &originalDesc)
{
       RBWindControl *c = new RBWindControl();
       RUDE_ASSERT(c, "Failed to construct control");
       
       // Rect {top, left, bottom, right}
       std::string rectstr = RudeControl::PopToken(tokens, originalDesc, "rect");
       
       RudeRect rect;
       RudeControl::ParseRect(rectstr, rect);
       c->SetRect(rect);
       
       return c;
}

RudeControlRegistration rbWindControlRegistration("RBWindControl", ConstructRBWindControl);