Simplify OpenTK gamepad discovery/enumeration
This commit is contained in:
parent
ee0848d7d0
commit
be19b1bb14
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
using BizHawk.Common;
|
using BizHawk.Common;
|
||||||
|
|
||||||
|
@ -22,7 +23,7 @@ namespace BizHawk.Bizware.OpenTK3
|
||||||
|
|
||||||
private static readonly object _syncObj = new object();
|
private static readonly object _syncObj = new object();
|
||||||
|
|
||||||
private static readonly List<OTK_GamePad> Devices = new();
|
private static readonly OTK_GamePad[] Devices = new OTK_GamePad[MAX_GAMEPADS];
|
||||||
|
|
||||||
private static volatile bool initialized = false;
|
private static volatile bool initialized = false;
|
||||||
|
|
||||||
|
@ -34,42 +35,38 @@ namespace BizHawk.Bizware.OpenTK3
|
||||||
|
|
||||||
public static IEnumerable<OTK_GamePad> EnumerateDevices()
|
public static IEnumerable<OTK_GamePad> EnumerateDevices()
|
||||||
{
|
{
|
||||||
if (!initialized) yield break;
|
if (!initialized) return Enumerable.Empty<OTK_GamePad>();
|
||||||
lock (_syncObj)
|
lock (_syncObj) return Devices.Where(pad => pad is not null).ToList();
|
||||||
{
|
|
||||||
foreach (var device in Devices) yield return device;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void UpdateAll()
|
public static void UpdateAll()
|
||||||
{
|
{
|
||||||
static void DropAt(int knownAsIndex, IList<OTK_GamePad> devices)
|
static void DropAt(int index, IList<OTK_GamePad> devices)
|
||||||
{
|
{
|
||||||
var known = devices[knownAsIndex];
|
var known = devices[index];
|
||||||
Console.WriteLine($"Dropped gamepad #{knownAsIndex}: was {known.VerboseName}");
|
devices[index] = null;
|
||||||
devices.RemoveAt(knownAsIndex);
|
Console.WriteLine(known is null ? $"Dropped gamepad X{index}/J{index}" : $"Dropped gamepad {known.InputNamePrefixShort}: was {known.MappingsDatabaseName}");
|
||||||
}
|
}
|
||||||
if (!initialized) return;
|
if (!initialized) return;
|
||||||
lock (_syncObj)
|
lock (_syncObj)
|
||||||
{
|
{
|
||||||
for (var tryIndex = 0; tryIndex < MAX_GAMEPADS; tryIndex++)
|
for (var tryIndex = 0; tryIndex < MAX_GAMEPADS; tryIndex++)
|
||||||
{
|
{
|
||||||
var knownAsIndex = Devices.FindIndex(dev => dev._deviceIndex == tryIndex);
|
var known = Devices[tryIndex];
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var isConnectedAtIndex = OpenTKGamePad.GetState(tryIndex).IsConnected || Joystick.GetState(tryIndex).IsConnected;
|
var isConnectedAtIndex = OpenTKGamePad.GetState(tryIndex).IsConnected || Joystick.GetState(tryIndex).IsConnected;
|
||||||
if (knownAsIndex != -1)
|
if (known is not null)
|
||||||
{
|
{
|
||||||
if (isConnectedAtIndex) Devices[knownAsIndex].Update();
|
if (isConnectedAtIndex) known.Update();
|
||||||
else DropAt(knownAsIndex, Devices);
|
else DropAt(tryIndex, Devices);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (isConnectedAtIndex)
|
if (isConnectedAtIndex)
|
||||||
{
|
{
|
||||||
var newConn = new OTK_GamePad(tryIndex, Devices.Count);
|
var newConn = Devices[tryIndex] = new(tryIndex);
|
||||||
Devices.Insert(tryIndex, newConn); // try and keep our indices in line with the OpenTK ones
|
Console.WriteLine($"Connected new gamepad {newConn.InputNamePrefixShort}: {newConn.MappingsDatabaseName}");
|
||||||
Console.WriteLine($"Connected new gamepad as #{tryIndex}: {newConn.VerboseName}");
|
|
||||||
}
|
}
|
||||||
// else was and remains disconnected, move along
|
// else was and remains disconnected, move along
|
||||||
}
|
}
|
||||||
|
@ -77,7 +74,7 @@ namespace BizHawk.Bizware.OpenTK3
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Util.DebugWriteLine($"caught {e.GetType().FullName} while enumerating OpenTK gamepads");
|
Util.DebugWriteLine($"caught {e.GetType().FullName} while enumerating OpenTK gamepads");
|
||||||
if (knownAsIndex != -1) DropAt(knownAsIndex, Devices);
|
DropAt(tryIndex, Devices);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,74 +88,66 @@ namespace BizHawk.Bizware.OpenTK3
|
||||||
return num * 10000.0f;
|
return num * 10000.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>The GUID as detected by OpenTK.Input.Joystick (or if that failed, a random one generated on construction)</summary>
|
|
||||||
public readonly Guid Guid;
|
|
||||||
|
|
||||||
/// <summary>Signals whether OpenTK returned a GUID for this device</summary>
|
/// <summary>Signals whether OpenTK returned a GUID for this device</summary>
|
||||||
private readonly bool _guidObtained;
|
private readonly bool _guidObtained;
|
||||||
|
|
||||||
/// <summary>The OpenTK device index</summary>
|
/// <summary>The OpenTK device index</summary>
|
||||||
private readonly int _deviceIndex;
|
private readonly int _deviceIndex;
|
||||||
|
|
||||||
/// <summary>The index to lookup into Devices</summary>
|
|
||||||
private readonly int _playerIndex;
|
|
||||||
|
|
||||||
/// <summary>The name (if any) that OpenTK GamePad has resolved via its internal mapping database</summary>
|
|
||||||
private readonly string _name;
|
|
||||||
|
|
||||||
/// <summary>The object returned by <see cref="OpenTKGamePad.GetCapabilities"/></summary>
|
/// <summary>The object returned by <see cref="OpenTKGamePad.GetCapabilities"/></summary>
|
||||||
private readonly GamePadCapabilities? _gamePadCapabilities;
|
private readonly GamePadCapabilities? _gamePadCapabilities;
|
||||||
|
|
||||||
/// <summary>The object returned by <see cref="Joystick.GetCapabilities"/></summary>
|
/// <summary>The object returned by <see cref="Joystick.GetCapabilities"/></summary>
|
||||||
private readonly JoystickCapabilities? _joystickCapabilities;
|
private readonly JoystickCapabilities? _joystickCapabilities;
|
||||||
|
|
||||||
private readonly string VerboseName;
|
|
||||||
|
|
||||||
public readonly IReadOnlyCollection<string> HapticsChannels;
|
public readonly IReadOnlyCollection<string> HapticsChannels;
|
||||||
|
|
||||||
/// <summary>For use in keybind boxes</summary>
|
/// <summary>For use in keybind boxes</summary>
|
||||||
public readonly string InputNamePrefix;
|
public readonly string InputNamePrefix;
|
||||||
|
|
||||||
|
/// <summary>as <see cref="InputNamePrefix"/> but without the trailing space</summary>
|
||||||
|
private readonly string InputNamePrefixShort;
|
||||||
|
|
||||||
/// <summary>Public check on whether mapped gamepad config is being used</summary>
|
/// <summary>Public check on whether mapped gamepad config is being used</summary>
|
||||||
public bool MappedGamePad => _gamePadCapabilities?.IsMapped == true;
|
public bool MappedGamePad => _gamePadCapabilities?.IsMapped == true;
|
||||||
|
|
||||||
|
/// <summary>GUID from <see cref="Joystick"/> (also used for DB) and name from <see cref="OpenTKGamePad"/> via DB</summary>
|
||||||
|
private readonly string MappingsDatabaseName;
|
||||||
|
|
||||||
/// <summary>Gamepad Device state information - updated constantly</summary>
|
/// <summary>Gamepad Device state information - updated constantly</summary>
|
||||||
private GamePadState state;
|
private GamePadState state;
|
||||||
|
|
||||||
/// <summary>Joystick Device state information - updated constantly</summary>
|
/// <summary>Joystick Device state information - updated constantly</summary>
|
||||||
private JoystickState jState;
|
private JoystickState jState;
|
||||||
|
|
||||||
private OTK_GamePad(int index, int playerIndex)
|
private OTK_GamePad(int deviceIndex)
|
||||||
{
|
{
|
||||||
_deviceIndex = index;
|
_deviceIndex = deviceIndex;
|
||||||
_playerIndex = playerIndex;
|
|
||||||
|
|
||||||
|
Guid? guid = null;
|
||||||
if (Joystick.GetState(_deviceIndex).IsConnected)
|
if (Joystick.GetState(_deviceIndex).IsConnected)
|
||||||
{
|
{
|
||||||
Guid = Joystick.GetGuid(_deviceIndex);
|
guid = Joystick.GetGuid(_deviceIndex);
|
||||||
_guidObtained = true;
|
|
||||||
_joystickCapabilities = Joystick.GetCapabilities(_deviceIndex);
|
_joystickCapabilities = Joystick.GetCapabilities(_deviceIndex);
|
||||||
}
|
}
|
||||||
else
|
_guidObtained = guid is not null;
|
||||||
{
|
|
||||||
Guid = Guid.NewGuid();
|
|
||||||
_guidObtained = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
string name;
|
||||||
if (OpenTKGamePad.GetState(_deviceIndex).IsConnected)
|
if (OpenTKGamePad.GetState(_deviceIndex).IsConnected)
|
||||||
{
|
{
|
||||||
_name = OpenTKGamePad.GetName(_deviceIndex);
|
name = OpenTKGamePad.GetName(_deviceIndex);
|
||||||
_gamePadCapabilities = OpenTKGamePad.GetCapabilities(_deviceIndex);
|
_gamePadCapabilities = OpenTKGamePad.GetCapabilities(_deviceIndex);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_name = "OTK GamePad Undetermined Name";
|
name = "OTK GamePad Undetermined Name";
|
||||||
}
|
}
|
||||||
HapticsChannels = _gamePadCapabilities != null && _gamePadCapabilities.Value.HasLeftVibrationMotor && _gamePadCapabilities.Value.HasRightVibrationMotor
|
HapticsChannels = _gamePadCapabilities != null && _gamePadCapabilities.Value.HasLeftVibrationMotor && _gamePadCapabilities.Value.HasRightVibrationMotor
|
||||||
? new[] { "Left", "Right" } // two haptic motors
|
? new[] { "Left", "Right" } // two haptic motors
|
||||||
: new[] { "Mono" }; // one or zero haptic motors -- in the latter case, pretend it's mono anyway as that doesn't seem to cause problems
|
: new[] { "Mono" }; // one or zero haptic motors -- in the latter case, pretend it's mono anyway as that doesn't seem to cause problems
|
||||||
InputNamePrefix = $"{(MappedGamePad ? "X" : "J")}{_playerIndex} ";
|
InputNamePrefixShort = $"{(MappedGamePad ? "X" : "J")}{_deviceIndex}";
|
||||||
VerboseName = $"port #{_deviceIndex} {(MappedGamePad ? "mapped" : "unmapped")} {Guid} {_name}";
|
InputNamePrefix = $"{InputNamePrefixShort} ";
|
||||||
|
MappingsDatabaseName = $"{guid ?? Guid.Empty} {name}";
|
||||||
Update();
|
Update();
|
||||||
InitializeMappings();
|
InitializeMappings();
|
||||||
}
|
}
|
||||||
|
@ -222,8 +211,6 @@ namespace BizHawk.Bizware.OpenTK3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name => $"Joystick {_playerIndex} ({_name})";
|
|
||||||
|
|
||||||
/// <summary>Contains name and delegate function for all buttons, hats and axis</summary>
|
/// <summary>Contains name and delegate function for all buttons, hats and axis</summary>
|
||||||
public readonly List<ButtonObject> buttonObjects = new List<ButtonObject>();
|
public readonly List<ButtonObject> buttonObjects = new List<ButtonObject>();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue