Introduction and overview of core "Falagard" support systems
From CEGUIWiki
The Falagard skinning system for CEGUI consists partly of a set of enhancements to the CEGUI base library, and partly of a new 'look' module called "CEGUIFalagardBase". Combined, these elements are intended to make it easier to create custom skins or 'looks' for CEGUI window and widget elements. The Falagard system is designed to allow widget imagery specification, sub-widget layout, and default property initialisers to be specified via XML files rather than in C++ or scripted code (which, before now, was the only way to do these things). The system is named "Falagard" after the forum name of the person who initially suggested the feature (as is the trend in all things CEGUI), although it was designed and implemented by the core CEGUI team.
The Falagard extensions are not limited to the 'looknfeel' XML files only; there are supporting elements within the core library, as well as extensions to the GUI scheme system to allow you to create what are essentially new widget types. This is achieved by mapping a named widget 'look' to a base widget type taken from the CEGUIFalagardBase module (I know I'm probably just about losing you now, don't worry about all these details too much for the time being!). Once your new type has been defined in a scheme and loaded, you can specify the name of that new type name when creating windows or widgets via the WindowManager singleton as you would for any other widget type. There are no additional issues to be considered when using a 'skinned' widget than when using one of the old 'programmed' widget types.
Contents |
The Unified Co-ordinate System
As part of the Falagard system, CEGUI has effectively replaced the old either/or approach to relative and absolute co-ordinates with a new 'unified' co-ordinate system. Using this new system, each co-ordinate can specify both a parent-relative and absolute-pixel component. Since most people baulk at the idea of this, I'll use examples to introduce these concepts.
Introducing UDim
The basic building block of the unified system is the UDim, which is defined as:
UDim(scale, offset)
- where
- 'scale' represents what would be the relative component, as is usually a value between 0 and 1.0.
'offset' represents the absolute component and basically represents a number of screen 'pixels'.
Still confused? On to the examples!
Simple UDim examples
Example 1
UDim(0, 10)
Here we see a UDim with a scale of 0, and an offset of 10. This simply represents an absolute value of 10, if you used such a UDim to set a window width, then under the old system it's the equivalent of:
myWindow->setWidth(Absolute, 10);
Example 2
UDim(0.25f, 0)
Here we see a UDim with a scale of 0.25 and an offset of 0. This represents a simple relative co-ordinate. If you were to set the y position of a window using this UDim, then the window would be a quarter of the way down it's parent, and it's the same as the following under the old system:
myWindow->setYPosition(Relative, 0.25f);
Example 3
UDim(0.33f, -15)
Here we see the power of UDim. We have a scale of 0.33 and an offset of -15. If we used this as the height of a window, you would get a height that is approximately one third of the height of the window's parent, minus 15 pixels. There is no simple equivalent for this under the old system.
Property format
The format of a UDim to be used in the window property strings is as follows:
{s,o}
- where
- 's' is the scale value
'o' is the pixel offset.
The UVector2 type
There is a UVector2 type which consists of two UDim elements; one for the x axis, and one for the y axis. Note that the UVector2 is used to specify both positional points and also sizes (i.e. there is no separate USize type).
The UVector2 is defined as:
UVector2(x_udim, y_udim)
- where
- 'x_udim' is a UDim value that specifies the x co-ordinate or width.
'y_udim' is a UDim value that specifies the y co-ordinate or height.
Simple UVector2 examples
Example 1
UVector2(UDim(0, 25), UDim(0.2f, 12))
The above example specifies a point that is 25 pixels along the x-axis and one fifth of the way down the parent window plus twelve pixels.
Example 2
UVector(UDim(1.0f, -25), UDim(1.0f, -25))
This example, intended as a size for a window, would give the window the same width as its parent, minus 25 pixels, and the same height as its parent, minus 25 pixels.
Property format
The format of a UVector2 to be used in the window property strings is as follows:
{{sx,ox},{sy,oy}}
- where
- 'sx' is the scale value for the x-axis, and 'ox' is the pixel offset for the x-axis.
'sy' is the scale value for the y-axis, and 'oy' is the pixel offset for the y-axis.
Finally the URect
The last of the Unified co-ordinate types is URect. The URect defines four sides of a rectangle using UDim elements. You generally access the URect as you would the normal 'Rect' type (though each 'side' of the rectangle is made up of a UDim rather than a float):
URect(left_udim, top_udim, right_udim, bottom_udim)
- where
- 'left_udim' is a UDim defining the left edge.
'top_udim' is a UDim defining the top edge.
'right_udim' is a UDim defining the right edge.
'bottom_udim' is a UDim defining the bottom edge.
You can also define a URect with two UVector2 objects; one for the top-left corner, and the other for the bottom-right corner:
URect(tl_uvec2, br_uvec2)
- where
- 'tl_uvec2' is a UVector2 that describes the top-left point of the rect area.
'br_uvec2' is a UVector2 that describes the bottom-right point of the rect area (not the size of the area).
Simple URect Example
URect(UDim(0, 25),
UDim(0, 25),
UDim(1.0f, -25),
UDim(1.0f, -25))
If we used the URect defined here to specify the area for a window, we would get a window that was 25 pixels smaller than its parent on each edge.
Property format
The format of a URect to be used in the window property strings is as follows:
{{sl,ol},{st,ot},{sr,or},{sb,ob}}
- where
- 'sl' is the scale value for the left edge, and 'ol' is the pixel offset for the left edge.
'st' is the scale value for the top edge, and 'ot' is the pixel offset for the top edge.
'sr' is the scale value for the right edge, and 'or' is the pixel offset for the right edge.
'sb' is the scale value for the bottom edge, and 'ob' is the pixel offset for the bottom edge.
New Window Alignments
The Falagard enhancements also include new settings to specify alignments for windows. This gives the possibility to position child windows from the right edge, bottom edge and centre positions of their parents, as well as the previous left edge and top edge possibilities.
It is possible to set the alignment options in C++ code by using methods in the Window class, and also via the properties system which is used by XML layouts system.
Vertical Alignments
To set the vertical alignment use the Window class member function:
void setVerticalAlignment(const VerticalAlignment alignment);
This function takes one of the VerticalAlignment enumerated values as its input. The VerticalAlignment enumeration is defined as:
enum VerticalAlignment
{
VA_TOP,
VA_CENTRE,
VA_BOTTOM
};
- Where
- VA_TOP specifies that y-axis positions specify an offset for a window's top edge from the top edge of it's parent window.
VA_CENTRE specifies that y-axis positions specify an offset for a window's centre point from the centre point of it's parent window.
VA_BOTTOM specifies that y-axis positions specify an offset for a window's bottom edge from the bottom edge of it's parent window.
The window property to access the vertical alignment setting is:
"VerticalAlignment"
This property takes a simple string as its value, which should be one of the following options:
"Top" "Centre" "Bottom"
Where these setting values correspond to the similar values in the VerticalAlignment enumeration.
Horizontal Alignments
To set the horizontal alignment use the Window class member function:
void setHorizontalAlignment(const HorizontalAlignment alignment);
This function takes one of the HorizontalAlignment enumerated values as its input. The HorizontalAlignment enumeration is defined as:
enum HorizontalAlignment
{
HA_LEFT,
HA_CENTRE,
HA_RIGHT
};
- Where
- HA_LEFT specifies that x-axis positions specify an offset for a window's left edge from the left edge of it's parent window.
HA_CENTRE specifies that x-axis positions specify an offset for a window's centre point from the centre point of it's parent window.
HA_RIGHT specifies that x-axis positions specify an offset for a window's right edge from the right edge of it's parent window.
The window property to access the horizontal alignment setting is:
"HorizontalAlignment"
This property takes a simple string as its value, which should be one of the following options:
"Left" "Centre" "Right"
Where these setting values correspond to the similar values in the HorizontalAlignment enumeration.
Falagard in Schemes
The CEGUI scheme system has had some extensions added to enable you to specify how the system is to load your XML skin definition files (known as 'looknfeel' files), and how these skins are to be mapped to the Falagard widget base classes to create new widget types.
The CEGUIFalagardBase module
One of the main parts of the Falagard system is the new 'look' module known as CEGUIFalagardBase (which will be named libCEGUIFalagardBase.so on linux style systems and CEGUIFalagardBase.dll on Win32 systems). This module is where actions are taken to transform skinning data loaded from XML files into rendering operations and layout adjustments required by the CEGUI base widget components.
The first important thing you need to know about this widget module is, that like the old TaharezLook and WindowsLook modules, you must specify it in one of your scheme files so that it's available to the system. This can be done with a single line of XML in a scheme file, such as:
<WindowSet Filename="CEGUIFalagardBase" />
Notice that there is no longer a need to specify the individual widget types to be loaded from the module; if you use XML as shown above, the module will register all widget types it has available.
The other important thing about the module is that for each widget base type, it defines various required "states" and other such elements. These required elements need to be defined within the widget look definitions of your looknfeel XML files; they enable the system to make use of your skin imagery and related data in a logical fashion. All of the required elements for each widget can be found in the "Falagard Base Widgets Reference" section.
LookNFeel Elements
The new "LookNFeel" XML element for schemes is the means by which you will usually get CEGUI to load the XML 'looknfeel' files containing your widget skin definitions. The LookNFeel element should appear after any Font or Imageset elements, but before any WindowSet elements.
The following is an example of how to use the LookNFeel element:
<LookNFeel Filename="FunkyWidgets.looknfeel" />
Here we can see a single 'Filename' attribute which specifies the name the file to be loaded. It is acceptable to specify as many LookNFeel elements as is required. This allows you to configure your XML files in the way that best suits your application. This might mean that all definitions for all widget elements will go into a single file, it might mean that you have multiple files with a single widget definition in each, or it could be any place in between the two extremes - it's up to you.
FalagardMapping Elements
The CEGUI scheme system now supports a "FalagardMapping" element. This new element creates a new window or widget type within the system. It does this by mapping a named widget 'LookNFeel' to a target base widget. The named 'LookNFeel' is what you specify in your XML looknfeel files (via the WidgetLook elements), and the available base widget types are those which get loaded from the CEGUIFalagardBase module.
A small example mapping:
<FalagardMapping
WindowType="FunkyLook/Button"
TargetType="Falagard/Button"
LookNFeel="MyButtonSkin"
/>
In this example, a new widget type named "FunkyLook/Button" is being created. The new widget is based upon the "Falagard/Button" base type, and takes its skin from the loaded WidgetLook named "MyButtonSkin". Once the scheme with this mapping has been loaded, you can then use the new type within the system:
// Get access to the main window manager CEGUI::WindowManager wMgr& = CEGUI::WindowManager::getSingleton();
// Create a new wigget wMgr.createWindow("FunkyLook/Button", "myFunkyButton");
Here we create an instance of the new widget, and name it "myFunkyButton". The widget can now be attached to other windows and generally used as you would any 'normal' widget.
Conclusion
This concludes the overview of the new parts of the CEGUI system. You have seen how the new "Unified" co-ordinate system works, and how to make use of the new window alignment options. You have also learned the basics of how to set up your scheme files to initialise the Falagard base module, and how to map XML defined skins to the base Falagard widgets to create new widget types. The next section of this document will introduce the XML format and elements used in the 'looknfeel' files.

