Paleta UI Usage Documentation

By:Alfredo Alvarez

Introduction
PaletaUI is a system that allows us to draw on top of opengl a general ui. The
system was meant to be used in programmatic way by creating the hierarchichal
structure inside your cpp classes or in a declarative by loading position and looks
from and xml file and finding the component to set the interactions. The system
takes care of font loading, quad drawing and image loading for you. The system is
build to be extensible and we will describe the components and process on this
document and in the design document for the system.

Setting up PaletaUI
No matter which way you plan to use the system there is an initial setup that needs
to happen in order for paletaUI to work we describe here the entry points that are
needed. All of them are encapsulated in the class UIManager

Initializing the Ui Manager
UI Manager requires to know the size of the screen before it can do anything. Do a
call like this before you call any other methods
UIManager::initialize(GAME_WIDTH, GAME_HEIGHT);

Making it part of the draw update loop
To be able to draw and update components you need to call the following methods
for the ui manager from your rendering loop. After you have drawn your 3d scene
UIManager::update();
UIManager::draw();

Taking input
The Mouse Is a bit harder to use than the other calls we have done so far you
basically need to retrieve the virtualMouse from Ui manager and then pass in the
options. Example using GLUT
void MousePress(int button, int state, int x, int y)
{
VirtualMouse * m = UIManager::getVirtualMouse();
m->X = x;
m->Y = y;
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
m->LeftButtonPressed = true;
}
if (button == GLUT_LEFT_BUTTON && state == GLUT_UP)
{
m->LeftButtonPressed = false;
}

if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
{
m->RightButtonPressed = true;
}
if (button == GLUT_RIGHT_BUTTON && state == GLUT_UP)
{
m->LeftButtonPressed = false;
}
}
void MousePos(int x, int y)
{
VirtualMouse * m = UIManager::getVirtualMouse();
m->X = x;
m->Y = y;
}

For the Keyboard is just a call to:
UIManager::handlekeyStroke(key);

Where key is the enum from GLUT

Programmatic Usage
Loading up Fonts
To load fonts u need to initialize the font manager then call font load and pass and
identifier: The third parameter Is the font size.
FontLoader::initialize();
//Initialize FontManager
FontLoader::loadFont("cyberspace.ttf", 'a', 56);
FontLoader::loadFont("arial.ttf", 'b', 16);

Loading up Images
We are using the texture manager from Azul:
TextureMan::addTexture("Rocks.tga", ROCKS );

View
To be able to use the system the minimum requirement is to have one View set To
Active with one frame in it.
View * startupUI = new View();
startupUI->addFrame(BottomFrame);
UIManager::setActiveView(startupUI);

Frame
Frames are used to control Z order First frame in is the lowest one in the system.
You need to set a widget to a frame. In a lot of scenarios You will add a panel to the
frame to be able to add multiple widgets into the panel.
Frame* topframe = new Frame();
Panel* onlyPanel = new Panel(GAME_WIDTH,GAME_HEIGHT);
onlyPanel->setBottom(0);
onlyPanel->setLeft(0);
onlyPanel->clearBackground();
topframe->setWidget(onlyPanel);
startupUI->addFrame(BottomFrame);
startupUI->addFrame(topframe);

Widget
Is the base class for all the component from here on on all widget have the following
attributes: This is the class you inherit from if you are adding a new component
Widget * img2 = new Image();
img2->setSize(140, 100);
img2->setBottom(40);
img2->setLeft(100);

Panel
The Panel is a Widget that can hold a multitude of widgets inside their main point is
that they are a reference point to move widget together.
Panel* onlyPanel = new Panel(GAME_WIDTH,GAME_HEIGHT);
onlyPanel->setBottom(0);
onlyPanel->setLeft(0);
onlyPanel->clearBackground();
Image * img = new Image();
img->setSize(160, 100);
img->setTexture(LASER);
img->setBottom(190);
img->setLeft(100);
onlyPanel->addChildren(img);

Label
The label is a panel that contains text inside of it. Is Used like most of the others but
contains a property SetText. In the example left Side is a panel.
Label * WeaponsLabel = new Label();
WeaponsLabel->setFontName('b');
WeaponsLabel->setFontColor(&Colors::White);
WeaponsLabel->setBackground(&Colors::DarkerGrey);
WeaponsLabel->setText("WEAPONS:");
WeaponsLabel->setBottom(300);
WeaponsLabel->setLeft(20);
WeaponsLabel->setSize(140, 50);

LeftSide->addChildren(WeaponsLabel);

Textbox
The textbox is similar to the label but it allows people to write on it. getText will give
you back the updated text.
Textbox * tb = new Textbox();
tb->setSize(240, 25);
tb->setFontName('b');
tb->setText("Name");
tb->setBottom(450);
tb->setLeft(20);
LeftSide->addChildren(tb);

Button
The Button takes click and hover commands. Basically allows actions when clicked
and hovered over it. We show how to create a command from scratch below. But the
importan thing is that it needs to be setup.
Button * playButton = new Button();
playButton->setFontName('b');
playButton->setText("Play");
playButton->setSize(70, 30);
playButton->setLeft(305);
playButton->setBottom(200-35);
GotoPlaySceneAndSaveDataCommand * pCommand = new
GotoPlaySceneAndSaveDataCommand(tb2->getText(), tb->getText());
playButton->setClickCommand(pCommand);
RightSide->addChildren(playButton);

Image
The Image is a panel that takes an Azul TextureName to allow to display that image.
Image * img9 = new Image();
img9->setSize(50, 50);
img9->setTexture(STAR);
img9->setBottom(5);
img9->setLeft(630);
onlyPanel->addChildren(img9);

Command System
Below a sample of how to implement a command:
#ifndef IncrementIntClickCommand_H
#define IncrementIntClickCommand_H
#include "Command.h"
class IncrementIntClickCommand : public Command
{

public:
IncrementIntClickCommand();
virtual bool Execute(Widget * parent, EventDetails *);
void setValue(float f);
float getValue();
void setIncrement(float f);
~IncrementIntClickCommand();
private:
float value;
float increment;
};

#endif

Cpp
#include "OpenGL.h"
#include "CDM_Debug.h"
#include "IncrementIntClickCommand.h"
IncrementIntClickCommand::IncrementIntClickCommand()
{
out("IncrementIntClickCommand(): ---------------------\n");
}
bool IncrementIntClickCommand::Execute(Widget * parent, EventDetails *)
{
parent;
value += increment;
return false;
}
void IncrementIntClickCommand::setValue(float f)
{
value = f;
}
float IncrementIntClickCommand::getValue()
{
return value;
}
void IncrementIntClickCommand::setIncrement(float f)
{
increment = f;
}
IncrementIntClickCommand::~IncrementIntClickCommand()
{
}

Declarative Usage
How to Load:
Is a very simple call to deserialize and entire view.
View * currentView = ViewSerializer::Load("GameScene.xml");

How to Search For a Component:
You can Search for a component by name to programmatically change is properties
even if it was originally in declarative form: Using on Frame getFrameByName and
the getWidgetByName on Widget.
View * currentView = ViewSerializer::Load("GameScene.xml");
Frame * of = currentView->getFrameByName("OnlyFrame");
Panel * p = (Panel*)of->getWidget();
Button* bb = (Button *)p->getWidgetByName("BackButton");

Sample Scene
Displaying the usage of the components.
<View Name="MainView">
<Frame Name="OnlyFrame">
<Panel Name="ThePanel">
<Label Name="CountLabel" Font="b" Left="360"
Bottom="550" Text="0" Width ="60" Height ="20" />
<Label Name="ScoreLabel" Font="c" Left="320"
Bottom="570" Text="Score:" Width ="60" Height ="20" />
<Label Name="LivesLabel" Font="c" Left="600"
Bottom="570" Text="Lives:" Width ="60" Height ="20" />
<Button Name="BackButton" Font="b" Left="20"
Bottom="560" Text="Start Screen" Width ="130" Height ="30"/>
<Image Name="Star1" Left="700" Bottom="570"
TextureName="STAR" Width ="20" Height ="20" />
<Image Name="Star2" Left="735" Bottom="570"
TextureName="STAR" Width ="20" Height ="20" />
<Image Name="Star3" Left="770" Bottom="570"
TextureName="STAR" Width ="20" Height ="20" />
<Label Name="PilotLabel" Font="c" Left="10" Bottom="120"
Text="Pilot Name:" Width ="60" Height ="20" FontColor= "RED" />
<Label Name="PilotName" Font="b" Left="20" Bottom="95"
Text="REal NAme" Width ="60" Height ="20"/>
<Label Name="ShipLabel" Font="c" Left="10" Bottom="60"
Text="Ship Name:" Width ="60" Height ="20" FontColor="RED" />
<Label Name="ShipName" Font="b" Left="20" Bottom="35"
Text="REal NAme" Width ="60" Height ="20"/>

</Panel>
</Frame>
</View>

Extending Paleta
Creating a new Widget
All of the main components in Paleta Ui have virtual methods to follow the
open/closed principles and extend for them. With that said the most common case
is the need for a widget or a panel if needs to have widget children’s. To do you do
public inheritance from Widget or Panel and you are required to implement. The
update method.
Below is an example of a HighScoreWidget this is an interesting example because is
a component that uses other widgets from the framework. Note that implementing
a widget won’t make it discoverable to the serialization pipeline for that please look
below.
To see the UML of the Ui Objects please refer to the design document.
HighScoreWidget.h
#ifndef HighScoreWidget_H
#define HighScoreWidget_H
#include "Label.h"
#include "Widget.h"
class HighScoreWidget:public Widget
{
public:
HighScoreWidget();
virtual void draw(int x, int y);
virtual void update();
void setHeaderFont(char f);
void setScoreFont(char f);
void setItem1(char* initials, char * score);
void setItem2(char* initials, char * score);
void setItem3(char* initials, char * score);
~HighScoreWidget();
private:
Label * titleName;
Label * titleScore;
Label * name1;
Label * name2;
Label * name3;
Label * score1;
Label * score2;
Label * score3;
};

#endif

HighScoreWidget.cpp
HighScoreWidget::HighScoreWidget()
{
titleName = new Label();
titleName->setText("Initials");
titleName->setSize(100, 30);
titleName->setLeft(20);
titleName->setBottom(320);
titleScore = new Label();
titleScore->setText("Score");
titleScore->setSize(100, 30);
titleScore->setLeft(160);
titleScore->setBottom(320);
name1 = new Label();
name1->setSize(100, 30);
name1->setLeft(25);
name1->setBottom(270);
name2 = new Label();
name2->setSize(100, 30);
name2->setLeft(25);
name2->setBottom(220);
name3 = new Label();
name3->setSize(100, 30);
name3->setLeft(25);
name3->setBottom(170);

score1 = new Label();
score1->setSize(100, 30);
score1->setLeft(185);
score1->setBottom(270);
score2 = new Label();
score2->setSize(100, 30);
score2->setLeft(185);
score2->setBottom(220);
score3 = new Label();
score3->setSize(100, 30);
score3->setLeft(185);
score3->setBottom(170);
}
void HighScoreWidget::draw(int x, int y)
{
int posx = this->left + x;
int posy = this->bottom + y;
Widget::draw(posx, posy);
titleName->draw(posx,posy);
titleScore->draw(posx, posy);;
name1->draw(posx, posy);
name2->draw(posx, posy);
name3->draw(posx, posy);
score1->draw(posx, posy);
score2->draw(posx, posy);

score3->draw(posx, posy);
}
void HighScoreWidget::update()
{
}
void HighScoreWidget::setHeaderFont(char f)
{
titleName->setFontName(f);
titleScore->setFontName(f);
}
void HighScoreWidget::setScoreFont(char f)
{
name1->setFontName(f);
name2->setFontName(f);
name3->setFontName(f);
score1->setFontName(f);
score2->setFontName(f);
score3->setFontName(f);
}
void HighScoreWidget::setItem1(char * initials, char * score)
{
name1->setText(initials);
score1->setText(score);
}
void HighScoreWidget::setItem2(char * initials, char * score)
{
name2->setText(initials);
score2->setText(score);
}
void HighScoreWidget::setItem3(char * initials, char * score)
{
name3->setText(initials);
score3->setText(score);
}
HighScoreWidget::~HighScoreWidget()
{
delete titleName;
delete titleScore;
delete name1;
delete name2;
delete name3;
delete score1;
delete score2;
delete score3;
}

Adding Serialization Ability
In order to Serialize a custom class two things need to happen you need to create a
serializer class for it that inherits publically from WidgetSerializerComponent and
You need to register this component with the static class Widget Serializer by calling
Add. I recommend to that right after your UiManager Initialize Call.
Example:
Sample element for HighsScoreWidget
<HighScoreBoard Name="HighScore" ScoreFont="b" HeaderFont="c" Left="250"
Bottom="150"
Width="300" Height="350" Background="DARKERGREY"
Player1="AAA" Score1="20"
Player2="BBB" Score2="25" Player3="CCC" Score3="35" />
HighScoreWidgetSerializer
#include "HighScoreWidgetSerializer.h"
#include "HighScoreWidget.h"
HighScoreWidgetSerializer::HighScoreWidgetSerializer()
{
out("HighScoreWidgetSerializer(): ---------------------\n");
serializationName = "HighScoreBoard";
}
Widget * HighScoreWidgetSerializer::Load(tinyxml2::XMLElement * el)
{
if (el != 0)
{
const char * elementName = el->Name();
if (strcmp(elementName, serializationName) == 0)
{
HighScoreWidget * l = new HighScoreWidget();
this->SetWidgetPropertiesFromXml(l, el);
if (el->Attribute("HeaderFont"))
{
l->setHeaderFont(el->Attribute("HeaderFont")[0]);
}
if (el->Attribute("ScoreFont"))
{
l->setScoreFont(el->Attribute("ScoreFont")[0]);
}
if (el->Attribute("Player1") && el->Attribute("Score1"))
{
l->setItem1((char *)el->Attribute("Player1"), (char*)el>Attribute("Score1"));
}
if (el->Attribute("Player2") && el->Attribute("Score2"))
{
l->setItem2((char *)el->Attribute("Player2"), (char*)el>Attribute("Score2"));
}
if (el->Attribute("Player3") && el->Attribute("Score3"))
{

l->setItem3((char *)el->Attribute("Player3"), (char*)el>Attribute("Score3"));
}
return l;
}
}
return 0;
}
HighScoreWidgetSerializer::~HighScoreWidgetSerializer()
{
}

Master your semester with Scribd & The New York Times

Special offer for students: Only $4.99/month.

Master your semester with Scribd & The New York Times

Cancel anytime.