Is anyone able to track mouse movement?
by John Kanalakis · in Torque X 2D · 12/26/2007 (11:59 pm) · 9 replies
Has anyone implemented any mouse tracking code? I am able to process the mouse clicks, but can't seem to track the specific mouse movement. I thought that binding to the MoveMapTypes.StickAnalogHorizontal would do it, but it doesn't seem to work for me (unless I'm missing something). Here's some of my sample code.
With this code implementation, state.LeftButton is properly set to "Pressed" as a recognized mouse click, but the move.Sticks[1].X is always 0. True I've mapped this to "Sticks" which is normally for the gamepad, but there doesn't seem to be a Move structure specific to the mouse. Any ideas would be greatly appreciated.
John K.
protected override void _SetupInputMap()
{
InputMap.BindMove( 0, (int)XMouseDevice.MouseObjects.X, MoveMapTypes.StickAnalogHorizontal, 1);
}public void ProcessTick(Move move, float elapsed)
{
if (_enabled)
{
MouseState state = Mouse.GetState();
if (state.LeftButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
{
float rotX = move.Sticks[1].X * move.Sticks[1].X;
if (move.Sticks[1].X < 0.0f)
rotX = -rotX;
float rotY = move.Sticks[1].Y * move.Sticks[1].Y;
if (move.Sticks[1].Y < 0.0f)
rotY = -rotY;
}
}
} With this code implementation, state.LeftButton is properly set to "Pressed" as a recognized mouse click, but the move.Sticks[1].X is always 0. True I've mapped this to "Sticks" which is normally for the gamepad, but there doesn't seem to be a Move structure specific to the mouse. Any ideas would be greatly appreciated.
John K.
About the author
John Kanalakis is the owner of EnvyGames, an independent game development studio in Silicon Valley that produces games and tools for Xbox 360, Windows, and the Web.
#2
Just an idea :D
12/27/2007 (6:50 am)
In my guibutton enhanced button, I supported the mouse activity by pretty much foregoing the move structure, and forwarding the action via a delegate. I wonder if you could do something similar, and call a delegate passing in your MouseState when the mouse is within a certain position or state. I did this specific to my button:public void ProcessTick(Move move, float elapsed)
{
if (this.Awake)
{
MouseState state = Mouse.GetState();
if (state.X > this.Position.X
&& state.X < this.Position.X + this.Size.Width
&& state.Y > this.Position.Y
&& state.Y < this.Position.Y + this.Size.Height)
{
// If it does not have the focus, set it to be focused
if (!GUICanvas.Instance.ControlHasFocus(this))
{
GUICanvas.Instance.SetFocusControl(this);
}
if (_processMouseEvents)
{
if (state.LeftButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
{
// This means they are within the bounds of the button, and the button is pressed
if (_onMouseClick != null)
{
ProcessList.Instance.SetEnabled(this, false); // disable it as we will be switching canvases
GameData.Instance.SoundBank.PlayCue("mouseDown"); // Play the mousedown sound
_onMouseClick(state); // Call the delegate set by the caller
}
}
else
{
if (_onMouseHover != null)
{
_onMouseHover(state);
}
}
}
}
}
}Just an idea :D
#3
It seems like each event (mouse press and mouse click) generate a new Move structure, so as I process the mouse movement, a mouse press clears the movement data. I'll try a new approach based on your example. Maybe to set a "lock" variable when the mouse is down, then process the movement while the "lock" variable is set, and reset the "lock" variable when the mouse is up.
John K.
12/27/2007 (7:03 am)
David, thank you for the helpful thoughts. I might need to take a new direction as you've outlined above. The problem I seem to have is that I can track a mouse press and I can track mouse movement - but - I can not track mouse movement with a mouse pressed (for a dragging effect). It seems like each event (mouse press and mouse click) generate a new Move structure, so as I process the mouse movement, a mouse press clears the movement data. I'll try a new approach based on your example. Maybe to set a "lock" variable when the mouse is down, then process the movement while the "lock" variable is set, and reset the "lock" variable when the mouse is up.
John K.
#4
12/27/2007 (7:31 am)
Ahh, ok. Hmm, I wonder if you had a mousetracking class and when several processticks have passed, and the mousebutton is still pressed but the x and y have changed within a set range, it could raise a mousedrag event on the mousetracking class. When I was going through the torquex code for the mouse a while back, it looked like it is meant for basic movement and actions. At some point, I plan on implementing my own mousesupport class to handle events like drag n drop,etc. Let me know what you come up with, I would be curious to see the various ideas on this.
#5
It turns out that there's an overloaded method for the BindMove() method that accepts input modifiers (such as mouse down). So, the binding code above DOES NOT accept movements with mouse pressed intentionally. To ACCEPT mouse movements with mouse pressed, set the binding as follows:
Note the new TorqueInputDevice.Action.LeftClick third parameter.
Then, you can check for the mouse button press along with your mouse movements in the ProcessTick() method with the following
That seems to do it. Thank you David for helping me through this.
John K.
12/27/2007 (7:39 am)
Mission Accomplished ;)It turns out that there's an overloaded method for the BindMove() method that accepts input modifiers (such as mouse down). So, the binding code above DOES NOT accept movements with mouse pressed intentionally. To ACCEPT mouse movements with mouse pressed, set the binding as follows:
_inputMap.BindMove(mouseId, (int)XMouseDevice.MouseObjects.X, TorqueInputDevice.Action.LeftClick, MoveMapTypes.StickAnalogHorizontal, 0); _inputMap.BindMove(mouseId, (int)XMouseDevice.MouseObjects.Y, TorqueInputDevice.Action.LeftClick, MoveMapTypes.StickAnalogVertical, 0);
Note the new TorqueInputDevice.Action.LeftClick third parameter.
Then, you can check for the mouse button press along with your mouse movements in the ProcessTick() method with the following
public void ProcessTick(Move move, float elapsed)
{
MouseState state = Mouse.GetState();
if (move.Sticks[0].Y > 0.0 || move.Sticks[0].X > 0.0f)
{
if (state.LeftButton == ButtonState.Pressed)
{
//you are currently dragging the mouse ;)
}
}
} That seems to do it. Thank you David for helping me through this.
John K.
#6
12/27/2007 (8:17 am)
Ahh, is that 1.5 and 1.1, or just 1.5? Another thread for me to bookmark , good work! :)
#7
John K.
12/27/2007 (8:21 am)
I'm running version 1.5. I don't think it was around for version 1.1, but it's really useful - a great way to filter input (when you know that it actually exists ;) ). Also, in case my last post was misleading, you don't *need* to check if the button is pressed as you will only get a Move structure if the button is already pressed. John K.
#8
http://underdog32.spaces.live.com/default.aspx
01/16/2008 (9:28 pm)
FYI, if anyone cares how to do this in straight XNA, or if you want a component that allows windows like events, I wrote a component that will do this:http://underdog32.spaces.live.com/default.aspx
#9
05/01/2008 (2:04 pm)
After implementing Johns code above, it seems as though I am unable to click-drag select objects when starting from top-left going to bottom-right. Is anyone else seeing this? All other directions of selection seem to be working fine.
Associate John Kanalakis
EnvyGames
Binding
protected virtual void _SetupInputMap() { if (PlayerManager.Instance.GetPlayer(_playerIndex).ControlObject == null) { PlayerManager.Instance.GetPlayer(_playerIndex).ControlObject = Owner; _inputMap = PlayerManager.Instance.GetPlayer(_playerIndex).InputMap; } else { _inputMap = new InputMap(); } int mouseId = InputManager.Instance.FindDevice("mouse"); if (mouseId >= 0) { _inputMap.BindMove(mouseId, (int)XMouseDevice.MouseObjects.LeftButton, MoveMapTypes.Button, 0); _inputMap.BindMove(mouseId, (int)XMouseDevice.MouseObjects.RightButton, MoveMapTypes.Button, 0); _inputMap.BindMove(mouseId, (int)XMouseDevice.MouseObjects.X, MoveMapTypes.StickAnalogHorizontal, 0); _inputMap.BindMove(mouseId, (int)XMouseDevice.MouseObjects.Y, MoveMapTypes.StickAnalogVertical, 0); } }ProcessTick() method
public void ProcessTick(Move move, float elapsed) { if (move == null) return; Vector3 vel = Vector3.Zero; if (move.Buttons[0].Pushed) { if (move.Sticks.Count > 0) { Vector3 right = MatrixUtil.MatrixGetRow(0, ref _transform); Vector3 forward = MatrixUtil.MatrixGetRow(1, ref _transform); vel += ((forward * move.Sticks[0].Y) + (right * move.Sticks[0].X)) * _cameraMoveSpeed; } } SceneGroup.Position += vel; }This should move the camera around the scene while the button is pressed. But, it kinda seems like I get either valid mouse X-Y movement tracking or notification that the button is pressed. I never seem to get a Move structure with X-Y movement information AND button pressed information.
So, does the button press clear out the move structure? As always, thoughts are welcome.
John K.