GUI in OpenGL

Started by
14 comments, last by hogosha 20 years, 9 months ago
I am trying to write make a graphical interface in my OpenGL, so whats the best way to do it. im going to use it for a game, doesnt necessarily have to use textures, but it may help. Using SDL as well in my code. Higher Forces
Advertisement
This isn''t the best way, but its the way I do it...

1. Make a list of widgets your going to use, and the functions you''ll need to use them
2. Make a base GUI class, call it CGUI
3. GUI contains all the functions common to all you widgets(gain focus, lose focus, keypress, etc), and virtual functions to the ones that arn''t.
4. Create a class for all your widgets, inherite CGUI to each one, that way you already have obtained all your functinos.


5. Now, make a array of CGUI*, and initalize all your gui

array[0] = new CGUIBUTTON(location);
array[1] = new CGUITEXTBOX(location);

Then, whatever you have a need for a new press, do this

OnKeyPress()
{
for i = 0 to array_size
array->key_press();
}

etc, etc, so on and so forth.

~~~~~Screaming Statue Software. | OpenGL FontLibWhy does Data talk to the computer? Surely he's Wi-Fi enabled... - phaseburn
depending on how flexible you want to be you can use function or method pointers. so you write your onclick function for a certain button and just "link" it via the function pointer.

my current version:
http://festini.device-zero.de/downloads/ui.zip

only the source and it requires glut for now.. if you just want to have a look you can download the binary (i left out most textures in the src version)
http://festini.device-zero.de/downloads/srcc.zip

you still have to write your own class derived from dialogue and a a way to parse external files to build them at runtime wouldnt be a bad modification, but i wouldnt know how to add event functions without writing an interpreter for them.
f@dzhttp://festini.device-zero.de
@ dede:

A better way to do this is to:
1) Register all windows to somekind of 'GUIBase' object
2) Link GUI elements (like buttons) to a window, so they get rendered relatively to the window coordinates
3) When registering a window, also register a function that is called each render loop, that does actions on the controls:

GUIBase    guibase;GUIWindow  window(&guibase, callbackFunction, x, y);GUIButton  button1(&window, x, y, width, height);GUIText    textfield1(&window, &string, x, y, width, height);callbackFunction(){  // render button and return 'true' if button was clicked  if (button1.DoActions())     DoStuff();  // render and set &string if text was changed  textfield1.DoActions();}


[edit] This, together with GUI elements like checkboxes, textfields, labels and other took about 3 days to code. The window manager took 1/3 of that time. I didn't mention it because it's kinda complex, but If you need more info:
The window manager sits between the window and the gui base. It makes sure that all windows are rendered in a good order and checks if the user clicks a window and if that window needs to be brought to the front of the screen. I first worked with a linked list, but working with priority ID's (1 per window) is a better thing to do imho.

[edited by - Vich on July 3, 2003 4:57:22 PM]
[www.LifeIsDigital.net - My open source projects and articles.
If you are interested, see my GUI at http://ionware.8m.com. It currently have some controls, but its not completed yet.

If you have any questions, my MSN is: acolytee@hotmail.com
or ICQ: 42699190

Good luck.

" Do we need us? "


Ionware Productions - Games and Game Tools Development

if you need some impressions
here is the start of my Gui

i have created a basic CGui object which i am going to use as base object for all controls and so on

and a CGuiManager
the manager stores all the menus

and the controls are added to a child list of each individual menu

you can even add a button to a button LOL


here s some sample code( not much done though)

#include "standardheader.h"CGui::CGui(int x, int y, int width, int height){	m_pChildren=NULL;	m_pNext=NULL;	m_pParent=NULL;}CGui::CGui(int x, int y, int width, int height, CGui *pParent){	CGui(x,y,width,height);	SetParent(pParent);}//Setvoid CGui::SetParent(CGui *pParent){	if(!pParent)		return;	m_pParent=pParent;	pParent->AddChild(this);}void CGui::SetVisible(BOOL bVisible){	m_bVisible=bVisible;}void CGui::SetBorder(int size){	m_iBorderSize=size;}void CGui::SetFgColorfv(float *color){	if(!color)		return;	m_flFgColor[0]=color[0];	m_flFgColor[1]=color[1];	m_flFgColor[2]=color[2];	m_flFgColor[3]=color[3];}void CGui::SetFgColorf(float r,float g, float b, float a){	m_flFgColor[0]=r;	m_flFgColor[1]=g;	m_flFgColor[2]=b;	m_flFgColor[3]=a;}void CGui::SetFgColoriv(int *color){	if(!color)		return;	m_flFgColor[0]=color[0]/255;	m_flFgColor[1]=color[1]/255;	m_flFgColor[2]=color[2]/255;	m_flFgColor[3]=color[3]/255;}void CGui::SetFgColori(int r, int g, int b, int a){	m_flFgColor[0]=r/255;	m_flFgColor[1]=g/255;	m_flFgColor[2]=b/255;	m_flFgColor[3]=a/255;}void CGui::SetBgColorfv(float *color){	if(!color)		return;	m_flBgColor[0]=color[0];	m_flBgColor[1]=color[1];	m_flBgColor[2]=color[2];	m_flBgColor[3]=color[3];}void CGui::SetBgColorf(float r,float g, float b, float a){	m_flBgColor[0]=r;	m_flBgColor[1]=g;	m_flBgColor[2]=b;	m_flBgColor[3]=a;}void CGui::SetBgColoriv(int *color){	if(!color)		return;	m_flBgColor[0]=color[0]/255;	m_flBgColor[1]=color[1]/255;	m_flBgColor[2]=color[2]/255;	m_flBgColor[3]=color[3]/255;}void CGui::SetBgColori(int r, int g, int b, int a){	m_flBgColor[0]=r/255;	m_flBgColor[1]=g/255;	m_flBgColor[2]=b/255;	m_flBgColor[3]=a/255;}void CGui::SetPos(int x, int y){	m_iX=x;	m_iY=y;}void CGui::SetSize(int width, int height){	m_iWidth=width;	m_iHeight=height;}//Addvoid CGui::AddChild(CGui *pChild){	if(!pChild)		return;	CGui *p=NULL;;	if(m_pChildren==NULL)	{		m_pChildren=pChild;	}	else	{		p=m_pChildren;		while(p)		{			if(p->m_pNext==NULL)			{				p->m_pNext=pChild;				return;			}			p=p->m_pNext;		}	}}//Get/IsBOOL CGui::IsVisible(){	return m_bVisible;}//onvoid CGui::onPaint(){}void CGui::onPaintBackground(){}   




http://www.8ung.at/basiror/theironcross.html
hm.. if youre using a simple linked list (why not stl list or a minimal own list storing at least a first and last pointer?)... does the order matter? because if not it would seem a lot easier to do:

pChild->m_pNext=m_pChildren;
m_pChildren=pChild;

instead of:

if(m_pChildren==NULL) m_pChildren=pChild;
else {
p=m_pChildren;
while(p){
if(p->m_pNext==NULL) {
p->m_pNext=pChild;
return;
}
p=p->m_pNext;
}
}

or in other words: add them to the front, not the back.
f@dzhttp://festini.device-zero.de
performance is not an issue in my implementation since these functions are only called at start up time
when i initialize all the menues

that s only because i usually only work with lists where order matters

of course you could change itbut you probably get crazy when you have positioned an object incorrect

i am planning to implement a function that automatically aligns the controls so they don t intersect and that s easiest to do when you have got a sorted list
http://www.8ung.at/basiror/theironcross.html
Hi!

Since you''re using OGL, why wouldn''t use use one of the existing libraries? I''d suggest ParaGUI as the best one(search on google), I''d use it myself if it didn''t use OGL and SDL The other option would be glgui(I think it''s glgui.sourceforge.net), so give it a try.



--------
Leave all your expectations behind, or
they''ll pull you down on your way to the top.

-Ivan
-----------------------------------------------------It's better to rule in hell than to serve in heaven.------------------------------------------------------Ivan
I define GUIs using XML and then push and pop them to and from the screen when required. For example I define an About GUI:

	<gui name="About">        <component name="AboutCanvas" type="hbGuiCanvas">			<size>1.0, 1.0</size>			<position>0.0, 0.0</position>			<hpos>left</hpos>			<vpos>top</vpos>			<hsize>relative</hsize>			<vsize>relative</vsize>			<component name="AboutFrame" type="hbGuiBitmapFrame">				<position>0.2, 0.2</position>				<hpos>centre</hpos>				<vpos>centre</vpos>				<size>0.7, 360</size>				<hsize>relative</hsize>				<vsize>absolute</vsize>				<colour>128, 128, 128, 255</colour>				<bitmap>./data/gui/frame.png</bitmap>				<border>20, 20, 20, 20</border>				<component name="AboutButton" type="hbGuiBitmapButton">					<normal>./data/gui/TestExitNormal.tga</normal>					<focus>./data/gui/TestExitFocused.tga</focus>					<active>./data/gui/TestExitActive.tga</active>					<position>0.5, 0.05</position>					<hpos>centre</hpos>					<vpos>bottom</vpos>					<hsize>absolute</hsize>					<vsize>absolute</vsize>					<size>50.0, 33.0</size>					<audioOver>ButtonOver</audioOver>					<audioClick>Buttwhenclickedon</audioClick>					<command>ExitAbout</command>				</component>				<component name="TextArea1" type="hbGuiTextArea">					<font>DebugText</font>					<position>0.0, 0.0</position>					<hpos>centre</hpos>					<vpos>top</vpos>					<hsize>relative</hsize>					<vsize>relative</vsize>					<size>1.0, 0.8</size>					<text>./data/gui/about.txt</text>					<colour>225, 225, 225, 255</colour>				</component>			</component>		</component>    </gui> 


I then push it to the screen with a Lua script call like this:

Gui:Push("About") 


Gui components are coded in C++ and call Lua script functions when events occur, such as a button being pressed.

Edit: Fixed the source tags (I was using code instead of source - must remember that!).

[edited by - stodge on July 4, 2003 12:25:26 PM]
---------------------http://www.stodge.net

This topic is closed to new replies.

Advertisement