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.
#22
del *.dso /s
That does nicely. There are other resources where people have mentioned this, including a more linux style snswer.
Thanks for the great tutorials. Tracing through the call stack on these simplified apps has really helped me understand how things are called, especially with namespaces in torque script, which through me off at first.
06/22/2005 (12:57 pm)
I have seen several replies about people trying to delete their dso files. I added a little batch file to my root directory that has this one line:del *.dso /s
That does nicely. There are other resources where people have mentioned this, including a more linux style snswer.
Thanks for the great tutorials. Tracing through the call stack on these simplified apps has really helped me understand how things are called, especially with namespaces in torque script, which through me off at first.
#23
If you change your fading picture's size to your resolution you are using currently, set it's position to 0 0, and change it's v/h movement to "relative" then it should line up perfectly =)
-
@ a lot of people ;)
Gary was right, in order to hit the back button you must FIRST have a place you were at before this! Or else it doesn't know where you want it to go ;)
p.s. Thanks a lot for these tutorials! =D
06/10/2006 (4:44 pm)
@ KayleyIf you change your fading picture's size to your resolution you are using currently, set it's position to 0 0, and change it's v/h movement to "relative" then it should line up perfectly =)
-
@ a lot of people ;)
Gary was right, in order to hit the back button you must FIRST have a place you were at before this! Or else it doesn't know where you want it to go ;)
p.s. Thanks a lot for these tutorials! =D
#24
Any help would be greatly appreciated! =)
06/15/2006 (1:21 pm)
Hm. I've been trying to play with the main.cs file, but I havent' been able to get the mission to load from minapp. I've tried borrowing code from the Torque demo's loadMyMission() and main.cs files, but I haven't found anything that actually lets me load anything =(Any help would be greatly appreciated! =)
#25
05/14/2007 (11:21 am)
Do please continue! 
Torque Owner janet kim
who hope that there is more to come. The tutorials have been very
helpful - thanks John!