openecho's picture

Mouse Capture - My Implementation and Slow OSX Cursor Position

Hello Everyone,

I have really just started with the OpenTK framework and C#. I have been struggling with a decent mouse capture that works across Linux, OSX and Windows. Its pretty much meant to be a first person view on a box (link to current build at bottom of post). My current implementation works fine on Linux but is not so great on OSX (I have not tested windows). Getting to the bottom of it, OSX appears to take about 100ms to move the cursor after I set System.Windows.Forms.Cursor.Position where as linux is instant. I am guessing this has something to do with the X server that sits on OSX.

Does anyone have any experience with this on OSX or have any suggestions?

I have a custom Game Window that is extending from the OpenTK NativeWindow and the following is my method for getting the X and Y mouse movement deltas. If the mouse moves outside of the game window I reset it to the center. xStore and yStore are simply global floats to my Game Window.

 
public override MouseMoveDeltaEventArgs ProcessHeldMouse ()
{
	if (closing) {
		return new MouseMoveDeltaEventArgs(0,0);
	}
	Point windowLocation = window.Location;
	Point center = new Point (windowLocation.X + (window.Width / 2), windowLocation.Y + (window.Height / 2));
	Point cursorLocation = System.Windows.Forms.Cursor.Position;
 
	int xDelta = cursorLocation.X - xStore;
	int yDelta = cursorLocation.Y - yStore;
	if (!(xDelta == 0 && yDelta == 0)) {
		inputRegister.MouseMoveDeltaInput (xDelta, yDelta);
		if(cursorLocation.X >= windowLocation.X + Width || cursorLocation.X <= windowLocation.X ||
		   cursorLocation.Y >= windowLocation.Y + Height || cursorLocation.Y <= windowLocation.Y) {
			xStore = center.X;
			yStore = center.Y;
			Point newLocation = new Point(xStore,yStore);
			System.Windows.Forms.Cursor.Position = newLocation;
		} else {
			xStore = cursorLocation.X;
			yStore = cursorLocation.Y;
		}
	}
	return new MouseMoveDeltaEventArgs(xDelta, yDelta);
}

If you want to see it in action, you can find it here. I have left the mouse shown so its obvious what its doing.

Thanks,

John


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
openecho's picture

So I have updated to the trunk in the sourceforge subversion repository as some threads have suggested. I have had a play with GameWindow.CursorVisible and as promised it hides the cursor but as it hits the walls I loose deltas.

I have however seen OpenTK.Input.Mouse.SetPosition which works nice on OSX. Now I just need a nice way to hide the cursor.

Here is my updated code.

public override MouseMoveDeltaEventArgs ProcessHeldMouse ()
{
	if (closing) {
		return new MouseMoveDeltaEventArgs(0,0);
	}
	Point windowLocation = window.Location;
	Point center = new Point (windowLocation.X + (window.Width / 2), windowLocation.Y + (window.Height / 2));
	Point cursorLocation = System.Windows.Forms.Cursor.Position;
 
	int xDelta = cursorLocation.X - xStore;
	int yDelta = cursorLocation.Y - yStore;
 
	if (!(xDelta == 0 && yDelta == 0)) {
		inputRegister.MouseMoveDeltaInput (xDelta, yDelta);
		if(cursorLocation.X >= windowLocation.X + Width || cursorLocation.X <= windowLocation.X ||
		   cursorLocation.Y >= windowLocation.Y + Height || cursorLocation.Y <= windowLocation.Y) {
			xStore = center.X;
			yStore = center.Y;
			Point newLocation = new Point(xStore,yStore);
			OpenTK.Input.Mouse.SetPosition(newLocation.X, newLocation.Y);
		} else {
			xStore = cursorLocation.X;
			yStore = cursorLocation.Y;
		}
	}
	return new MouseMoveDeltaEventArgs(xDelta, yDelta);
}

John

Drakemor's picture

I found out that CursorVisible is broken:
When cursor is hidden:
depending on window position it lets you move mouse between something like screen.0 and screen.0+window size or it calculates values relatively to the window.

I haven't got any experiance with OSX, but here's some code I use:

// In OnLoad :
Mouse.Move += new EventHandler<MouseMoveEventArgs>(Mouse_Move);
 
// in Game Class
void Mouse_Move(object sender, MouseMoveEventArgs e)
        {
         // use e.XDelta and e.YDelta
            if (e.X < 5 || e.Y<5 || e.Y>Height-5 || e.X > Width -5) System.Windows.Forms.Cursor.Position=this.PointToScreen(new Point(Width/2, Height/2));
        }