Chapter 7: OpenTK.Input

[Todo: describe keyboard and joystick input]

OpenTK provides two distinct methods for mouse input.

  1. OpenTK.Input.Mouse, which provides low-level access to mouse motions. It is independent of windows/displays and provides raw (i.e. non-accelerated) values, if possible. Use this for games that require mouse motions not confined to the display, for instance first-person shooters and 3d games with mouse-controlled cameras.

    OpenTK.Input requires OpenTK 1.1 or higher. Its methods are thread-safe and may be used from any thread.

  2. GameWindow.Mouse* events, which are equivalent to WinForms/WPF/GTK# mouse events. The values are accelerated by the OS and are reported in window coordinates. Use this for menu/UI navigation and games that require absolute coordinates, for instance and 2d games.

    Mouse events require OpenTK 1.0 or higher. They are not thread-safe and may only be used on the thread that created the GameWindow.

OpenTK.Input.Mouse

You can move the mouse cursor using OpenTK.Input.Mouse.SetPosition(x, y). This method will not generate GameWindow events. This method may generate GLControl events, depending on the operating system.

Use Mouse.GetState() to retrieve the aggregate state of all connected mice.

Use Mouse.GetState(int) to retrieve the state of the specified mouse.

To check whether a button is pressed:

using OpenTK.Input;
 
var mouse = Mouse.GetState();
if (mouse[MouseButton.Left])
{
    // Left mouse button is pressed
}

To check whether a mouse button is not pressed:

using OpenTK.Input;
 
var mouse = Mouse.GetState();
if (!mouse[MouseButton.Left])
{
    // Left mouse button is not pressed
}

To check whether the mouse state has changed:

using OpenTK.Input;
 
MouseState current, previous;
 
void UpdateMouse()
{
    current = Mouse.GetState();
    if (current != previous)
    {
        // Mouse state has changed
        int xdelta = current.X - previous.X;
        int ydelta = current.Y - previous.Y;
        int zdelta = current.Wheel - previous.Wheel;
    }
    previous = current;
}

To get the mouse coordinates:

using OpenTK.Input;
 
var mouse = Mouse.GetState();
int x = mouse.X;
int y = mouse.Y;
int z = mouse.Wheel;

Note that these mouse coordinates do not correspond physically to the monitor and should only be used for relative motion. Code that requires physical coordinates should use GameWindow or GLControl mouse events instead.

GameWindow Mouse Input

Use these methods if you want the exact mouse position on the screen. Some examples include:

           this.Mouse.ButtonUp += (object sender, MouseButtonEventArgs buttonEvent) => {
                Console.WriteLine("Mouse button up: " + buttonEvent.Button + " at: " + buttonEvent.Position);
            };

or

            Vector2 pos = new Vector2(this.Mouse.X, this.Mouse.Y);

Where "this" is a GameWindow.


Comments

Comment viewing options

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

Where's the info?

makarone's picture

I'm new to OpenTK so I may have got this all wrong. The article says that you should use the OpenTK.Inputs.Mouse if you're making a game. But to use that you need OpenTK 1.1, which doesn't exists besides an extremely old alpha version. Does this mean that the input function of OpenTK is useless if you're making a game?

the Fiddler's picture

You can get 1.1 from SVN trunk. It's not ready for a public release yet but the input code is stable and works.

makarone's picture

Thanks!

fkj's picture

I have used AnkhSVN to download OpenTK 1.1, and changed my own projects reference from OpenTK 1.0 to the dll created by the OpenTK solution (OpenTK.dll). It all works fine, but when compiling my own project it tells me OpenTK.Input.Mouse does not have a GetState() method.

Tal's picture
Quote:

Note that these mouse coordinates do not correspond physically to the monitor and should only be used for relative motion. Code that requires physical coordinates should use GameWindow or GLControl mouse events instead.

I do understand what it does mean "do not correspond physically to the monitor", but didn't understand why, and why I have to use GameWindow or GLControl mouse events...

the Fiddler's picture
Quote:

I have used AnkhSVN to download OpenTK 1.1, and changed my own projects reference from OpenTK 1.0 to the dll created by the OpenTK solution (OpenTK.dll). It all works fine, but when compiling my own project it tells me OpenTK.Input.Mouse does not have a GetState() method.

Remove the references, clean your project and add them again. You must add the new OpenTK.dll using the "Browse" tab in "Add References", not the ".NET" tab.

Quote:

I do understand what it does mean "do not correspond physically to the monitor", but didn't understand why, and why I have to use GameWindow or GLControl mouse events...

The GLControl and GameWindow report mouse events that are bounded by the monitor and/or window boundaries (i.e. if your mouse reaches (0, 0) it will no longer be able to move up or left). Mouse.GetState() allows infinite movements (the mouse can move beyond (0, 0)), which means its coordinates no longer correspond to the physical screen.

Tal's picture

Thanks fiddler!
I thought you mean that they wait until some Update() method is called, but it is irrelevant...

fkj's picture
Quote:
Quote:

I have used AnkhSVN to download OpenTK 1.1, and changed my own projects reference from OpenTK 1.0 to the dll created by the OpenTK solution (OpenTK.dll). It all works fine, but when compiling my own project it tells me OpenTK.Input.Mouse does not have a GetState() method.

Remove the references, clean your project and add them again. You must add the new OpenTK.dll using the "Browse" tab in "Add References", not the ".NET" tab.

Thank you for your quick reply!

I have just found the cause of the problem, and it turned out to be something quite different.

C# has a name collision problem between class names and property names (a weakness of the language). I usually avoid naming my classes/properties with the same names to avoid this problem. If you always use full namespace path this is not a problem, but I don't like the extra text this adds to my source code. True to this, I used the following:

using OpenTK.Input;
 
...
 
  class Game : GameWindow {
 
    ...
 
    ... = Mouse.GetState();
 
    ...
 
  }

The problem is that GameWindow has a property Mouse, hence I was trying to call GetState() on this property (an instance of MouseDevice), and not calling the static method GetState() on the class OpenTK.Input.Mouse.

It would be nice if Visual Studio could issue a warning on these name collisions.