Support other switch controller types (#487)
* Make controllers modular, support changing controller type * return readable events * signal hid events * fix style
This commit is contained in:
parent
0c36835f6d
commit
dc02ac08ca
24 changed files with 574 additions and 409 deletions
216
Ryujinx/Ui/NpadController.cs
Normal file
216
Ryujinx/Ui/NpadController.cs
Normal file
|
@ -0,0 +1,216 @@
|
|||
using OpenTK;
|
||||
using OpenTK.Input;
|
||||
using Ryujinx.HLE.Input;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.UI.Input
|
||||
{
|
||||
public enum ControllerInputId
|
||||
{
|
||||
Invalid,
|
||||
|
||||
LStick,
|
||||
DPadUp,
|
||||
DPadDown,
|
||||
DPadLeft,
|
||||
DPadRight,
|
||||
Back,
|
||||
LShoulder,
|
||||
|
||||
RStick,
|
||||
A,
|
||||
B,
|
||||
X,
|
||||
Y,
|
||||
Start,
|
||||
RShoulder,
|
||||
|
||||
LTrigger,
|
||||
RTrigger,
|
||||
|
||||
LJoystick,
|
||||
RJoystick
|
||||
}
|
||||
|
||||
public struct NpadControllerLeft
|
||||
{
|
||||
public ControllerInputId Stick;
|
||||
public ControllerInputId StickButton;
|
||||
public ControllerInputId DPadUp;
|
||||
public ControllerInputId DPadDown;
|
||||
public ControllerInputId DPadLeft;
|
||||
public ControllerInputId DPadRight;
|
||||
public ControllerInputId ButtonMinus;
|
||||
public ControllerInputId ButtonL;
|
||||
public ControllerInputId ButtonZl;
|
||||
}
|
||||
|
||||
public struct NpadControllerRight
|
||||
{
|
||||
public ControllerInputId Stick;
|
||||
public ControllerInputId StickButton;
|
||||
public ControllerInputId ButtonA;
|
||||
public ControllerInputId ButtonB;
|
||||
public ControllerInputId ButtonX;
|
||||
public ControllerInputId ButtonY;
|
||||
public ControllerInputId ButtonPlus;
|
||||
public ControllerInputId ButtonR;
|
||||
public ControllerInputId ButtonZr;
|
||||
}
|
||||
|
||||
public class NpadController
|
||||
{
|
||||
public bool Enabled { private set; get; }
|
||||
public int Index { private set; get; }
|
||||
public float Deadzone { private set; get; }
|
||||
public float TriggerThreshold { private set; get; }
|
||||
|
||||
public NpadControllerLeft Left { private set; get; }
|
||||
public NpadControllerRight Right { private set; get; }
|
||||
|
||||
public NpadController(
|
||||
bool enabled,
|
||||
int index,
|
||||
float deadzone,
|
||||
float triggerThreshold,
|
||||
NpadControllerLeft left,
|
||||
NpadControllerRight right)
|
||||
{
|
||||
Enabled = enabled;
|
||||
Index = index;
|
||||
Deadzone = deadzone;
|
||||
TriggerThreshold = triggerThreshold;
|
||||
Left = left;
|
||||
Right = right;
|
||||
|
||||
//Unmapped controllers are problematic, skip them
|
||||
if (GamePad.GetName(index) == "Unmapped Controller")
|
||||
{
|
||||
Enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
public HidControllerButtons GetButtons()
|
||||
{
|
||||
if (!Enabled)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
GamePadState gpState = GamePad.GetState(Index);
|
||||
|
||||
HidControllerButtons buttons = 0;
|
||||
|
||||
if (IsPressed(gpState, Left.DPadUp)) buttons |= HidControllerButtons.DpadUp;
|
||||
if (IsPressed(gpState, Left.DPadDown)) buttons |= HidControllerButtons.DpadDown;
|
||||
if (IsPressed(gpState, Left.DPadLeft)) buttons |= HidControllerButtons.DpadLeft;
|
||||
if (IsPressed(gpState, Left.DPadRight)) buttons |= HidControllerButtons.DPadRight;
|
||||
if (IsPressed(gpState, Left.StickButton)) buttons |= HidControllerButtons.StickLeft;
|
||||
if (IsPressed(gpState, Left.ButtonMinus)) buttons |= HidControllerButtons.Minus;
|
||||
if (IsPressed(gpState, Left.ButtonL)) buttons |= HidControllerButtons.L;
|
||||
if (IsPressed(gpState, Left.ButtonZl)) buttons |= HidControllerButtons.Zl;
|
||||
|
||||
if (IsPressed(gpState, Right.ButtonA)) buttons |= HidControllerButtons.A;
|
||||
if (IsPressed(gpState, Right.ButtonB)) buttons |= HidControllerButtons.B;
|
||||
if (IsPressed(gpState, Right.ButtonX)) buttons |= HidControllerButtons.X;
|
||||
if (IsPressed(gpState, Right.ButtonY)) buttons |= HidControllerButtons.Y;
|
||||
if (IsPressed(gpState, Right.StickButton)) buttons |= HidControllerButtons.StickRight;
|
||||
if (IsPressed(gpState, Right.ButtonPlus)) buttons |= HidControllerButtons.Plus;
|
||||
if (IsPressed(gpState, Right.ButtonR)) buttons |= HidControllerButtons.R;
|
||||
if (IsPressed(gpState, Right.ButtonZr)) buttons |= HidControllerButtons.Zr;
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
public (short, short) GetLeftStick()
|
||||
{
|
||||
if (!Enabled)
|
||||
{
|
||||
return (0, 0);
|
||||
}
|
||||
|
||||
return GetStick(Left.Stick);
|
||||
}
|
||||
|
||||
public (short, short) GetRightStick()
|
||||
{
|
||||
if (!Enabled)
|
||||
{
|
||||
return (0, 0);
|
||||
}
|
||||
|
||||
return GetStick(Right.Stick);
|
||||
}
|
||||
|
||||
private (short, short) GetStick(ControllerInputId joystick)
|
||||
{
|
||||
GamePadState gpState = GamePad.GetState(Index);
|
||||
|
||||
switch (joystick)
|
||||
{
|
||||
case ControllerInputId.LJoystick:
|
||||
return ApplyDeadzone(gpState.ThumbSticks.Left);
|
||||
|
||||
case ControllerInputId.RJoystick:
|
||||
return ApplyDeadzone(gpState.ThumbSticks.Right);
|
||||
|
||||
default:
|
||||
return (0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private (short, short) ApplyDeadzone(Vector2 axis)
|
||||
{
|
||||
return (ClampAxis(MathF.Abs(axis.X) > Deadzone ? axis.X : 0f),
|
||||
ClampAxis(MathF.Abs(axis.Y) > Deadzone ? axis.Y : 0f));
|
||||
}
|
||||
|
||||
private static short ClampAxis(float value)
|
||||
{
|
||||
if (value <= -short.MaxValue)
|
||||
{
|
||||
return -short.MaxValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (short)(value * short.MaxValue);
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsPressed(GamePadState gpState, ControllerInputId button)
|
||||
{
|
||||
switch (button)
|
||||
{
|
||||
case ControllerInputId.A: return gpState.Buttons.A == ButtonState.Pressed;
|
||||
case ControllerInputId.B: return gpState.Buttons.B == ButtonState.Pressed;
|
||||
case ControllerInputId.X: return gpState.Buttons.X == ButtonState.Pressed;
|
||||
case ControllerInputId.Y: return gpState.Buttons.Y == ButtonState.Pressed;
|
||||
case ControllerInputId.LStick: return gpState.Buttons.LeftStick == ButtonState.Pressed;
|
||||
case ControllerInputId.RStick: return gpState.Buttons.RightStick == ButtonState.Pressed;
|
||||
case ControllerInputId.LShoulder: return gpState.Buttons.LeftShoulder == ButtonState.Pressed;
|
||||
case ControllerInputId.RShoulder: return gpState.Buttons.RightShoulder == ButtonState.Pressed;
|
||||
case ControllerInputId.DPadUp: return gpState.DPad.Up == ButtonState.Pressed;
|
||||
case ControllerInputId.DPadDown: return gpState.DPad.Down == ButtonState.Pressed;
|
||||
case ControllerInputId.DPadLeft: return gpState.DPad.Left == ButtonState.Pressed;
|
||||
case ControllerInputId.DPadRight: return gpState.DPad.Right == ButtonState.Pressed;
|
||||
case ControllerInputId.Start: return gpState.Buttons.Start == ButtonState.Pressed;
|
||||
case ControllerInputId.Back: return gpState.Buttons.Back == ButtonState.Pressed;
|
||||
|
||||
case ControllerInputId.LTrigger: return gpState.Triggers.Left >= TriggerThreshold;
|
||||
case ControllerInputId.RTrigger: return gpState.Triggers.Right >= TriggerThreshold;
|
||||
|
||||
//Using thumbsticks as buttons is not common, but it would be nice not to ignore them
|
||||
case ControllerInputId.LJoystick:
|
||||
return gpState.ThumbSticks.Left.X >= Deadzone ||
|
||||
gpState.ThumbSticks.Left.Y >= Deadzone;
|
||||
|
||||
case ControllerInputId.RJoystick:
|
||||
return gpState.ThumbSticks.Right.X >= Deadzone ||
|
||||
gpState.ThumbSticks.Right.Y >= Deadzone;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue