Method for Getting MouseDown on TopMost Object Only
by Charlie Patterson · in Torque Game Builder · 05/17/2011 (5:37 pm) · 8 replies
I only wanted to select one scene object when the mouse was clicked. In my case, this could be the top-most object. However, Torque sends all objects under the mouse point the mouse click no matter what. Further I'm trying hard not to change the C++ code. I also couldn't find a forum post about this. So here is a solution...
All of your onMouseDown() scripts will run no matter what (I checked the code). You'll need to synchronize your onMouseDown() functions and have them communicate to each other globally. Sort of like this:
The trick is resetting the global synchronization variables between each tick. The scenegraph has a callback "onUpdateSceneTick" which is called AFTER your objects receive their callbacks. Note that this isn't "onUpdateScene" which appears to be called many times per scene tick as far as I can gather!
So my case would need something like this:
This isn't super-elegant but I hope it can be modified to your use case.
All of your onMouseDown() scripts will run no matter what (I checked the code). You'll need to synchronize your onMouseDown() functions and have them communicate to each other globally. Sort of like this:
function MyObject::onMouseDown(%this, %modifier, %worldPos)
{
// did a fellow object already use up the mouseDown?
if ($mouseDownEaten)
return;
// do some work if you are the one to get the click
echo(%this.getName() SPC "Yay! I get the mouse click!");
// now register the mouseDown as used up for your fellow objects
$mouseDownEaten = %this;
}The trick is resetting the global synchronization variables between each tick. The scenegraph has a callback "onUpdateSceneTick" which is called AFTER your objects receive their callbacks. Note that this isn't "onUpdateScene" which appears to be called many times per scene tick as far as I can gather!
So my case would need something like this:
function MySceneGraph::onUpdateSceneTick(%this){
if ($mouseDownEaten) {
echo($mouseEaten.getName() SPC "ate the mouse down. I'll reset it for the next click.");
$mouseDownEaten = "";
}
}This isn't super-elegant but I hope it can be modified to your use case.
#2
Though, the second part is:
function t2dSceneGraph::onUpdateSceneTick(%this)
{
if ($mouseDownEaten) {
$mouseDownEaten = "";
}
}
09/26/2012 (9:12 pm)
Started implementing this to fix an issue and it works pretty well :)Though, the second part is:
function t2dSceneGraph::onUpdateSceneTick(%this)
{
if ($mouseDownEaten) {
$mouseDownEaten = "";
}
}
#3
you can do something like:
www.garagegames.com/community/blogs/view/19719
There are also other ways there of doing it through script.
09/27/2012 (3:10 am)
Guys you want to block mouse evens for sprites below, so when you click on the top most object all beneath ones were not receiving the click, am I correct?you can do something like:
function topSprite::onMouseEnter(blabla)
{
belowSprite.setUseMouseEvents(false);
}But a better way would be to modify the source and save tons of time, here is the linkwww.garagegames.com/community/blogs/view/19719
There are also other ways there of doing it through script.
#4
Hope your problems are solved!
You can give your t2dSceneGraph a name and use it specifically. In my case I used MySceneGraph. I agree that was a bit confusing. Thanks for the pointer.
Now if you are feeling like updating some C++ and you have more complicated situations where you want to get only one mouse call, I wrote this patch: http://www.garagegames.com/community/forums/viewthread/129829 . Warning that this is getting into the guts of Torque and recompiling it and all that.
09/27/2012 (7:30 am)
Hi @Harry,Hope your problems are solved!
You can give your t2dSceneGraph a name and use it specifically. In my case I used MySceneGraph. I agree that was a bit confusing. Thanks for the pointer.
Now if you are feeling like updating some C++ and you have more complicated situations where you want to get only one mouse call, I wrote this patch: http://www.garagegames.com/community/forums/viewthread/129829 . Warning that this is getting into the guts of Torque and recompiling it and all that.
#5
Good topic, may I suggest that you can also use schedule function to reset $mouseDownEaten, like so:
function MyObject::onMouseDown(%this, %modifier, %worldPos)
{
// did a fellow object already use up the mouseDown?
if ($mouseDownEaten)
return;
// do some work if you are the one to get the click
echo(%this.getName() SPC "Yay! I get the mouse click!");
// now register the mouseDown as used up for your fellow objects
$mouseDownEaten = %this;
schedule(32,%this,"resetmouseDownEaten");
}
function resetmouseDownEaten()
{
if ($mouseDownEaten) {
echo($mouseEaten.getName() SPC "ate the mouse down. I'll reset it for the next click.");
$mouseDownEaten = "";
}
}
10/22/2012 (8:03 am)
@Charlie, Good topic, may I suggest that you can also use schedule function to reset $mouseDownEaten, like so:
function MyObject::onMouseDown(%this, %modifier, %worldPos)
{
// did a fellow object already use up the mouseDown?
if ($mouseDownEaten)
return;
// do some work if you are the one to get the click
echo(%this.getName() SPC "Yay! I get the mouse click!");
// now register the mouseDown as used up for your fellow objects
$mouseDownEaten = %this;
schedule(32,%this,"resetmouseDownEaten");
}
function resetmouseDownEaten()
{
if ($mouseDownEaten) {
echo($mouseEaten.getName() SPC "ate the mouse down. I'll reset it for the next click.");
$mouseDownEaten = "";
}
}
#6
The issue seemed to be that the load game code would try to clear the screen and restart the loaded game - however, the engine was still trying to process the onMouseDown part for the other object - even though that code should have just found $mouseDownEaten and aborted. I actually had to make a short bit of code to turn off UseMouseEvents for all other screen items when opening the main menu to avoid this issue.
07/09/2013 (5:15 am)
Dredging up this old thread, but I actually ran into issues with this implementation and maybe this will help someone else :). When loading a game, my main menu overlay would pop up over other buttons. Even though it was supposed to be ignoring the clicks on lower buttons the game would actually crash.The issue seemed to be that the load game code would try to clear the screen and restart the loaded game - however, the engine was still trying to process the onMouseDown part for the other object - even though that code should have just found $mouseDownEaten and aborted. I actually had to make a short bit of code to turn off UseMouseEvents for all other screen items when opening the main menu to avoid this issue.
#7
I've had a problem with loadLevel if you don't finish the current function before it runs!
07/11/2013 (9:21 pm)
Hmm. If I follow, you may want to change your loadLevel function to run on a schedule. Something like schedule(1, loadLevel, "levelName")I've had a problem with loadLevel if you don't finish the current function before it runs!
#8
07/11/2013 (10:38 pm)
Not exactly, but it's in the same vein. I ran into that issue when I started my project and ended up ditching the whole loadLevel function (after the initial one). My LoadGame function just deletes the current screen objects, then reloads data and creates objects based on the save game information. What I was running into was, after it did the delete portion, it was apparently trying to run the onMouseDown code for a no-longer existing object and the game would crash out. It took me forever to realize it was because I was only handling button layers using the $mouseDownEaten scheme, and that I had to actually turn off UseMouseEvents for the objects to avoid this problem.
Associate Charlie Patterson
Default Studio Name
To solve this, I'd propose a future version of T2D could either send mouseLock objects their events AFTER the unlocked objects. Or, even better, sort the locked objects into appropriate order along with the layered objects.
Note that the above fixes (either one of the two) would also solve a bug where you sometimes get two events while unlocking the mouse. For instance, you first receive the mouseDown due to being locked. Let's suppose your callback unlocks the mouse. Then, T2D calls all objects that are actually under the mouse. At this point, T2D tries to skip objects that are locked but under the mouse, because they've already been called. However, you just unlocked the mouse, so you receive the event again.