2011-01-11 02:55:51 +00:00
using System ;
using System.Collections.Generic ;
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
{
// ********************************** Static interface **********************************
2017-04-08 15:49:04 +00:00
private static readonly object _syncObj = new object ( ) ;
private static readonly List < GamePad > _devices = new List < GamePad > ( ) ;
private static DirectInput _dinput ;
2011-06-19 23:39:25 +00:00
public static void Initialize ( )
{
2017-04-08 15:49: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
2017-04-08 15:49:04 +00:00
_dinput = new DirectInput ( ) ;
2013-08-25 17:11:19 +00:00
2017-04-08 15:49:04 +00:00
foreach ( DeviceInstance device in _dinput . GetDevices ( DeviceClass . GameController , DeviceEnumerationFlags . AttachedOnly ) )
2011-06-19 23:39:25 +00:00
{
2017-04-08 15:49:04 +00:00
Console . WriteLine ( "joydevice: {0} `{1}`" , device . InstanceGuid , device . ProductName ) ;
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)
var joystick = new Joystick ( _dinput , device . InstanceGuid ) ;
joystick . SetCooperativeLevel ( GlobalWin . MainForm . Handle , CooperativeLevel . Background | CooperativeLevel . Nonexclusive ) ;
foreach ( DeviceObjectInstance deviceObject in joystick . GetObjects ( ) )
{
if ( ( deviceObject . ObjectType & ObjectDeviceType . Axis ) ! = 0 )
joystick . GetObjectPropertiesById ( ( int ) deviceObject . ObjectType ) . SetRange ( - 1000 , 1000 ) ;
}
joystick . Acquire ( ) ;
2017-04-08 16:40:31 +00:00
GamePad p = new GamePad ( device . InstanceName , device . InstanceGuid , joystick , _devices . Count ) ;
2017-04-08 15:49:04 +00:00
_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 ( )
{
lock ( _syncObj )
{
foreach ( var device in _devices )
{
yield return device ;
}
2011-06-19 23:39:25 +00:00
}
}
public static void UpdateAll ( )
{
2017-04-08 15:49:04 +00:00
lock ( _syncObj )
{
foreach ( var device in _devices )
{
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
{
2017-04-08 15:49:04 +00:00
lock ( _syncObj )
2014-12-29 04:20:47 +00:00
{
2017-04-08 15:49:04 +00:00
foreach ( var device in _devices )
{
2014-12-29 04:20:47 +00:00
device . joystick . Dispose ( ) ;
2017-04-08 15:49:04 +00:00
}
_devices . Clear ( ) ;
if ( _dinput ! = null )
{
_dinput . Dispose ( ) ;
_dinput = null ;
}
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 **********************************
2012-09-30 06:29:30 +00:00
readonly string name ;
readonly Guid guid ;
readonly Joystick joystick ;
JoystickState state = new JoystickState ( ) ;
2011-06-19 23:39:25 +00:00
2017-04-08 16:40:31 +00:00
GamePad ( string name , Guid guid , Joystick joystick , int index )
2011-06-19 23:39:25 +00:00
{
this . name = name ;
this . guid = guid ;
this . 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
{
if ( joystick . Acquire ( ) . IsFailure )
return ;
}
catch
{
2011-06-19 23:39:25 +00:00
return ;
2012-10-20 22:44:15 +00:00
}
2011-06-19 23:39:25 +00:00
if ( joystick . Poll ( ) . IsFailure )
return ;
state = joystick . GetCurrentState ( ) ;
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 )
yield return new Tuple < string , float > ( pi . Name , 10.0f * ( float ) ( int ) pi . GetValue ( state , null ) ) ;
}
2012-09-29 19:16:37 +00:00
/// <summary>FOR DEBUGGING ONLY</summary>
public JoystickState GetInternalState ( )
{
return state ;
2011-06-19 23:39:25 +00:00
}
public string Name { get { return name ; } }
public Guid Guid { get { return guid ; } }
2017-04-08 16:40:31 +00:00
public int PlayerNumber { get ; private set ; }
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
{
2012-09-29 19:16:37 +00:00
return names [ index ] ;
}
public bool Pressed ( int index )
{
return actions [ index ] ( ) ;
2011-06-19 23:39:25 +00:00
}
2012-09-29 19:16:37 +00:00
public int NumButtons { get ; private set ; }
2011-06-19 23:39:25 +00:00
2013-04-15 02:14:14 +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
2013-04-15 02:14:14 +00:00
void AddItem ( string _name , Func < bool > callback )
2011-06-19 23:39:25 +00:00
{
2013-04-15 02:14:14 +00:00
names . Add ( _name ) ;
2012-09-29 19:16:37 +00:00
actions . Add ( callback ) ;
NumButtons + + ;
2011-06-19 23:39:25 +00:00
}
2012-09-29 19:16:37 +00:00
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 ;
names . Clear ( ) ;
actions . Clear ( ) ;
NumButtons = 0 ;
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 ) ;
// i don't know what the "Slider"s do, so they're omitted for the moment
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 ;
AddItem ( string . Format ( "B{0}" , i + 1 ) , ( ) = > state . IsPressed ( j ) ) ;
2011-06-19 23:39:25 +00:00
}
2012-09-29 19:16:37 +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 ;
AddItem ( string . Format ( "POV{0}U" , i + 1 ) ,
( ) = > { int t = state . GetPointOfViewControllers ( ) [ j ] ; return ( t > = 0 & & t < = 4500 ) | | ( t > = 31500 & & t < 36000 ) ; } ) ;
AddItem ( string . Format ( "POV{0}D" , i + 1 ) ,
( ) = > { int t = state . GetPointOfViewControllers ( ) [ j ] ; return t > = 13500 & & t < = 22500 ; } ) ;
AddItem ( string . Format ( "POV{0}L" , i + 1 ) ,
( ) = > { int t = state . GetPointOfViewControllers ( ) [ j ] ; return t > = 22500 & & t < = 31500 ; } ) ;
AddItem ( string . Format ( "POV{0}R" , i + 1 ) ,
( ) = > { int t = state . GetPointOfViewControllers ( ) [ j ] ; return t > = 4500 & & t < = 13500 ; } ) ;
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 )
{
int [ ] temp1 , temp2 ;
// my first clue that it doesnt work is that LEFT and RIGHT _ARENT USED_
// 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
} ;
2011-06-19 23:39:25 +00:00
parameters . GetAxes ( out temp1 , out temp2 ) ;
parameters . SetAxes ( temp1 , temp2 ) ;
var effect = new Effect ( joystick , EffectGuid . ConstantForce ) ;
effect . SetParameters ( parameters ) ;
effect . Start ( 1 ) ;
}
}
2012-09-30 06:29:30 +00:00
}