Controller progress

This commit is contained in:
Garry Newman 2019-06-20 10:41:57 +01:00
parent 1c5cdd2d39
commit fa48a1ce33
10 changed files with 166 additions and 142 deletions

View File

@ -20,6 +20,8 @@ namespace Steamworks
foreach ( var controller in SteamInput.Controllers )
{
Console.Write( $"Controller: {controller}" );
var state = controller.GetDigitalState( "fire" );
}
}
}

View File

@ -26,17 +26,14 @@ namespace Steamworks
_GetActiveActionSetLayers = Marshal.GetDelegateForFunctionPointer<FGetActiveActionSetLayers>( Marshal.ReadIntPtr( VTable, 80) );
_GetDigitalActionHandle = Marshal.GetDelegateForFunctionPointer<FGetDigitalActionHandle>( Marshal.ReadIntPtr( VTable, 88) );
_GetDigitalActionData = Marshal.GetDelegateForFunctionPointer<FGetDigitalActionData>( Marshal.ReadIntPtr( VTable, 96) );
_GetDigitalActionData_Windows = Marshal.GetDelegateForFunctionPointer<FGetDigitalActionData_Windows>( Marshal.ReadIntPtr( VTable, 96) );
_GetDigitalActionOrigins = Marshal.GetDelegateForFunctionPointer<FGetDigitalActionOrigins>( Marshal.ReadIntPtr( VTable, 104) );
_GetAnalogActionHandle = Marshal.GetDelegateForFunctionPointer<FGetAnalogActionHandle>( Marshal.ReadIntPtr( VTable, 112) );
_GetAnalogActionData = Marshal.GetDelegateForFunctionPointer<FGetAnalogActionData>( Marshal.ReadIntPtr( VTable, 120) );
_GetAnalogActionData_Windows = Marshal.GetDelegateForFunctionPointer<FGetAnalogActionData_Windows>( Marshal.ReadIntPtr( VTable, 120) );
_GetAnalogActionOrigins = Marshal.GetDelegateForFunctionPointer<FGetAnalogActionOrigins>( Marshal.ReadIntPtr( VTable, 128) );
_GetGlyphForActionOrigin = Marshal.GetDelegateForFunctionPointer<FGetGlyphForActionOrigin>( Marshal.ReadIntPtr( VTable, 136) );
_GetStringForActionOrigin = Marshal.GetDelegateForFunctionPointer<FGetStringForActionOrigin>( Marshal.ReadIntPtr( VTable, 144) );
_StopAnalogActionMomentum = Marshal.GetDelegateForFunctionPointer<FStopAnalogActionMomentum>( Marshal.ReadIntPtr( VTable, 152) );
_GetMotionData = Marshal.GetDelegateForFunctionPointer<FGetMotionData>( Marshal.ReadIntPtr( VTable, 160) );
_GetMotionData_Windows = Marshal.GetDelegateForFunctionPointer<FGetMotionData_Windows>( Marshal.ReadIntPtr( VTable, 160) );
_TriggerVibration = Marshal.GetDelegateForFunctionPointer<FTriggerVibration>( Marshal.ReadIntPtr( VTable, 168) );
_SetLEDColor = Marshal.GetDelegateForFunctionPointer<FSetLEDColor>( Marshal.ReadIntPtr( VTable, 176) );
_TriggerHapticPulse = Marshal.GetDelegateForFunctionPointer<FTriggerHapticPulse>( Marshal.ReadIntPtr( VTable, 184) );
@ -67,17 +64,14 @@ namespace Steamworks
_GetActiveActionSetLayers = null;
_GetDigitalActionHandle = null;
_GetDigitalActionData = null;
_GetDigitalActionData_Windows = null;
_GetDigitalActionOrigins = null;
_GetAnalogActionHandle = null;
_GetAnalogActionData = null;
_GetAnalogActionData_Windows = null;
_GetAnalogActionOrigins = null;
_GetGlyphForActionOrigin = null;
_GetStringForActionOrigin = null;
_StopAnalogActionMomentum = null;
_GetMotionData = null;
_GetMotionData_Windows = null;
_TriggerVibration = null;
_SetLEDColor = null;
_TriggerHapticPulse = null;
@ -228,21 +222,12 @@ namespace Steamworks
#region FunctionMeta
[UnmanagedFunctionPointer( CallingConvention.ThisCall )]
private delegate InputDigitalActionData_t FGetDigitalActionData( IntPtr self, InputHandle_t inputHandle, InputDigitalActionHandle_t digitalActionHandle );
private delegate DigitalState FGetDigitalActionData( IntPtr self, InputHandle_t inputHandle, InputDigitalActionHandle_t digitalActionHandle );
private FGetDigitalActionData _GetDigitalActionData;
[UnmanagedFunctionPointer( CallingConvention.ThisCall )]
private delegate InputDigitalActionData_t FGetDigitalActionData_Windows( IntPtr self, InputHandle_t inputHandle, InputDigitalActionHandle_t digitalActionHandle );
private FGetDigitalActionData_Windows _GetDigitalActionData_Windows;
#endregion
internal InputDigitalActionData_t GetDigitalActionData( InputHandle_t inputHandle, InputDigitalActionHandle_t digitalActionHandle )
internal DigitalState GetDigitalActionData( InputHandle_t inputHandle, InputDigitalActionHandle_t digitalActionHandle )
{
if ( Config.Os == OsType.Windows )
{
var retVal = _GetDigitalActionData_Windows( Self, inputHandle, digitalActionHandle );
return retVal;
}
return _GetDigitalActionData( Self, inputHandle, digitalActionHandle );
}
@ -270,21 +255,12 @@ namespace Steamworks
#region FunctionMeta
[UnmanagedFunctionPointer( CallingConvention.ThisCall )]
private delegate InputAnalogActionData_t FGetAnalogActionData( IntPtr self, InputHandle_t inputHandle, InputAnalogActionHandle_t analogActionHandle );
private delegate AnalogState FGetAnalogActionData( IntPtr self, InputHandle_t inputHandle, InputAnalogActionHandle_t analogActionHandle );
private FGetAnalogActionData _GetAnalogActionData;
[UnmanagedFunctionPointer( CallingConvention.ThisCall )]
private delegate InputAnalogActionData_t FGetAnalogActionData_Windows( IntPtr self, InputHandle_t inputHandle, InputAnalogActionHandle_t analogActionHandle );
private FGetAnalogActionData_Windows _GetAnalogActionData_Windows;
#endregion
internal InputAnalogActionData_t GetAnalogActionData( InputHandle_t inputHandle, InputAnalogActionHandle_t analogActionHandle )
internal AnalogState GetAnalogActionData( InputHandle_t inputHandle, InputAnalogActionHandle_t analogActionHandle )
{
if ( Config.Os == OsType.Windows )
{
var retVal = _GetAnalogActionData_Windows( Self, inputHandle, analogActionHandle );
return retVal;
}
return _GetAnalogActionData( Self, inputHandle, analogActionHandle );
}
@ -334,21 +310,12 @@ namespace Steamworks
#region FunctionMeta
[UnmanagedFunctionPointer( CallingConvention.ThisCall )]
private delegate InputMotionData_t FGetMotionData( IntPtr self, InputHandle_t inputHandle );
private delegate MotionState FGetMotionData( IntPtr self, InputHandle_t inputHandle );
private FGetMotionData _GetMotionData;
[UnmanagedFunctionPointer( CallingConvention.ThisCall )]
private delegate InputMotionData_t FGetMotionData_Windows( IntPtr self, InputHandle_t inputHandle );
private FGetMotionData_Windows _GetMotionData_Windows;
#endregion
internal InputMotionData_t GetMotionData( InputHandle_t inputHandle )
internal MotionState GetMotionData( InputHandle_t inputHandle )
{
if ( Config.Os == OsType.Windows )
{
var retVal = _GetMotionData_Windows( Self, inputHandle );
return retVal;
}
return _GetMotionData( Self, inputHandle );
}

View File

@ -1100,7 +1100,7 @@ namespace Steamworks
//
// EInputSourceMode
//
internal enum InputSourceMode : int
public enum InputSourceMode : int
{
None = 0,
Dpad = 1,

View File

@ -12508,95 +12508,6 @@ namespace Steamworks.Data
#endregion
}
[StructLayout( LayoutKind.Sequential, Pack = 4 )]
internal struct InputAnalogActionData_t
{
internal InputSourceMode EMode; // eMode EInputSourceMode
internal float X; // x float
internal float Y; // y float
internal byte BActive; // bActive byte
#region Marshalling
internal static InputAnalogActionData_t Fill( IntPtr p ) => Config.PackSmall ? ((InputAnalogActionData_t)(InputAnalogActionData_t) Marshal.PtrToStructure( p, typeof(InputAnalogActionData_t) )) : ((InputAnalogActionData_t)(Pack8) Marshal.PtrToStructure( p, typeof(Pack8) ));
#endregion
#region Packed Versions
[StructLayout( LayoutKind.Sequential, Pack = 8 )]
public struct Pack8
{
internal InputSourceMode EMode; // eMode EInputSourceMode
internal float X; // x float
internal float Y; // y float
internal byte BActive; // bActive byte
public static implicit operator InputAnalogActionData_t ( InputAnalogActionData_t.Pack8 d ) => new InputAnalogActionData_t{ EMode = d.EMode,X = d.X,Y = d.Y,BActive = d.BActive, };
public static implicit operator InputAnalogActionData_t.Pack8 ( InputAnalogActionData_t d ) => new InputAnalogActionData_t.Pack8{ EMode = d.EMode,X = d.X,Y = d.Y,BActive = d.BActive, };
}
#endregion
}
[StructLayout( LayoutKind.Sequential, Pack = 4 )]
internal struct InputMotionData_t
{
internal float RotQuatX; // rotQuatX float
internal float RotQuatY; // rotQuatY float
internal float RotQuatZ; // rotQuatZ float
internal float RotQuatW; // rotQuatW float
internal float PosAccelX; // posAccelX float
internal float PosAccelY; // posAccelY float
internal float PosAccelZ; // posAccelZ float
internal float RotVelX; // rotVelX float
internal float RotVelY; // rotVelY float
internal float RotVelZ; // rotVelZ float
#region Marshalling
internal static InputMotionData_t Fill( IntPtr p ) => Config.PackSmall ? ((InputMotionData_t)(InputMotionData_t) Marshal.PtrToStructure( p, typeof(InputMotionData_t) )) : ((InputMotionData_t)(Pack8) Marshal.PtrToStructure( p, typeof(Pack8) ));
#endregion
#region Packed Versions
[StructLayout( LayoutKind.Sequential, Pack = 8 )]
public struct Pack8
{
internal float RotQuatX; // rotQuatX float
internal float RotQuatY; // rotQuatY float
internal float RotQuatZ; // rotQuatZ float
internal float RotQuatW; // rotQuatW float
internal float PosAccelX; // posAccelX float
internal float PosAccelY; // posAccelY float
internal float PosAccelZ; // posAccelZ float
internal float RotVelX; // rotVelX float
internal float RotVelY; // rotVelY float
internal float RotVelZ; // rotVelZ float
public static implicit operator InputMotionData_t ( InputMotionData_t.Pack8 d ) => new InputMotionData_t{ RotQuatX = d.RotQuatX,RotQuatY = d.RotQuatY,RotQuatZ = d.RotQuatZ,RotQuatW = d.RotQuatW,PosAccelX = d.PosAccelX,PosAccelY = d.PosAccelY,PosAccelZ = d.PosAccelZ,RotVelX = d.RotVelX,RotVelY = d.RotVelY,RotVelZ = d.RotVelZ, };
public static implicit operator InputMotionData_t.Pack8 ( InputMotionData_t d ) => new InputMotionData_t.Pack8{ RotQuatX = d.RotQuatX,RotQuatY = d.RotQuatY,RotQuatZ = d.RotQuatZ,RotQuatW = d.RotQuatW,PosAccelX = d.PosAccelX,PosAccelY = d.PosAccelY,PosAccelZ = d.PosAccelZ,RotVelX = d.RotVelX,RotVelY = d.RotVelY,RotVelZ = d.RotVelZ, };
}
#endregion
}
[StructLayout( LayoutKind.Sequential, Pack = 4 )]
internal struct InputDigitalActionData_t
{
internal byte BState; // bState byte
internal byte BActive; // bActive byte
#region Marshalling
internal static InputDigitalActionData_t Fill( IntPtr p ) => Config.PackSmall ? ((InputDigitalActionData_t)(InputDigitalActionData_t) Marshal.PtrToStructure( p, typeof(InputDigitalActionData_t) )) : ((InputDigitalActionData_t)(Pack8) Marshal.PtrToStructure( p, typeof(Pack8) ));
#endregion
#region Packed Versions
[StructLayout( LayoutKind.Sequential, Pack = 8 )]
public struct Pack8
{
internal byte BState; // bState byte
internal byte BActive; // bActive byte
public static implicit operator InputDigitalActionData_t ( InputDigitalActionData_t.Pack8 d ) => new InputDigitalActionData_t{ BState = d.BState,BActive = d.BActive, };
public static implicit operator InputDigitalActionData_t.Pack8 ( InputDigitalActionData_t d ) => new InputDigitalActionData_t.Pack8{ BState = d.BState,BActive = d.BActive, };
}
#endregion
}
[StructLayout( LayoutKind.Sequential, Pack = 4 )]
internal struct SteamInventoryDefinitionUpdate_t
{

View File

@ -87,6 +87,8 @@ namespace Steamworks
initialized = false;
SteamInput.Shutdown();
ShutdownInterfaces();
SteamApps.Shutdown();
SteamUtils.Shutdown();
@ -103,7 +105,7 @@ namespace Steamworks
SteamParties.Shutdown();
SteamNetworkingUtils.Shutdown();
SteamNetworkingSockets.Shutdown();
SteamInput.Shutdown();
ServerList.Base.Shutdown();
SteamAPI.Shutdown();

View File

@ -1,15 +1,11 @@
using System;
using Steamworks.Data;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using Steamworks.Data;
namespace Steamworks
{
public static class SteamInput
{
internal const int STEAM_CONTROLLER_MAX_COUNT = 16;
internal const int STEAM_CONTROLLER_MAX_COUNT = 16;
static ISteamInput _internal;
internal static ISteamInput Internal
@ -40,11 +36,20 @@ namespace Steamworks
// None?
}
/// <summary>
/// You shouldn't really need to call this because it get called by RunCallbacks on SteamClient
/// but Valve think it might be a nice idea if you call it right before you get input info -
/// just to make sure the info you're getting is 100% up to date.
/// </summary>
public static void RunFrame()
{
Internal.RunFrame();
}
static InputHandle_t[] queryArray = new InputHandle_t[STEAM_CONTROLLER_MAX_COUNT];
/// <summary>
/// Return a list of connected controllers. Will return null if none found.
/// Return a list of connected controllers.
/// </summary>
public static IEnumerable<Controller> Controllers
{
@ -56,9 +61,38 @@ namespace Steamworks
{
yield return new Controller( queryArray[i] );
}
}
}
internal static Dictionary<string, InputDigitalActionHandle_t> DigitalHandles = new Dictionary<string, InputDigitalActionHandle_t>();
internal static InputDigitalActionHandle_t GetDigitalActionHandle( string name )
{
if ( DigitalHandles.TryGetValue( name, out var val ) )
return val;
val = Internal.GetDigitalActionHandle( name );
DigitalHandles.Add( name, val );
return val;
}
internal static Dictionary<string, InputAnalogActionHandle_t> AnalogHandles = new Dictionary<string, InputAnalogActionHandle_t>();
internal static InputAnalogActionHandle_t GetAnalogActionHandle( string name )
{
if ( AnalogHandles.TryGetValue( name, out var val ) )
return val;
val = Internal.GetAnalogActionHandle( name );
AnalogHandles.Add( name, val );
return val;
}
/// <summary>
/// Lookup the handle for an Action Set. Best to do this once on startup, and store the handles for all future API calls.
/// </summary>
public static ActionSet GetActionSet( string name )
{
return new ActionSet( Internal.GetActionSetHandle( name ) );
}
}
}

View File

@ -0,0 +1,15 @@
using Steamworks.Data;
using System.Collections.Generic;
namespace Steamworks
{
public struct ActionSet
{
internal InputActionSetHandle_t Handle;
internal ActionSet( InputActionSetHandle_t handle )
{
this.Handle = handle;
}
}
}

View File

@ -1,18 +1,96 @@
using Steamworks.Data;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace Steamworks
{
public struct Controller
{
private InputHandle_t inputHandle;
internal InputHandle_t Handle;
internal Controller( InputHandle_t inputHandle_t )
{
this.inputHandle = inputHandle_t;
this.Handle = inputHandle_t;
}
public InputType InputType => SteamInput.Internal.GetInputTypeForHandle( inputHandle );
public ulong Id => Handle.Value;
public InputType InputType => SteamInput.Internal.GetInputTypeForHandle( Handle );
public override string ToString() => $"{InputType}.{inputHandle.Value}";
/// <summary>
/// Reconfigure the controller to use the specified action set (ie 'Menu', 'Walk' or 'Drive')
/// This is cheap, and can be safely called repeatedly. It's often easier to repeatedly call it in
/// our state loops, instead of trying to place it in all of your state transitions.
/// </summary>
public ActionSet ActionSet
{
get => new ActionSet( SteamInput.Internal.GetCurrentActionSet( Handle ) );
set => SteamInput.Internal.ActivateActionSet( Handle, value.Handle );
}
public void DeactivateLayer( ActionSet layer ) => SteamInput.Internal.DeactivateActionSetLayer( Handle, layer.Handle );
public void ActivateLayer( ActionSet layer ) => SteamInput.Internal.ActivateActionSetLayer( Handle, layer.Handle );
public void ClearLayers( ActionSet layer ) => SteamInput.Internal.DeactivateAllActionSetLayers( Handle );
/// <summary>
/// Returns the current state of the supplied digital game action
/// </summary>
public DigitalState GetDigitalState( string actionName )
{
return SteamInput.Internal.GetDigitalActionData( Handle, SteamInput.GetDigitalActionHandle( actionName ) );
}
/// <summary>
/// Returns the current state of these supplied analog game action
/// </summary>
public AnalogState GetAnalogState( string actionName )
{
return SteamInput.Internal.GetAnalogActionData( Handle, SteamInput.GetAnalogActionHandle( actionName ) );
}
public override string ToString() => $"{InputType}.{Handle.Value}";
public static bool operator ==( Controller a, Controller b ) => a.Equals( b );
public static bool operator !=( Controller a, Controller b ) => !(a == b);
public override bool Equals( object p ) => this.Equals( (Controller)p );
public override int GetHashCode() => Handle.GetHashCode();
public bool Equals( Controller p ) => p.Handle == Handle;
}
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
public struct AnalogState
{
public InputSourceMode EMode; // eMode EInputSourceMode
public float X; // x float
public float Y; // y float
internal byte BActive; // bActive byte
public bool Active => BActive != 0;
}
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
internal struct MotionState
{
public float RotQuatX; // rotQuatX float
public float RotQuatY; // rotQuatY float
public float RotQuatZ; // rotQuatZ float
public float RotQuatW; // rotQuatW float
public float PosAccelX; // posAccelX float
public float PosAccelY; // posAccelY float
public float PosAccelZ; // posAccelZ float
public float RotVelX; // rotVelX float
public float RotVelY; // rotVelY float
public float RotVelZ; // rotVelZ float
}
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
public struct DigitalState
{
internal byte BState; // bState byte
internal byte BActive; // bActive byte
public bool Pressed => BState != 0;
public bool Active => BActive != 0;
}
}

View File

@ -40,6 +40,9 @@ public static class Cleanup
type = type.Replace( "SteamNetworkingSocketsDebugOutputType", "DebugOutputType" );
type = type.Replace( "SteamNetworkingGetConfigValueResult", "NetConfigResult" );
type = type.Replace( "SteamInputType", "InputType" );
type = type.Replace( "InputDigitalActionData_t", "DigitalState" );
type = type.Replace( "InputAnalogActionData_t", "AnalogState" );
type = type.Replace( "InputMotionData_t", "MotionState" );
return type;
}
@ -50,6 +53,9 @@ public static class Cleanup
if ( type == "LeaderboardSort" ) return false;
if ( type == "LeaderboardDisplay" ) return false;
if ( type == "AppId" ) return false;
if ( type == "AnalogState" ) return false;
if ( type == "DigitalState" ) return false;
if ( type == "MotionState" ) return false;
return true;
}
@ -77,6 +83,7 @@ public static class Cleanup
if ( name == "RoomEnter" ) return "public";
if ( name == "P2PSessionError" ) return "public";
if ( name == "InputType" ) return "public";
if ( name == "InputSourceMode" ) return "public";
return "internal";
}

View File

@ -159,6 +159,14 @@ internal class StructType : BaseType
return AsArgument();
}
static string[] SpecialTypes = new string[]
{
"DigitalState",
"AnalogState",
};
public override bool IsReturnedWeird => SpecialTypes.Contains( TypeName );
}
internal class SteamApiCallType : BaseType