IgnoreMouse property on GuiControl for easier embedding
by Jaimi McEntire · 09/22/2008 (11:44 am) · 4 comments
Have you ever wanted to embed a control inside of a button? I wanted to do just that in TGEA 1.7 - embed a GuiMLTextCtrl inside of a GuiButtonCtrl for my save game system. The problem was that the GuiMLTextCtrl would eat the mouse events so you had to click around it. You could of course click on the embedded control and have it call the same function as the button, but visually this doesn't work because it doesn't look like the button has been pressed.
To fix this, I added a property to GuiControl (and thus to all descendant controls) that allows any control to Ignore the mouse. This will effectively make it so the you can no longer click on that control (or any of the children of that control) - all mouse events are handled by the parent - perfect for my GuiMLTextCtrl buttons!
Note that this effectively locks the control in the GUI editor also, so if you set this property to true, you have to select the control manually in the tree. I like this behavior, so I didn't code in the ability to detect if you were in the editor or not.
On to the changes.
GUICONTROL.H:
in the class GuiControl, right after mIsContainer, add a boolean for our property:
GUICONTROL.CPP:
In the constructor, GuiControl::GuiControl(), initialize mIgnoreMouse to false:
in the function initPersistFields(), add the property after the canSave property:
Replace the function GuiControl::findHitControl with this function:
Now you're done. By default, everything will behave like it did before. However, if you want to embed an object inside of another (and have the mouse ignore it), just set the IsContainer to true, embed the control, and on the embedded control, set "IgnoreMouse" to 1. Put a bitmap, a label, an MLTextControl, whatever you want inside.
Example:
To fix this, I added a property to GuiControl (and thus to all descendant controls) that allows any control to Ignore the mouse. This will effectively make it so the you can no longer click on that control (or any of the children of that control) - all mouse events are handled by the parent - perfect for my GuiMLTextCtrl buttons!
Note that this effectively locks the control in the GUI editor also, so if you set this property to true, you have to select the control manually in the tree. I like this behavior, so I didn't code in the ability to detect if you were in the editor or not.
On to the changes.
GUICONTROL.H:
in the class GuiControl, right after mIsContainer, add a boolean for our property:
bool mIsContainer; ///< if true, then the GuiEditor can drag other controls into this one.
/// IGNORE MOUSE CHANGES
bool mIgnoreMouse; // of true, then does not get selected.
/// IGNORE MOUSE CHANGESGUICONTROL.CPP:
In the constructor, GuiControl::GuiControl(), initialize mIgnoreMouse to false:
/// IGNORE MOUSE CHANGES
mIgnoreMouse = false;
/// IGNORE MOUSE CHANGES
mConsoleVariable = StringTable->insert("");in the function initPersistFields(), add the property after the canSave property:
addField("canSave", TypeBool, Offset(mCanSave, GuiControl));
/// IGNORE MOUSE CHANGES
addField("IgnoreMouse", TypeBool, Offset(mIgnoreMouse, GuiControl));
/// IGNORE MOUSE CHANGESReplace the function GuiControl::findHitControl with this function:
GuiControl* GuiControl::findHitControl(const Point2I &pt, S32 initialLayer)
{
iterator i = end(); // find in z order (last to first)
while (i != begin())
{
i--;
GuiControl *ctrl = static_cast<GuiControl *>(*i);
if (initialLayer >= 0 && ctrl->mLayer > initialLayer)
{
continue;
}
else if (ctrl->mVisible && ctrl->pointInControl(pt))
{
/// IGNORE MOUSE CHANGES
if (!ctrl->mIgnoreMouse)
{
Point2I ptemp = pt - ctrl->getPosition();
GuiControl *hitCtrl = ctrl->findHitControl(ptemp);
if(hitCtrl->getControlProfile()->mModal)
return hitCtrl;
}
}
}
return this;
}Now you're done. By default, everything will behave like it did before. However, if you want to embed an object inside of another (and have the mouse ignore it), just set the IsContainer to true, embed the control, and on the embedded control, set "IgnoreMouse" to 1. Put a bitmap, a label, an MLTextControl, whatever you want inside.
Example:
new GuiButtonCtrl(LoadSlotButton10) {
canSaveDynamicFields = "0";
Enabled = "1";
isContainer = "1";
HorizSizing = "right";
VertSizing = "bottom";
position = "0 477";
Extent = "243 47";
MinExtent = "8 2";
canSave = "1";
IgnoreMouse = "0";
Visible = "1";
hovertime = "1000";
groupNum = "-1";
buttonType = "PushButton";
useMouseEvents = "0";
new GuiMLTextCtrl(LoadSlotText10) {
canSaveDynamicFields = "0";
Enabled = "1";
isContainer = "0";
HorizSizing = "right";
VertSizing = "bottom";
position = "11 3";
Extent = "226 14";
MinExtent = "8 2";
canSave = "1";
IgnoreMouse = "1";
Visible = "1";
hovertime = "1000";
lineSpacing = "2";
allowColorChars = "0";
maxChars = "-1";
text = "Test ML";
};
};About the author
Recent Blogs
• Replicator Updates for TGEA 1.8.1• GuiLensFlareHud - Lens flares and white out for TGEA 1.8.1
• fxGenericObject for TGEA 1.8.1
• GuiStatusCtrl - *Updated* Display Field Name, Values, Status Bar for any field or method on any named object. TGEA and (new! TGE 1.52)
• Bitmap Channel Embedder
#2
but it is a bit of a hassle to create a whole new profile just for that.
here's a basic nonmodal profile:
09/25/2008 (4:54 pm)
i typically use a "NonModal" GuiProfile to do the same thing,but it is a bit of a hassle to create a whole new profile just for that.
here's a basic nonmodal profile:
new GuiControlProfile(NonModalProfile : GuiDefaultProfile)
{
modal = false;
};
#3
10/07/2008 (6:22 am)
I actually ended up using this a lot in code for buttons - to turn mouse interactions on and off for various things.
#4
02/07/2009 (3:47 pm)
hum... I'm was looking for something like this... I've got many problems in a old game! I'll test it later with TGB :D 
Torque Owner Stefan Lundmark