Gui Instancing helper functions
by Alex Huck · 07/25/2010 (6:56 am) · 0 comments
Torque's GUI editor is designed with the goal of making huds, full screen pages and dialogs, things that are single instances objects. I needed a way for me to design my GUI element in the editor, save it out, and then when I need it, make and manage many copies of it somewhere.
Instructions:
Make a GUI that you intend to use over and over again, like an InventoryIcon, or a spell cooldown timer icon
Only have the root group of your gui named. Anything you intend to be variable, like a GuiBitmapCtrl for an icon should have an internalName set. So for example, I had a spell cast icon it looked like this:
|GuiControl(SpellIcon)
|-->GuiBitmapCtrl([icon])
|-->GuiProgressCtrl([castTime])
Note on SpellIcon's 2 children, they are internally, not globally named
How to use the helper functions:
The above code adds these new functions to all GuiControls:
createInstance(%addGroup)
This returns the ID of a new copy of a the GUI. You can optionally add it to a SimSet/GuiControl group on the fly. If you don't specify a group it will simply add it to the Gui screen that's currently shown.
getInstanceRoot(%instanceObjectID)
This returns the highest parent of an element in the instance. So if I call this function on the SpellIcon's GuiBitmapCtrl, it will go up a level to the parent, and see that the GuiControl that owns it is part of the instance, and return that.
getInstanceOwner(instanceObjectID)
This does what getInstanceRoot does, but returns the parent of that. In other words it returns the GuiControl/SimSet that contains the instance.
So now you can design all your widgets right in Torque's gui editor, and be able to make as many clones as you want of it, each with unique properties. To set the unique properties of each instance simply access the internal name with the --> operator. Example:
Misc notes:
When you create an instance, it has no global name at all. Only way to reference it is through the local variable you get at creation time through the createInstance() function.
EDIT:
Added an extention to GuiControl::onRemove, now if you remove an instance and it's inside an GuiArrayCtrl type thing, it will automatically refresh it.
function GuiControl::getInstanceOwner(%this)
{
if(%this.isInstance)
{
%owner = %this;
while(%owner.isInstance)
{
%owner = %owner.getGroup();
}
return %owner.getGroup();
}
return NULL;
}
function GuiControl::getInstanceRoot(%this)
{
if(%this.isInstance)
{
%owner = %this;
while(%owner.isInstance)
{
%owner = %owner.getGroup();
}
return %owner;
}
return NULL;
}
function GuiControl::onRemove(%this)
{
if(%this.isInstance)
{
%owner = %this.getInstanceOwner();
if((%owner.getClassName() $= "GuiControlArrayControl") ||
(%owner.getClassName() $= "GuiDynamicCtrlArrayControl"))
{
%owner.refresh();
}
}
}
function GuiControl::setAsInstance(%this)
{
foreach(%child in %this)
{
%child.isInstance = true;
%child.setName("");
%child.setAsInstance();
}
}
function GuiControl::createInstance(%this, %optionalAddTo)
{
if(%optionalAddTo $= "")
{
%optionalAddTo = Canvas.getContent();
}
%instance = %this.deepClone();
%instance.setAsInstance();
%optionalAddTo.add(%instance);
return %instance;
}Instructions:
Make a GUI that you intend to use over and over again, like an InventoryIcon, or a spell cooldown timer icon
Only have the root group of your gui named. Anything you intend to be variable, like a GuiBitmapCtrl for an icon should have an internalName set. So for example, I had a spell cast icon it looked like this:
|GuiControl(SpellIcon)
|-->GuiBitmapCtrl([icon])
|-->GuiProgressCtrl([castTime])
Note on SpellIcon's 2 children, they are internally, not globally named
How to use the helper functions:
The above code adds these new functions to all GuiControls:
createInstance(%addGroup)
This returns the ID of a new copy of a the GUI. You can optionally add it to a SimSet/GuiControl group on the fly. If you don't specify a group it will simply add it to the Gui screen that's currently shown.
getInstanceRoot(%instanceObjectID)
This returns the highest parent of an element in the instance. So if I call this function on the SpellIcon's GuiBitmapCtrl, it will go up a level to the parent, and see that the GuiControl that owns it is part of the instance, and return that.
getInstanceOwner(instanceObjectID)
This does what getInstanceRoot does, but returns the parent of that. In other words it returns the GuiControl/SimSet that contains the instance.
So now you can design all your widgets right in Torque's gui editor, and be able to make as many clones as you want of it, each with unique properties. To set the unique properties of each instance simply access the internal name with the --> operator. Example:
%myInstance = SpellIcon.createInstance(SpellIconGroup);
%myInstance.setPosition(64,0);
%myInstance-->icon.setBitmap("art/gui/icons/flamesOdoom");
%myInstance-->castTime.setValue(0.5);Misc notes:
When you create an instance, it has no global name at all. Only way to reference it is through the local variable you get at creation time through the createInstance() function.
EDIT:
Added an extention to GuiControl::onRemove, now if you remove an instance and it's inside an GuiArrayCtrl type thing, it will automatically refresh it.
About the author