| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- using System.Collections.Generic;
- using System;
- using System.IO;
- using System.Linq;
- namespace Ryujinx.Input.Assigner
- {
- /// <summary>
- /// <see cref="IButtonAssigner"/> implementation for regular <see cref="IGamepad"/>.
- /// </summary>
- public class GamepadButtonAssigner : IButtonAssigner
- {
- private IGamepad _gamepad;
- private GamepadStateSnapshot _currState;
- private GamepadStateSnapshot _prevState;
- private JoystickButtonDetector _detector;
- private bool _forStick;
- public GamepadButtonAssigner(IGamepad gamepad, float triggerThreshold, bool forStick)
- {
- _gamepad = gamepad;
- _detector = new JoystickButtonDetector();
- _forStick = forStick;
- _gamepad?.SetTriggerThreshold(triggerThreshold);
- }
- public void Initialize()
- {
- if (_gamepad != null)
- {
- _currState = _gamepad.GetStateSnapshot();
- _prevState = _currState;
- }
- }
- public void ReadInput()
- {
- if (_gamepad != null)
- {
- _prevState = _currState;
- _currState = _gamepad.GetStateSnapshot();
- }
- CollectButtonStats();
- }
- public bool HasAnyButtonPressed()
- {
- return _detector.HasAnyButtonPressed();
- }
- public bool ShouldCancel()
- {
- return _gamepad == null || !_gamepad.IsConnected;
- }
- public string GetPressedButton()
- {
- IEnumerable<GamepadButtonInputId> pressedButtons = _detector.GetPressedButtons();
- if (pressedButtons.Any())
- {
- return !_forStick ? pressedButtons.First().ToString() : ((StickInputId)pressedButtons.First()).ToString();
- }
- return "";
- }
- private void CollectButtonStats()
- {
- if (_forStick)
- {
- for (StickInputId inputId = StickInputId.Left; inputId < StickInputId.Count; inputId++)
- {
- (float x, float y) = _currState.GetStick(inputId);
- float value;
- if (x != 0.0f)
- {
- value = x;
- }
- else if (y != 0.0f)
- {
- value = y;
- }
- else
- {
- continue;
- }
- _detector.AddInput((GamepadButtonInputId)inputId, value);
- }
- }
- else
- {
- for (GamepadButtonInputId inputId = GamepadButtonInputId.A; inputId < GamepadButtonInputId.Count; inputId++)
- {
- if (_currState.IsPressed(inputId) && !_prevState.IsPressed(inputId))
- {
- _detector.AddInput(inputId, 1);
- }
- if (!_currState.IsPressed(inputId) && _prevState.IsPressed(inputId))
- {
- _detector.AddInput(inputId, -1);
- }
- }
- }
- }
- private class JoystickButtonDetector
- {
- private Dictionary<GamepadButtonInputId, InputSummary> _stats;
- public JoystickButtonDetector()
- {
- _stats = new Dictionary<GamepadButtonInputId, InputSummary>();
- }
- public bool HasAnyButtonPressed()
- {
- return _stats.Values.Any(CheckButtonPressed);
- }
- public IEnumerable<GamepadButtonInputId> GetPressedButtons()
- {
- return _stats.Where(kvp => CheckButtonPressed(kvp.Value)).Select(kvp => kvp.Key);
- }
- public void AddInput(GamepadButtonInputId 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()
- {
- StringWriter 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}";
- }
- }
- }
- }
|