mirror of
https://github.com/Ale32bit/Capy64.git
synced 2025-01-19 11:06:44 +00:00
291 lines
7.9 KiB
C#
291 lines
7.9 KiB
C#
using Microsoft.Xna.Framework;
|
|
using Microsoft.Xna.Framework.Graphics;
|
|
using Microsoft.Xna.Framework.Input;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace Capy64.Eventing;
|
|
|
|
public class InputManager
|
|
{
|
|
public enum MouseButton
|
|
{
|
|
Left = 1,
|
|
Right = 2,
|
|
Middle = 3,
|
|
Button4 = 4,
|
|
Button5 = 5,
|
|
}
|
|
|
|
[Flags]
|
|
public enum Modifiers
|
|
{
|
|
None = 0,
|
|
|
|
LShift = 1,
|
|
RShift = 2,
|
|
|
|
LAlt = 4,
|
|
RAlt = 8,
|
|
|
|
LCtrl = 16,
|
|
RCtrl = 32,
|
|
|
|
Shift = LShift | RShift,
|
|
Alt = LAlt | RAlt,
|
|
Ctrl = LCtrl | RCtrl,
|
|
}
|
|
|
|
private static Keys[] IgnoredTextInputKeys =
|
|
{
|
|
Keys.Enter,
|
|
Keys.Back,
|
|
Keys.Tab,
|
|
Keys.Delete,
|
|
Keys.Escape,
|
|
Keys.VolumeDown,
|
|
Keys.VolumeUp,
|
|
Keys.VolumeMute,
|
|
};
|
|
|
|
private readonly Dictionary<MouseButton, ButtonState> mouseButtonStates = new()
|
|
{
|
|
[MouseButton.Left] = ButtonState.Released,
|
|
[MouseButton.Right] = ButtonState.Released,
|
|
[MouseButton.Middle] = ButtonState.Released,
|
|
[MouseButton.Button4] = ButtonState.Released,
|
|
[MouseButton.Button5] = ButtonState.Released,
|
|
};
|
|
|
|
public Texture2D Texture { get; set; }
|
|
public float WindowScale { get; set; }
|
|
public const int MouseScrollDelta = 120;
|
|
|
|
private Point mousePosition;
|
|
private int vMouseScroll;
|
|
private int hMouseScroll;
|
|
|
|
private Modifiers keyboardMods = 0;
|
|
private HashSet<Keys> pressedKeys = new();
|
|
|
|
private readonly Game _game;
|
|
private readonly EventEmitter _eventEmitter;
|
|
public InputManager(Game game, EventEmitter eventManager)
|
|
|
|
{
|
|
_game = game;
|
|
_eventEmitter = eventManager;
|
|
|
|
_game.Window.KeyDown += OnKeyDown;
|
|
_game.Window.KeyUp += OnKeyUp;
|
|
_game.Window.TextInput += OnTextInput;
|
|
|
|
var mouseState = Mouse.GetState();
|
|
vMouseScroll = mouseState.ScrollWheelValue;
|
|
hMouseScroll = mouseState.HorizontalScrollWheelValue;
|
|
}
|
|
|
|
public void Update(bool IsActive)
|
|
{
|
|
UpdateMouse(Mouse.GetState(), IsActive);
|
|
UpdateKeyboard(Keyboard.GetState(), IsActive);
|
|
}
|
|
|
|
private void UpdateMouse(MouseState state, bool isActive)
|
|
{
|
|
if (!isActive)
|
|
return;
|
|
|
|
var rawPosition = state.Position;
|
|
var pos = new Point((int)(rawPosition.X / WindowScale), (int)(rawPosition.Y / WindowScale)) + new Point(1, 1);
|
|
|
|
if (pos.X < 1 || pos.Y < 1 || pos.X > Texture.Width || pos.Y > Texture.Height)
|
|
return;
|
|
|
|
if (pos != mousePosition)
|
|
{
|
|
mousePosition = pos;
|
|
_eventEmitter.RaiseMouseMove(new()
|
|
{
|
|
Position = mousePosition,
|
|
PressedButtons = mouseButtonStates
|
|
.Where(q => q.Value == ButtonState.Pressed)
|
|
.Select(q => (int)q.Key)
|
|
.ToArray()
|
|
});
|
|
}
|
|
|
|
int vValue = 0;
|
|
int hValue = 0;
|
|
if (state.ScrollWheelValue != vMouseScroll)
|
|
{
|
|
var vDelta = vMouseScroll - state.ScrollWheelValue;
|
|
vMouseScroll = state.ScrollWheelValue;
|
|
vValue = vDelta / MouseScrollDelta;
|
|
}
|
|
|
|
if (state.HorizontalScrollWheelValue != hMouseScroll)
|
|
{
|
|
var hDelta = hMouseScroll - state.ScrollWheelValue;
|
|
hMouseScroll = state.ScrollWheelValue;
|
|
hValue = hDelta / MouseScrollDelta;
|
|
}
|
|
|
|
if (vValue != 0 || hValue != 0)
|
|
{
|
|
_eventEmitter.RaiseMouseWheelEvent(new()
|
|
{
|
|
Position = mousePosition,
|
|
VerticalValue = vValue,
|
|
HorizontalValue = hValue,
|
|
});
|
|
}
|
|
|
|
// detect changes in mouse buttons
|
|
if (state.LeftButton != mouseButtonStates[MouseButton.Left])
|
|
{
|
|
_eventEmitter.RaiseMouseButton(new()
|
|
{
|
|
Button = MouseButton.Left,
|
|
State = state.LeftButton,
|
|
Position = mousePosition,
|
|
});
|
|
}
|
|
|
|
if (state.RightButton != mouseButtonStates[MouseButton.Right])
|
|
{
|
|
_eventEmitter.RaiseMouseButton(new()
|
|
{
|
|
Button = MouseButton.Right,
|
|
State = state.RightButton,
|
|
Position = mousePosition,
|
|
});
|
|
}
|
|
|
|
if (state.MiddleButton != mouseButtonStates[MouseButton.Middle])
|
|
{
|
|
_eventEmitter.RaiseMouseButton(new()
|
|
{
|
|
Button = MouseButton.Middle,
|
|
State = state.MiddleButton,
|
|
Position = mousePosition,
|
|
});
|
|
}
|
|
|
|
if (state.XButton1 != mouseButtonStates[MouseButton.Button4])
|
|
{
|
|
_eventEmitter.RaiseMouseButton(new()
|
|
{
|
|
Button = MouseButton.Button4,
|
|
State = state.XButton1,
|
|
Position = mousePosition,
|
|
});
|
|
}
|
|
|
|
if (state.XButton2 != mouseButtonStates[MouseButton.Button5])
|
|
{
|
|
_eventEmitter.RaiseMouseButton(new()
|
|
{
|
|
Button = MouseButton.Button5,
|
|
State = state.XButton2,
|
|
Position = mousePosition,
|
|
});
|
|
}
|
|
|
|
// update mouse states
|
|
mouseButtonStates[MouseButton.Left] = state.LeftButton;
|
|
mouseButtonStates[MouseButton.Right] = state.RightButton;
|
|
mouseButtonStates[MouseButton.Middle] = state.MiddleButton;
|
|
mouseButtonStates[MouseButton.Button4] = state.XButton1;
|
|
mouseButtonStates[MouseButton.Button5] = state.XButton2;
|
|
}
|
|
|
|
private void UpdateKeyboard(KeyboardState state, bool isActive)
|
|
{
|
|
var keys = state.GetPressedKeys();
|
|
|
|
if (keys.Contains(Keys.LeftControl))
|
|
keyboardMods |= Modifiers.LCtrl;
|
|
else
|
|
keyboardMods &= ~Modifiers.LCtrl;
|
|
|
|
if (keys.Contains(Keys.RightControl))
|
|
keyboardMods |= Modifiers.RCtrl;
|
|
else
|
|
keyboardMods &= ~Modifiers.RCtrl;
|
|
|
|
if (keys.Contains(Keys.LeftAlt))
|
|
keyboardMods |= Modifiers.LAlt;
|
|
else
|
|
keyboardMods &= ~Modifiers.LAlt;
|
|
|
|
if (keys.Contains(Keys.RightAlt))
|
|
keyboardMods |= Modifiers.RAlt;
|
|
else
|
|
keyboardMods &= ~Modifiers.RAlt;
|
|
|
|
if (keys.Contains(Keys.LeftShift))
|
|
keyboardMods |= Modifiers.LShift;
|
|
else
|
|
keyboardMods &= ~Modifiers.LShift;
|
|
|
|
if (keys.Contains(Keys.RightShift))
|
|
keyboardMods |= Modifiers.RShift;
|
|
else
|
|
keyboardMods &= ~Modifiers.RShift;
|
|
}
|
|
|
|
private void OnKeyDown(object sender, InputKeyEventArgs e)
|
|
{
|
|
_eventEmitter.RaiseKeyDown(new()
|
|
{
|
|
KeyCode = (int)e.Key,
|
|
KeyName = GetKeyName(e.Key),
|
|
IsHeld = pressedKeys.Contains(e.Key),
|
|
Key = e.Key,
|
|
Mods = keyboardMods,
|
|
});
|
|
pressedKeys.Add(e.Key);
|
|
}
|
|
|
|
private void OnKeyUp(object sender, InputKeyEventArgs e)
|
|
{
|
|
_eventEmitter.RaiseKeyUp(new()
|
|
{
|
|
KeyCode = (int)e.Key,
|
|
KeyName = GetKeyName(e.Key),
|
|
Key = e.Key,
|
|
Mods = keyboardMods,
|
|
});
|
|
pressedKeys.Remove(e.Key);
|
|
}
|
|
|
|
private void OnTextInput(object sender, TextInputEventArgs e)
|
|
{
|
|
if (IgnoredTextInputKeys.Contains(e.Key))
|
|
{
|
|
return;
|
|
}
|
|
_eventEmitter.RaiseCharEvent(new()
|
|
{
|
|
Character = e.Character,
|
|
});
|
|
}
|
|
|
|
public static string GetKeyName(Keys key)
|
|
{
|
|
var keyName = ToUnderscore(key.ToString());
|
|
if (key >= Keys.D0 && key <= Keys.D9)
|
|
{
|
|
keyName = keyName.TrimStart('d');
|
|
}
|
|
keyName = keyName.Replace("oem_", "");
|
|
return keyName;
|
|
}
|
|
|
|
public static string ToUnderscore(string str)
|
|
{
|
|
return string.Concat(str.Select((x, i) => i > 0 && char.IsUpper(x) ? "_" + x.ToString() : x.ToString())).ToLower();
|
|
}
|
|
}
|