Home - Forums - Documentation - Gallery - Bugs
m
(work in progress)
Line 2: Line 2:
= Step Four: : Using CEGUI =
= Step Four: : Using CEGUI =
 +
== Introduction ==
In this tutorial we will create our applications’ windows with the help of CEGUI. This tutorial contains basic information only about the library , when CEGUI is new for you, please visit the project website for more information:
In this tutorial we will create our applications’ windows with the help of CEGUI. This tutorial contains basic information only about the library , when CEGUI is new for you, please visit the project website for more information:
[http://www.cegui.org.uk www.cegui.org.uk]
[http://www.cegui.org.uk www.cegui.org.uk]
-
The CS SDK has a '''Ceguitest''', a basic example, how you can integrate CEGUI into your application. The viewmesh test application uses also CEGUI, here you can find a long and detailed example to deal with this impressive windowing system.
+
The CS SDK has the '''Ceguitest''' demo, a basic example, how you can integrate CEGUI into your application. The '''viewmesh'' test application uses also CEGUI, here you can find a long and detailed example, how to deal with this impressive windowing system under CS.
 +
 
 +
== Important notes ==
 +
 
Some notes about CEGUI under CS. There is an introduction to Cegui in the manual, please read this section first. I cite the most important section:
Some notes about CEGUI under CS. There is an introduction to Cegui in the manual, please read this section first. I cite the most important section:
Line 18: Line 22:
the same instance as calling getSingleton() from the CEGUI plugin.
the same instance as calling getSingleton() from the CEGUI plugin.
</pre>
</pre>
 +
 +
Don't forget to link the CEGUIBase* library, when you build this demo. The correct name is depend on your build system. When you use '''MSVC8''', you need ''CEGUIBase-vc8_d.lib'' (in debug mode) or ''CEGUIBase-vc8.lib '' in release mode. These are in your ''CS\libs\csutil\win32\libs'' folder.
 +
 +
 +
== Loading CEGUI plugin ==
 +
 +
To load CEGUI plugin, first we need change the ''cimGame::OnInitialize '' al little bit:
 +
 +
<pre>
 +
if (!csInitializer::RequestPlugins(object_reg = GetObjectRegistry(),
 +
CS_REQUEST_VFS,
 +
CS_REQUEST_OPENGL3D,
 +
CS_REQUEST_ENGINE,
 +
CS_REQUEST_FONTSERVER,
 +
CS_REQUEST_IMAGELOADER,
 +
CS_REQUEST_LEVELLOADER,
 +
CS_REQUEST_REPORTER,
 +
CS_REQUEST_REPORTERLISTENER,
 +
CS_REQUEST_PLUGIN("crystalspace.collisiondetection.opcode",
 +
iCollideSystem),
 +
CS_REQUEST_PLUGIN("crystalspace.console.output.standard",
 +
iConsoleOutput),
 +
CS_REQUEST_PLUGIN ("crystalspace.cegui.wrapper", iCEGUI),
 +
CS_REQUEST_END))
 +
return ReportError("Failed to initialize plugins!");
 +
</pre>
 +
 +
The ''CS_REQUEST_PLUGIN ("crystalspace.cegui.wrapper", iCEGUI)'' will load the CEGUI plugin.
 +
 +
We introduce a new class to handle the interface of our game. This new ''cimGuiHandler'' class qwill:
 +
 +
* initialize CEGUI plugin, loading skin and layouts.
 +
* render CEGUI interface, show the actual window
 +
* encapsulate all CEGUI callback functions
 +
 +
== The header ==
 +
<pre>
 +
class cimGuiHandler
 +
{
 +
public:
 +
 +
bool Initialize(iObjectRegistry* obj_reg);
 +
</pre>
 +
Yes, initializing. This function will intiailaze CEGUI and the event handler.
 +
 +
<pre>
 +
 +
bool HandleEvent(iEvent& ev);
 +
 +
struct EventHandler : public scfImplementation1<EventHandler, iEventHandler>
 +
{
 +
cimGui* parent;
 +
 +
EventHandler (cimGui* parent) : scfImplementationType (this),
 +
parent (parent) {}
 +
 +
virtual ~EventHandler() {}
 +
 +
virtual bool HandleEvent (iEvent& e) { return parent->HandleEvent(e); }
 +
CS_EVENTHANDLER_NAMES("cim.gui")
 +
CS_EVENTHANDLER_NIL_CONSTRAINTS
 +
};
 +
</pre>
 +
We need an event handler to subscribe to the PostProcess event. We will render cegui in this phase. The solution is same, as in the prvious tutorial.
 +
 +
<pre>
 +
private:
 +
 +
bool OnBtnNewGameClicked(const CEGUI::EventArgs&);
 +
 +
bool OnBtnLoadGameClicked(const CEGUI::EventArgs&);
 +
 +
bool OnBtnSettingsClicked(const CEGUI::EventArgs&);
 +
 +
bool OnBtnExitClicked(const CEGUI::EventArgs&);
 +
</pre>
 +
These are the window callback functions. Ehen the user will push a button on the cegui layout, the corresponding function will be called. Important, that all CEGUI callback function must foloww the following definition:
 +
 +
<pre>bool MyCEGUIEventHandlerconst CEGUI::EventArgs&);</pre>
 +
 +
 +
<pre>
 +
 +
iObjectRegistry* object_reg;
 +
 +
csEventID FinalProcess;
 +
 +
csRef<iCEGUI> cegui;
 +
 +
csRef<EventHandler> eventHandler;
 +
</pre>
 +
 +
We need a pointer to the object registry, (to communicate with the CS framework), a refernce to cegui plugin and the event handler.
 +
 +
== Implementing ''Initalize'' function ==
 +
 +
<pre>
 +
bool cimGuiHandler::Initialize(iObjectRegistry *obj_reg)
 +
{
 +
object_reg = obj_reg;
 +
eventHandler.AttachNew (new EventHandler (this));
 +
csRef<iEventQueue> queue = CS_QUERY_REGISTRY(object_reg, iEventQueue);
 +
if (queue.IsValid())
 +
{
 +
csEventID events[]=
 +
{
 +
csevPostProcess(object_reg),
 +
CS_EVENTLIST_END
 +
};
 +
 +
queue->RegisterListener(eventHandler,events);
 +
}
 +
 +
FinalProcess = csevPostProcess (object_reg);
 +
</pre>
 +
TOur event handler will interesting for the Postprocess event. I described the sunscribing mechanism in the previous totorial.
 +
<pre>
 +
//init Cegui plugin
 +
cegui = CS_QUERY_REGISTRY (object_reg,iCEGUI);
 +
if (!cegui) return false;
 +
if( !cegui->Initialize() ) return false;
 +
</pre>
 +
We query and start Cegui plugin. <br>
 +
<pre>
 +
cegui->GetLoggerPtr ()->setLoggingLevel(CEGUI::Informative);
 +
cegui->GetSchemeManagerPtr ()->loadScheme("Falagard.scheme");
 +
cegui->GetSystemPtr ()->setDefaultMouseCursor("Falagard", "MouseArrow");
 +
CEGUI::Font* font = cegui->GetFontManagerPtr ()->createFont("FreeType",
 +
"Vera", "/fonts/ttf/Vera.ttf");
 +
font->setProperty("PointSize", "10");
 +
font->load();
 +
 +
</pre>
 +
CEGUI has a builtin logging system. We can choose the needed logging level from this enum:
 +
<pre>
 +
enum LoggingLevel
 +
{
 +
Errors, //!< Only actual error conditions will be logged.
 +
Standard, //!< Basic events will be logged (default level).
 +
Informative, //!< Useful tracing (object creations etc) information will be logged.
 +
Insane //!< Mostly everything gets logged (use for heavy tracing only, log WILL be big).
 +
};
 +
</pre>
 +
 +
Next we load our scheme file (that describes the skin of our windows), and we set up the mouse cursor. Cegui depends on freetype font, so we load a symphatic one (Vera.ttf).
 +
 +
== Callback functions ==
 +
 +
<pre>
 +
//setup CEGUI callback functions
 +
CEGUI::WindowManager* winMgr = cegui->GetWindowManagerPtr ();
 +
 +
// Load layout and set as root
 +
cegui->GetSystemPtr ()->setGUISheet(winMgr->loadWindowLayout("cimmain.xml"));
 +
 +
//main window
 +
CEGUI::Window* btn = winMgr->getWindow("BtnNewGame");
 +
btn->subscribeEvent(CEGUI::PushButton::EventClicked,
 +
CEGUI::Event::Subscriber(&cimGuiHandler::OnBtnNewGameClicked, this));
 +
 +
CEGUI::Window* btn = winMgr->getWindow("BtnLoadGame");
 +
btn->subscribeEvent(CEGUI::PushButton::EventClicked,
 +
CEGUI::Event::Subscriber(&cimGuiHandler::OnBtnLoadGameClicked, this));
 +
 +
CEGUI::Window* btn = winMgr->getWindow("BtnSettings");
 +
btn->subscribeEvent(CEGUI::PushButton::EventClicked,
 +
CEGUI::Event::Subscriber(&cimGuiHandler::OnBtnSettingsClicked, this));
 +
 +
CEGUI::Window* btn = winMgr->getWindow("BtnExit");
 +
btn->subscribeEvent(CEGUI::PushButton::EventClicked,
 +
CEGUI::Event::Subscriber(&cimGuiHandler::OnBtnExitClicked, this));
 +
 +
</pre>
 +
 +
 +
The first version of the main menu will be something, like this:
 +
 +
[[Image:cim4_1.jpg]]
 +
 +
I created this "wonderful" interface with the Celayout editor. You can find this application on the cegui website.
 +
 +
Every button has an unique name. It's important, because the CEGUI windows manager will find our windows by name. This is the right way to subscrie to an CEGUI event:
 +
 +
CEGUI::Window* btn = winMgr->getWindow("BtnExit");
 +
btn->subscribeEvent(CEGUI::PushButton::EventClicked,
 +
CEGUI::Event::Subscriber(&cimGuiHandler::OnBtnExitClicked, this));
 +
 +
The ''OnBtnExitClicked'' function will be called, when he user clicks on the exit button (name ''BtnExit''). The function will add to the button real functionality.
 +
 +
== The event handler section ==
 +
 +
bool cimGuiHandler::HandleEvent(iEvent &ev)
 +
{
 +
if (ev.Name == FinalProcess)
 +
cegui->Render();
 +
}
 +
 +
This is easy. Just call the ''Render'' function to render CEGUI interface.

Revision as of 09:54, 31 January 2007

Contents

Step Four: : Using CEGUI

Introduction

In this tutorial we will create our applications’ windows with the help of CEGUI. This tutorial contains basic information only about the library , when CEGUI is new for you, please visit the project website for more information:

www.cegui.org.uk

The CS SDK has the Ceguitest' demo, a basic example, how you can integrate CEGUI into your application. The viewmesh test application uses also CEGUI, here you can find a long and detailed example, how to deal with this impressive windowing system under CS.

Important notes

Some notes about CEGUI under CS. There is an introduction to Cegui in the manual, please read this section first. I cite the most important section:

It is important that applications using CEGUI from Crystal Space do not use any of
the CEGUI getSingleton() or getSingletonPtr() calls, such as 
CEGUI::Singleton<T>::getSingleton() or CEGUI::System::getSingleton(). The reason 
for this is that global and static variables (declared in methods, classes, 
namespaces, or globally) are not normally shared between modules. Calling 
getSingleton() from the Crystal Space application will not necessarily return 
the same instance as calling getSingleton() from the CEGUI plugin.

Don't forget to link the CEGUIBase* library, when you build this demo. The correct name is depend on your build system. When you use MSVC8, you need CEGUIBase-vc8_d.lib (in debug mode) or CEGUIBase-vc8.lib in release mode. These are in your CS\libs\csutil\win32\libs folder.


Loading CEGUI plugin

To load CEGUI plugin, first we need change the cimGame::OnInitialize al little bit:

if (!csInitializer::RequestPlugins(object_reg = GetObjectRegistry(),
    CS_REQUEST_VFS,
    CS_REQUEST_OPENGL3D,
    CS_REQUEST_ENGINE,
    CS_REQUEST_FONTSERVER,
    CS_REQUEST_IMAGELOADER,
    CS_REQUEST_LEVELLOADER,
    CS_REQUEST_REPORTER,
    CS_REQUEST_REPORTERLISTENER,
    CS_REQUEST_PLUGIN("crystalspace.collisiondetection.opcode",
		iCollideSystem),
    CS_REQUEST_PLUGIN("crystalspace.console.output.standard",
		iConsoleOutput),
   CS_REQUEST_PLUGIN ("crystalspace.cegui.wrapper", iCEGUI),
    CS_REQUEST_END))
    return ReportError("Failed to initialize plugins!");

The CS_REQUEST_PLUGIN ("crystalspace.cegui.wrapper", iCEGUI) will load the CEGUI plugin.

We introduce a new class to handle the interface of our game. This new cimGuiHandler class qwill:

  • initialize CEGUI plugin, loading skin and layouts.
  • render CEGUI interface, show the actual window
  • encapsulate all CEGUI callback functions

The header

class cimGuiHandler
{
public:

	bool Initialize(iObjectRegistry* obj_reg);

Yes, initializing. This function will intiailaze CEGUI and the event handler.


	bool HandleEvent(iEvent& ev);
	
	struct EventHandler : public scfImplementation1<EventHandler,           iEventHandler>
	{
	  cimGui* parent;

	EventHandler (cimGui* parent) : scfImplementationType (this), 
      parent (parent) {}

    virtual ~EventHandler() {}

    virtual bool HandleEvent (iEvent& e) { return parent->HandleEvent(e); }
	 CS_EVENTHANDLER_NAMES("cim.gui")
    CS_EVENTHANDLER_NIL_CONSTRAINTS
	};

We need an event handler to subscribe to the PostProcess event. We will render cegui in this phase. The solution is same, as in the prvious tutorial.

private:

    bool OnBtnNewGameClicked(const CEGUI::EventArgs&);

    bool OnBtnLoadGameClicked(const CEGUI::EventArgs&);

    bool OnBtnSettingsClicked(const CEGUI::EventArgs&);

    bool OnBtnExitClicked(const CEGUI::EventArgs&);

These are the window callback functions. Ehen the user will push a button on the cegui layout, the corresponding function will be called. Important, that all CEGUI callback function must foloww the following definition:

bool MyCEGUIEventHandlerconst CEGUI::EventArgs&);



    iObjectRegistry* object_reg;

    csEventID FinalProcess;
    
    csRef<iCEGUI> cegui;

    csRef<EventHandler> eventHandler;

We need a pointer to the object registry, (to communicate with the CS framework), a refernce to cegui plugin and the event handler.

Implementing Initalize function

bool cimGuiHandler::Initialize(iObjectRegistry *obj_reg)
{
	object_reg = obj_reg;
	 eventHandler.AttachNew (new EventHandler (this));
  csRef<iEventQueue> queue = CS_QUERY_REGISTRY(object_reg, iEventQueue);
  if (queue.IsValid())
  {
	  csEventID events[]=
	  {
		  csevPostProcess(object_reg),
		  CS_EVENTLIST_END
	  };

	  queue->RegisterListener(eventHandler,events);
  }

    FinalProcess = csevPostProcess (object_reg);

TOur event handler will interesting for the Postprocess event. I described the sunscribing mechanism in the previous totorial.

	//init Cegui plugin 
	cegui = CS_QUERY_REGISTRY (object_reg,iCEGUI);
	if (!cegui) return false;
	if( !cegui->Initialize() ) return false;

We query and start Cegui plugin.

	cegui->GetLoggerPtr ()->setLoggingLevel(CEGUI::Informative);
	cegui->GetSchemeManagerPtr ()->loadScheme("Falagard.scheme");
    cegui->GetSystemPtr ()->setDefaultMouseCursor("Falagard", "MouseArrow");
    CEGUI::Font* font = cegui->GetFontManagerPtr ()->createFont("FreeType",
     "Vera", "/fonts/ttf/Vera.ttf");
    font->setProperty("PointSize", "10");
    font->load();

CEGUI has a builtin logging system. We can choose the needed logging level from this enum:

enum LoggingLevel
{
	Errors,			//!< Only actual error conditions will be  logged.
	Standard,		//!< Basic events will be logged (default level).
	Informative,	//!< Useful tracing (object creations etc) information will be logged.
	Insane			//!< Mostly everything gets logged (use for heavy tracing only, log WILL be big).
};

Next we load our scheme file (that describes the skin of our windows), and we set up the mouse cursor. Cegui depends on freetype font, so we load a symphatic one (Vera.ttf).

Callback functions

    //setup CEGUI callback functions
	CEGUI::WindowManager* winMgr = cegui->GetWindowManagerPtr ();

    // Load layout and set as root
    cegui->GetSystemPtr ()->setGUISheet(winMgr->loadWindowLayout("cimmain.xml"));

	//main window
	CEGUI::Window* btn = winMgr->getWindow("BtnNewGame");
    btn->subscribeEvent(CEGUI::PushButton::EventClicked,
		CEGUI::Event::Subscriber(&cimGuiHandler::OnBtnNewGameClicked, this));

	CEGUI::Window* btn = winMgr->getWindow("BtnLoadGame");
    btn->subscribeEvent(CEGUI::PushButton::EventClicked,
		CEGUI::Event::Subscriber(&cimGuiHandler::OnBtnLoadGameClicked, this));

	CEGUI::Window* btn = winMgr->getWindow("BtnSettings");
    btn->subscribeEvent(CEGUI::PushButton::EventClicked,
		CEGUI::Event::Subscriber(&cimGuiHandler::OnBtnSettingsClicked, this));

	CEGUI::Window* btn = winMgr->getWindow("BtnExit");
    btn->subscribeEvent(CEGUI::PushButton::EventClicked,
		CEGUI::Event::Subscriber(&cimGuiHandler::OnBtnExitClicked, this));


The first version of the main menu will be something, like this:

Image:cim4_1.jpg

I created this "wonderful" interface with the Celayout editor. You can find this application on the cegui website.

Every button has an unique name. It's important, because the CEGUI windows manager will find our windows by name. This is the right way to subscrie to an CEGUI event:

CEGUI::Window* btn = winMgr->getWindow("BtnExit");

   btn->subscribeEvent(CEGUI::PushButton::EventClicked,

CEGUI::Event::Subscriber(&cimGuiHandler::OnBtnExitClicked, this));

The OnBtnExitClicked function will be called, when he user clicks on the exit button (name BtnExit). The function will add to the button real functionality.

The event handler section

bool cimGuiHandler::HandleEvent(iEvent &ev) { if (ev.Name == FinalProcess) cegui->Render(); }

This is easy. Just call the Render function to render CEGUI interface.

| Article | Discussion | View source | History |