Game Development Community

Mouse Input Callbacks

by Caleb · in Torque 2D Beginner · 03/18/2013 (9:12 pm) · 20 replies

I need some help finding/creating some mouse input callbacks. I'm looking for something similar to what was used in TGB for:

onMouseEnter
onMouseLeave
onRightMouseDown (Up, Dragged...ect)

Other than the .ontouchdown, onmousewheeldown...ect found in some of the toy's, I can't seem to find what I would use for the above input events. If anyone can point me in the right directions it would be much appreciated.

#1
03/18/2013 (9:18 pm)
mouse is userfull at pc.

If you want your game to run at ipads and iphones, you need focus on touch event :)



#2
03/18/2013 (9:53 pm)
Use the touch events - on platforms with a mouse they are converted internally and will respond to the mouse. However, the touch ID will always be 0, and a right-touch doesn't make much sense....
#3
03/18/2013 (10:11 pm)
As Richard stated, 'onTouchDown', 'onTouchUp' and 'onTouchDragged' will
handle both Touch Input for iOS and Mouse Input for PC/MAC.

You would use them like so :

SceneWindow::onTouchDown(%this, %touchid, %worldposition)
{
//insert your code here!
}

If you want to enable these callbacks on SceneObjects, you need to do two things.

First, tell your SceneWindow that the SceneObjects should process InputEvents :
SceneWindow.UseObjectInputEvents = true;

Then, you must specify for each object whether to process these events or not :
SceneObject.UseObjectInputEvents = true;

You could then implement the following method :
SceneObject::onTouchDown(%this, %touchid, %worldposition);

For the Right Mouse Button, you still have the following functions which will be unavailable on iOS and touch-based devices :

onRightMouseDown
onRightMouseUp
onRightMouseDragged

Since they are not Touch-based events, they will have different arguments
SceneWindow::onRightMouseUp(%modifier, %worldposition, %mouseclicks)
{
//Insert your code here!
}

You also have the following for MouseWheel controls :

onMouseWheelUp
onMouseWheelDown

onMouseEnter and onMouseLeave are not implemented on all controls, browse the source code to find out which objects have it!
#4
03/18/2013 (11:01 pm)
The right mouse button functions are only available to the SceneWindow, they do not work on SceneObjects. Is this intended or is it a bug? If someone wants to release a PC only game, they should have all the mouse event options on a per object basis available and not just touch events.
#5
03/19/2013 (3:57 am)
I had a look inside SceneWindow.cc where all the mouse and touch event callbacks are located. It's funny coming from a Torquescript only background, upon opening the file it was like one of those movie moments where the clouds in the sky part, sun rays shining down, and the choir in the background sings.

My reaction: "Wow, I can read this."

So I see towards the top of the file the input event names are defined:
// Touch input event names.
mInputEventDownName = StringTable->insert("onTouchDown");
mInputEventUpName = StringTable->insert("onTouchUp");
mInputEventMovedName = StringTable->insert("onTouchMoved");
mInputEventDraggedName = StringTable->insert("onTouchDragged");
mInputEventEnterName = StringTable->insert("onTouchEnter");
mInputEventLeaveName = StringTable->insert("onTouchLeave");

// Mouse input event names.
mMouseEventRightMouseDownName = StringTable->insert("onRightMouseDown");
mMouseEventRightMouseUpName = StringTable->insert("onRightMouseUp");
mMouseEventRightMouseDraggedName= StringTable->insert("onRightMouseDragged");
mMouseEventWheelUpName = StringTable->insert("onMouseWheelUp");
mMouseEventWheelDownName = StringTable->insert("onMouseWheelDown");
mMouseEventEnterName = StringTable->insert("onMouseEnter");
mMouseEventLeaveName = StringTable->insert("onMouseLeave");

Then a bit further down in SceneWindow::sendObjectInputEvent there is this section:
// Only process appropriate input events.
if ( !( name == mInputEventDownName ||
name == mInputEventUpName ||
name == mInputEventMovedName ||
name == mInputEventDraggedName ) )
return;

I guess it would be easy enough to expand that whitelist to include right mouse events as well. Would just need to figure out a smart way for "onMouseDown" and "onTouchDown" to share the same name for object input events.
#6
03/19/2013 (3:28 pm)
Right-"touch" can be emulated with a second touch - weird, but just test for touchID of 1 instead of 0. Perhaps pop up a secondary button to touch while holding the main one?

Unless you can think of a way to programmatically determine if it's my right or left index finger that I'm touching with....
#7
03/19/2013 (4:18 pm)
@Richard : %touchid returns the id of the touch event, nothing more. If you look in the Sandbox module, under scripts/manipulation.cs, it uses %touchid to determine if the current touch input event occurs while another touch input event (one with a different %touchid) is already under way to determine if the current gesture should be a pan or rotate.

From what I understand, Right touch doesn't make sense on TouchScreen devices.
#8
03/19/2013 (4:31 pm)
How did we get on the topic of right touch? It's perfectly valid to use T2D to make a Windows only game - and at the moment right mouse clicks are not implemented on scene objects like they were in TGB.
#9
03/19/2013 (4:51 pm)
Yes, %touchId returns the id of the touch event. The first is 0, the second is 1, etc - this is equal to the number of current touches - 1, so placing a finger on a button can pop up a radial menu while the finger is still touching - and a second finger can then touch a button on that menu. Right-"touch" doesn't mean anything, but second-touch does.

@Mike - I suppose it came up because this would allow you to emulate the right-click on touch devices. Plus, I have three pointing devices on my home PC and could probably get more than one "touch" there, too. <Shrug> - sorry if I derailed you....

Quote:
Would just need to figure out a smart way for "onMouseDown" and "onTouchDown" to share the same name for object input events.
Well, I'd leave the current "touch" events alone and just add onRightMouseDown, onRightMouseDragged, etc - since the "touch" events are translated as mouse events when appropriate as it is. Since the "right" mouse events won't be used on iOS I can't see a reason to worry over-much about it. Hey, do Macs have a right button yet?
#10
03/19/2013 (9:06 pm)
Thanks for all the replies guys. This definitly gave me what I needed! I was looking through the source before I posted but didn't find where they were being called from.

Also, I should have stated I was working with scene objects in regards to the mouse events and was aware of the onTouch uses for the left mouse clicks.

As Mike suggested, I added the mouse events to the white list. So my SceneWindow.cc source now looks like this:

// Only process appropriate input events.
    if ( !( name == mInputEventDownName ||
            name == mInputEventUpName ||
            name == mInputEventMovedName ||
            name == mInputEventDraggedName ||
            name == mMouseEventRightMouseDownName ||
            name == mMouseEventRightMouseUpName ||
            name == mMouseEventRightMouseDraggedName ||
            name == mMouseEventEnterName ||
            name == mMouseEventLeaveName ) )
        return;

After recompiling and testing, everything seems to be working as desired. That being said, I wonder if there's a reason why these are left out. I don't know enough about the source, or c++ in general, to know if these changes would cause an issue in another area...other than not being supported by touch devices, which is kind of a given.

Thanks again for the help! If I run into an issue down the road I'll update the post.
#11
03/20/2013 (2:04 am)
@Richard - sorry, I didn't know if you were replying to my post (as it didn't make sense in that context) or if you were going off on a different tangent. It's no problem though, derail away. :)

Quote:Well, I'd leave the current "touch" events alone and just add onRightMouseDown, onRightMouseDragged, etc - since the "touch" events are translated as mouse events when appropriate as it is. Since the "right" mouse events won't be used on iOS I can't see a reason to worry over-much about it. Hey, do Macs have a right button yet?

I don't necessarily want to modify the touch events. I am asking why the input interaction system has been handicapped with a focus only on the lowest common denominator (touch based devices). In stock T2D we have the following (only using touch/mouse down to simplify things):

function SceneWindow::onTouchDown(%this, %touchID, %worldPosition)
{
}

function SceneWindow::onMouseDown(%this, %mod, %worldPosition, %clicks)
{
}

function SceneObject::onTouchDown(%this, %touchID, %worldPosition)
{
}

Why no SceneObject::onMouseDown? I know you can use onTouchDown to handle mouse clicks, but 1. the naming convention is funny if I am only developing for Windows/OSX and not iOS, 2. %touchID is not a replacement for %mod, shift/alt/ctrl plus mouse click no longer return a mouse modifier value.

I know most of this can be readded in source, as Caleb and I showed partly with right mouse clicks. But why not have input support for everything in stock T2D and let developers decide what input methods make sense to use based on their game and the platforms they want to support?
#12
03/20/2013 (2:57 am)
I'll give you a little bit of knowledge to use when asking the question "why is T2D the way it is".

That piece of knowledge is this:

T2D has a long history of branching and merging and T2D is not finished.

By this I don't mean finished in the sense that software never is truly finished but in the sense that the merge of TGB/iT2D into T2D MIT addressed many, many things but not everything and it was released with many of the problems it has had for years in its various guises (TGB, T2D & iT2D).

The input, audio & GUI systems are some of the worst areas and have received very little love. The Input system is basically skewed towards iT2D still.

The best way to approach this is to come up with a set of suggestions and put them out there, try to cover all the bases. This might be a document, it might be a pull request.

Either you, other community members or GG itself might want to discuss/make those changes.
#13
03/20/2013 (3:46 am)
You're right Melv. Just asking why is poorly thought out and it would be more constructive to detail the current system as is and ask others if they are satisfied with it or should it be improved. I will try to keep that in mind for the future.
#14
03/20/2013 (7:49 am)
Yeah, audio could use a bit of love - but I'm up to my neck in trying to get scriptable .dll plug-ins working at the moment. Perhaps I'll turn my attention to those audio improvements Mike and I were discussing here next.
#15
03/22/2013 (1:46 pm)
Well, after working with this a little more the onMouseLeave and onMouseEnter events are only being called when the sceneWindow receives focus from another gui control. This makes since for the sceneWindow event, but does not allow us to use the onMouseLeave and onMouseEnter callbacks for sceneObjects as desired.

So...the only way my sceneObject gets passed the onMouseEnter event is when the mouse cursor happens to be over the sceneObject at the time the sceneWindow receives focus from another gui(say when the console window is pop'ed). For example, say I have the console window awake or opened, and I was to toggle the console closed, then the onMouseEnter event would be called and passed to the sceneObject if the mouse cursor happened to be over the sceneObject at that time. The opposite is true as well, if the mouse cursor is over the sceneObject and the sceneWindow loses focus by pushing the console to the front, the sceneObject would get passed the onMouseLeave event.

Hopefully I'm missing something simple.

Oh, and while messing with this, I noticed that setting pickingallowed to false on an object seems to disable all input events on that object despite the useInputEvents being set to true. This might be expected, but I was unaware as I haven't looked much into "picking" yet.
#16
03/22/2013 (11:24 pm)
Well, this did end up being something fairly simple. I looked back at the source and realized the onTouchMoved was being used for the onMouseMove events and that I can use onTouchLeave and onTouchEnter for my mouse callbacks instead of onMouseLeave and onMouseEnter (just as with onTouchDown/Up for the left mouse click events).

Given this, there is no need to have the onMouseLeave and onMouseEnter added to the white list as these events are only passed to the sceneObject when captured by the sceneWindow...as my last post confusingly explained. The white list only needs to include the right mouse events:

// Only process appropriate input events.
    if ( !( name == mInputEventDownName ||
            name == mInputEventUpName ||
            name == mInputEventMovedName ||
            name == mInputEventDraggedName ||
            name == mMouseEventRightMouseDownName ||
            name == mMouseEventRightMouseUpName ||
            name == mMouseEventRightMouseDraggedName ) )
        return;

With that being said...one could easily add the onMouseLeave and onMouseEnter callbacks to sceneObjects by modifying the sceneWinodow.cc source as shown here:

// Process "leave" events.
    for ( U32 index = 0; index < (U32)mInputEventLeaving.size(); ++index )
    {
        // Fetch scene object.
        SceneObject* pSceneObject = mInputEventLeaving[index];

        // Emit event.
        pSceneObject->onInputEvent( mInputEventLeaveName, event, worldMousePoint );
        //****added next line for onMouseLeave sceneObject callback
        pSceneObject->onInputEvent( mMouseEventLeaveName, event, worldMousePoint );
        // Remove scene object.
        mInputEventWatching.removeObject( pSceneObject );
    }

    // Process "enter" events.
    for ( U32 index = 0; index < (U32)mInputEventEntering.size(); ++index )
    {
        // Fetch scene object.
        SceneObject* pSceneObject = mInputEventEntering[index];

        // Emit event.
        pSceneObject->onInputEvent( mInputEventEnterName, event, worldMousePoint );
        //***added next line for onMouseEnter sceneObject callback
        pSceneObject->onInputEvent( mMouseEventEnterName, event, worldMousePoint ); 
        // Process "moved" or "dragged" events.
        if ( name == mInputEventMovedName || name == mInputEventDraggedName )
            pSceneObject->onInputEvent( name, event, worldMousePoint );

        // Add scene object.
        mInputEventWatching.addObject( pSceneObject );
    }
#17
04/08/2013 (6:55 pm)
I am having a very frustrating time with mouse input. It is not working for whatever reason and I think everything here is correct. The game runs fine it just never evaluates echo(). Here is my code:

function buildScene()
{
    new Scene (mainScene)
    {
        Modal = true;   
    };

    new SceneWindow (mainWindow)
    {
        Modal = true;
    };
    mainWindow.profile = new GuiControlProfile();
    mainWindow.setScene(mainScene);
    ...
    mainWindow.UseObjectInputEvents = true;
    mainScene.UseObjectInputEvents = true;
    
    Canvas.setContent(mainWindow);
}

function mainScene::onTouchDown(%this, %touchId, %worldposition)
{
    echo("#########################");
}

function mainWindow::onTouchDown(%this, %touchId, %worldposition)
{
    echo("#########################");
}
#18
04/08/2013 (7:25 pm)
@Fox Trot : The error lies in your definition of Modal=true;

The Modal property means nothing to the SceneWindow, it needs to be set in the ControlProfile.

I've pasted your code in a fresh new project, removed Modal=true; from the new SceneWindow call and replaced the new GuiControlProfile with this code :

mainWindow.profile = new GuiControlProfile()
{
Modal = true;       
 };

Works like a charm!

Don't worry, though, everyone dealing with the intricacies of the Gui System has experienced immense amounts of frustration at one point or another and has uttered their fair share of swear words :)
#19
04/08/2013 (7:40 pm)
WOHOO!

@Simon Love: I LOVE YOU
#20
04/08/2013 (7:56 pm)
My pleasure, Fox.

t.qkme.me/3qol9d.jpg