CEGUI In Practice - Creating widgets
Written for CEGUI 0.7
Works with versions 0.7.x (obsolete)
CEGUI In Practice series
Contents
CEGUI In-Practice 2
Welcome back. This is the second installment of CEGUI In-Practice tutorial series. In this we will build upon the previous tutorial, CEGUI In Practice - Introduction. We will show how to create Widgets and manage them.
The Widget
In the last example we showed how to bootstrap the system with Ogre, and gave a brief introduction to CEGUI's script files. Now we will work on understanding what a widget is and how to use them. Lets jump in and create a window which will display a box with an image in the middle of the screen:
CEGUI::Window *myImageWindow = CEGUI::WindowManager::getSingleton().createWindow("TaharezLook/StaticImage","PrettyWindow" );
CEGUI uses numerous derived classes code-side to create windows. The base class CEGUI::Window is the generic window. the CEGUI::WindowManager calls a factory class when creating a window which returns the windows pointer. The first argument, "TaharezLook/StaticImage" tells the factory what kind of window to make. These windows are defined in .scheme, which are subsequently defined more depth in other .xml files. The second argument is the name which the window will have.
[Note: As a point to note, there is no strict requirement on naming of windows, except to avoid repeat names. Some users tend to prefer a naming convention using ParentName/ChildName. ie. "ConsoleWindow/SendButton" or "_MasterRoot/HealthBar"]
Once we have created the window, myImageWindow will be a pointer to a CEGUI::DefaultWindow which is derived from CEGUI::Window. If you look in the .scheme file you can see can see what a Widget is derived from via the TargetType= tag.
Next we need to set some properties for this window. There are two ways of doing this. The first is via the propertyset, or the second way by calling the function. The latter way can be more annoying at times, as you may have to cast the window to the correct type to get access to the member functions, but may be more intuitive depending on how you think.
The Unified Dimension System
We created our widget, now we need to position it and define its size. Lets do that via code shall we?
Before we jump in too far, we need to understand how CEGUI Handles positions. CEGUI Uses a Unified Dimension system.
CEGUI::UDim(scale,offset)
The first number is the relative point on the screen between (0,1). So if we were looking at the X axis (left to right on the screen) a UDim(0.5,0) would be Halfway across the screen with zero pixels offset. Udim(0.0,50) would be starting at the left side of the screen +50 pixels. You can combine them too Udim(0.75,10) would be 3/4 of the way across the screen, with an additional 10 pixels.
A point on the screen (or a UVector2) is made up of two UDims:
CEGUI::UVector2(UDim x,UDim y)
As such, a CEGUI::Rect is as you would imagine, 4 UDims
CEGUI::URect(CEGUI::Udim left,CEGUI::Udim top,CEGUI::Udim right,CEGUI::Udim bottom)
So now that we know how positions are done, lets move our created window to the middle of the screen:
The Widget in Practice
myImageWindow->setPosition(CEGUI::UVector2(CEGUI::UDim(0.5,0),CEGUI::UDim(0.5,0)));
That may look a little ugly but break it down. setPosition takes a UVector2, and each UVector2 is made up of an X and Y Udim, which is made up of a Scale and Absolute float.
So, we have moved our window to the middle of the screen.. but CEGUI doesn't know how big to make it? So set its size to 150 pixels by 100 pixels [Note: I dropped the namespace for this to increase readability].
myImageWindow->setSize(UVector2(UDim(0,150),UDim(0,100)));
In this case we specified the Udim using 0 for scales, and the actual pixel size in the absolute argument. The Absolute argument is additive to the scale, and in this case we didn't want to have the size be affected by the scale argument. If we were creating a splash screen that took up the entire window, we would likely want the size to be UVector2(UDim(1,0),UDim(1,0) with the position being at UVector2(Udim(0,0), UDim(0,0).
Now that we have created the window to the size we want. We need to tell it what image to display! That we will do by using the PropertySet as follows.
myImageWindow->setProperty("Image","set:TaharezLook image:full_image");
The first agument is what Property we want to set, and the second argument is what value to set. The second argument is a string broken into two pieces in this example. We need to know what ImageSet we are looking in, which is referenced following the 'set:' portion. And then the image via the 'image:' portion. In this case we want it to show the full_image.
A Listing of properties for TaharezLook is available here [1]
Now that we have created the window. We need to attach it to the current root window.
CEGUI::System::getGUISheet()->addChildWindow(myImageWindow);
This will allow the Window to be displayed.
Conclusion
So with this quick tutorial we got a very short introduction to PropertySet usage (Important!) and a little bit about how the Unified Dimension System in CEGUI Works. While still not terribly useful, we're beginning to understand how to use some of CEGUI's faculties. Next up, we'll learn how to get some interactivity from this thing.