T3D Quad Menus
by Rene Damm · 08/14/2011 (9:00 am) · 9 comments
Download
Inspired by Ryan Mounts' T3D editor work, I started putting together 3DSMAX-style right-click context menus for T3D's editors some time ago on a weekend as I have always missed right-click menus in both the World Editor and the Gui Editor. Unfortunately, after the weekend, the thing just kept lying there incomplete so this is weekend I set out to at least get it to the state where it may at least be useful to someone.

In the current form, GuiQuadMenuCtrl is roughly feature-complete but the scripting side is still pretty rudimentary. Only the Object Editor in T3D's World Editor gets right-click menus with the current scripts and the even the menus that are there could definitely be made way more useful and complete. Also, I haven't really given this a whole lot of testing.
Still, it's a start and maybe someone finds the time and motivation to push this further along.
Inspired by Ryan Mounts' T3D editor work, I started putting together 3DSMAX-style right-click context menus for T3D's editors some time ago on a weekend as I have always missed right-click menus in both the World Editor and the Gui Editor. Unfortunately, after the weekend, the thing just kept lying there incomplete so this is weekend I set out to at least get it to the state where it may at least be useful to someone.

In the current form, GuiQuadMenuCtrl is roughly feature-complete but the scripting side is still pretty rudimentary. Only the Object Editor in T3D's World Editor gets right-click menus with the current scripts and the even the menus that are there could definitely be made way more useful and complete. Also, I haven't really given this a whole lot of testing.
Still, it's a start and maybe someone finds the time and motivation to push this further along.
Installation Instructions
- Copy the contents of the game/ folder in the zip to your game folder.
- Copy the contents of the Engine/ folder in the zip to your Engine/ folder.
- Re-run projectGenerator or manually add guiQuadMenuCtrl.h and .cpp.
- Add the following to game/core/art/gui/profiles.cs (or somewhere else where's it is executed on startup)
- Add the following after the existing exec()s to initializeWorldEditor() in tools/worldEditor/main.cs
- Finally, to allow the scripts to hook into editor right-clicks, add the following snippets to EditTSCtrl. To where the member variables are declared in the EditTSCtrl class in editTSCtrl.h, add
- Optionally, add the following snippet to GuiEditor::isFilteredClass in guiEditor.ed.cs to make GuiQuadMenuCtrl not show up in the Gui Editor's palette:
//>rd: quad menus
if( !isObject( GuiQuadMenuProfile ) )
new GuiControlProfile( GuiQuadMenuProfile )
{
bitmap = "./images/quadMenu";
// Fonts.
fontType = "Arial";
fontSize = 13;
fontColor = "0 0 0";
// Border.
border = true;
borderThickness = 1;
borderColor = "20 20 20";
// Background.
fillColor = "242 241 240";
fillColorNA = "162 161 160"; // Fill color used for title entries.
fillColorSEL = "228 228 235"; // Fill color used for mouse-overs.
};
//<rd: quad menus//>rd: quad menus exec( "./scripts/quadMenus.ed.cs" ); //<rd: quad menus
//>rd: quad menus
Point2I mRightMouseDownPos;
Point2I mRightMouseDragDelta;
bool mRightMouseDragDetected;
/// @name Callbacks
/// @{
DECLARE_CALLBACK( void, onRightMouseClick, ( Point2I mousePos, Point3F screenPos, Point3F viewVector, S32 modifiers ) );
/// @}
//<rd: quad menusSomewhere after the #includes, add//>rd: quad menus IMPLEMENT_CALLBACK( EditTSCtrl, onRightMouseClick, void, ( Point2I mousePos, Point3F screenPos, Point3F viewVec, S32 modifiers ), ( mousePos, screenPos, viewVec, modifiers ), "Called when the user clicks the right mouse button on the control.\n\n" "@param mousePos 2D screen-space mouse position.\n" "@param screenPos World-space position of the mouse cursor.\n" "@param viewVec View direction vector.\n" "@param modifiers Bitmask of keyboard modifiers." ); //<rd: quad menusRight to the beginning of EditTSCtrl::onRightMouseDown add
//>rd: quad menus mRightMouseDownPos = event.mousePoint; mRightMouseDragDelta = Point2I( 0, 0 ); mRightMouseDragDetected = false; //<rd: quad menusAnd at the end of EditTSCtrl::onRightMouseUp add
//>rd: quad menus
if( !mRightMouseDragDetected )
onRightMouseClick_callback( mLastEvent.mousePoint, mLastEvent.pos, mLastEvent.vec, mLastEvent.modifier );
//<rd: quad menusRight to the beginning of EditTSCtrl::onInputEvent add//>rd: quad menus
// Detect when the right mouse button is dragged beyond
// a 2x2 region around its press-down point.
if( mRightMouseDown &&
!mRightMouseDragDetected &&
event.deviceType == MouseDeviceType &&
( event.objInst == SI_XAXIS || event.objInst == SI_YAXIS ) &&
event.action == SI_MOVE )
{
if( event.objInst == SI_XAXIS )
mRightMouseDragDelta.x += S32( event.fValue );
else
mRightMouseDragDelta.y += S32( event.fValue );
if( mAbs( mRightMouseDragDelta.x ) > 2 && mAbs( mRightMouseDragDelta.y ) > 2 )
mRightMouseDragDetected = true;
}
//<rd: quad menus//>rd: quad menus
case "GuiQuadMenuCtrl": return true; // Not meant to be placed on other controls like that.
//<rd: quad menus
#2
08/14/2011 (11:25 am)
Yes. If you click and don't move the mouse beyond a certain small threshold, it registers as a click and pops up the menu. Otherwise, it just does the camera rotation like before.
#3
08/14/2011 (8:19 pm)
Very cool! I've kind of gotten used to using the editors as they are, but imagine the great stuff you could do with context menus. I've often wondered about creating an interface for objects where you could call methods on them for debugging purposes without having to fiddle with the console (especially for mounting).
#4
08/15/2011 (6:00 am)
Awesome stuff, big thanks for this -- funnily enough just working on adding a new editor to Torque 3D where right-click functionality could be of value.
#5
08/15/2011 (8:24 am)
Hardcore max user here, and to make the interface similar to that is absolutely awesome! Thanks a bunch!
#6
08/16/2011 (1:49 am)
This feature will be available in Torque 3D 1.2?
#7
EDIT: I'm assuming the fact that I get "WorldEditor::getSelectedObject: invalid object index" in the console every time I right click has something to do with it. I'll see if I can trace that first...
08/16/2011 (3:44 am)
This looks great! However, When I right click I'm getting the menu appear very briefly in the top left of the screen, then it disappears.. Any ideas?EDIT: I'm assuming the fact that I get "WorldEditor::getSelectedObject: invalid object index" in the console every time I right click has something to do with it. I'll see if I can trace that first...
#8
Thanks for the kind words guys.
I don't think this is mature enough to go into a release. So far, it's really little more than a (two) weekend project.
Hmm, I wouldn't think getSelectedObject() would play a part here since it's only used for checking hide and lock toggles for the menu checkmarks.
Actually, I think this is the dreaded engineAPI bug where the use of getReturnBuffer() in all the console getters causes arguments to be stomped in callbacks. This if fixed for 1.2 but not in 1.1--which only occurred to me after posting this. Admittedly, I didn't write this on a vanilla 1.1.
Try this. Replace the existing method in engineAPI.h with:
08/19/2011 (11:44 am)
Bah... sorry for the delay.Thanks for the kind words guys.
Quote:This feature will be available in Torque 3D 1.2?
I don't think this is mature enough to go into a release. So far, it's really little more than a (two) weekend project.
Quote:This looks great! However, When I right click I'm getting the menu appear very briefly in the top left of the screen, then it disappears.. Any ideas?
EDIT: I'm assuming the fact that I get "WorldEditor::getSelectedObject: invalid object index" in the console every time I right click has something to do with it. I'll see if I can trace that first...
Hmm, I wouldn't think getSelectedObject() would play a part here since it's only used for checking hide and lock toggles for the menu checkmarks.
Actually, I think this is the dreaded engineAPI bug where the use of getReturnBuffer() in all the console getters causes arguments to be stomped in callbacks. This if fixed for 1.2 but not in 1.1--which only occurred to me after posting this. Admittedly, I didn't write this on a vanilla 1.1.
Try this. Replace the existing method in engineAPI.h with:
/// Marshal data from native into client form stored directly in
/// client function invocation vector.
template< typename T >
inline void EngineMarshallData( const T& arg, S32& argc, const char** argv )
{
argv[ argc ] = Con::getStringArg( castConsoleTypeToString( arg ) );
argc ++;
}
#9
08/22/2011 (3:56 am)
@Rene - yeah, that was it. Works perfectly now - thanks! 
Torque Owner Richard Ranft
Roostertail Games