2014-11-16 23:36:17 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using SharpDX;
|
|
|
|
|
using SharpDX.XInput;
|
|
|
|
|
using System.Windows.Forms;
|
|
|
|
|
using System.Text.RegularExpressions;
|
|
|
|
|
using System.Collections.Specialized;
|
|
|
|
|
|
2017-12-23 23:22:30 +00:00
|
|
|
|
using SCJMapper_V2.Common;
|
|
|
|
|
|
|
|
|
|
namespace SCJMapper_V2.Devices.Gamepad
|
2014-11-16 23:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Handles one JS device as DXInput device
|
|
|
|
|
/// In addition provide some static tools to handle JS props here in one place
|
|
|
|
|
/// Also owns the GUI i.e. the user control that shows all values
|
|
|
|
|
/// </summary>
|
|
|
|
|
public class GamepadCls : DeviceCls
|
|
|
|
|
{
|
|
|
|
|
private static readonly log4net.ILog log = log4net.LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod( ).DeclaringType );
|
2017-05-06 00:20:42 +00:00
|
|
|
|
private static readonly AppSettings appSettings = new AppSettings( );
|
2014-11-16 23:36:17 +00:00
|
|
|
|
|
|
|
|
|
#region Static Items
|
|
|
|
|
|
2017-04-14 22:33:21 +00:00
|
|
|
|
public new const string DeviceClass = "xboxpad"; // the device name used throughout this app
|
|
|
|
|
public new const string DeviceID = "xi1_";
|
2015-12-22 00:47:23 +00:00
|
|
|
|
static public int RegisteredDevices = 0;
|
2017-04-14 22:33:21 +00:00
|
|
|
|
public const string DevNameCIG = "Controller (Gamepad)"; // seems CIG names the Gamepad always like this - and not as the device replies
|
2015-12-22 00:47:23 +00:00
|
|
|
|
|
2017-04-14 22:33:21 +00:00
|
|
|
|
public const string JsUnknown = "xi_";
|
2017-12-26 12:53:55 +00:00
|
|
|
|
public new const string DisabledInput = DeviceID + DeviceCls.DisabledInput;
|
|
|
|
|
static public new bool IsDisabledInput( string input )
|
2015-12-22 00:47:23 +00:00
|
|
|
|
{
|
2017-12-26 12:53:55 +00:00
|
|
|
|
if ( input == DisabledInput ) return true;
|
2015-12-22 00:47:23 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
2014-11-16 23:36:17 +00:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Returns the currently valid color
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns>A color</returns>
|
|
|
|
|
static public System.Drawing.Color XiColor()
|
|
|
|
|
{
|
|
|
|
|
return MyColors.GamepadColor;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Returns true if the devicename is a gamepad
|
|
|
|
|
/// </summary>
|
2014-11-18 22:50:35 +00:00
|
|
|
|
/// <param name="deviceClass"></param>
|
2014-11-16 23:36:17 +00:00
|
|
|
|
/// <returns></returns>
|
2017-04-14 22:33:21 +00:00
|
|
|
|
static public new bool IsDeviceClass( string deviceClass )
|
2014-11-16 23:36:17 +00:00
|
|
|
|
{
|
2014-11-18 22:50:35 +00:00
|
|
|
|
return ( deviceClass == DeviceClass );
|
2014-11-16 23:36:17 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-12-22 00:47:23 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Return this deviceClass if the input string contains something like xiN_
|
|
|
|
|
/// </summary>
|
2015-12-22 21:30:57 +00:00
|
|
|
|
/// <param name="devInput"></param>
|
2015-12-22 00:47:23 +00:00
|
|
|
|
/// <returns></returns>
|
2017-04-14 22:33:21 +00:00
|
|
|
|
static public new string DeviceClassFromInput( string devInput )
|
2015-12-22 00:47:23 +00:00
|
|
|
|
{
|
2015-12-22 21:30:57 +00:00
|
|
|
|
if ( DevMatch( devInput ) )
|
2015-12-22 00:47:23 +00:00
|
|
|
|
return DeviceClass; // this
|
|
|
|
|
else
|
|
|
|
|
return DeviceCls.DeviceClass; // unknown
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-02 23:15:26 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Create a DevInput string if the input does look like not having a device ID
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="input">A gamepad input</param>
|
|
|
|
|
/// <returns>DevInput</returns>
|
2017-04-14 22:33:21 +00:00
|
|
|
|
static public new string DevInput( string input )
|
2016-01-02 23:15:26 +00:00
|
|
|
|
{
|
|
|
|
|
if ( DevMatch( input ) )
|
|
|
|
|
return input; // already
|
|
|
|
|
else
|
2017-05-06 00:20:42 +00:00
|
|
|
|
return FromAC1( input );
|
2016-01-02 23:15:26 +00:00
|
|
|
|
}
|
2015-12-22 00:47:23 +00:00
|
|
|
|
|
2014-11-16 23:36:17 +00:00
|
|
|
|
/// <summary>
|
2015-12-22 21:30:57 +00:00
|
|
|
|
/// Returns true if the input matches this device
|
2014-11-16 23:36:17 +00:00
|
|
|
|
/// </summary>
|
2015-12-22 21:30:57 +00:00
|
|
|
|
/// <param name="devInput">A devInput string</param>
|
|
|
|
|
/// <returns>True for a match</returns>
|
2017-04-14 22:33:21 +00:00
|
|
|
|
static public new bool DevMatch( string devInput )
|
2014-11-16 23:36:17 +00:00
|
|
|
|
{
|
2015-12-22 21:30:57 +00:00
|
|
|
|
return devInput.StartsWith( DeviceID );
|
2014-11-16 23:36:17 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-11-19 22:58:05 +00:00
|
|
|
|
|
|
|
|
|
const string xil_pattern = @"^xi_thumb[lr][xy]$";
|
|
|
|
|
static Regex rgx_xil = new Regex( xil_pattern, RegexOptions.IgnoreCase );
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// returns true if the ctrl can be inverted - for now this is thumb[lr][xyz]
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="control"></param>
|
|
|
|
|
/// <returns></returns>
|
2017-04-14 22:33:21 +00:00
|
|
|
|
static public bool CanInvert( string control )
|
2014-11-19 22:58:05 +00:00
|
|
|
|
{
|
|
|
|
|
return rgx_xil.IsMatch( control );
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-22 00:47:23 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Reformat the input from AC1 style to AC2 style
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="input">The AC1 input string</param>
|
|
|
|
|
/// <returns>An AC2 style input string</returns>
|
2017-04-14 22:33:21 +00:00
|
|
|
|
static public string FromAC1( string input )
|
2015-12-22 00:47:23 +00:00
|
|
|
|
{
|
|
|
|
|
// input is something like a xi_something or compositions like triggerl_btn+thumbrx
|
|
|
|
|
// try easy: add xi1_ at the beginning; if xi_start subst with xi1_
|
2017-05-06 00:20:42 +00:00
|
|
|
|
string retVal = input.Replace( " ", "" );
|
2017-12-26 12:53:55 +00:00
|
|
|
|
if ( IsDisabledInput( input ) ) return input;
|
2015-12-22 00:47:23 +00:00
|
|
|
|
|
|
|
|
|
if ( retVal.StartsWith( "xi_" ) )
|
|
|
|
|
retVal = retVal.Insert( 2, "1" );
|
|
|
|
|
else
|
|
|
|
|
retVal = "xi1_" + retVal;
|
|
|
|
|
|
|
|
|
|
return retVal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2014-11-19 22:58:05 +00:00
|
|
|
|
|
2014-11-16 23:36:17 +00:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
private Controller m_device;
|
2017-04-14 22:33:21 +00:00
|
|
|
|
private string m_devName = DevNameCIG;
|
2014-11-16 23:36:17 +00:00
|
|
|
|
private Capabilities m_gpCaps = new Capabilities( );
|
|
|
|
|
|
|
|
|
|
private State m_state = new State( );
|
|
|
|
|
private State m_prevState = new State( );
|
|
|
|
|
|
2017-04-14 22:33:21 +00:00
|
|
|
|
private string m_lastItem = "";
|
2014-11-16 23:36:17 +00:00
|
|
|
|
private int m_senseLimit = 500; // axis jitter avoidance...
|
2017-05-06 00:20:42 +00:00
|
|
|
|
private int m_thlx_zero = 0;
|
|
|
|
|
private int m_thly_zero = 0;
|
|
|
|
|
private int m_thrx_zero = 0;
|
|
|
|
|
private int m_thry_zero = 0;
|
|
|
|
|
|
2014-11-16 23:36:17 +00:00
|
|
|
|
private bool m_activated = false;
|
|
|
|
|
|
|
|
|
|
private UC_GpadPanel m_gPanel = null; // the GUI panel
|
2017-05-06 00:20:42 +00:00
|
|
|
|
internal int MyTabPageIndex = -1;
|
2014-11-16 23:36:17 +00:00
|
|
|
|
|
|
|
|
|
|
2017-04-14 22:33:21 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Return the device instance number (which is always 1)
|
|
|
|
|
/// </summary>
|
|
|
|
|
public override int XmlInstance { get { return 1; } } // const for Gamepad
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Return the DX device instance number (which is always 0)
|
|
|
|
|
/// </summary>
|
|
|
|
|
public override int DevInstance { get { return 0; } }
|
2014-11-18 22:50:35 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// The DeviceClass of this instance
|
|
|
|
|
/// </summary>
|
2017-04-14 22:33:21 +00:00
|
|
|
|
public override string DevClass { get { return GamepadCls.DeviceClass; } }
|
2014-11-16 23:36:17 +00:00
|
|
|
|
/// <summary>
|
2017-04-14 22:33:21 +00:00
|
|
|
|
/// The Gamepad ProductName property
|
2014-11-16 23:36:17 +00:00
|
|
|
|
/// </summary>
|
2017-04-14 22:33:21 +00:00
|
|
|
|
public override string DevName { get { return m_devName; } }
|
2014-11-16 23:36:17 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
2017-04-14 22:33:21 +00:00
|
|
|
|
public void SetDeviceName( string devName )
|
2014-11-18 22:50:35 +00:00
|
|
|
|
{
|
2017-04-14 22:33:21 +00:00
|
|
|
|
m_devName = DevNameCIG; // hard override ...
|
2014-11-18 22:50:35 +00:00
|
|
|
|
m_gPanel.Caption = DevName;
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-14 22:33:21 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// The JS Instance GUID for multiple device support (VJoy gets 2 of the same name)
|
|
|
|
|
/// </summary>
|
|
|
|
|
public override string DevInstanceGUID { get { return "17809207-4663-4629-b5f8-26cc6afa0e70"; } } // artifical GUID - DX does not maintain one
|
2014-11-18 22:50:35 +00:00
|
|
|
|
|
2014-11-16 23:36:17 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Returns the mapping color for this device
|
|
|
|
|
/// </summary>
|
|
|
|
|
public override System.Drawing.Color MapColor
|
|
|
|
|
{
|
|
|
|
|
get { return MyColors.GamepadColor; }
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-14 22:33:21 +00:00
|
|
|
|
|
|
|
|
|
// Note: GP has deadzone on left and right thumb only
|
2017-05-06 00:20:42 +00:00
|
|
|
|
/*
|
|
|
|
|
<deviceoptions name="Controller (Gamepad)">
|
|
|
|
|
<option input="thumbl" deadzone="0.21575999"/>
|
|
|
|
|
<option input="thumbr" deadzone="0.22475"/>
|
|
|
|
|
</deviceoptions>
|
|
|
|
|
*/
|
2017-04-14 22:33:21 +00:00
|
|
|
|
public override List<string> AnalogCommands
|
|
|
|
|
{
|
|
|
|
|
get {
|
2017-05-06 00:20:42 +00:00
|
|
|
|
List<string> cmds = new List<string>( );
|
2017-04-14 22:33:21 +00:00
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// Enumerate all the objects on the device.
|
|
|
|
|
if ( ( m_gpCaps.Gamepad.LeftThumbX != 0 ) || ( m_gpCaps.Gamepad.LeftThumbY != 0 ) ) { cmds.Add( "thumbl" ); }
|
2017-05-06 00:20:42 +00:00
|
|
|
|
if ( ( m_gpCaps.Gamepad.RightThumbX != 0 ) || ( m_gpCaps.Gamepad.RightThumbY != 0 ) ) { cmds.Add( "thumbr" ); }
|
2017-04-14 22:33:21 +00:00
|
|
|
|
} catch ( Exception ex ) {
|
|
|
|
|
log.Error( "AnalogCommands - Get Gamepad Objects failed", ex );
|
|
|
|
|
}
|
|
|
|
|
cmds.Sort( );
|
|
|
|
|
return cmds;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public override bool Activated
|
2014-11-16 23:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
get { return m_activated; }
|
2017-05-06 00:20:42 +00:00
|
|
|
|
set {
|
2014-11-16 23:36:17 +00:00
|
|
|
|
m_activated = value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-14 22:33:21 +00:00
|
|
|
|
private bool Bit( GamepadButtonFlags set, GamepadButtonFlags check )
|
2014-11-16 23:36:17 +00:00
|
|
|
|
{
|
2017-05-06 00:20:42 +00:00
|
|
|
|
Int32 s = (Int32)set; Int32 c = (Int32)check;
|
2014-11-16 23:36:17 +00:00
|
|
|
|
return ( ( s & c ) == c );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// ctor and init
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="device">A DXInput device</param>
|
|
|
|
|
/// <param name="hwnd">The WinHandle of the main window</param>
|
|
|
|
|
/// <param name="panel">The respective JS panel to show the properties</param>
|
2017-04-14 22:33:21 +00:00
|
|
|
|
public GamepadCls( Controller device, UC_GpadPanel panel, int tabIndex )
|
2014-11-16 23:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
log.DebugFormat( "GamepadCls ctor - Entry with index {0}", device.ToString( ) );
|
|
|
|
|
|
|
|
|
|
m_device = device;
|
|
|
|
|
m_gPanel = panel;
|
|
|
|
|
MyTabPageIndex = tabIndex;
|
2017-04-28 20:26:49 +00:00
|
|
|
|
m_activated = false;
|
2014-11-16 23:36:17 +00:00
|
|
|
|
|
|
|
|
|
m_senseLimit = AppConfiguration.AppConfig.gpSenseLimit; // can be changed in the app.config file if it is still too little
|
|
|
|
|
|
|
|
|
|
// Set BufferSize in order to use buffered data.
|
|
|
|
|
log.Debug( "Get GP Objects" );
|
|
|
|
|
try {
|
|
|
|
|
m_gpCaps = m_device.GetCapabilities( DeviceQueryType.Gamepad );
|
2017-05-06 00:20:42 +00:00
|
|
|
|
} catch ( Exception ex ) {
|
2014-11-16 23:36:17 +00:00
|
|
|
|
log.Error( "Get GamepadCapabilities failed", ex );
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-28 20:26:49 +00:00
|
|
|
|
m_gPanel.Caption = m_devName;
|
2014-11-16 23:36:17 +00:00
|
|
|
|
int n = 0;
|
|
|
|
|
if ( Bit( m_gpCaps.Gamepad.Buttons, GamepadButtonFlags.DPadDown ) ) n++;
|
|
|
|
|
if ( Bit( m_gpCaps.Gamepad.Buttons, GamepadButtonFlags.DPadLeft ) ) n++;
|
|
|
|
|
if ( Bit( m_gpCaps.Gamepad.Buttons, GamepadButtonFlags.DPadRight ) ) n++;
|
|
|
|
|
if ( Bit( m_gpCaps.Gamepad.Buttons, GamepadButtonFlags.DPadUp ) ) n++;
|
|
|
|
|
m_gPanel.nDPads = n.ToString( );
|
|
|
|
|
m_gPanel.DPadE = ( n > 0 );
|
|
|
|
|
|
|
|
|
|
n = 0;
|
|
|
|
|
if ( ( m_gpCaps.Gamepad.LeftThumbX != 0 ) || ( m_gpCaps.Gamepad.LeftThumbY != 0 ) || Bit( m_gpCaps.Gamepad.Buttons, GamepadButtonFlags.LeftThumb ) ) { n++; m_gPanel.TStickLE = true; }
|
|
|
|
|
if ( ( m_gpCaps.Gamepad.RightThumbX != 0 ) || ( m_gpCaps.Gamepad.RightThumbY != 0 ) || Bit( m_gpCaps.Gamepad.Buttons, GamepadButtonFlags.RightThumb ) ) { n++; m_gPanel.TStickRE = true; }
|
|
|
|
|
m_gPanel.nTSticks = n.ToString( );
|
|
|
|
|
|
|
|
|
|
n = 0;
|
|
|
|
|
if ( Bit( m_gpCaps.Gamepad.Buttons, GamepadButtonFlags.A ) ) n++;
|
|
|
|
|
if ( Bit( m_gpCaps.Gamepad.Buttons, GamepadButtonFlags.B ) ) n++;
|
|
|
|
|
if ( Bit( m_gpCaps.Gamepad.Buttons, GamepadButtonFlags.X ) ) n++;
|
|
|
|
|
if ( Bit( m_gpCaps.Gamepad.Buttons, GamepadButtonFlags.Y ) ) n++;
|
|
|
|
|
if ( Bit( m_gpCaps.Gamepad.Buttons, GamepadButtonFlags.Start ) ) { n++; m_gPanel.StartE = true; }
|
|
|
|
|
if ( Bit( m_gpCaps.Gamepad.Buttons, GamepadButtonFlags.Back ) ) { n++; m_gPanel.BackE = true; }
|
|
|
|
|
if ( Bit( m_gpCaps.Gamepad.Buttons, GamepadButtonFlags.LeftShoulder ) ) { n++; m_gPanel.ShoulderLE = true; }
|
|
|
|
|
if ( Bit( m_gpCaps.Gamepad.Buttons, GamepadButtonFlags.RightShoulder ) ) { n++; m_gPanel.ShoulderRE = true; }
|
|
|
|
|
m_gPanel.nButtons = n.ToString( );
|
|
|
|
|
|
|
|
|
|
n = 0;
|
|
|
|
|
if ( m_gpCaps.Gamepad.LeftTrigger > 0 ) { n++; m_gPanel.TriggerLE = true; }
|
|
|
|
|
if ( m_gpCaps.Gamepad.RightTrigger > 0 ) { n++; m_gPanel.TriggerRE = true; }
|
|
|
|
|
m_gPanel.nTriggers = n.ToString( );
|
|
|
|
|
|
|
|
|
|
m_gPanel.ButtonE = true; // what else ...
|
|
|
|
|
|
2017-04-28 20:26:49 +00:00
|
|
|
|
ApplySettings_low( ); // get whatever is needed here from Settings
|
2015-12-22 00:47:23 +00:00
|
|
|
|
|
|
|
|
|
GamepadCls.RegisteredDevices++;
|
2017-04-28 20:26:49 +00:00
|
|
|
|
m_activated = true;
|
2014-11-16 23:36:17 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Shutdown device access
|
|
|
|
|
/// </summary>
|
2017-05-06 00:20:42 +00:00
|
|
|
|
public override void FinishDX()
|
2014-11-16 23:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
log.DebugFormat( "Release Input device: {0}", m_device );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Tells the Joystick to re-read settings
|
|
|
|
|
/// </summary>
|
2017-04-28 20:26:49 +00:00
|
|
|
|
public override void ApplySettings()
|
|
|
|
|
{
|
|
|
|
|
ApplySettings_low( );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ApplySettings_low()
|
2014-11-16 23:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
appSettings.Reload( );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Returns true if a modifer button is pressed
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
2017-05-06 00:20:42 +00:00
|
|
|
|
private bool ModButtonPressed()
|
2014-11-16 23:36:17 +00:00
|
|
|
|
{
|
2017-05-06 00:20:42 +00:00
|
|
|
|
bool retVal = m_state.Gamepad.Buttons != GamepadButtonFlags.None;
|
|
|
|
|
retVal = ( retVal || ( Math.Abs( (Int32)m_state.Gamepad.LeftTrigger ) > 0 ) );
|
|
|
|
|
retVal = ( retVal || ( Math.Abs( (Int32)m_state.Gamepad.RightTrigger ) > 0 ) );
|
2014-11-16 23:36:17 +00:00
|
|
|
|
return retVal;
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-06 00:20:42 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Checks if all 4 buttons are pressed and then calibrates the thumbaxes
|
|
|
|
|
/// </summary>
|
|
|
|
|
private void CheckAndCalibrate( ref State state )
|
|
|
|
|
{
|
|
|
|
|
bool check = true;
|
|
|
|
|
check &= Bit( state.Gamepad.Buttons, GamepadButtonFlags.A );
|
|
|
|
|
check &= Bit( state.Gamepad.Buttons, GamepadButtonFlags.B );
|
|
|
|
|
check &= Bit( state.Gamepad.Buttons, GamepadButtonFlags.X );
|
|
|
|
|
check &= Bit( state.Gamepad.Buttons, GamepadButtonFlags.Y );
|
|
|
|
|
|
|
|
|
|
if (check) {
|
|
|
|
|
m_thlx_zero = state.Gamepad.LeftThumbX;
|
|
|
|
|
m_thly_zero = state.Gamepad.LeftThumbY;
|
|
|
|
|
m_thrx_zero = state.Gamepad.RightThumbX;
|
|
|
|
|
m_thry_zero = state.Gamepad.RightThumbY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ApplyCalibration( ref state );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Applies the calibration to the state
|
|
|
|
|
/// and makes sure the values are still in range of +-32767
|
|
|
|
|
/// </summary>
|
|
|
|
|
private void ApplyCalibration( ref State state )
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
int val = 0; int sign = 1;
|
|
|
|
|
sign = Math.Sign( (int)state.Gamepad.LeftThumbX - m_thlx_zero );
|
|
|
|
|
val = Math.Abs( (int)state.Gamepad.LeftThumbX - m_thlx_zero );
|
|
|
|
|
state.Gamepad.LeftThumbX = (short)( val > 32767 ? 32767 * sign : val * sign );
|
|
|
|
|
|
|
|
|
|
sign = Math.Sign( (int)state.Gamepad.LeftThumbY - m_thly_zero );
|
|
|
|
|
val = Math.Abs( (int)state.Gamepad.LeftThumbY - m_thly_zero );
|
|
|
|
|
state.Gamepad.LeftThumbY = (short)( val > 32767 ? 32767 * sign : val * sign );
|
|
|
|
|
|
|
|
|
|
sign = Math.Sign( (int)state.Gamepad.RightThumbX - m_thrx_zero );
|
|
|
|
|
val = Math.Abs( (int)state.Gamepad.RightThumbX - m_thrx_zero );
|
|
|
|
|
state.Gamepad.RightThumbX = (short)( val > 32767 ? 32767 * sign : val * sign );
|
|
|
|
|
|
|
|
|
|
sign = Math.Sign( (int)state.Gamepad.RightThumbY - m_thry_zero );
|
|
|
|
|
val = Math.Abs( (int)state.Gamepad.RightThumbY - m_thry_zero );
|
|
|
|
|
state.Gamepad.RightThumbY = (short)( val > 32767 ? 32767 * sign : val * sign );
|
|
|
|
|
}
|
2014-11-16 23:36:17 +00:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Find the last change the user did on that device
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns>The last action as CryEngine compatible string</returns>
|
2017-05-06 00:20:42 +00:00
|
|
|
|
public override string GetLastChange()
|
2014-11-16 23:36:17 +00:00
|
|
|
|
{
|
2017-05-06 00:20:42 +00:00
|
|
|
|
if ( ModButtonPressed( ) ) {
|
2014-11-16 23:36:17 +00:00
|
|
|
|
m_lastItem = "";
|
2017-05-06 00:20:42 +00:00
|
|
|
|
if ( ( Math.Abs( (Int32)m_state.Gamepad.LeftThumbX ) > m_senseLimit )
|
|
|
|
|
&& ( Math.Abs( (Int32)m_state.Gamepad.LeftThumbX ) > Math.Abs( (Int32)m_state.Gamepad.LeftThumbY ) )
|
|
|
|
|
&& !Bit( m_state.Gamepad.Buttons, GamepadButtonFlags.LeftThumb ) ) m_lastItem += "xi_thumblx+";
|
|
|
|
|
if ( ( Math.Abs( (Int32)m_state.Gamepad.LeftThumbY ) > m_senseLimit )
|
|
|
|
|
&& ( Math.Abs( (Int32)m_state.Gamepad.LeftThumbY ) > Math.Abs( (Int32)m_state.Gamepad.LeftThumbX ) )
|
2014-11-16 23:36:17 +00:00
|
|
|
|
&& !Bit( m_state.Gamepad.Buttons, GamepadButtonFlags.LeftThumb ) ) m_lastItem += "xi_thumbly+";
|
|
|
|
|
|
2017-05-06 00:20:42 +00:00
|
|
|
|
if ( ( Math.Abs( (Int32)m_state.Gamepad.RightThumbX ) > m_senseLimit )
|
|
|
|
|
&& ( Math.Abs( (Int32)m_state.Gamepad.RightThumbX ) > Math.Abs( (Int32)m_state.Gamepad.RightThumbY ) )
|
2014-11-16 23:36:17 +00:00
|
|
|
|
&& !Bit( m_state.Gamepad.Buttons, GamepadButtonFlags.RightThumb ) ) m_lastItem += "xi_thumbrx+";
|
2017-05-06 00:20:42 +00:00
|
|
|
|
if ( ( Math.Abs( (Int32)m_state.Gamepad.RightThumbY ) > m_senseLimit )
|
|
|
|
|
&& ( Math.Abs( (Int32)m_state.Gamepad.RightThumbY ) > Math.Abs( (Int32)m_state.Gamepad.RightThumbX ) )
|
2014-11-16 23:36:17 +00:00
|
|
|
|
&& !Bit( m_state.Gamepad.Buttons, GamepadButtonFlags.RightThumb ) ) m_lastItem += "xi_thumbry+";
|
|
|
|
|
|
2017-05-06 00:20:42 +00:00
|
|
|
|
if ( Math.Abs( (Int32)m_state.Gamepad.LeftTrigger ) > 0 ) m_lastItem += "xi_triggerl_btn+";
|
|
|
|
|
if ( Math.Abs( (Int32)m_state.Gamepad.RightTrigger ) > 0 ) m_lastItem += "xi_triggerr_btn+";
|
2014-11-16 23:36:17 +00:00
|
|
|
|
|
|
|
|
|
if ( Bit( m_state.Gamepad.Buttons, GamepadButtonFlags.A ) ) m_lastItem += "xi_a+";
|
|
|
|
|
if ( Bit( m_state.Gamepad.Buttons, GamepadButtonFlags.B ) ) m_lastItem += "xi_b+";
|
|
|
|
|
if ( Bit( m_state.Gamepad.Buttons, GamepadButtonFlags.X ) ) m_lastItem += "xi_x+";
|
|
|
|
|
if ( Bit( m_state.Gamepad.Buttons, GamepadButtonFlags.Y ) ) m_lastItem += "xi_y+";
|
|
|
|
|
|
|
|
|
|
if ( Bit( m_state.Gamepad.Buttons, GamepadButtonFlags.Start ) ) m_lastItem += "xi_start+";
|
|
|
|
|
if ( Bit( m_state.Gamepad.Buttons, GamepadButtonFlags.Back ) ) m_lastItem += "xi_back+";
|
|
|
|
|
|
|
|
|
|
if ( Bit( m_state.Gamepad.Buttons, GamepadButtonFlags.DPadDown ) ) m_lastItem += "xi_dpad_down+";
|
|
|
|
|
if ( Bit( m_state.Gamepad.Buttons, GamepadButtonFlags.DPadLeft ) ) m_lastItem += "xi_dpad_left+";
|
|
|
|
|
if ( Bit( m_state.Gamepad.Buttons, GamepadButtonFlags.DPadRight ) ) m_lastItem += "xi_dpad_right+";
|
|
|
|
|
if ( Bit( m_state.Gamepad.Buttons, GamepadButtonFlags.DPadUp ) ) m_lastItem += "xi_dpad_up+";
|
|
|
|
|
|
|
|
|
|
if ( Bit( m_state.Gamepad.Buttons, GamepadButtonFlags.LeftShoulder ) ) m_lastItem += "xi_shoulderl+";
|
|
|
|
|
if ( Bit( m_state.Gamepad.Buttons, GamepadButtonFlags.RightShoulder ) ) m_lastItem += "xi_shoulderr+";
|
|
|
|
|
|
|
|
|
|
if ( Bit( m_state.Gamepad.Buttons, GamepadButtonFlags.LeftThumb ) ) m_lastItem += "xi_thumbl+";
|
|
|
|
|
if ( Bit( m_state.Gamepad.Buttons, GamepadButtonFlags.RightThumb ) ) m_lastItem += "xi_thumbr+";
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
// no button -> only non button items will reported - single events
|
2017-05-06 00:20:42 +00:00
|
|
|
|
if ( ( Math.Abs( (Int32)m_state.Gamepad.LeftThumbX ) > m_senseLimit )
|
|
|
|
|
&& ( Math.Abs( (Int32)m_state.Gamepad.LeftThumbX ) > Math.Abs( (Int32)m_state.Gamepad.LeftThumbY ) ) ) m_lastItem = "xi_thumblx+";
|
|
|
|
|
if ( ( Math.Abs( (Int32)m_state.Gamepad.LeftThumbY ) > m_senseLimit )
|
|
|
|
|
&& ( Math.Abs( (Int32)m_state.Gamepad.LeftThumbY ) > Math.Abs( (Int32)m_state.Gamepad.LeftThumbX ) ) ) m_lastItem = "xi_thumbly+";
|
|
|
|
|
|
|
|
|
|
if ( ( Math.Abs( (Int32)m_state.Gamepad.RightThumbX ) > m_senseLimit )
|
|
|
|
|
&& ( Math.Abs( (Int32)m_state.Gamepad.RightThumbX ) > Math.Abs( (Int32)m_state.Gamepad.RightThumbY ) ) ) m_lastItem = "xi_thumbrx+";
|
|
|
|
|
if ( ( Math.Abs( (Int32)m_state.Gamepad.RightThumbY ) > m_senseLimit )
|
|
|
|
|
&& ( Math.Abs( (Int32)m_state.Gamepad.RightThumbY ) > Math.Abs( (Int32)m_state.Gamepad.RightThumbX ) ) ) m_lastItem = "xi_thumbry+";
|
|
|
|
|
|
|
|
|
|
if ( Math.Abs( (Int32)m_state.Gamepad.LeftTrigger ) > 0 ) m_lastItem = "xi_triggerl_btn+";
|
|
|
|
|
if ( Math.Abs( (Int32)m_state.Gamepad.RightTrigger ) > 0 ) m_lastItem = "xi_triggerr_btn+";
|
2014-11-16 23:36:17 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return m_lastItem.TrimEnd( new char[] { '+' } ); ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///<summary>
|
|
|
|
|
/// Figure out if an axis changed enough to consider it as a changed state
|
|
|
|
|
/// The change is polled every 100ms (timer1) so the user has to change so much within that time
|
|
|
|
|
/// Then an axis usually swings back when left alone - that is the real recording of a change.
|
|
|
|
|
/// We know that the range is -32758 .. 32767 so we can judge absolute
|
|
|
|
|
/// % relative is prone to small changes around 0 - which is likely the case with axes
|
|
|
|
|
/// </summary>
|
|
|
|
|
private bool DidAxisChange2( int current, int prev )
|
|
|
|
|
{
|
|
|
|
|
// determine if the axis drifts more than x units to account for bounce
|
|
|
|
|
// old-new/old
|
|
|
|
|
if ( current == prev )
|
|
|
|
|
return false;
|
2017-05-06 00:20:42 +00:00
|
|
|
|
int change = ( Math.Abs( current ) - Math.Abs( prev ) ) / 32;
|
2014-11-16 23:36:17 +00:00
|
|
|
|
// if the axis has changed more than x units to it's last value
|
|
|
|
|
return change > m_senseLimit ? true : false;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///<summary>
|
|
|
|
|
/// Figure out if an axis changed enough to consider it as a changed state
|
|
|
|
|
/// </summary>
|
|
|
|
|
private bool DidAxisChange( int current, int prev )
|
|
|
|
|
{
|
|
|
|
|
// determine if the axis drifts more than x% to account for bounce
|
|
|
|
|
// old-new/old
|
|
|
|
|
if ( current == prev )
|
|
|
|
|
return false;
|
|
|
|
|
if ( prev == 0 )
|
|
|
|
|
prev = 1;
|
|
|
|
|
int changepct = Math.Abs( prev ) - Math.Abs( current ) / Math.Abs( prev );
|
|
|
|
|
// if the axis has changed more than 70% relative to it's last value
|
|
|
|
|
return changepct > 70 ? true : false;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Show the current props in the GUI
|
|
|
|
|
/// </summary>
|
2017-05-06 00:20:42 +00:00
|
|
|
|
private void UpdateUI()
|
2014-11-16 23:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
// This function updated the UI with joystick state information.
|
|
|
|
|
string strText = "";
|
|
|
|
|
|
|
|
|
|
strText += ( ( m_state.Gamepad.Buttons & GamepadButtonFlags.DPadDown ) > 0 ) ? "d" : " ";
|
|
|
|
|
strText += ( ( m_state.Gamepad.Buttons & GamepadButtonFlags.DPadLeft ) > 0 ) ? "l" : " ";
|
|
|
|
|
strText += ( ( m_state.Gamepad.Buttons & GamepadButtonFlags.DPadRight ) > 0 ) ? "r" : " ";
|
|
|
|
|
strText += ( ( m_state.Gamepad.Buttons & GamepadButtonFlags.DPadUp ) > 0 ) ? "u" : " ";
|
|
|
|
|
m_gPanel.DPad = strText;
|
|
|
|
|
|
|
|
|
|
m_gPanel.TStickXL = m_state.Gamepad.LeftThumbX.ToString( );
|
|
|
|
|
m_gPanel.TStickYL = m_state.Gamepad.LeftThumbY.ToString( );
|
|
|
|
|
m_gPanel.TStickBtL = ( ( m_state.Gamepad.Buttons & GamepadButtonFlags.LeftThumb ) > 0 ) ? "pressed" : "_";
|
|
|
|
|
m_gPanel.TStickXR = m_state.Gamepad.RightThumbX.ToString( );
|
|
|
|
|
m_gPanel.TStickYR = m_state.Gamepad.RightThumbY.ToString( );
|
|
|
|
|
m_gPanel.TStickBtR = ( ( m_state.Gamepad.Buttons & GamepadButtonFlags.RightThumb ) > 0 ) ? "pressed" : "_";
|
|
|
|
|
|
|
|
|
|
m_gPanel.TriggerL = m_state.Gamepad.LeftTrigger.ToString( );
|
|
|
|
|
m_gPanel.TriggerR = m_state.Gamepad.RightTrigger.ToString( );
|
|
|
|
|
|
|
|
|
|
m_gPanel.ShoulderL = ( ( m_state.Gamepad.Buttons & GamepadButtonFlags.LeftShoulder ) > 0 ) ? "pressed" : "_";
|
|
|
|
|
m_gPanel.ShoulderR = ( ( m_state.Gamepad.Buttons & GamepadButtonFlags.RightShoulder ) > 0 ) ? "pressed" : "_";
|
|
|
|
|
|
|
|
|
|
m_gPanel.Start = ( ( m_state.Gamepad.Buttons & GamepadButtonFlags.Start ) > 0 ) ? "pressed" : "_";
|
|
|
|
|
m_gPanel.Back = ( ( m_state.Gamepad.Buttons & GamepadButtonFlags.Back ) > 0 ) ? "pressed" : "_";
|
|
|
|
|
|
|
|
|
|
|
2017-04-14 22:33:21 +00:00
|
|
|
|
string buttons = "";
|
2014-11-16 23:36:17 +00:00
|
|
|
|
buttons += ( Bit( m_state.Gamepad.Buttons, GamepadButtonFlags.A ) ) ? "A" : "_";
|
|
|
|
|
buttons += ( Bit( m_state.Gamepad.Buttons, GamepadButtonFlags.B ) ) ? "B" : "_";
|
|
|
|
|
buttons += ( Bit( m_state.Gamepad.Buttons, GamepadButtonFlags.X ) ) ? "X" : "_";
|
|
|
|
|
buttons += ( Bit( m_state.Gamepad.Buttons, GamepadButtonFlags.Y ) ) ? "Y" : "_";
|
|
|
|
|
m_gPanel.Button = buttons;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2014-11-18 22:50:35 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Collect the current data from the device
|
|
|
|
|
/// </summary>
|
2017-04-14 22:33:21 +00:00
|
|
|
|
public override void GetCmdData( string cmd, out int data )
|
2014-11-18 22:50:35 +00:00
|
|
|
|
{
|
|
|
|
|
// Make sure there is a valid device.
|
|
|
|
|
if ( m_device == null ) {
|
|
|
|
|
data = 0;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get the state of the device - retaining the previous state to find the lates change
|
|
|
|
|
m_prevState = m_state;
|
|
|
|
|
|
|
|
|
|
// Poll the device for info.
|
|
|
|
|
try {
|
|
|
|
|
m_state = m_device.GetState( );
|
2017-05-06 00:20:42 +00:00
|
|
|
|
CheckAndCalibrate( ref m_state );
|
2014-11-18 22:50:35 +00:00
|
|
|
|
|
|
|
|
|
switch ( cmd ) {
|
2017-05-06 00:20:42 +00:00
|
|
|
|
case "thumblx": data = (int)( m_state.Gamepad.LeftThumbX / 32.767f ); break; // data should be -1000..1000
|
|
|
|
|
case "thumbly": data = (int)( m_state.Gamepad.LeftThumbY / 32.767f ); break;
|
|
|
|
|
case "thumbrx": data = (int)( m_state.Gamepad.RightThumbX / 32.767f ); break;
|
|
|
|
|
case "thumbry": data = (int)( m_state.Gamepad.RightThumbY / 32.767f ); break;
|
2014-11-18 22:50:35 +00:00
|
|
|
|
default: data = 0; break;
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-06 00:20:42 +00:00
|
|
|
|
} catch ( SharpDXException e ) {
|
2014-11-18 22:50:35 +00:00
|
|
|
|
log.Error( "Gamepad-GetData: Unexpected Poll Exception", e );
|
|
|
|
|
data = 0;
|
|
|
|
|
return; // EXIT see ex code
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-16 23:36:17 +00:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Collect the current data from the device
|
|
|
|
|
/// </summary>
|
2017-05-06 00:20:42 +00:00
|
|
|
|
public override void GetData()
|
2014-11-16 23:36:17 +00:00
|
|
|
|
{
|
|
|
|
|
// Make sure there is a valid device.
|
|
|
|
|
if ( m_device == null )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// Get the state of the device - retaining the previous state to find the lates change
|
|
|
|
|
m_prevState = m_state;
|
|
|
|
|
|
|
|
|
|
// Poll the device for info.
|
|
|
|
|
try {
|
|
|
|
|
m_state = m_device.GetState( );
|
2017-05-06 00:20:42 +00:00
|
|
|
|
CheckAndCalibrate( ref m_state );
|
|
|
|
|
} catch ( SharpDXException e ) {
|
2014-11-16 23:36:17 +00:00
|
|
|
|
log.Error( "Gamepad-GetData: Unexpected Poll Exception", e );
|
|
|
|
|
return; // EXIT see ex code
|
|
|
|
|
}
|
|
|
|
|
UpdateUI( ); // and update the GUI
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|