Alternative to using pushDialog() and popDialog() for GUI elements...
by Ted Southard · 10/30/2004 (6:43 pm) · 16 comments
Assuming two GUI controls named mapGui and inventoryGui, you can create functions to toggle them on and off like so:
function toggleInventory()
{
if(!Canvas.getContent().isMember(inventoryGui))
{
Canvas.getContent().add(inventoryGui);
}
else
{
Canvas.getContent().remove(inventoryGui);
}
}
function toggleMap()
{
if(!Canvas.getContent().isMember(mapGui))
{
Canvas.getContent().add(mapGui);
}
else
{
Canvas.getContent().remove(mapGui);
}
}
That's it. The isMember() function checks to see if the GUI element is there and returns a bool, and using that as the switch I put the add() and remove() functions in dependent on the return value.
You can bind those toggles to a key or as commands called from buttons, easy as pie. The screenshot shows the mapGui and inventoryGui added to the screen.
function toggleInventory()
{
if(!Canvas.getContent().isMember(inventoryGui))
{
Canvas.getContent().add(inventoryGui);
}
else
{
Canvas.getContent().remove(inventoryGui);
}
}
function toggleMap()
{
if(!Canvas.getContent().isMember(mapGui))
{
Canvas.getContent().add(mapGui);
}
else
{
Canvas.getContent().remove(mapGui);
}
}
That's it. The isMember() function checks to see if the GUI element is there and returns a bool, and using that as the switch I put the add() and remove() functions in dependent on the return value.
You can bind those toggles to a key or as commands called from buttons, easy as pie. The screenshot shows the mapGui and inventoryGui added to the screen.
About the author
Started with indie games over a decade ago, and now creates tools and tech for games. Currently working as a contractor for startups and game studios.
#2
Wouldn't it be best to toggle the visible state and check with 'isVisible' instead of adding and removing the GUI objects to each other? :/ (I don't know, I just really wanted to post something for one :D)
10/29/2004 (6:21 pm)
Let the nashing of teeth begin!!! :)Wouldn't it be best to toggle the visible state and check with 'isVisible' instead of adding and removing the GUI objects to each other? :/ (I don't know, I just really wanted to post something for one :D)
#3
You can do it like this(assuming a GUI element named "map" in the playGui.gui):
function toggleMap()
{
if(!map.isVisible())
{
map.visible = "1";
}
else
{
map.visible = "0";
}
}
[/gnashing teeth]
10/30/2004 (3:58 pm)
[gnashing teeth]You can do it like this(assuming a GUI element named "map" in the playGui.gui):
function toggleMap()
{
if(!map.isVisible())
{
map.visible = "1";
}
else
{
map.visible = "0";
}
}
[/gnashing teeth]
#4
10/31/2004 (1:23 am)
Why not do this then...function toggleGUI(%what)
{
if(!Canvas.getContent().isMember(%what))
{
Canvas.getContent().add(%what);
}
else
{
Canvas.getContent().remove(%what);
}
}
#5
(toggle with this command)
AdminDlg.toggle();
10/31/2004 (2:23 am)
One more thing, the more simple you keep your code, the better and faster it will perform. That's a fact you can never change about programming. Since every GUI gets a name it's even better to name space call them than anything else IMO. But of course, you were trying not to use push and pop for some reason. This is the best type of toggle IMO...(toggle with this command)
AdminDlg.toggle();
function AdminDlg::toggle(%this)
{
if(%this.isAwake())
{
Canvas.popDialog(%this);
}
else
{
Canvas.pushDialog(%this);
}
}
#6
10/31/2004 (3:50 am)
What were the issues with using the "normal" commands Ted, if you don't mind telling? I'd like to have a look at it.
#7
After searching around on the subject, I came across Labrat's post, and it worked like a charm. So do the visibility commands. Nothing wrong with the "normal" commands, except in this instance I ran into some issues that were faster put behind me using this, and I figured I'd share the wealth.
10/31/2004 (4:21 am)
@Stefan: No issues with the commands themselves. Originally, I had the gui elements set up as dialogs and I used push and pop commands to get to them. However, I found that when I pushed dialogs, I couldn't click on the shortcut bar to toggle them off(I had key bindings, but I want the play to be able to toggle things on and off from that shortcut bar). That was an issue with the size of the gui interfering with the mouse events, and I played with trying to fix that for a bit, but found it a bit confusing to say the least in trying to size the GuiControl and it's children so that none of them covered the whole screen(they kept coming up distorted). After searching around on the subject, I came across Labrat's post, and it worked like a charm. So do the visibility commands. Nothing wrong with the "normal" commands, except in this instance I ran into some issues that were faster put behind me using this, and I figured I'd share the wealth.
#8
For instance, if you push a GUI to the canvas that sits to the left, and then push another GUI to the canvas that sits to the right, you would be able to see both, but only interact with the one on the right because in reality it is layered on top of the left gui which is layered on top of the canvas.
If you want 4 different menus to be available but only want to see the ones you want to see while interacting with all of them, then they all need to be built into the same GUI and their visibility has to be toggled, in which case you would use the visibility toggle. Which in reality is NOT an alternate method for push an pop. The canvas and the GUI elements are two totally different things.
The canvas.getcontent.add() method is actually transfering the content of one gui into the content of your currently displayed GUI. This is different because it relies on correct control sizing.
Here is an example piece of a datablock....
With the GUI control named we can push and pop this GUI by name, but you cannot easily add the content of this GUI to another and when you push it to the canvas, it will take full control of your screen. Obviously that is not what you wanted to do. But if we give the inner window a name as well....
Then you could use canvas.getContent().add(AdminDlgWindow); to push the Admin GUI element that you really need to the currently controlled GUI. This would allow you to interact with your current gui and the AdminWindow as well. Notice that set visibility never came into play either. To remove the GUI you just added, you would use "canvas.getContent().remove(AdminDlgWindow);" So to bring the admin window up in my play gui, all I would need is "playGui.add(AdminDlgWindow);"
Keep in mind that you can use the onWake method for the Window as well as the main control (AdminDlgWindow::onWake()). Each will get called when the main control is pushed to the canvas and they fire in reverse order... meaning...
AdminDlgWindow::onWake()
first and then
AdminDlg::onWake()
This is handy for deviding needed tasks as well.
10/31/2004 (6:08 am)
To make this a better resource, you should upload a demo GUI that uses the exact principles you describe so we could view the operaional aspects and what makes them different. I'm having a hard time picturing why you were having the problem unless you were doing something else wrong.For instance, if you push a GUI to the canvas that sits to the left, and then push another GUI to the canvas that sits to the right, you would be able to see both, but only interact with the one on the right because in reality it is layered on top of the left gui which is layered on top of the canvas.
If you want 4 different menus to be available but only want to see the ones you want to see while interacting with all of them, then they all need to be built into the same GUI and their visibility has to be toggled, in which case you would use the visibility toggle. Which in reality is NOT an alternate method for push an pop. The canvas and the GUI elements are two totally different things.
The canvas.getcontent.add() method is actually transfering the content of one gui into the content of your currently displayed GUI. This is different because it relies on correct control sizing.
Here is an example piece of a datablock....
//--- OBJECT WRITE BEGIN ---
new GuiControl(AdminDlg) {
profile = "GuiDefaultProfile";
new GuiWindowCtrl() {
profile = "GuiProgressProfile";
horizSizing = "center";
vertSizing = "center";
position = "110 113";
extent = "580 374";
visible = "1";
closeCommand = "Canvas.popDialog(AdminDlg);"; With the GUI control named we can push and pop this GUI by name, but you cannot easily add the content of this GUI to another and when you push it to the canvas, it will take full control of your screen. Obviously that is not what you wanted to do. But if we give the inner window a name as well....
//--- OBJECT WRITE BEGIN ---
new GuiControl(AdminDlg) {
profile = "GuiDefaultProfile";
new GuiWindowCtrl(AdminDlgWindow) {
profile = "GuiProgressProfile";
horizSizing = "center";
vertSizing = "center";
position = "110 113";
extent = "580 374";
visible = "1";
closeCommand = "Canvas.popDialog(AdminDlg);";Then you could use canvas.getContent().add(AdminDlgWindow); to push the Admin GUI element that you really need to the currently controlled GUI. This would allow you to interact with your current gui and the AdminWindow as well. Notice that set visibility never came into play either. To remove the GUI you just added, you would use "canvas.getContent().remove(AdminDlgWindow);" So to bring the admin window up in my play gui, all I would need is "playGui.add(AdminDlgWindow);"
Keep in mind that you can use the onWake method for the Window as well as the main control (AdminDlgWindow::onWake()). Each will get called when the main control is pushed to the canvas and they fire in reverse order... meaning...
AdminDlgWindow::onWake()
first and then
AdminDlg::onWake()
This is handy for deviding needed tasks as well.
#9
That's exactly the problem that I had that this gets around. There's a few ways to skin this cat, and I thought it would be good to show another one of those ways. I'll probably update this resource in the next couple days with a few scripts that demonstrate the different ways of doing this so people can see how each way behaves.
10/31/2004 (9:50 am)
Quote:For instance, if you push a GUI to the canvas that sits to the left, and then push another GUI to the canvas that sits to the right, you would be able to see both, but only interact with the one on the right because in reality it is layered on top of the left gui which is layered on top of the canvas.
That's exactly the problem that I had that this gets around. There's a few ways to skin this cat, and I thought it would be good to show another one of those ways. I'll probably update this resource in the next couple days with a few scripts that demonstrate the different ways of doing this so people can see how each way behaves.
#10
10/31/2004 (12:19 pm)
I've already written a killer script based on all this and I've discovered some bad code in cursor.cs.
#11
10/31/2004 (2:06 pm)
Care to post it for everyone's benefit?
#12
To make that better it should be...
The first way assumes no variable exists at all. If you had %this.noCursor = "0"; then the cursor on function would fail. I discovered this today while working with some new stuff after all this got started.
10/31/2004 (3:50 pm)
in Cursor.cs at line 52 you should see...%control = %this.getObject(%i);
if(%control.noCursor $= "")
{
%cursorShouldBeOn = true;
break;
} To make that better it should be...
%control = %this.getObject(%i);
if(%control.noCursor <= 0)
{
%cursorShouldBeOn = true;
break;
}The first way assumes no variable exists at all. If you had %this.noCursor = "0"; then the cursor on function would fail. I discovered this today while working with some new stuff after all this got started.
#13
11/01/2004 (5:20 am)
If you don't want the top gui layer stopping lower gui layers from recieving mouse clicks than you can also use the GuiModelessDialogProfile for the profile of the GuiControl. new GuiControl(ThemeEditorGui) {
profile = "GuiModelessDialogProfile";
...
#14
I'll give this a try.
11/05/2004 (4:07 am)
Ah, cool Ted. I worked around this with using setVisible instead of popping/pushing Dialogs, but it can get messy.I'll give this a try.
#15
//--- OBJECT WRITE BEGIN ---new GuiControl(AdminDlg) { profile = "GuiDefaultProfile";
new GuiWindowCtrl() { profile = "GuiProgressProfile";
horizSizing = "center";
vertSizing = "center";
position = "110 113";
extent = "580 374";
visible = "1";
closeCommand = "Canvas.popDialog(AdminDlg);";
09/30/2006 (5:41 pm)
why are both of the '{' the same way wich is { and { and not { } ?//--- OBJECT WRITE BEGIN ---new GuiControl(AdminDlg) { profile = "GuiDefaultProfile";
new GuiWindowCtrl() { profile = "GuiProgressProfile";
horizSizing = "center";
vertSizing = "center";
position = "110 113";
extent = "580 374";
visible = "1";
closeCommand = "Canvas.popDialog(AdminDlg);";
#16
function AdminDlg::toggle(%this)
{
if(%this.isAwake()) {
Canvas.popDialog(%this);
}
else
{
Canvas.pushDialog(%this); }
}
OR THIS SCRIPT WHERE WOULD I PUT IT AND HOW WOULD I USE IT TO BRING UP INVENTORYGUI THH VERY MUCH FOR ANY HELP
function toggleGUI(%what)
{
if(!Canvas.getContent().isMember(%what))
{
Canvas.getContent().add(%what);
}
else
{
Canvas.getContent().remove(%what);
}
}
09/30/2006 (5:49 pm)
where does this script belong? and how would i bind it to a key to pull up my inventorygui ? thx if u can helpfunction AdminDlg::toggle(%this)
{
if(%this.isAwake()) {
Canvas.popDialog(%this);
}
else
{
Canvas.pushDialog(%this); }
}
OR THIS SCRIPT WHERE WOULD I PUT IT AND HOW WOULD I USE IT TO BRING UP INVENTORYGUI THH VERY MUCH FOR ANY HELP
function toggleGUI(%what)
{
if(!Canvas.getContent().isMember(%what))
{
Canvas.getContent().add(%what);
}
else
{
Canvas.getContent().remove(%what);
}
}

Torque 3D Owner Ted Southard