MinApp Tutorial #4 - More GUI Work
by John Vanderbeck · 01/22/2004 (3:12 pm) · 26 comments
Download Code File
Tutorial #4 - More GUI Work
Overview
This tutorial adds in a bunch more of the GUI code for our application. We will create several new GUIs and tie them together with the buttons we made in the previous tutorial.
There is really a lot to learn in this installment.
1) The credits screen
The credits screen will be a simple popup dialog box with credits listed on it. While this seems simple enough, it was right here that I ran into the first major problem of the series. But we'll get to that in a minute.
First, run the MinApp and press F10 to get into the GUI editor. Click on the File menu and choose New GUI. In the name field enter the name "creditsDlg" and click Create. You will now have a clean GUI slate to start working with. Next, we need to create our popup window. It seems a tad weird, since you would normally think of the window itself as the GUI, but in this case its a control. The GUI itself is the slate we just created. Click on New Control and select the profile "GuiWindowCtrl".
You will now see a blank default window control. Left click and drag to move the window somewhere in the center of the screen, and then resize it to make it slightly wider than tall. If you want to use the exact same numbers as I did, then you can manually set the position and extent. I used a position of 208,80 and an extent of 100,200. Once you have done that, set the "text" property of th window control to "MinApp Credits". If you look at the properties list, under the property "maxLength" you will see a series of checkboxes which control window features such as resizing, minimzing, etc. We want all of those OFF except for canClose and canMove which should be checked.
Now we come to the big problem that I ran into. At first, my next step was to create a GuiMLTextCtrl to hold the credits. I then placed this over the window and everything worked great. At least, until I clicked on the window. At that point, my text vanished. What was happening was that the window was being brought to the top of the "z-order". All the controls in the GUI have a top to bottom ordering, and when the window came to the top it covered the text. Obviously I needed some way to make the GUI understand that the text was part of the window.
So how do we make the text part of the window? We do this by making it a child control of the window control. In the upper right corner of the GUI editor you will see text that looks something like this: 1182: CreditsDlg - GuiControl
The number may be different on yours, but the text will be the same after that. To the left of that text is a small plus sign. Click the plus sign to expand it. This is a treeview of our GUI. The indentations show children. You will notice that the window we created is indented under the GuiControl. This signifies the window control is a child of the main GUI. What we want is to make a text control a child of the window. If you were to create a GuiMLTextCtrl control right now, it would become a child of the main GUI just like the window. Let's do that so we can see. Click New Control and select the GuiMLTextCtrl profile. See how the new control shows up with the same indentation as our window? Click on that new text control and press the DEL key to remove it. Now, right click on the GuiWindowCtrl. You will not notice much of a change, except a small red line at the top of the GUI. By right clicking though, you have told the GUI editor that you want to make a control that is a child of the window. Click New Control and select the GuiMLTextCtrl again. This time you will see that it shows up indented under the window control. We've now made it a child of the window control.
Position the text and resize it so it covers the interior of the window control. I used a position of 11,29 and an extent of 216, 84. If you look at the position, it should be more clear that this text control is a child of the window. Notice how its position is such a small number? That's because the coordinates are relative to the upper left corner of the window control.
Once you have positioned and sized the text control, it is time to put some text in it. Just like the window control, the text control has a property named "text". Set the text property to read "Tutorials\nJohn W Vanderbeck\n\nMinApp Code\nJames Yong\nJohn W Vanderbeck\nYour Name" obviouslly replacing "Your Name" with your name, and click the apply button.
Congratulations on making your first brand new GUI. The next step is to link this GUI into the main menu. We want it so that when you click on the Credits button in the main menu, this dialog pops up. When you close this dialog, you are returned to the main menu.
To do this, we need to make some additions to both the main menu gui and this one. Since we're in this one, we'll make those changes first. Select the window control again, and scroll to the bottom of its property list. You will see a property named "closeCommand". This is the script commands that will be executed when the user closes the window by pressing the X in the upper right corner. Before we set that however, let's look briefly at how the GUI system works in Torque.
In essence, the GUI system is a stack of various GUIs. You push a GUI onto the stack to display it and pop it off the stack to remove it and go to the previous GUI. At first this may seem awkward, but it is actually a very nice design when you consider how a user moves through your GUIs.
So, in order for our user to move from the main menu to displaying the credits gui, we would push the credits gui onto the gui stack. to return from the credits back to the main menu, we would pop it back off the stack. The advantage to this system is you don't ever need to know where you are coming from, as you will always just return to wherever it was.
Back to our credits gui. For the closeCommand property, we want to pop the gui off the stack. So we use this command "canvas.popDialog("creditsDlg");"
Click on File and save the GUI to minapp/demo/client/ui/creditsDlg.gui
Now we need to add this new GUI into our scripts so that it is loaded at startup.
Edit minapp/demo/client/init.cs and add the code listed in bold below.
2) The options screen
For the options screen, we will once again be reusing code from the FPS starter kit. I originally wanted to do this from scratch, but after looking at the options stuff in the FPS starter kit, I realized that it is mostly all generic stuff anyway.
Copy optionsDlg.gui from starter.fps/client/ui/ to minapp/demo/client/ui/
Copy optionsDlg.cs from starter.fps/client/scripts/ to minapp/demo/client/scripts/
Edit minapp/demo/client/init.cs and add the code listed in bold below.
3) The Play Game screen
This GUI will present a few options to the player. From here they can create a new single player game, host a new game, or join an existing server.
First, create a new GUI (you should know how to do this by now without a step by step) named "playGameGui". Set the GUI profile to GuiWindowProfile.
Next, create a new control with the profile GuiFadeinBitmapCtrl. Set the bitmap to demo/client/ui/background, the fadeinTime to 2000, and set the fadeoutTime to 0. This will create a neat little fade in background for the new GUI. We could have made a normal bitmap but I wanted to spice things up a bit.
Now, create 4 buttons, just like we did on the main menu. Make buttons for "Instant Action", "Join Game", "Host Game", and "Back". For the "Back" button, set the command property to "canvas.popDialog("playGameGui");"
4) The Main Menu
The last step for this tutorial is to make some changes to our Main Menu so that we can link in our new GUIs.
Select the Play Game button, and set its command to "canvas.pushDialog("playGameGui");". Select the Options button and set its command to "canvas.pushDialog("optionsDlg");". Select the Credits button and set its command to "canvas.pushDialog("creditsDlg");"
Lastly, we need to add the new GUI to our startup:
Edit minapp/demo/client/init.cs and add the code listed in bold below.
Summary
Really, the major thing to learn in this tutorial is how the GUI stack works. You should now have a firm grasp of how to move between GUIs and create new ones. As a sort of homework assignment to see how much you learned, go ahead and create a new GUI screen named "hostGameGui" with the same background as we have in the main menu (not a fade one, just basic like the main menu). Then add a window control to it. Add a "Cancel" button to the bottom of the window control as a child. Link the Host Game button on the Play Game GUI into this new GUI and link the Cancel button back the other way. We'll build upon this in the next tutorial.
This is by far the largest tutorial in the series so far. It took me most of the day to write, so it is entirely possible there are some unintended gaps. Please speak up if something doesn't work right or isn't clear, and i'll get it fixed ASAP.
Tutorial #4 - More GUI Work
Overview
This tutorial adds in a bunch more of the GUI code for our application. We will create several new GUIs and tie them together with the buttons we made in the previous tutorial.
There is really a lot to learn in this installment.
1) The credits screen
The credits screen will be a simple popup dialog box with credits listed on it. While this seems simple enough, it was right here that I ran into the first major problem of the series. But we'll get to that in a minute.
First, run the MinApp and press F10 to get into the GUI editor. Click on the File menu and choose New GUI. In the name field enter the name "creditsDlg" and click Create. You will now have a clean GUI slate to start working with. Next, we need to create our popup window. It seems a tad weird, since you would normally think of the window itself as the GUI, but in this case its a control. The GUI itself is the slate we just created. Click on New Control and select the profile "GuiWindowCtrl".
You will now see a blank default window control. Left click and drag to move the window somewhere in the center of the screen, and then resize it to make it slightly wider than tall. If you want to use the exact same numbers as I did, then you can manually set the position and extent. I used a position of 208,80 and an extent of 100,200. Once you have done that, set the "text" property of th window control to "MinApp Credits". If you look at the properties list, under the property "maxLength" you will see a series of checkboxes which control window features such as resizing, minimzing, etc. We want all of those OFF except for canClose and canMove which should be checked.
Now we come to the big problem that I ran into. At first, my next step was to create a GuiMLTextCtrl to hold the credits. I then placed this over the window and everything worked great. At least, until I clicked on the window. At that point, my text vanished. What was happening was that the window was being brought to the top of the "z-order". All the controls in the GUI have a top to bottom ordering, and when the window came to the top it covered the text. Obviously I needed some way to make the GUI understand that the text was part of the window.
So how do we make the text part of the window? We do this by making it a child control of the window control. In the upper right corner of the GUI editor you will see text that looks something like this: 1182: CreditsDlg - GuiControl
The number may be different on yours, but the text will be the same after that. To the left of that text is a small plus sign. Click the plus sign to expand it. This is a treeview of our GUI. The indentations show children. You will notice that the window we created is indented under the GuiControl. This signifies the window control is a child of the main GUI. What we want is to make a text control a child of the window. If you were to create a GuiMLTextCtrl control right now, it would become a child of the main GUI just like the window. Let's do that so we can see. Click New Control and select the GuiMLTextCtrl profile. See how the new control shows up with the same indentation as our window? Click on that new text control and press the DEL key to remove it. Now, right click on the GuiWindowCtrl. You will not notice much of a change, except a small red line at the top of the GUI. By right clicking though, you have told the GUI editor that you want to make a control that is a child of the window. Click New Control and select the GuiMLTextCtrl again. This time you will see that it shows up indented under the window control. We've now made it a child of the window control.
Position the text and resize it so it covers the interior of the window control. I used a position of 11,29 and an extent of 216, 84. If you look at the position, it should be more clear that this text control is a child of the window. Notice how its position is such a small number? That's because the coordinates are relative to the upper left corner of the window control.
Once you have positioned and sized the text control, it is time to put some text in it. Just like the window control, the text control has a property named "text". Set the text property to read "Tutorials\nJohn W Vanderbeck\n\nMinApp Code\nJames Yong\nJohn W Vanderbeck\nYour Name" obviouslly replacing "Your Name" with your name, and click the apply button.
Congratulations on making your first brand new GUI. The next step is to link this GUI into the main menu. We want it so that when you click on the Credits button in the main menu, this dialog pops up. When you close this dialog, you are returned to the main menu.
To do this, we need to make some additions to both the main menu gui and this one. Since we're in this one, we'll make those changes first. Select the window control again, and scroll to the bottom of its property list. You will see a property named "closeCommand". This is the script commands that will be executed when the user closes the window by pressing the X in the upper right corner. Before we set that however, let's look briefly at how the GUI system works in Torque.
In essence, the GUI system is a stack of various GUIs. You push a GUI onto the stack to display it and pop it off the stack to remove it and go to the previous GUI. At first this may seem awkward, but it is actually a very nice design when you consider how a user moves through your GUIs.
So, in order for our user to move from the main menu to displaying the credits gui, we would push the credits gui onto the gui stack. to return from the credits back to the main menu, we would pop it back off the stack. The advantage to this system is you don't ever need to know where you are coming from, as you will always just return to wherever it was.
Back to our credits gui. For the closeCommand property, we want to pop the gui off the stack. So we use this command "canvas.popDialog("creditsDlg");"
Click on File and save the GUI to minapp/demo/client/ui/creditsDlg.gui
Now we need to add this new GUI into our scripts so that it is loaded at startup.
Edit minapp/demo/client/init.cs and add the code listed in bold below.
// Load up the shell GUIs
exec("./ui/mainMenuGui.gui");
[b] exec("./ui/creditsDlg.gui");[/b]
// Client scripts
exec("./scripts/mainMenuGui.cs");2) The options screen
For the options screen, we will once again be reusing code from the FPS starter kit. I originally wanted to do this from scratch, but after looking at the options stuff in the FPS starter kit, I realized that it is mostly all generic stuff anyway.
Copy optionsDlg.gui from starter.fps/client/ui/ to minapp/demo/client/ui/
Copy optionsDlg.cs from starter.fps/client/scripts/ to minapp/demo/client/scripts/
Edit minapp/demo/client/init.cs and add the code listed in bold below.
// Load up the shell GUIs
exec("./ui/mainMenuGui.gui");
exec("./ui/creditsDlg.gui");
[b] exec("./ui/optionsDlg.gui"); [/b]
// Client scripts
exec("./scripts/mainMenuGui.cs");
[b] exec("./scripts/optionsDlg.cs"); [/b]3) The Play Game screen
This GUI will present a few options to the player. From here they can create a new single player game, host a new game, or join an existing server.
First, create a new GUI (you should know how to do this by now without a step by step) named "playGameGui". Set the GUI profile to GuiWindowProfile.
Next, create a new control with the profile GuiFadeinBitmapCtrl. Set the bitmap to demo/client/ui/background, the fadeinTime to 2000, and set the fadeoutTime to 0. This will create a neat little fade in background for the new GUI. We could have made a normal bitmap but I wanted to spice things up a bit.
Now, create 4 buttons, just like we did on the main menu. Make buttons for "Instant Action", "Join Game", "Host Game", and "Back". For the "Back" button, set the command property to "canvas.popDialog("playGameGui");"
4) The Main Menu
The last step for this tutorial is to make some changes to our Main Menu so that we can link in our new GUIs.
Select the Play Game button, and set its command to "canvas.pushDialog("playGameGui");". Select the Options button and set its command to "canvas.pushDialog("optionsDlg");". Select the Credits button and set its command to "canvas.pushDialog("creditsDlg");"
Lastly, we need to add the new GUI to our startup:
Edit minapp/demo/client/init.cs and add the code listed in bold below.
// Load up the shell GUIs
exec("./ui/mainMenuGui.gui");
exec("./ui/creditsDlg.gui");
exec("./ui/optionsDlg.gui");
[b]exec("./ui/playGameGui.gui");[/b]
// Client scripts
exec("./scripts/mainMenuGui.cs");
exec("./scripts/optionsDlg.cs");Summary
Really, the major thing to learn in this tutorial is how the GUI stack works. You should now have a firm grasp of how to move between GUIs and create new ones. As a sort of homework assignment to see how much you learned, go ahead and create a new GUI screen named "hostGameGui" with the same background as we have in the main menu (not a fade one, just basic like the main menu). Then add a window control to it. Add a "Cancel" button to the bottom of the window control as a child. Link the Host Game button on the Play Game GUI into this new GUI and link the Cancel button back the other way. We'll build upon this in the next tutorial.
This is by far the largest tutorial in the series so far. It took me most of the day to write, so it is entirely possible there are some unintended gaps. Please speak up if something doesn't work right or isn't clear, and i'll get it fixed ASAP.
#2
If I can give some advice to others following this (a couple things I ran into myself!):
1) Always remember to "Apply" your property changes and "Save Gui" when done with the screen.
2) Careful what you click on! I meant to add a "GuiButtonCtrl" and accidentally clicked on "GuiCanvas" instead - crashed the whole app.
01/22/2004 (7:39 pm)
Great job! Possible omission - I assumed that on the Play Game screen you wanted to add a window control to contain the buttons?If I can give some advice to others following this (a couple things I ran into myself!):
1) Always remember to "Apply" your property changes and "Save Gui" when done with the screen.
2) Careful what you click on! I meant to add a "GuiButtonCtrl" and accidentally clicked on "GuiCanvas" instead - crashed the whole app.
#3
First I made the buttons all children of the GuiFadeinBitmapCtrl, but only the last button added would fade in.
Then I tried creating a GuiFadeinBitmapCtrl parent for each button and they all faded in fine, but only the last button was funtional.
Oh well, it is still a good effect...
01/23/2004 (2:29 am)
I actually tried to get the buttons to fade in along with the background but was unable to accomplish this while keeping all the buttons functional.First I made the buttons all children of the GuiFadeinBitmapCtrl, but only the last button added would fade in.
Then I tried creating a GuiFadeinBitmapCtrl parent for each button and they all faded in fine, but only the last button was funtional.
Oh well, it is still a good effect...
#4
The file should be there. Perhaps you tried to download it before GG had finished setting it up.
@Glen
No, just the bitmap background and the buttons was how I had called for it. But that doesn't have to be the only way :)
@Joe
Experimenting is always good :) I too could find no way to make it all fade in. I suspect its an engine bug. One way you could do it though would be to make it all with GuiFadeinBitmapCtrl objects. Similar to how you make a webpage with graphics all chopped up. You would make bitmaps that stood in place of the buttons. You can assign a command to a bitmap just like you can a button.
01/23/2004 (5:30 am)
@BenoitThe file should be there. Perhaps you tried to download it before GG had finished setting it up.
@Glen
No, just the bitmap background and the buttons was how I had called for it. But that doesn't have to be the only way :)
@Joe
Experimenting is always good :) I too could find no way to make it all fade in. I suspect its an engine bug. One way you could do it though would be to make it all with GuiFadeinBitmapCtrl objects. Similar to how you make a webpage with graphics all chopped up. You would make bitmaps that stood in place of the buttons. You can assign a command to a bitmap just like you can a button.
#5
I was trying to get the Back button working from the Play game screen and it doesn't seem to work for me. I downloaded the files you have here and for the back button you have "canvas.pushDialog("playGameGui");" instead of "canvas.popDialog("playGameGui");". But when I try and pop the play game gui it just freezes.
I haven't run it through the debugger to see what is happening yet.
***EDIT*** Ok I tried it again and now its working. The computer gods are toying with me
***2nd EDIT*** Ahh it happens only after I go into the GUI editor
02/12/2004 (7:04 am)
I hope everything is going well for you John, I'm eargerly anticipating the next installment of the tutorial.I was trying to get the Back button working from the Play game screen and it doesn't seem to work for me. I downloaded the files you have here and for the back button you have "canvas.pushDialog("playGameGui");" instead of "canvas.popDialog("playGameGui");". But when I try and pop the play game gui it just freezes.
I haven't run it through the debugger to see what is happening yet.
***EDIT*** Ok I tried it again and now its working. The computer gods are toying with me
***2nd EDIT*** Ahh it happens only after I go into the GUI editor
#6
Thanks for the information. I will look into it.
My apologies on the delay of #5, but rest assured THE PROJECT IS NOT DEAD. It is just taking me a while. My day job (the one that actually makes me money) comes first, then my company (the one that hopefully someday will make me money) comes second, and then Torque comes third :)
The complexity of tutorial #5, coupled with the severe time shortage has contributed to the lengthy delay. As soon as it is all working though (and i'm very close) I will sit down and write out that tutorial and get it posted. Just a few more things to iron out.
02/17/2004 (10:02 am)
@TomThanks for the information. I will look into it.
My apologies on the delay of #5, but rest assured THE PROJECT IS NOT DEAD. It is just taking me a while. My day job (the one that actually makes me money) comes first, then my company (the one that hopefully someday will make me money) comes second, and then Torque comes third :)
The complexity of tutorial #5, coupled with the severe time shortage has contributed to the lengthy delay. As soon as it is all working though (and i'm very close) I will sit down and write out that tutorial and get it posted. Just a few more things to iron out.
#7
as I suspect others like me are desperate ;-)
and looking forward to it.
04/25/2004 (11:44 pm)
John I was wondering if you have had time to finish of #5???as I suspect others like me are desperate ;-)
and looking forward to it.
#8
04/27/2004 (9:47 pm)
Please do work on #5...! I've just finished all 5 of your awesome tutorials in three days, and eagerly await more! Thanks alot for all the great work you've done John.
#9
05/15/2004 (2:27 pm)
John - any joy completing #5 - great work so far.
#10
06/10/2004 (5:44 pm)
Excellent job John!
#11
06/15/2004 (6:28 pm)
@John: Great tutorials!!! What a great set of primers, and you left me wanting many, many more!
#12
06/30/2004 (6:54 pm)
Excellent! Thank You! You've saved me many, many hours of floundering around learning this on my own. Please...MORE!
#13
I've read over the posts, maybe I'm just blind, but what is the topic of the #5 tutorial?
I'm glad to be back into it. Maybe I'll actually have time to work with it this time around.
08/04/2004 (8:18 pm)
Thank you John for providing these samples, I have been away from Torque for nearly 2 years, the time seems to fly... I found these samples helping me get caught back up to where I left off.I've read over the posts, maybe I'm just blind, but what is the topic of the #5 tutorial?
I'm glad to be back into it. Maybe I'll actually have time to work with it this time around.
#14
08/22/2004 (2:46 pm)
Be careful if you press F10 when you've created a sub-menu that you don't try to use the back buttons, since you have not yet PUSHED anything onto the gui stack, poping could cause it to freeze. When your ready to test, always return to your first menu then press F10 and go from there.
#15
09/05/2004 (5:10 am)
Thanks for these, John. It is my opinion that this series (obviously including James Yong's starter) should be the official GarageGames answer to the question, "Where do I begin?".
#16
09/08/2004 (5:43 pm)
Great work! Thanks a lot~~
#17
10/04/2004 (3:03 pm)
I have found that for the options dialog to fully work (specifically, remapping keys), you also need to copy "remapDlg.gui" from starter.fps and exec it. I don't know if this was an oversight or if the code has changed since the tutorial was written.
#18
Two problems when I was trying this tutorial:
1) my playerGameGui was not the same size as the main window
2) there was no checkbox option for canmove nor canclose for my creditDlg (they were listed on the left but had no checkbox associated with them)
as for suggestions:
it would be really helpful to a newbie like myself to have the tree structure of Torque explained. What is the difference between the common VS the client folder? Why do you place/modify the files sometimes in one folder instead of the other? What are all the folders within? What do all the files do?
But again, EXCELLENT work John! Thanks so much!
12/09/2004 (6:44 am)
Like everyone, I'm EAGERLY awaiting for your next tutorial John!!!!!!!Two problems when I was trying this tutorial:
1) my playerGameGui was not the same size as the main window
2) there was no checkbox option for canmove nor canclose for my creditDlg (they were listed on the left but had no checkbox associated with them)
as for suggestions:
it would be really helpful to a newbie like myself to have the tree structure of Torque explained. What is the difference between the common VS the client folder? Why do you place/modify the files sometimes in one folder instead of the other? What are all the folders within? What do all the files do?
But again, EXCELLENT work John! Thanks so much!
#19
Any Idea what could cause this?
Anyway, this is a nice tutorial.
Keep it up ;-)
Edit
Uh... Every time I push the back Button in the playGameGui the game crashes.
Has someone encountered the same problem?
12/10/2004 (8:55 am)
I have the same problem as Kayley.Any Idea what could cause this?
Anyway, this is a nice tutorial.
Keep it up ;-)
Edit
Uh... Every time I push the back Button in the playGameGui the game crashes.
Has someone encountered the same problem?

Torque Owner Benoit Touchette