Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

DarkBASIC Professional Discussion / The Official GUI Discussion Thread

Author
Message
Sasuke
20
Years of Service
User Offline
Joined: 2nd Dec 2005
Location: Milton Keynes UK
Posted: 9th Aug 2010 20:06
I thought I'd start a GUI discussion thread because GUI's are not only a life saver when creating tools to interact with your engine, but can be used for many things, even if it's simple controls to a simple demo, even a hud. So we can cover the benifits, how to make them, use them and etc here. So...

What's A GUI?
A graphical user interface (GUI) (sometimes pronounced gooey) is a type of user interface item that allows people to interact with programs in more ways than typing such as computers; hand-held devices such as MP3 players, portable media players or gaming devices; household appliances and office equipment with images rather than text commands. A GUI offers graphical icons, and visual indicators, as opposed to text-based interfaces, typed command labels or text navigation to fully represent the information and actions available to a user. The actions are usually performed through direct manipulation of the graphical elements. - Wikipedia

Now that's out of the way, we need to discuss them. So where should we start... no seriously, where should we start?

Note: Will edit that last sentence in the future.

A dream is a fantasy, if you achieve that fantasy it was never a dream to begin with.
Zotoaster
21
Years of Service
User Offline
Joined: 20th Dec 2004
Location: Scotland
Posted: 9th Aug 2010 20:16 Edited at: 9th Aug 2010 20:16
The problem with a lot of GUI systems that are written by non-experienced people is that they are completely different layers to the actual program you're writing. The problem with this is that a lot of work is put into linking up events in the GUI to their effects in the program.

Using an object oriented system, it's not difficult for gadgets in the GUI system to have delegate objects, such that when a button (for example) is clicked, it doesn't simply return 'true', but it calls a method such as 'Clicked()' in the delegate object, which is set when the button is created. That means a lot of the responsibility is taken away from the user, even if it's not quite as intuitive to think about. Unfortunately this is impossible in DBP.

There's a good conversation starter.

"everyone forgets a semi-colon sometimes." - Phaelax
mikewhl
16
Years of Service
User Offline
Joined: 19th Jul 2010
Location: Columbus,Ohio
Posted: 9th Aug 2010 22:26
Hi all,
I am so new to DBP that my posts in these forums still have that new car smell!
There sure seems to be a lot of talk about GUI's. I really don't know why that is.

""(for example) is clicked, it doesn't simply return 'true', but it calls a method such as 'Clicked()' in the delegate object""

My comment is this, can't you just use a "IF" statement to call your function once it's clicked?

I guess I am still under the influence of ignorance!
I will keep an eye on this thread! Trying to learn as much as I can.

Thanks for all you help guys!

Mike

some cool stuff someone else said here
baxslash
Valued Member
Bronze Codemaster
19
Years of Service
User Offline
Joined: 26th Dec 2006
Location: Duffield
Posted: 9th Aug 2010 22:30
@Zotoaster is talking about Object Oriented Programming (or OOP). It does sound simple but it gets complicated, I suggest looking it up in Wikipedia if you get bored but DBP is not an OOP language so maybe get stuck into DBP for a while first!

IanM
Retired Moderator
23
Years of Service
User Offline
Joined: 11th Sep 2002
Location: In my moon base
Posted: 9th Aug 2010 22:37
Of course, you can dump all of the OO-gui stuff and simply render your gui as you need to, linking the gui directly with the code that it controls, i.e. even closer than is possible with an OO system.

Google 'Immediate GUI' and at least watch the Molly Rocket video for the ideas behind it.

Zotoaster
21
Years of Service
User Offline
Joined: 20th Dec 2004
Location: Scotland
Posted: 9th Aug 2010 23:42
mikewhl,

Of course, using an if-statement is the intuitive way of doing it. if this button is clicked then do something. The problem with this is that it takes a lot of manual code to link the GUI with the actual program. Using an OO (object oriented system), the button would be an object, which, when clicked, affects another object in the system. You set a 'delegate' object in the button object, and when the button is clicked it automatically does something to the delegate object. All that you need to do to link the UI to the program is setting the delegate object, and nothing else. All the responsibility you have now is to actually fill in the functionality of the method invoked when the button is clicked.

IanM,

I'll look into that.

"everyone forgets a semi-colon sometimes." - Phaelax
Diggsey
20
Years of Service
User Offline
Joined: 24th Apr 2006
Location: On this web page.
Posted: 10th Aug 2010 00:41 Edited at: 10th Aug 2010 19:05
Quote: "Unfortunately this is impossible in DBP."


I wrote a GUI for DBPro called ViewGUI ages ago which let you do this by using the function pointer functionality of IanM's plugins.

It had a visual designer which let you easily add events by simply double clicking, and it would automatically generate the name (<control name>_<event name> or you could choose your own. When you saved your GUI to a .dba file it generated these functions and attached them to their events. My latest Box2D plugin can optionally support function pointer event handlers too.

It even had a rich text control which supported embedded images and you could detect when a piece of text or image was clicked.

Its main let-down was that the default style was not very professional, it used flat coloured rectangles with borders for most of the controls.

After doing ViewGUI I started on ExtraGUI which was based on using Lua to design controls making it truly customizable, allowing you to easily use images and rounded rectangles for controls. The problem there was that I over-engineered it too much and it was simply so flexible that it was a pain to work with.

I think the key to a good GUI system (and the same for most APIs) is getting the right balance between flexibility and ease of use.

Strangely enough I recently started on a javascript library which incorporates a GUI among other things as a fun project to do.

It's quite useful as you can design a whole webpage exactly how you want it to be, and since the javascript library itself can be cached, the code which displays the page will be far smaller than any normal web-page, and yet will be more compatible with browsers and will resize better than normal pages. The library itself handles all browser issues and standardises event handling across all browsers.

Another benefit is that the entire page will be easily AJAX compatible. Since every 'control' on the page has a script object you can edit the page as much as you want, without fear of breaking the layout.

[b]
Zotoaster
21
Years of Service
User Offline
Joined: 20th Dec 2004
Location: Scotland
Posted: 10th Aug 2010 19:53 Edited at: 10th Aug 2010 19:55
IanM,

That seems very similar to some of the earliest ways I would make GUI systems, way back in the day (Okay I'm not old enough to say that yet). It's a decent system but it doesn't really give you much power over the organisation of your interface. I like to have a hierarchy where forms contain further 'child' forms, and effects on them can cascade down the tree. Also, I wouldn't like to embed every single button press code in my main loop, or that would become a huge mess!

I'm still standing by that using the delegate pattern is the best way, or of course using function pointers.

On that note (but slightly off topic), anyone know of any languages where you can create "anonymous" functions/methods? For instance, say you wanted something to happen on the click of a button. It might look like this:


That way, the button would have a piece of code handy, ready to run it whenever it needs to. I know this is possible using function pointers, but I don't know if they can be inlined like that.

"everyone forgets a semi-colon sometimes." - Phaelax
Diggsey
20
Years of Service
User Offline
Joined: 24th Apr 2006
Location: On this web page.
Posted: 10th Aug 2010 20:07
@Zotoaster
Javascript can do just that. C++0x can too (VC++ 2010).

@IanM
Just watched that video. It's a technique I've used a few times before but never really considered as a serious option, mainly due to my prejudice about it not being OOP.

However, I can see that it's a much better way of doing things, at least when hardware acceleration is used anyway.

I had this code lying around from the last time I used an immediate mode GUI:


It doesn't require any plugins. You just need to call 'updateInput()' once a loop, and then call 'updateXXX' to draw a control.

[b]
Sasuke
20
Years of Service
User Offline
Joined: 2nd Dec 2005
Location: Milton Keynes UK
Posted: 10th Aug 2010 23:31
Although the immediate method maybe a better way of doing things, in DBP, not so much.

All the drawing of 2d and text is just too demanding, even with cloggy's plugins. The problem is we can't keep something drawn, something that doesn't need to be drawn again until it changes state or moves (unless your a mad scientist like me and found a highly impracticable method around this by dumping all inactive elements to a single image). We can cut the cost by pre rendered (externally I mean, like created in Photoshop and loaded in dbp as a resource) parts of the gui like the corners, edges and middle of a window and paste these elements together to form one and apply text afterwards. The main issue is text which is demanding a hell.

Then again, this depends on what your using it for. If it's only a small gui for altering a few things in a demo or something then I'd use the immediate method. But when alot of GUI elements need to be draw to the screen, then the immediate method wouldn't work.

I think the main topic should be the drawing of the GUI.

A dream is a fantasy, if you achieve that fantasy it was never a dream to begin with.
Diggsey
20
Years of Service
User Offline
Joined: 24th Apr 2006
Location: On this web page.
Posted: 11th Aug 2010 00:14
@Sasuke
With ViewGUI I had no problem rendering hundreds of pieces of text and semi-transparent windows in realtime, and that did not use dirty regions. Text is obviously more demanding than drawing boxes, but drawing 1000 characters in a textbox can easily be done in a single drawing operation using Direct3D in no time at all.

It only takes 2 polies per character, which is nothing for even fairly old graphics cards.

A perfect example is WPF. WPF uses hardware acceleration AND it only draws the dirty regions. I don't know if you've ever used WPF, but it is ridiculously slow compared to what it should be. This is because of the massive overhead of all the data that is stored per GUI item, and worst of all this overhead is on the CPU.

I would much rather get rid of the 'dirty regions' functionality if it included the overhead.

As long as hardware acceleration is used, I see no reason why an immediate GUI cannot be as fast if not faster than any normal GUI.

[b]
Phaelax
DBPro Master
23
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 11th Aug 2010 02:19
I'll have to watch that mollyrocket video later and see what this immediate gui method is you're all talking about.

Quote: "On that note (but slightly off topic), anyone know of any languages where you can create "anonymous" functions/methods? For instance, say you wanted something to happen on the click of a button. It might look like this"


Java can do something like that by defining a listener's action at the time you assign it to the button.



Quote: "We can cut the cost by pre rendered (externally I mean, like created in Photoshop and loaded in dbp as a resource) parts of the gui like the corners, edges and middle of a window and paste these elements together to form one and apply text afterwards. The main issue is text which is demanding a hell."


I used a similar method when redesigning my iTunes clone. With all the drawing operations, framerates were under 40. I then got the idea that images were probably faster and so I drew the majority of the components (rounded corners, buttons, scrollbars, etc) into memblocks and created images from them directly. It required a little extra code not only to draw the images but also to position the parts properly, but the payoff was well worth it. The GUI's frame rates jumped to over 1000 at first, but then fell to about 400 after I drew the text, which isn't practical to draw to an image. But still, that's 10x what I was getting before and now my images were able to make use of my many AA drawing functions efficiently.

I kept design and functionality as separate as possible, with one function call to update the GUI and another to handle the UI controls.



Quote: "I think the main topic should be the drawing of the GUI."

Depending on the complexity of the GUI, using simple box commands might be sufficient. If you plan on drawing several elements or rely heavily on transparency, then I'd go with prerendered images.


"Any sufficiently advanced technology is indistinguishable from magic" ~ Arthur C. Clarke
GIDustin
18
Years of Service
User Offline
Joined: 30th May 2008
Location:
Posted: 11th Aug 2010 08:50
I just watched that Immediate Gui video and it was interesting. One of the things that bothered me, which he finally did mention at the end, is that no gui element has any knowledge of the other gui elements. Maybe I am just not in the right mind of thinking, but imagine a gui with windows that can be moved around. Two windows, each with a button, and you move one on top of the other. How does an IM GUI know which one is on top? When you call DoButton() for each button, both are going to see the mouse on top of them and think they are "hot".

I do see the benefits though. My RichText controls have alot of variables, keeping track of Cursor positions, click states, scrollbar states, etc. My "label" control, which simply prints text and has no interaction at all, wastes all those variables since they are both stored in the same UTD array.

/shrug

Interesting video, but I am not ready to jump ship. If it isn't broke....
Diggsey
20
Years of Service
User Offline
Joined: 24th Apr 2006
Location: On this web page.
Posted: 11th Aug 2010 12:48
@GIDustin
There are a number of ways to do that. The most obvious is for the client application to manage it.

On the client side you would have an array of windows, and for each element in the array you call the app function associated with that window. Inside that function, when you call 'DoWindow' you check if it became the active window. If it did, you move it to the end of the window array.

Alternatively, the library could have built in Z-depth functionality, where it either clips other controls around the shape of the window, or it buffers all drawing commands until the main GUI update, and then before executing them it sorts them based on the Z depth of their associated control.

If the drawing commands are buffered, it could even be optimised to only draw areas on the screen which changed.

[b]
Omen
19
Years of Service
User Offline
Joined: 7th Nov 2006
Location: Maple Grove, MN US
Posted: 15th Aug 2010 05:14 Edited at: 15th Aug 2010 06:41
You could always write the whole thing in DarkBASIC too - with the proper code you can keep up to 100 elements on the screen simultaneously with no significant performance degradation (of course, YMMV with hardware, all my HW is 10 yrs old).

I did everything with sprites that are only updated when they _absolutely_ need to be using a secondary (or in some cases tertiary) BITMAP instead of BITMAP 0 for all the update work.

Attached is the GUI I used for World of OMEN. It's 4389 lines, so I couldn't just add it to the message unfortunately.

I've also included sample skins, and all the INI files for the various windows used.

@IanM,

Ahh, I know where I've heard that term before now... Immediate Mode GUI is what Unity uses

http://unity3d.com/support/documentation/Components/GUI%20Scripting%20Guide.html

heheh right from the Unity GUI tutorial - yeah, seems to be what everyone is raving about right now:



Sasuke
20
Years of Service
User Offline
Joined: 2nd Dec 2005
Location: Milton Keynes UK
Posted: 25th Aug 2010 22:39
One thing I've done which I think is a good idea is to have a sort of Gui Director, that controls and directs the gui. For instance, the guiDirector stores the first container (windows or things you can attach gadgets too) and first child (gadgets not attached to a container). The way it works is anything attached to the guiDirector is classed as Active. Each container knows it's next and last container, but this only applies to active containers/childs. The reason I did this is so I don't need to check if a container is active/hidden or dead since being a child of the guiDirector it's already active. I only have to loop from the first container attached to the guiDirector until a containers next container equals -1. Anything else doesn't need updating or drawing since isn't not a child of the guiDirector. Just note, there's also a hidden container list and other lists from the guiDirector (these are linked lists if I didn't mention already).

The guiDirector also can lockout the child lists, telling it to not update its childs, or not to draw its childs or update a specific child only.

Containers work similar, directing their childs as the guiDirector does though only if a container is 'hot' meaning mouse over or some special condition is met.

At the moment, I'm experimenting with the drawing method to do what I said earlier.

@Omen, that's pretty neat, took awhile to figure it out though, there's a ton there. Still going through it though, but cheers for the upload

A dream is a fantasy, if you achieve that fantasy it was never a dream to begin with.
Omen
19
Years of Service
User Offline
Joined: 7th Nov 2006
Location: Maple Grove, MN US
Posted: 26th Aug 2010 00:57
@sasuke,
Ah thanks - can't take all the credit tho -- it's an extension of something called demongui originally posted by Lancewrath in July 2008. I got everything working, added quite a bit to it, streamlined and simplified parts, and generally made it more self-contained. But at the core, it's demongui

Sasuke
20
Years of Service
User Offline
Joined: 2nd Dec 2005
Location: Milton Keynes UK
Posted: 26th Aug 2010 01:54
I remember that project, I followed it until Lancewrath disappeared of the face of the earth. Wonder what happen to him?

A dream is a fantasy, if you achieve that fantasy it was never a dream to begin with.
Sasuke
20
Years of Service
User Offline
Joined: 2nd Dec 2005
Location: Milton Keynes UK
Posted: 27th Sep 2010 00:02 Edited at: 27th Sep 2010 14:53
Quote: "
One thing I've done which I think is a good idea is to have a sort of Gui Director, that controls and directs the gui. For instance, the guiDirector stores the first container (windows or things you can attach gadgets too) and first child (gadgets not attached to a container). The way it works is anything attached to the guiDirector is classed as Active. Each container knows it's next and last container, but this only applies to active containers/childs. The reason I did this is so I don't need to check if a container is active/hidden or dead since being a child of the guiDirector it's already active. I only have to loop from the first container attached to the guiDirector until a containers next container equals -1. Anything else doesn't need updating or drawing since isn't not a child of the guiDirector. Just note, there's also a hidden container list and other lists from the guiDirector (these are linked lists if I didn't mention already).

The guiDirector also can lockout the child lists, telling it to not update its childs, or not to draw its childs or update a specific child only.

Containers work similar, directing their childs as the guiDirector does though only if a container is 'hot' meaning mouse over or some special condition is met.
"


This is kind of the idea I was talking about, nothing overly complex, but works wonders and is very easy to expand on:



A dream is a fantasy, if you achieve that fantasy it was never a dream to begin with.
David Gervais
Retired Moderator
20
Years of Service
User Offline
Joined: 28th Sep 2005
Location: Montreal, Canada
Posted: 27th Sep 2010 03:34 Edited at: 27th Sep 2010 03:38
When I do buttons and stuff in DBPro, I make the different versions of the buttons (normal, mouse-over, clicked/pressed) and place all the corresponding sprites on the screen. I then use 'logic' and the 'Hide sprite/show sprite' commands to set which sprite should be seen. it works and seems to be allot faster than using paste sprite or sprite #,x,y all the time.

That's just one trick I use on my end..

OOP is overrated, it was invented by people who believe in the simplification of code through complicated algorythms and hyper dynamic coding.. using 'logic' is so 'old school'..

I AM Old school,.. if I know that the results of calculating the length of a diagonal line 10 inches long at a 45deg tangent from the center is a length of 7.02 inches, the then I can safely use Length *.7 and forgo the lengthly calcs.. but some people 'require' nay 'demand' double precision floating point accuracy, even if the end user will 'NEVER' see or notice the difference.

I once had to make 'invisible' transparent 1x1 pixel sprites for a game to fix a floating point bug in a game.. for lack of any good names for these 'special' sprites I called them pig_arm, pig_foot, pig_tail, and pig_wings. yes, I worked on a game that 'required' invisible flying pigs to make the game work. And this was because the very idea of inserting a (if var_x =0 then var_x = 0.01) before the line that did the (var_p = var_y/var_x) which would have avoided that particular divide by zero bug. seemed to be incomprehensible to them. they inserted the invisible pig parts and gave them a width of 0.01 and used that in their over complicated formula. lol

Anyways, the hide sprite show sprite works for me, and it's fast,.. try it!

Cheers!

Sasuke
20
Years of Service
User Offline
Joined: 2nd Dec 2005
Location: Milton Keynes UK
Posted: 28th Sep 2010 02:44 Edited at: 28th Sep 2010 03:06
Quote: "I once had to make 'invisible' transparent 1x1 pixel sprites for a game to fix a floating point bug in a game.. for lack of any good names for these 'special' sprites I called them pig_arm, pig_foot, pig_tail, and pig_wings. yes, I worked on a game that 'required' invisible flying pigs to make the game work. And this was because the very idea of inserting a (if var_x =0 then var_x = 0.01) before the line that did the (var_p = var_y/var_x) which would have avoided that particular divide by zero bug. seemed to be incomprehensible to them. they inserted the invisible pig parts and gave them a width of 0.01 and used that in their over complicated formula. lol"


LOL

Another idea I had was to have GUI Styles for the drawing of gui elements. So I create a windowStyle, telling it where and how I want things drawn (like a template). Then input my window coords into the style and its drawn based on the template. Very handy with an editor. Here's and example of what I mean:



It could be expanded to add a paste image element, shadow element and even further.

A dream is a fantasy, if you achieve that fantasy it was never a dream to begin with.
Grog Grueslayer
Valued Member
21
Years of Service
User Offline
Joined: 30th May 2005
Playing: Green Hell
Posted: 1st Oct 2010 05:04
Quoting Sasukes code:
Quote: "get image 1,0,0,testWindow.size.x,testWindow.size.y,1"


I do this too for the GUI on the replacement application I'm making for work. But after the GUI images are grabbed they are then saved to files. When the application is first ran it checks to see if the menu images exist. If they do exist they're loaded... if not they're drawn and saved for the next time it's ran. Any changes the user makes to the color scheme the menus are all drawn and saved again. It makes loading the application a lot faster since it only draws the menus as needed.

Sasuke
20
Years of Service
User Offline
Joined: 2nd Dec 2005
Location: Milton Keynes UK
Posted: 1st Oct 2010 08:36 Edited at: 1st Oct 2010 08:37
I do something sort of similar (not shown here yet), which is an ImageBatch, an image that contains all the GUI drawing elements (or anything I want the batch to contain, like every icon). So if I draw something that doesn't have varying sizes like a close button on a window, I draw all it's states and add it to an ImageBatch which draws it to an image and stores it's coords. When ImageBatchEnd is declared, it's image and coords are stored in files, which can be loaded and used for pasting or copying. (Sven B's ImageKit is required for this though)

The advantage of this is you don't have a ton of images with the same stuff on them, just one big image with everything you need on it.

A dream is a fantasy, if you achieve that fantasy it was never a dream to begin with.

Login to post a reply

Server time is: 2026-07-23 11:20:26
Your offset time is: 2026-07-23 11:20:26