using Facepunch.Steamworks.Data; using System.Collections.Generic; using System.Runtime.InteropServices; namespace Facepunch.Steamworks { public struct Controller { internal InputHandle_t Handle; internal Controller( InputHandle_t inputHandle_t ) { this.Handle = inputHandle_t; } public ulong Id => Handle.Value; public InputType InputType => SteamInput.Internal.GetInputTypeForHandle( Handle ); /// /// 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. /// public string ActionSet { set => SteamInput.Internal.ActivateActionSet( Handle, SteamInput.Internal.GetActionSetHandle( value ) ); } public void DeactivateLayer( string layer ) => SteamInput.Internal.DeactivateActionSetLayer( Handle, SteamInput.Internal.GetActionSetHandle( layer ) ); public void ActivateLayer( string layer ) => SteamInput.Internal.ActivateActionSetLayer( Handle, SteamInput.Internal.GetActionSetHandle( layer ) ); public void ClearLayers() => SteamInput.Internal.DeactivateAllActionSetLayers( Handle ); /// /// Returns the current state of the supplied digital game action /// public DigitalState GetDigitalState( string actionName ) { return SteamInput.Internal.GetDigitalActionData( Handle, SteamInput.GetDigitalActionHandle( actionName ) ); } /// /// Returns the current state of these supplied analog game action /// 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 { [MarshalAs( UnmanagedType.I1 )] internal byte BState; // bState byte [MarshalAs( UnmanagedType.I1 )] internal byte BActive; // bActive byte public bool Pressed => BState != 0; public bool Active => BActive != 0; } }