using System.Numerics; using SDL2; namespace Nerfed.Runtime; internal static class Mouse { public static Vector2 Position { get; private set; } private static readonly ButtonState[] buttonStates; private static readonly ButtonState[] lastButtonStates; private static int wheelX; private static int wheelY; static Mouse() { int numButtons = Enum.GetValues().Length; buttonStates = new ButtonState[numButtons]; lastButtonStates = new ButtonState[numButtons]; } /// /// /// True if the button is pressed or continued to be held this frame. /// public static bool IsButtonDown(MouseButton button) { return buttonStates[(int)button] == ButtonState.Pressed; } /// /// True if the button is pressed this frame. /// public static bool IsButtonPressed(MouseButton button) { return buttonStates[(int)button] == ButtonState.Pressed && lastButtonStates[(int)button] == ButtonState.Released; } /// /// True if the button is released or continued to be released this frame. /// /// /// public static bool IsButtonUp(MouseButton button) { return buttonStates[(int)button] == ButtonState.Released; } /// /// True if the button is released this frame. /// public static bool IsButtonReleased(MouseButton button) { return buttonStates[(int)button] == ButtonState.Released && lastButtonStates[(int)button] == ButtonState.Pressed; } public static int GetWheel() { return wheelY; } public static int GetWheelHorizontal() { return wheelX; } internal static void Update() { Array.Copy(buttonStates, lastButtonStates, buttonStates.Length); } internal static void ProcessEvent(ref SDL.SDL_Event ev) { switch (ev.type) { case SDL.SDL_EventType.SDL_MOUSEBUTTONDOWN: ProcessButtonDownEvent(ref ev.button); break; case SDL.SDL_EventType.SDL_MOUSEBUTTONUP: ProcessButtonUpEvent(ref ev.button); break; case SDL.SDL_EventType.SDL_MOUSEWHEEL: ProcessWheelEvent(ref ev.wheel); break; case SDL.SDL_EventType.SDL_MOUSEMOTION: ProcessMotionEvent(ref ev.motion); break; } } private static void ProcessButtonDownEvent(ref SDL.SDL_MouseButtonEvent ev) { if (TryConvertButton(ev.button, out MouseButton button)) { buttonStates[(int)button] = ButtonState.Pressed; } } private static void ProcessButtonUpEvent(ref SDL.SDL_MouseButtonEvent ev) { if (TryConvertButton(ev.button, out MouseButton button)) { buttonStates[(int)button] = ButtonState.Released; } } private static void ProcessWheelEvent(ref SDL.SDL_MouseWheelEvent ev) { wheelX += ev.x; wheelY += ev.y; } private static void ProcessMotionEvent(ref SDL.SDL_MouseMotionEvent ev) { Position = new Vector2(ev.x, ev.y); } private static bool TryConvertButton(byte rawButton, out MouseButton button) { MouseButton? result = rawButton switch { (byte)SDL.SDL_BUTTON_LEFT => MouseButton.Left, (byte)SDL.SDL_BUTTON_MIDDLE => MouseButton.Middle, (byte)SDL.SDL_BUTTON_RIGHT => MouseButton.Right, (byte)SDL.SDL_BUTTON_X1 => MouseButton.XButton1, (byte)SDL.SDL_BUTTON_X2 => MouseButton.XButton2, _ => null }; button = result.GetValueOrDefault(); return result.HasValue; } }