| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- using OpenTK.Input;
- using Ryujinx.Common.Configuration.Hid;
- using System.Collections.Generic;
- using System;
- using System.IO;
- namespace Ryujinx.Ui.Input
- {
- class JoystickButtonAssigner : ButtonAssigner
- {
- private int _index;
- private double _triggerThreshold;
- private JoystickState _currState;
- private JoystickState _prevState;
- private JoystickButtonDetector _detector;
- public JoystickButtonAssigner(int index, double triggerThreshold)
- {
- _index = index;
- _triggerThreshold = triggerThreshold;
- _detector = new JoystickButtonDetector();
- }
- public void Init()
- {
- _currState = Joystick.GetState(_index);
- _prevState = _currState;
- }
- public void ReadInput()
- {
- _prevState = _currState;
- _currState = Joystick.GetState(_index);
- CollectButtonStats();
- }
- public bool HasAnyButtonPressed()
- {
- return _detector.HasAnyButtonPressed();
- }
- public bool ShouldCancel()
- {
- return Mouse.GetState().IsAnyButtonDown || Keyboard.GetState().IsAnyKeyDown;
- }
- public string GetPressedButton()
- {
- List<ControllerInputId> pressedButtons = _detector.GetPressedButtons();
- // Reverse list so axis button take precedence when more than one button is recognized.
- pressedButtons.Reverse();
- return pressedButtons.Count > 0 ? pressedButtons[0].ToString() : "";
- }
- private void CollectButtonStats()
- {
- JoystickCapabilities capabilities = Joystick.GetCapabilities(_index);
- ControllerInputId pressedButton;
- // Buttons
- for (int i = 0; i != capabilities.ButtonCount; i++)
- {
- if (_currState.IsButtonDown(i) && _prevState.IsButtonUp(i))
- {
- Enum.TryParse($"Button{i}", out pressedButton);
- _detector.AddInput(pressedButton, 1);
- }
- if (_currState.IsButtonUp(i) && _prevState.IsButtonDown(i))
- {
- Enum.TryParse($"Button{i}", out pressedButton);
- _detector.AddInput(pressedButton, -1);
- }
- }
- // Axis
- for (int i = 0; i != capabilities.AxisCount; i++)
- {
- float axisValue = _currState.GetAxis(i);
- Enum.TryParse($"Axis{i}", out pressedButton);
- _detector.AddInput(pressedButton, axisValue);
- }
- // Hats
- for (int i = 0; i != capabilities.HatCount; i++)
- {
- string currPos = GetHatPosition(_currState.GetHat((JoystickHat)i));
- string prevPos = GetHatPosition(_prevState.GetHat((JoystickHat)i));
- if (currPos == prevPos)
- {
- continue;
- }
- if (currPos != "")
- {
- Enum.TryParse($"Hat{i}{currPos}", out pressedButton);
- _detector.AddInput(pressedButton, 1);
- }
- if (prevPos != "")
- {
- Enum.TryParse($"Hat{i}{prevPos}", out pressedButton);
- _detector.AddInput(pressedButton, -1);
- }
- }
- }
- private string GetHatPosition(JoystickHatState hatState)
- {
- if (hatState.IsUp) return "Up";
- if (hatState.IsDown) return "Down";
- if (hatState.IsLeft) return "Left";
- if (hatState.IsRight) return "Right";
- return "";
- }
- private class JoystickButtonDetector
- {
- private Dictionary<ControllerInputId, InputSummary> _stats;
- public JoystickButtonDetector()
- {
- _stats = new Dictionary<ControllerInputId, InputSummary>();
- }
- public bool HasAnyButtonPressed()
- {
- foreach (var inputSummary in _stats.Values)
- {
- if (checkButtonPressed(inputSummary))
- {
- return true;
- }
- }
-
- return false;
- }
- public List<ControllerInputId> GetPressedButtons()
- {
- List<ControllerInputId> pressedButtons = new List<ControllerInputId>();
- foreach (var kvp in _stats)
- {
- if (!checkButtonPressed(kvp.Value))
- {
- continue;
- }
- pressedButtons.Add(kvp.Key);
- }
- return pressedButtons;
- }
- public void AddInput(ControllerInputId button, float value)
- {
- InputSummary inputSummary;
- if (!_stats.TryGetValue(button, out inputSummary))
- {
- inputSummary = new InputSummary();
- _stats.Add(button, inputSummary);
- }
- inputSummary.AddInput(value);
- }
- public override string ToString()
- {
- TextWriter writer = new StringWriter();
- foreach (var kvp in _stats)
- {
- writer.WriteLine($"Button {kvp.Key} -> {kvp.Value}");
- }
- return writer.ToString();
- }
- private bool checkButtonPressed(InputSummary sequence)
- {
- float distance = Math.Abs(sequence.Min - sequence.Avg) + Math.Abs(sequence.Max - sequence.Avg);
- return distance > 1.5; // distance range [0, 2]
- }
- }
- private class InputSummary
- {
- public float Min, Max, Sum, Avg;
- public int NumSamples;
- public InputSummary()
- {
- Min = float.MaxValue;
- Max = float.MinValue;
- Sum = 0;
- NumSamples = 0;
- Avg = 0;
- }
- public void AddInput(float value)
- {
- Min = Math.Min(Min, value);
- Max = Math.Max(Max, value);
- Sum += value;
- NumSamples += 1;
- Avg = Sum / NumSamples;
- }
- public override string ToString()
- {
- return $"Avg: {Avg} Min: {Min} Max: {Max} Sum: {Sum} NumSamples: {NumSamples}";
- }
- }
- }
- }
|