I’m looking to make a simple shim that allows users to interact with my main menus (yes, it’s because my app isn’t passing the steam build review). I can’t find an InputManager based method to move the cursor, so I just linked to the user32.dll since my app is windows only (for now). This works great in that the cursor moves and I can trigger clicks with my gamepad. BUT: this approach badly breaks something in the unity event system, and sometimes clicks and mouse cursor location can be disassociated, as tho the event system thinks the cursor is somewhere FAR behind where it’s currently being displayed by Windows. I tried moving the cursor using setpos/getpos or using mouse_event and both have this flaw. Does anybody have a fix for this, or some other shim code that uses a different method to move a cursor to an arbitrary location on the screen and dispatch click events to any UI object under that location?
Here’s my code, showing both approaches I tried:
using System.Runtime.InteropServices;
using UnityEngine;
public class MouseController : MonoBehaviour
{
[DllImport("user32.dll")]
static extern bool SetCursorPos(int x, int y);
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int x;
public int y;
public static implicit operator Vector2(POINT p)
{
return new Vector2(p.x, p.y);
}
}
[DllImport("user32.dll")]
private static extern bool GetCursorPos(out POINT lpPoint);
[DllImport("user32.dll")]
static extern void mouse_event(uint dwFlags, int dx, int dy, uint cButtons, uint dwExtraInfo);
// Mouse event flags
const uint MOUSEEVENTF_LEFTDOWN = 0x02;
const uint MOUSEEVENTF_LEFTUP = 0x04;
const uint MOUSEEVENTF_MOVE = 0x0001;
public string buttonName = "Jump"; // The name of the button in Input Manager
public float cursorSpeed = .5f;
public void MoveMouse(Vector2 delta) // move mouse cursor relative to current location (set + getpos version)
{
POINT p;
GetCursorPos(out p);
SetCursorPos((int)(delta.x + p.x), (int)(delta.y + p.y));
}
/*
public void MoveMouse(Vector2 delta) // move mouse cursor relative to current location (mouse event version)
{
mouse_event(MOUSEEVENTF_MOVE, (int)delta.x, (int)delta.y, 0, 0);
}
*/
void Update()
{
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
Vector2 delta = new Vector2(horizontal * cursorSpeed, vertical * -cursorSpeed); // invert y maps more intuitively
MoveMouse(delta);
// Simulate mouse down on button press
if (Input.GetButtonDown(buttonName))
{
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
print ("clicked");
}
// Simulate mouse up on button release
if (Input.GetButtonUp(buttonName))
{
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
print ("released");
}
}
}