2011-01-11 02:55:51 +00:00
using System ;
using System.Collections.Generic ;
2020-01-03 16:38:04 +00:00
using System.Windows.Forms ;
2020-01-12 20:58:02 +00:00
using BizHawk.Common ;
2011-01-11 02:55:51 +00:00
using SlimDX ;
using SlimDX.DirectInput ;
2013-11-03 03:54:37 +00:00
namespace BizHawk.Client.EmuHawk
2011-01-11 02:55:51 +00:00
{
2011-06-19 23:39:25 +00:00
public class GamePad
{
2020-01-03 16:38:04 +00:00
private static readonly object SyncObj = new object ( ) ;
private static readonly List < GamePad > Devices = new List < GamePad > ( ) ;
private static DirectInput _directInput ;
2011-06-19 23:39:25 +00:00
2020-01-03 16:38:04 +00:00
public static void Initialize ( Control parent )
2011-06-19 23:39:25 +00:00
{
2020-01-03 16:38:04 +00:00
lock ( SyncObj )
2011-06-19 23:39:25 +00:00
{
2017-04-08 15:49:04 +00:00
Cleanup ( ) ;
2013-08-25 17:11:19 +00:00
2020-01-03 16:38:04 +00:00
_directInput = new DirectInput ( ) ;
2013-08-25 17:11:19 +00:00
2020-01-03 16:38:04 +00:00
foreach ( DeviceInstance device in _directInput . GetDevices ( DeviceClass . GameController , DeviceEnumerationFlags . AttachedOnly ) )
2011-06-19 23:39:25 +00:00
{
2020-01-03 16:38:04 +00:00
Console . WriteLine ( "joy device: {0} `{1}`" , device . InstanceGuid , device . ProductName ) ;
2017-04-08 15:49:04 +00:00
if ( device . ProductName . Contains ( "XBOX 360" ) )
continue ; // Don't input XBOX 360 controllers into here; we'll process them via XInput (there are limitations in some trigger axes when xbox pads go over xinput)
2020-01-03 16:38:04 +00:00
var joystick = new Joystick ( _directInput , device . InstanceGuid ) ;
joystick . SetCooperativeLevel ( parent . Handle , CooperativeLevel . Background | CooperativeLevel . Nonexclusive ) ;
2017-04-08 15:49:04 +00:00
foreach ( DeviceObjectInstance deviceObject in joystick . GetObjects ( ) )
{
if ( ( deviceObject . ObjectType & ObjectDeviceType . Axis ) ! = 0 )
2020-01-03 16:38:04 +00:00
{
2017-04-08 15:49:04 +00:00
joystick . GetObjectPropertiesById ( ( int ) deviceObject . ObjectType ) . SetRange ( - 1000 , 1000 ) ;
2020-01-03 16:38:04 +00:00
}
2017-04-08 15:49:04 +00:00
}
joystick . Acquire ( ) ;
2020-01-03 16:38:04 +00:00
GamePad p = new GamePad ( joystick , Devices . Count ) ;
Devices . Add ( p ) ;
2011-06-19 23:39:25 +00:00
}
2017-04-08 15:49:04 +00:00
}
}
2011-06-19 23:39:25 +00:00
2017-04-08 15:49:04 +00:00
public static IEnumerable < GamePad > EnumerateDevices ( )
{
2020-01-03 16:38:04 +00:00
lock ( SyncObj )
2017-04-08 15:49:04 +00:00
{
2020-01-03 16:38:04 +00:00
foreach ( var device in Devices )
2017-04-08 15:49:04 +00:00
{
yield return device ;
}
2011-06-19 23:39:25 +00:00
}
}
public static void UpdateAll ( )
{
2020-01-03 16:38:04 +00:00
lock ( SyncObj )
2017-04-08 15:49:04 +00:00
{
2020-01-03 16:38:04 +00:00
foreach ( var device in Devices )
2017-04-08 15:49:04 +00:00
{
device . Update ( ) ;
}
}
2011-06-19 23:39:25 +00:00
}
2017-04-08 15:49:04 +00:00
public static void Cleanup ( )
2012-11-09 19:21:33 +00:00
{
2020-01-03 16:38:04 +00:00
lock ( SyncObj )
2014-12-29 04:20:47 +00:00
{
2020-01-03 16:38:04 +00:00
foreach ( var device in Devices )
2017-04-08 15:49:04 +00:00
{
2020-01-03 16:38:04 +00:00
device . _joystick . Dispose ( ) ;
2017-04-08 15:49:04 +00:00
}
2020-01-03 16:38:04 +00:00
Devices . Clear ( ) ;
if ( _directInput ! = null )
2017-04-08 15:49:04 +00:00
{
2020-01-03 16:38:04 +00:00
_directInput . Dispose ( ) ;
_directInput = null ;
2017-04-08 15:49:04 +00:00
}
2014-12-29 04:20:47 +00:00
}
2012-11-09 19:21:33 +00:00
}
2011-06-19 23:39:25 +00:00
// ********************************** Instance Members **********************************
2020-01-03 16:38:04 +00:00
private readonly Joystick _joystick ;
private JoystickState _state = new JoystickState ( ) ;
2011-06-19 23:39:25 +00:00
2020-01-03 16:38:04 +00:00
GamePad ( Joystick joystick , int index )
2011-06-19 23:39:25 +00:00
{
2020-01-03 16:38:04 +00:00
_joystick = joystick ;
2017-04-08 16:40:31 +00:00
PlayerNumber = index + 1 ;
2011-06-19 23:39:25 +00:00
Update ( ) ;
2012-09-29 19:16:37 +00:00
InitializeCallbacks ( ) ;
2011-06-19 23:39:25 +00:00
}
public void Update ( )
{
2012-10-20 22:44:15 +00:00
try
{
2020-01-03 16:38:04 +00:00
if ( _joystick . Acquire ( ) . IsFailure )
2012-10-20 22:44:15 +00:00
return ;
}
catch
{
2011-06-19 23:39:25 +00:00
return ;
2012-10-20 22:44:15 +00:00
}
2020-01-03 16:38:04 +00:00
if ( _joystick . Poll ( )
. IsFailure )
{
2011-06-19 23:39:25 +00:00
return ;
2020-01-03 16:38:04 +00:00
}
2011-06-19 23:39:25 +00:00
2020-01-03 16:38:04 +00:00
_state = _joystick . GetCurrentState ( ) ;
2011-06-19 23:39:25 +00:00
if ( Result . Last . IsFailure )
2012-09-29 19:16:37 +00:00
// do something?
2011-06-19 23:39:25 +00:00
return ;
2012-09-29 19:16:37 +00:00
}
2011-06-19 23:39:25 +00:00
2013-07-18 16:18:17 +00:00
public IEnumerable < Tuple < string , float > > GetFloats ( )
{
var pis = typeof ( JoystickState ) . GetProperties ( ) ;
foreach ( var pi in pis )
2020-01-03 16:38:04 +00:00
{
yield return new Tuple < string , float > ( pi . Name , 10.0f * ( float ) ( int ) pi . GetValue ( _state , null ) ) ;
}
2013-07-18 16:18:17 +00:00
}
2012-09-29 19:16:37 +00:00
/// <summary>FOR DEBUGGING ONLY</summary>
public JoystickState GetInternalState ( )
{
2020-01-03 16:38:04 +00:00
return _state ;
2011-06-19 23:39:25 +00:00
}
2020-01-03 16:38:04 +00:00
public int PlayerNumber { get ; }
2011-06-19 23:39:25 +00:00
2012-09-29 19:16:37 +00:00
public string ButtonName ( int index )
2011-06-19 23:39:25 +00:00
{
2020-01-03 16:38:04 +00:00
return _names [ index ] ;
2012-09-29 19:16:37 +00:00
}
2020-01-03 16:38:04 +00:00
2012-09-29 19:16:37 +00:00
public bool Pressed ( int index )
{
2020-01-03 16:38:04 +00:00
return _actions [ index ] ( ) ;
2011-06-19 23:39:25 +00:00
}
2020-01-03 16:38:04 +00:00
2012-09-29 19:16:37 +00:00
public int NumButtons { get ; private set ; }
2011-06-19 23:39:25 +00:00
2020-01-03 16:38:04 +00:00
private readonly List < string > _names = new List < string > ( ) ;
private readonly List < Func < bool > > _actions = new List < Func < bool > > ( ) ;
2012-09-29 19:16:37 +00:00
2020-01-03 16:38:04 +00:00
private void AddItem ( string name , Func < bool > callback )
2011-06-19 23:39:25 +00:00
{
2020-01-03 16:38:04 +00:00
_names . Add ( name ) ;
_actions . Add ( callback ) ;
2012-09-29 19:16:37 +00:00
NumButtons + + ;
2011-06-19 23:39:25 +00:00
}
2020-01-03 16:38:04 +00:00
private void InitializeCallbacks ( )
2011-06-19 23:39:25 +00:00
{
2012-09-29 19:16:37 +00:00
const int dzp = 400 ;
const int dzn = - 400 ;
2020-01-03 16:38:04 +00:00
_names . Clear ( ) ;
_actions . Clear ( ) ;
2012-09-29 19:16:37 +00:00
NumButtons = 0 ;
2020-01-03 16:38:04 +00:00
AddItem ( "AccelerationX+" , ( ) = > _state . AccelerationX > = dzp ) ;
AddItem ( "AccelerationX-" , ( ) = > _state . AccelerationX < = dzn ) ;
AddItem ( "AccelerationY+" , ( ) = > _state . AccelerationY > = dzp ) ;
AddItem ( "AccelerationY-" , ( ) = > _state . AccelerationY < = dzn ) ;
AddItem ( "AccelerationZ+" , ( ) = > _state . AccelerationZ > = dzp ) ;
AddItem ( "AccelerationZ-" , ( ) = > _state . AccelerationZ < = dzn ) ;
AddItem ( "AngularAccelerationX+" , ( ) = > _state . AngularAccelerationX > = dzp ) ;
AddItem ( "AngularAccelerationX-" , ( ) = > _state . AngularAccelerationX < = dzn ) ;
AddItem ( "AngularAccelerationY+" , ( ) = > _state . AngularAccelerationY > = dzp ) ;
AddItem ( "AngularAccelerationY-" , ( ) = > _state . AngularAccelerationY < = dzn ) ;
AddItem ( "AngularAccelerationZ+" , ( ) = > _state . AngularAccelerationZ > = dzp ) ;
AddItem ( "AngularAccelerationZ-" , ( ) = > _state . AngularAccelerationZ < = dzn ) ;
AddItem ( "AngularVelocityX+" , ( ) = > _state . AngularVelocityX > = dzp ) ;
AddItem ( "AngularVelocityX-" , ( ) = > _state . AngularVelocityX < = dzn ) ;
AddItem ( "AngularVelocityY+" , ( ) = > _state . AngularVelocityY > = dzp ) ;
AddItem ( "AngularVelocityY-" , ( ) = > _state . AngularVelocityY < = dzn ) ;
AddItem ( "AngularVelocityZ+" , ( ) = > _state . AngularVelocityZ > = dzp ) ;
AddItem ( "AngularVelocityZ-" , ( ) = > _state . AngularVelocityZ < = dzn ) ;
AddItem ( "ForceX+" , ( ) = > _state . ForceX > = dzp ) ;
AddItem ( "ForceX-" , ( ) = > _state . ForceX < = dzn ) ;
AddItem ( "ForceY+" , ( ) = > _state . ForceY > = dzp ) ;
AddItem ( "ForceY-" , ( ) = > _state . ForceY < = dzn ) ;
AddItem ( "ForceZ+" , ( ) = > _state . ForceZ > = dzp ) ;
AddItem ( "ForceZ-" , ( ) = > _state . ForceZ < = dzn ) ;
AddItem ( "RotationX+" , ( ) = > _state . RotationX > = dzp ) ;
AddItem ( "RotationX-" , ( ) = > _state . RotationX < = dzn ) ;
AddItem ( "RotationY+" , ( ) = > _state . RotationY > = dzp ) ;
AddItem ( "RotationY-" , ( ) = > _state . RotationY < = dzn ) ;
AddItem ( "RotationZ+" , ( ) = > _state . RotationZ > = dzp ) ;
AddItem ( "RotationZ-" , ( ) = > _state . RotationZ < = dzn ) ;
AddItem ( "TorqueX+" , ( ) = > _state . TorqueX > = dzp ) ;
AddItem ( "TorqueX-" , ( ) = > _state . TorqueX < = dzn ) ;
AddItem ( "TorqueY+" , ( ) = > _state . TorqueY > = dzp ) ;
AddItem ( "TorqueY-" , ( ) = > _state . TorqueY < = dzn ) ;
AddItem ( "TorqueZ+" , ( ) = > _state . TorqueZ > = dzp ) ;
AddItem ( "TorqueZ-" , ( ) = > _state . TorqueZ < = dzn ) ;
AddItem ( "VelocityX+" , ( ) = > _state . VelocityX > = dzp ) ;
AddItem ( "VelocityX-" , ( ) = > _state . VelocityX < = dzn ) ;
AddItem ( "VelocityY+" , ( ) = > _state . VelocityY > = dzp ) ;
AddItem ( "VelocityY-" , ( ) = > _state . VelocityY < = dzn ) ;
AddItem ( "VelocityZ+" , ( ) = > _state . VelocityZ > = dzp ) ;
AddItem ( "VelocityZ-" , ( ) = > _state . VelocityZ < = dzn ) ;
AddItem ( "X+" , ( ) = > _state . X > = dzp ) ;
AddItem ( "X-" , ( ) = > _state . X < = dzn ) ;
AddItem ( "Y+" , ( ) = > _state . Y > = dzp ) ;
AddItem ( "Y-" , ( ) = > _state . Y < = dzn ) ;
AddItem ( "Z+" , ( ) = > _state . Z > = dzp ) ;
AddItem ( "Z-" , ( ) = > _state . Z < = dzn ) ;
2012-09-29 19:16:37 +00:00
// i don't know what the "Slider"s do, so they're omitted for the moment
2020-01-03 16:38:04 +00:00
for ( int i = 0 ; i < _state . GetButtons ( ) . Length ; i + + )
2011-06-19 23:39:25 +00:00
{
2012-09-29 19:16:37 +00:00
int j = i ;
2020-01-03 16:38:04 +00:00
AddItem ( $"B{i + 1}" , ( ) = > _state . IsPressed ( j ) ) ;
2011-06-19 23:39:25 +00:00
}
2020-01-03 16:38:04 +00:00
for ( int i = 0 ; i < _state . GetPointOfViewControllers ( ) . Length ; i + + )
2011-06-19 23:39:25 +00:00
{
2012-09-29 19:16:37 +00:00
int j = i ;
2020-01-12 20:58:02 +00:00
AddItem ( $"POV{i + 1}U" , ( ) = > {
var t = _state . GetPointOfViewControllers ( ) [ j ] ;
return 0. RangeTo ( 4500 ) . Contains ( t ) | | 31500. RangeToExclusive ( 36000 ) . Contains ( t ) ;
} ) ;
AddItem ( $"POV{i + 1}D" , ( ) = > 13500. RangeTo ( 22500 ) . Contains ( _state . GetPointOfViewControllers ( ) [ j ] ) ) ;
AddItem ( $"POV{i + 1}L" , ( ) = > 22500. RangeTo ( 31500 ) . Contains ( _state . GetPointOfViewControllers ( ) [ j ] ) ) ;
AddItem ( $"POV{i + 1}R" , ( ) = > 4500. RangeTo ( 13500 ) . Contains ( _state . GetPointOfViewControllers ( ) [ j ] ) ) ;
2011-06-19 23:39:25 +00:00
}
}
2012-09-30 06:29:30 +00:00
// Note that this does not appear to work at this time. I probably need to have more infos.
2011-06-19 23:39:25 +00:00
public void SetVibration ( int left , int right )
{
2020-01-03 16:38:04 +00:00
// my first clue that it doesn't work is that LEFT and RIGHT _AREN'T USED_
2011-06-19 23:39:25 +00:00
// I should just look for C++ examples instead of trying to look for SlimDX examples
2013-04-15 02:14:14 +00:00
var parameters = new EffectParameters
{
Duration = 0x2710 ,
Gain = 0x2710 ,
SamplePeriod = 0 ,
TriggerButton = 0 ,
TriggerRepeatInterval = 0x2710 ,
Flags = EffectFlags . None
} ;
2020-01-03 16:38:04 +00:00
parameters . GetAxes ( out var temp1 , out var temp2 ) ;
2011-06-19 23:39:25 +00:00
parameters . SetAxes ( temp1 , temp2 ) ;
2020-01-03 16:38:04 +00:00
var effect = new Effect ( _joystick , EffectGuid . ConstantForce ) ;
2011-06-19 23:39:25 +00:00
effect . SetParameters ( parameters ) ;
effect . Start ( 1 ) ;
}
}
2012-09-30 06:29:30 +00:00
}