Nebula
3D-Studio 3.1 exporter
Articles
Downloads
gMax Exporter
Models
Named Hierarchy Browser
nmax for RL SDK
Quake 2 Interpolator
Wateralgorithms
 
Diverse Jme Mangalore Nebula Project1 Project2 Tabletop

Nebula 2 nGUI System

Definition of a GUI window

Nebula2 has is a extenvise collection of GUI elments. These classes are located in the nebula2/code/inc/gui and nebula2/code/src/gui directories. Following is a selection of available elements:

  • nGuiWindow, nGuiClientWindow, nGuiTextWindow
  • nGuiButton, nGuiTextButton, nGuiCheckButton, nGuiCheckButtonGroup
  • nGuiLabel, nGuiTextLabel
  • nGuiTextView, nGuiTextEntry
  • nGuiToolTip
  • nGuiSlider2, nGuiHoriSliderGroup
  • . . .

The base class of all these elements is nGuiWidget. A widget is a clickable, rectangular area. nGuiWidget defines the basic functionality of a GUI elemnt. To create a new GUI for an application you create a new nGUIWindow or nGuiClientWindow derived class.




#ifndef N_TESTWINDOW_H

#define N_TESTWINDOW_H

//------------------------------------------------------

/**

A test window.

(C) 2006 Radon Labs GmbH

*/

#include "gui/nguiclientwindow.h"

#include "gui/nguitextbutton.h"

class nTestWindow : public nGuiClientWindow

{

public:

	/// constructor

	nTestWindow();

	/// destructor

	virtual ~nTestWindow();

	/// called when widget is becoming visible

	virtual void OnShow();

	/// called when widget is becoming invisible

	virtual void OnHide();

	/// notify widget of an event

	virtual void OnEvent(const nGuiEvent& event);

	/// called per frame when parent widget is visible

	virtual void OnFrame();

	/// set position of test window on screen

	void SetWindowPosition(vector2 position);

private:

	nRef closeButton;

	float windowPosX;

	float windowPosY;

};

//---------------------------------------------------------

inline

void

nTestWindow::SetWindowPosition(vector2 position)

{

	this->windowPosX = position.x;

	this->windowPosY = position.y;

}

#endif



Since nGuiWidet is derived from nRoot all conventions found at http://nebuladevice.cubik.org/documentation/nebula2/NebulaWritingClass.shtml for nRoot derived classes are to be used for a new GUI class. This includes among others the usage of the nNebulaClass(newClassName, superClassName) macros in your .cc files. It creates a nebula class without a script interface.




#include "nTest/ntestwindow.h"

nNebulaClass(nTestWindow, "nguiclientwindow");



By using the macro the new GUI class will be registered with the KernelServer and therafter it is possible to create objects of that class. Instances of GUI classes are not created by using the KernelServer but the GUIServer.




this->testWindow = static_cast(nGuiServer::Instance()->

NewWindow("menuWindow", false));



The window layout

Each widget has a OnShow() method called when the widget should be displayed. It is usual to define the layout of the window there. First general properties of the window are defined, if the window should be resizable, if a titlebar should be available, a close button, if it should be movable, if it should be modal (modal windows must be closed before a user can interact with windows behind), the brushes (textures for a widget) of the window.




void

nTestWindow::OnShow()

{

	// setup window style

	this->SetResizable(false);

	this->SetCloseButton(false);

	this->SetTitleBar(false);

	this->SetMovable(false);

	this->SetModal(true);

	this->SetDefaultBrush("window");

	...



Next the size and position of a window are defined. By using nGuiWidget::SetRect(const rectangle& r) a rectangle is passed as paramter which bottom left and top right points define the corners of the window.




	// setup window position and size

	rectangle rect(vector2(this->windowPosX,

	 	this->windowPosY), vector2(this->windowPosX

		this->SetRect(rect);



After the call of the OnShow method of the parent class the window is ready for the layout work.




// call parent class

nGuiClientWindow::OnShow();

// get client area form layout object

nGuiFormLayout* layout = this->refFormLayout.get();



After grabbing the reference to the layout and passing it over to the window rectangle so it will be of the same size as the whole window the layout object is placed at the top of the KernelServer stack for further processing. Finally ist is removed from there and the layout of the window is updated.




	// Stretch form layout to fit into client window.

	layout->SetRect(rect);

	kernelServer->PushCwd(layout);

	// layout definition done here

	kernelServer->PopCwd();

	this->UpdateLayout(rect);

}



Between the PushCwd and PopCwd the desired GUI elements are added and arranged to the window layout. The example only adds a button to close the window.




	// close button

	nRef textButton = 

		(nGuiTextButton*)kernelServer->New

		("nguitextbutton", "cancel");

	n_assert(textButton);

	textButton->SetDefaultBrush("button_n");

	textButton->SetPressedBrush("button_p");

	textButton->SetHighlightBrush("button_h");

	textButton->SetText("Close");

	textButton->SetColor(vector4(0.0f, 0.0f, 0.0f, 1.0f));

	textButton->SetMinSize(vector2(0.08f, 0.03f));

	textButton->SetMaxSize(vector2(0.08f, 0.03f));

	layout->AttachPos(textButton,

 		nGuiFormLayout::VCenter, 0.9f);

	layout->AttachPos(textButton,

 		nGuiFormLayout::Left, 0.2f);

		this->closeButton = textButton;



As most of this is self explaining we will only have a closer look at some nebula specialities:

  • color definitions use a vector4 in RGBA format
  • size definitios of a widget are done by providing height and width
  • positioning of a widget is achieved by one of three different methods:
    nGuiFormLayout::AttachToWidget(nGuiWidget* widget, Edge where, nGui- Widget* other, float offset)
    nGuiFormLayout::AttachToForm(nGuiWidget* widget, Edge where, float offset)
    nGuiFormLayout::AttachToPosition(nGuiWidget* widget, Edge where, float pos)

    You can also use a combination of the three methods. The following edge types are allowed:
    Top, Bottom, Left, Right
    HCenter, VCenter
  • float values for size and position are between 0.0f and 1.0f since they are relative values (percentage of total layout)

Creation of bigger or more complex user interfaces is not an easy task in Nebula2 and requires a lot of training especially with the AttachToXX methods which are not very intuitive and the result is visible only on execution of your program code.

Definition of brushes

You can assign up to four brusshes to each widget. These are used as textures for your widget in the corresponding state. You assign a brush with the nGuiWidget::SetXXBrush(const char* brushName) method. The four valid states are:

  • Default
  • Highlight (mouse over widget)
  • Pressed (mouse over widget and mouse button pressed)
  • Disabled (Widget is deactivated)

The names of the brushes are defined in a script. The nebula internal brushes are located in the data/scripts/systemskin.tcl script. The command




.addbrush       

    



creates a new brush.

The following "window" brush definition




.addbrush window skin 8 154 4 4 1.0 1.0 1.0 1.0



means: If your code uses a brush called "window" it uses the rectangle in the skin.dds file starting at position x = 8 and y = 154 which extends by 4 Pixel into the x (right) and y (down) direction. The color defined in the texture should be used without change (hence the four 1.0 values for color modulation). Brush names must be unique! Two different brushes with the same name will crash the application. picture of the image file used as a system gui texture skin

Trigger GUI events

On interaction with the GUI elements nGuiEvents are created (by nGuiServer::PutEvent()). By overriding the OnEvent() method in your nGuiWidget derived classes you define which Events should be handled by your class. The following code closes the TestWindow.




void

nTestWindow::OnEvent(const nGuiEvent& event)

{

	if (event.GetType() == nGuiEvent::ButtonUp)

	{

		if (event.GetWidget() == this->closeButton)

		{

			this->SetCloseRequested(true);

		}

	}

	nGuiClientWindow::OnEvent(event);

}



The following types of events exist among others (full list can be found in the nGuiEvent class):

  • ButtonUp, ButtonDown
  • SliderChanged
  • SelectionChanged
  • Action
  • DialogOk, DialogCancel
  • ...

That's it.




Something missing? Mail to contact


2009-06-01
WoW Importer for Max
The World of Warcraft tool for 3D Studio has been updated. It now converts model files from WoW Client version 2.x (upto 2.7) and displays correct animations for multi mesh models. The script can be found here....
2007-03-07
nGUI explained
If you ever wanted some more details on the nebula2 nGUI System you can find it in the nGUI System article.
2006-10-17
Mangalore entity ID's
If you need information about the mangalore entity ID usage have a look here..
2006-08-06
Mangalore Articles
Added a new section about the mangalore game framework from radonlabs. The section contains some articles about my experience with mangalore. Read more here:
2006-03-10
Free models
Finally some free models for the Radonlabs SDK. You can download them here.