The purpose of this tutorial is to show you how to create a simple
window and get it on screen. Before continuing here, it is very
important that you have already read and fully understood the articles The Beginner Guide to Getting CEGUI Rendering and The Beginner Guide to Loading Data Files and Initialisation; this is important because this tutorial builds upon the basic ideas introduced in those tutorials.
Introduction to window and widget concepts
Before we get the the meat of this tutorial there are some essential ideas that you must first consider.
Every widget is a window
This is the most central concept that must be grasped when working
with CEGUI. Every widget within the system is derived from the same
Window base class; so for the purposes of this tutorial, whenever I
mention a window, the same ideas could just as easily be applied to a
push button or scrollbar widget.
Many settings are inherited
Many of the settings and properties available for windows in CEGUI
are passed down the window hierarchy. For example, if you set the alpha
transparency on a particular window to 0.5, then by default, all window
and widgets attached to that window will also be affected by the change
applied at the higher level; although note also that the actual setting
on the child window remains unchanged - the final values and/or
settings used are usually some combination of the setting values from
all windows in the hierarchy down to the current window. This also
applies to things such as window destruction; by default, a window will
destroy attached child windows and widgets when it is destroyed. The
main advantages of this arrangement are that you can easily affect a
the whole GUI by making changes to the root window settings for things
like alpha, visibility, enabled / disabled state, and can easily 'clean
up' an entire GUI layout by simply destroying the root window. The
default 'inherited' behaviours can be overridden on a per window basis
where more fine grained control is needed, or where certain advanced
management techniques are to be used.
Creating the windows
Enough of the waffle! Lets create a window.
There are two ways of doing this, via C++ code and XML layout files. Each approach is discussed below.
GUI Creation via C++ code
All windows in CEGUI are created by the WindowManager singleton
object. You can get access to this object via the usual getSingleton
method as follows:
using namespace CEGUI;
WindowManager& wmgr = WindowManager::getSingleton();
In general, you will be using what is known as a DefaultWindow (or
to use it's old name, DefaultGUISheet) as the 'root' window in your
GUI. This is not required, but is the accepted pattern of usage for
CEGUI and, once you start adding more top-level windows, helps simplify
laying things out.
So, to get the ball rolling, we'll create a DefaultWindow as set it as the root 'GUI Sheet' for the GUI:
Window* myRoot = wmgr.createWindow( "DefaultWindow", "root" );
System::getSingleton().setGUISheet( myRoot );
The createWindow method of the WindowManager takes two strings as
its parameters. The first one, "DefaultWindow" in this example, tells
the system the type or class of the window you wish to create.
Generally, the windows you have available are those which were
registered when you loaded your scheme file, although some, like
DefaultWindow, are global types and are always available. The second
parameter, "root" in this example, is a unique name which will be
assigned to the window; this name can be used to retrieve a pointer to
the window from the WindowManager at a later time. Note that naming
your root window "root" is not required, but is a common convention.
The setGUISheet method in the System singleton object is used
to specify a given window as the root of the GUI. This will replace any
current sheet / root window, although do note that the previous window
hierarchy is not actually destroyed; it is just unlinked from the
display - you can easily switch between GUI 'pages' by simply flipping
between them using the setGUISheet method.
Now you have created your first window and attached it to the
GUI system, and the system will use this window as the root of the GUI
when it draws the GUI. But, if you were to compile a simple program
using this code, you still can't see anything; what gives? There's
nothing wrong with your application, the DefaultWindow which we created
above is just totally invisible! This is what makes the DeafultWindow
ideally suited as a root window; it serves as a blank canvas onto which
other window and widgets can be attached. So, lets do that now...
Here we will create a frame window; this is a window that
functions in a similar manner to the windows on your desktop UI, it has
a title bar and can be moved and re-sized.
FrameWindow* fWnd = (FrameWindow*)wmgr.createWindow( "TaharezLook/FrameWindow", "testWindow" );
here we are creating a "TaharezLook/FrameWindow" window. This name
uses a convention seen throughout the system, whereby a window type is
prefixed by the name of the widget set (if you were to load the
WindowsLook scheme, you could create a "WindowsLook/FrameWindow" object
instead). We have given our new window the simple test name of
"testWindow". One final thing to note is the use of the cast, this is
required since the createWindow method always returns a base Window
type; in this, and many other cases a basic Window pointer will
suffice, but there are times when you'll want to access methods
introduced in the window and widget sub-classes, so the use of the cast
as shown is common when using CEGUI.
In order for the system to be able to do something useful with our new window, we must perform a few additional steps.
First, we must attach the window to the root window we established above:
myRoot->addChildWindow( fWnd );
Now, we can set an initial position and size for our window. CEGUI
uses a 'unified' co-ordinate system enabling the use of relative
(scale) and absolute (offset) components at the same time - this is why
each co-ordinate you will see has two parts. For a slightly extended
introduction of this concept see Introduction and overview of core "Falagard" support systems. Back to the example:
// position a quarter of the way in from the top-left of parent.
fWnd->setPosition( UVector2( UDim( 0.25f, 0 ), UDim( 0.25f, 0 ) ) );
// set size to be half the size of the parent
fWnd->setSize( UVector2( UDim( 0.5f, 0 ), UDim( 0.5f, 0 ) ) );
Finally, we set a caption for the frame window's title bar:
fWnd->setText( "Hello World!" );
And that's it! When compiled into an application, you will now see a simple frame window in the middle of the display.
XML layouts
All of the above is very nice, but there is one major drawback; any
time you wish to adjust the GUI layout, you need to edit your code and
recompile. This will get old pretty quick, so what you really want is
to be able to specify your GUI layout externally, and have your code
load the layout via a file. This is the purpose of the CEGUI layout XML
files.
The system supports XML layout files, which can be loaded via
the WindowManager using the loadWindowLayout method. This method
creates all the windows for you and returns a pointer to the root
window of the loaded hierarchy; which is ideal for assigning as the
root of the GUI!
So, first of all we need a layout file. The following XML saved
as a text file, is a layout file equivalent to the code we discussed
above:
<?xml version="1.0" ?>
<GUILayout>
<Window Type="DefaultWindow" Name="root">
<Window Type="TaharezLook/FrameWindow" Name="testWindow">
<Property Name="UnifiedPosition" Value="{{0.25,0},{0.25,0}}" />
<Property Name="UnifiedSize" Value="{{0.5,0},{0.5,0}}" />
<Property Name="Text" Value="Hello World!" />
</Window>
</Window>
</GUILayout>
The Window elements show an obvious mapping to the createWindow
method from the WindowManager object; they take a type and a name which
directly correspond to the parameters discussed previously.
Nesting of the Window elements is used to attach certain
windows to others. Note that you may only have one 'root' level window
in a layout file, which is another reason you'll usually see the
DefaultWindow used as a canvas on which other windows and widgets are
placed.
The Property elements are used to set properties on the Window
being defined. There are many properties available for each
window/widget class, and each class also inherits all properties from
it's parent class. See the <element>Properties namespaces in the API reference
for documentation on the available hard-coded properties and their
'value string' formats. Since 'Falagard' skins can create their own
properties, it is likely that the windows you are using contain many
more properties than listed in the previous link - for these 'soft'
properties, you need to consult whichever documentation is provided
with the skin you are using (for the sample skins see TaharezLook and WindowsLook).
If saved as a file called "test.layout", you could load this layout and set it as the GUI root as follows:
using namespace CEGUI;
Window* myRoot = WindowManager::getSingleton().loadWindowLayout( "test.layout" );
System::getSingleton().setGUISheet( myRoot );
The end result is exactly the same as what was done in C++ code
earlier, except that now you can modify and enhance the GUI layout
without the need for constant editing and recompilation of the
application code.
理解以上教程很是简单,提供了两种创建widget的方法