@ -8,213 +8,231 @@ using System.Windows.Forms;
namespace SCJMapper_V2
{
/// <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>
class JoystickCls
{
#region Static Items
public const String DeviceName = "joystick" ; // the device name used throughout this app
static private int JSnum_UNKNOWN = 0 ;
/// <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
/// Returns true if the devicename is a joystick
/// </summary>
class JoystickCls
/// <param name="device"></param>
/// <returns></returns>
static public Boolean IsJoystick ( String device )
{
private Joystick m_device ;
private JoystickState m_state = new JoystickState ( ) ;
private JoystickState m_prevState = new JoystickState ( ) ;
private Control m_hwnd ;
private int m_numPOVs = 0 ; // static counter for UpdateControls
private int m_sliderCount = 0 ; // static counter for UpdateControls
private String m_lastItem = "" ;
private UC_JoyPanel m_jPanel = null ; // the GUI panel
/// <summary>
/// Returns a CryEngine compatible hat direction
/// </summary>
/// <param name="value">The Hat value</param>
/// <returns>The direction string</returns>
private String HatDir ( int value )
{
// Hats have a 360deg -> 36000 value reporting
if ( value = = 0 ) return "up" ;
if ( value = = 9000 ) return "right" ;
if ( value = = 18000 ) return "down" ;
if ( value = = 27000 ) return "left" ;
return "" ;
}
return ( device = = DeviceName ) ;
}
/// <summary>
/// Returns properly formatted jsn_ string
/// </summary>
/// <param name="jsNum">The JS number</param>
/// <returns>The formatted JS name for the CryEngine XML</returns>
static public String JSTag ( int jsNum )
{
return "js" + jsNum . ToString ( ) + "_" ;
}
/// <summary>
/// Returns properly formatted jsn_ string
/// </summary>
/// <param name="jsNum">The JS number</param>
/// <returns>The formatted JS name for the CryEngine XML</returns>
static public String JSTag ( int jsNum )
{
if ( IsJSValid ( jsNum ) ) return "js" + jsNum . ToString ( ) + "_" ;
else return "" ;
}
/// <summary>
/// Extract the JS number from a JS string
/// </summary>
/// <param name="jsTag">The JS string</param>
/// <returns>The JS number</returns>
static public int JSNum ( String jsTag )
{
int retNum = 0 ;
if ( ! String . IsNullOrEmpty ( jsTag ) )
{
int . TryParse ( jsTag . Substring ( 2 , 1 ) , out retNum ) ;
}
return retNum ;
}
/// <summary>
/// The povides the JS ProductName property
/// </summary>
public String DevName { get { return m_device . Properties . ProductName ; } }
public int AxisCount { get { return m_device . Capabilities . AxeCount ; } }
public int ButtonCount { get { return m_device . Capabilities . ButtonCount ; } }
public int POVCount { get { return m_device . Capabilities . PovCount ; } }
/// <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>
public JoystickCls ( Joystick device , Control hwnd , UC_JoyPanel panel )
{
m_device = device ;
m_hwnd = hwnd ;
m_jPanel = panel ;
// Set BufferSize in order to use buffered data.
m_device . Properties . BufferSize = 128 ;
m_jPanel . Caption = DevName ;
m_jPanel . nAxis = AxisCount . ToString ( ) ;
m_jPanel . nButtons = ButtonCount . ToString ( ) ;
m_jPanel . nPOVs = POVCount . ToString ( ) ;
// Set the data format to the c_dfDIJoystick pre-defined format.
//m_device.SetDataFormat( DeviceDataFormat.Joystick );
// Set the cooperative level for the device.
m_device . SetCooperativeLevel ( m_hwnd , CooperativeLevel . Exclusive | CooperativeLevel . Foreground ) ;
// Enumerate all the objects on the device.
foreach ( DeviceObjectInstance d in m_device . GetObjects ( ) )
{
// For axes that are returned, set the DIPROP_RANGE property for the
// enumerated axis in order to scale min/max values.
if ( ( 0 ! = ( d . ObjectId . Flags & DeviceObjectTypeFlags . Axis ) ) )
{
// Set the range for the axis.
m_device . Properties . Range = new InputRange ( - 1000 , + 1000 ) ;
}
// Update the controls to reflect what objects the device supports.
UpdateControls ( d ) ;
}
/// <summary>
/// Extract the JS number from a JS string
/// </summary>
/// <param name="jsTag">The JS string</param>
/// <returns>The JS number</returns>
static public int JSNum ( String jsTag )
{
int retNum = JSnum_UNKNOWN ;
if ( ! String . IsNullOrEmpty ( jsTag ) ) {
int . TryParse ( jsTag . Substring ( 2 , 1 ) , out retNum ) ;
}
return retNum ;
}
/// <summary>
/// Returns the validity of a JSnumber
/// Done here to maintain the ownership of how things are done
/// </summary>
/// <param name="jsNum">The JS number</param>
/// <returns>True if it is a valid one</returns>
static public Boolean IsJSValid ( int jsNum )
{
return ( jsNum > JSnum_UNKNOWN ) ;
}
# endregion
private Joystick m_device ;
private JoystickState m_state = new JoystickState ( ) ;
private JoystickState m_prevState = new JoystickState ( ) ;
private Control m_hwnd ;
private int m_numPOVs = 0 ; // static counter for UpdateControls
private int m_sliderCount = 0 ; // static counter for UpdateControls
private String m_lastItem = "" ;
private UC_JoyPanel m_jPanel = null ; // the GUI panel
/// <summary>
/// Returns a CryEngine compatible hat direction
/// </summary>
/// <param name="value">The Hat value</param>
/// <returns>The direction string</returns>
private String HatDir ( int value )
{
// Hats have a 360deg -> 36000 value reporting
if ( value = = 0 ) return "up" ;
if ( value = = 9000 ) return "right" ;
if ( value = = 18000 ) return "down" ;
if ( value = = 27000 ) return "left" ;
return "" ;
}
/// <summary>
/// The povides the JS ProductName property
/// </summary>
public String DevName { get { return m_device . Properties . ProductName ; } }
public int AxisCount { get { return m_device . Capabilities . AxeCount ; } }
public int ButtonCount { get { return m_device . Capabilities . ButtonCount ; } }
public int POVCount { get { return m_device . Capabilities . PovCount ; } }
}
/// <summary>
/// Shutdown device access
/// </summary>
public void FinishDX ( )
{
if ( null ! = m_device )
m_device . Unacquire ( ) ;
/// <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>
public JoystickCls ( Joystick device , Control hwnd , UC_JoyPanel panel )
{
m_device = device ;
m_hwnd = hwnd ;
m_jPanel = panel ;
// Set BufferSize in order to use buffered data.
m_device . Properties . BufferSize = 128 ;
m_jPanel . Caption = DevName ;
m_jPanel . nAxis = AxisCount . ToString ( ) ;
m_jPanel . nButtons = ButtonCount . ToString ( ) ;
m_jPanel . nPOVs = POVCount . ToString ( ) ;
// Set the data format to the c_dfDIJoystick pre-defined format.
//m_device.SetDataFormat( DeviceDataFormat.Joystick );
// Set the cooperative level for the device.
m_device . SetCooperativeLevel ( m_hwnd , CooperativeLevel . Exclusive | CooperativeLevel . Foreground ) ;
// Enumerate all the objects on the device.
foreach ( DeviceObjectInstance d in m_device . GetObjects ( ) ) {
// For axes that are returned, set the DIPROP_RANGE property for the
// enumerated axis in order to scale min/max values.
if ( ( 0 ! = ( d . ObjectId . Flags & DeviceObjectTypeFlags . Axis ) ) ) {
// Set the range for the axis.
m_device . Properties . Range = new InputRange ( - 1000 , + 1000 ) ;
}
// Update the controls to reflect what objects the device supports.
UpdateControls ( d ) ;
}
}
/// <summary>
/// Shutdown device access
/// </summary>
public void FinishDX ( )
{
if ( null ! = m_device )
m_device . Unacquire ( ) ;
}
/// <summary>
/// Enable the properties that are supported by the device
/// </summary>
/// <param name="d"></param>
private void UpdateControls ( DeviceObjectInstance d )
{
// Set the UI to reflect what objects the joystick supports.
if ( ObjectGuid . XAxis = = d . ObjectType )
{
m_jPanel . Xe = true ;
m_jPanel . Xname = d . Name + ":" ;
}
if ( ObjectGuid . YAxis = = d . ObjectType )
{
m_jPanel . Ye = true ;
m_jPanel . Yname = d . Name + ":" ;
}
if ( ObjectGuid . ZAxis = = d . ObjectType )
{
m_jPanel . Ze = true ;
m_jPanel . Zname = d . Name + ":" ;
}
if ( ObjectGuid . RxAxis = = d . ObjectType )
{
m_jPanel . Xre = true ;
m_jPanel . Xrname = d . Name + ":" ;
}
if ( ObjectGuid . RyAxis = = d . ObjectType )
{
m_jPanel . Yre = true ;
m_jPanel . Yrname = d . Name + ":" ;
}
if ( ObjectGuid . RzAxis = = d . ObjectType )
{
m_jPanel . Zre = true ;
m_jPanel . Zrname = d . Name + ":" ;
}
if ( ObjectGuid . Slider = = d . ObjectType )
{
switch ( m_sliderCount + + )
{
case 0 :
m_jPanel . S1e = true ;
m_jPanel . S1name = d . Name + ":" ;
break ;
case 1 :
m_jPanel . S2e = true ;
m_jPanel . S2name = d . Name + ":" ;
break ;
}
}
if ( ObjectGuid . PovController = = d . ObjectType )
{
switch ( m_numPOVs + + )
{
case 0 :
m_jPanel . H1e = true ;
m_jPanel . H1name = d . Name + ":" ;
break ;
case 1 :
m_jPanel . H2e = true ;
m_jPanel . H2name = d . Name + ":" ;
break ;
case 2 :
m_jPanel . H3e = true ;
m_jPanel . H3name = d . Name + ":" ;
break ;
case 3 :
m_jPanel . H4e = true ;
m_jPanel . H4name = d . Name + ":" ;
break ;
}
}
/// <summary>
/// Enable the properties that are supported by the device
/// </summary>
/// <param name="d"></param>
private void UpdateControls ( DeviceObjectInstance d )
{
// Set the UI to reflect what objects the joystick supports.
if ( ObjectGuid . XAxis = = d . ObjectType ) {
m_jPanel . Xe = true ;
m_jPanel . Xname = d . Name + ":" ;
}
if ( ObjectGuid . YAxis = = d . ObjectType ) {
m_jPanel . Ye = true ;
m_jPanel . Yname = d . Name + ":" ;
}
if ( ObjectGuid . ZAxis = = d . ObjectType ) {
m_jPanel . Ze = true ;
m_jPanel . Zname = d . Name + ":" ;
}
if ( ObjectGuid . RxAxis = = d . ObjectType ) {
m_jPanel . Xre = true ;
m_jPanel . Xrname = d . Name + ":" ;
}
if ( ObjectGuid . RyAxis = = d . ObjectType ) {
m_jPanel . Yre = true ;
m_jPanel . Yrname = d . Name + ":" ;
}
if ( ObjectGuid . RzAxis = = d . ObjectType ) {
m_jPanel . Zre = true ;
m_jPanel . Zrname = d . Name + ":" ;
}
if ( ObjectGuid . Slider = = d . ObjectType ) {
switch ( m_sliderCount + + ) {
case 0 :
m_jPanel . S1e = true ;
m_jPanel . S1name = d . Name + ":" ;
break ;
case 1 :
m_jPanel . S2e = true ;
m_jPanel . S2name = d . Name + ":" ;
break ;
}
}
if ( ObjectGuid . PovController = = d . ObjectType ) {
switch ( m_numPOVs + + ) {
case 0 :
m_jPanel . H1e = true ;
m_jPanel . H1name = d . Name + ":" ;
break ;
case 1 :
m_jPanel . H2e = true ;
m_jPanel . H2name = d . Name + ":" ;
break ;
case 2 :
m_jPanel . H3e = true ;
m_jPanel . H3name = d . Name + ":" ;
break ;
case 3 :
m_jPanel . H4e = true ;
m_jPanel . H4name = d . Name + ":" ;
break ;
}
}
}
/// <summary>
/// Find the last change the user did on that device
/// </summary>
/// <returns>The last action as CryEngine compatible string</returns>
public String GetLastChange ( )
{
// TODO: Expand this out into a joystick class (see commit for details)
Dictionary < string , string > axies = new Dictionary < string , string > ( )
/// <summary>
/// Find the last change the user did on that device
/// </summary>
/// <returns>The last action as CryEngine compatible string</returns>
public String GetLastChange ( )
{
// TODO: Expand this out into a joystick class (see commit for details)
Dictionary < string , string > axies = new Dictionary < string , string > ( )
{
{ "X" , "x" } ,
{ "Y" , "y" } ,
@ -224,146 +242,137 @@ namespace SCJMapper_V2
{ "RotationZ" , "rotz" }
} ;
foreach ( KeyValuePair < string , string > entry in axies )
{
PropertyInfo axisProperty = typeof ( JoystickState ) . GetProperty ( entry . Key ) ;
if ( DidAxisChange ( ( int ) axisProperty . GetValue ( this . m_state , null ) , ( int ) axisProperty . GetValue ( this . m_prevState , null ) ) )
this . m_lastItem = entry . Value ;
}
int [ ] slider = m_state . Sliders ;
int [ ] pslider = m_prevState . Sliders ;
if ( slider [ 0 ] ! = pslider [ 0 ] ) m_lastItem = "slider1" ;
if ( slider [ 1 ] ! = pslider [ 1 ] ) m_lastItem = "slider2" ;
int [ ] pov = m_state . PointOfViewControllers ;
int [ ] ppov = m_prevState . PointOfViewControllers ;
if ( pov [ 0 ] > = 0 ) if ( pov [ 0 ] ! = ppov [ 0 ] ) m_lastItem = "hat1_" + HatDir ( pov [ 0 ] ) ;
if ( pov [ 1 ] > = 0 ) if ( pov [ 1 ] ! = ppov [ 1 ] ) m_lastItem = "hat2_" + HatDir ( pov [ 0 ] ) ;
if ( pov [ 2 ] > = 0 ) if ( pov [ 2 ] ! = ppov [ 2 ] ) m_lastItem = "hat3_" + HatDir ( pov [ 0 ] ) ;
if ( pov [ 3 ] > = 0 ) if ( pov [ 3 ] ! = ppov [ 3 ] ) m_lastItem = "hat4_" + HatDir ( pov [ 0 ] ) ;
bool [ ] buttons = m_state . Buttons ;
bool [ ] prevButtons = m_prevState . Buttons ;
for ( int bi = 0 ; bi < buttons . Length ; bi + + )
{
if ( buttons [ bi ] & & buttons [ bi ] ! = prevButtons [ bi ] )
m_lastItem = "button" + ( bi + 1 ) . ToString ( ) ;
}
return m_lastItem ;
}
foreach ( KeyValuePair < string , string > entry in axies ) {
PropertyInfo axisProperty = typeof ( JoystickState ) . GetProperty ( entry . Key ) ;
if ( DidAxisChange ( ( int ) axisProperty . GetValue ( this . m_state , null ) , ( int ) axisProperty . GetValue ( this . m_prevState , null ) ) )
this . m_lastItem = entry . Value ;
}
int [ ] slider = m_state . Sliders ;
int [ ] pslider = m_prevState . Sliders ;
if ( slider [ 0 ] ! = pslider [ 0 ] ) m_lastItem = "slider1" ;
if ( slider [ 1 ] ! = pslider [ 1 ] ) m_lastItem = "slider2" ;
int [ ] pov = m_state . PointOfViewControllers ;
int [ ] ppov = m_prevState . PointOfViewControllers ;
if ( pov [ 0 ] > = 0 ) if ( pov [ 0 ] ! = ppov [ 0 ] ) m_lastItem = "hat1_" + HatDir ( pov [ 0 ] ) ;
if ( pov [ 1 ] > = 0 ) if ( pov [ 1 ] ! = ppov [ 1 ] ) m_lastItem = "hat2_" + HatDir ( pov [ 0 ] ) ;
if ( pov [ 2 ] > = 0 ) if ( pov [ 2 ] ! = ppov [ 2 ] ) m_lastItem = "hat3_" + HatDir ( pov [ 0 ] ) ;
if ( pov [ 3 ] > = 0 ) if ( pov [ 3 ] ! = ppov [ 3 ] ) m_lastItem = "hat4_" + HatDir ( pov [ 0 ] ) ;
bool [ ] buttons = m_state . Buttons ;
bool [ ] prevButtons = m_prevState . Buttons ;
for ( int bi = 0 ; bi < buttons . Length ; bi + + ) {
if ( buttons [ bi ] & & buttons [ bi ] ! = prevButtons [ bi ] )
m_lastItem = "button" + ( bi + 1 ) . ToString ( ) ;
}
return m_lastItem ;
}
///<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>
/// 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>
private void UpdateUI ( )
{
// This function updated the UI with joystick state information.
string strText = null ;
/// <summary>
/// Show the current props in the GUI
/// </summary>
private void UpdateUI ( )
{
// This function updated the UI with joystick state information.
string strText = null ;
m_jPanel . X = m_state . X . ToString ( ) ;
m_jPanel . Y = m_state . Y . ToString ( ) ;
m_jPanel . Z = m_state . Z . ToString ( ) ;
m_jPanel . X = m_state . X . ToString ( ) ;
m_jPanel . Y = m_state . Y . ToString ( ) ;
m_jPanel . Z = m_state . Z . ToString ( ) ;
m_jPanel . Xr = m_state . RotationX . ToString ( ) ;
m_jPanel . Yr = m_state . RotationY . ToString ( ) ;
m_jPanel . Zr = m_state . RotationZ . ToString ( ) ;
m_jPanel . Xr = m_state . RotationX . ToString ( ) ;
m_jPanel . Yr = m_state . RotationY . ToString ( ) ;
m_jPanel . Zr = m_state . RotationZ . ToString ( ) ;
int [ ] slider = m_state . Sliders ;
int [ ] slider = m_state . Sliders ;
m_jPanel . S1 = slider [ 0 ] . ToString ( ) ;
m_jPanel . S2 = slider [ 1 ] . ToString ( ) ;
m_jPanel . S1 = slider [ 0 ] . ToString ( ) ;
m_jPanel . S2 = slider [ 1 ] . ToString ( ) ;
int [ ] pov = m_state . PointOfViewControllers ;
int [ ] pov = m_state . PointOfViewControllers ;
m_jPanel . H1 = pov [ 0 ] . ToString ( ) ;
m_jPanel . H2 = pov [ 1 ] . ToString ( ) ;
m_jPanel . H3 = pov [ 2 ] . ToString ( ) ;
m_jPanel . H4 = pov [ 3 ] . ToString ( ) ;
m_jPanel . H1 = pov [ 0 ] . ToString ( ) ;
m_jPanel . H2 = pov [ 1 ] . ToString ( ) ;
m_jPanel . H3 = pov [ 2 ] . ToString ( ) ;
m_jPanel . H4 = pov [ 3 ] . ToString ( ) ;
// Fill up text with which buttons are pressed
bool [ ] buttons = m_state . Buttons ;
// Fill up text with which buttons are pressed
bool [ ] buttons = m_state . Buttons ;
int button = 0 ;
foreach ( bool b in buttons )
{
if ( b )
strText + = ( button + 1 ) . ToString ( "00 " ) ; // buttons are 1 based
button + + ;
}
m_jPanel . Button = strText ;
}
int button = 0 ;
foreach ( bool b in buttons ) {
if ( b )
strText + = ( button + 1 ) . ToString ( "00 " ) ; // buttons are 1 based
button + + ;
}
m_jPanel . Button = strText ;
}
/// <summary>
/// Collect the current data from the device
/// </summary>
public void GetData ( )
{
// Make sure there is a valid device.
if ( null = = m_device )
return ;
// Poll the device for info.
try
{
m_device . Poll ( ) ;
}
catch ( SharpDXException e )
{
if ( ( e . ResultCode = = ResultCode . NotAcquired ) | | ( e . ResultCode = = ResultCode . InputLost ) )
{
// Check to see if either the app needs to acquire the device, or
// if the app lost the device to another process.
try
{
// Acquire the device.
m_device . Acquire ( ) ;
}
catch ( SharpDXException )
{
// Failed to acquire the device.
// This could be because the app doesn't have focus.
return ;
}
}
}
// Get the state of the device - retaining the previous state to find the lates change
m_prevState = m_state ;
try { m_state = m_device . GetCurrentState ( ) ; }
// Catch any exceptions. None will be handled here,
// any device re-aquisition will be handled above.
catch ( SharpDXException )
{
return ;
}
UpdateUI ( ) ; // and update the GUI
/// <summary>
/// Collect the current data from the device
/// </summary>
public void GetData ( )
{
// Make sure there is a valid device.
if ( null = = m_device )
return ;
// Poll the device for info.
try {
m_device . Poll ( ) ;
}
catch ( SharpDXException e ) {
if ( ( e . ResultCode = = ResultCode . NotAcquired ) | | ( e . ResultCode = = ResultCode . InputLost ) ) {
// Check to see if either the app needs to acquire the device, or
// if the app lost the device to another process.
try {
// Acquire the device.
m_device . Acquire ( ) ;
}
catch ( SharpDXException ) {
// Failed to acquire the device.
// This could be because the app doesn't have focus.
return ;
}
}
}
// Get the state of the device - retaining the previous state to find the lates change
m_prevState = m_state ;
try { m_state = m_device . GetCurrentState ( ) ; }
// Catch any exceptions. None will be handled here,
// any device re-aquisition will be handled above.
catch ( SharpDXException ) {
return ;
}
UpdateUI ( ) ; // and update the GUI
}
}
}