V 2.34 - BETA Build 68

- improvement - complete rework of XML defaultProfile/mapping parsing
pull/104/head
bm98 6 years ago
parent 9696eb1752
commit d2d1aa1664

@ -0,0 +1,226 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SCJMapper_V2.Common;
using SCJMapper_V2.Devices;
using SCJMapper_V2.Devices.Keyboard;
using SCJMapper_V2.Devices.Mouse;
using SCJMapper_V2.Devices.Gamepad;
using SCJMapper_V2.Devices.Joystick;
namespace SCJMapper_V2.Actions
{
/// <summary>
/// Common Device Handling items for Action Classes
/// </summary>
public class Act
{
/// <summary>
/// Device Enums to be used within Action Classes
/// </summary>
public enum ActionDevice
{
AD_Unknown = -1,
AD_Joystick = 0,
AD_Gamepad,
AD_Keyboard,
AD_Mouse, // 20151220BM: add mouse device (from AC 2.0 defaultProfile usage)
}
// Static items to have this device mappings in only one place
#region Static Items
// device naming:
// ADevice - an enum from ActionDevice (above) used internally by the Action classes
// DevTag - one letter leader (K,J,X...) used to Key items
// DeviceClass - defined in class DeviceCls and inheritors (name used in XMLs)
// Input, devInput - the part of the input used in XML that defines the device e.g. jsN_, mo1_, kb1_, xi1_
/// <summary>
/// Return the Device Enum from a DeviceClass string
/// </summary>
/// <param name="deviceClass">Device Class string</param>
/// <returns>Device Enum</returns>
static public ActionDevice ADevice( string deviceClass )
{
switch ( deviceClass.ToLower( ) ) {
case KeyboardCls.DeviceClass: return ActionDevice.AD_Keyboard;
case JoystickCls.DeviceClass: return ActionDevice.AD_Joystick;
case GamepadCls.DeviceClass: return ActionDevice.AD_Gamepad;
case MouseCls.DeviceClass: return ActionDevice.AD_Mouse; // 20151220BM: add mouse device (from AC 2.0 defaultProfile usage)
case "ps3pad": return ActionDevice.AD_Gamepad;
default: return ActionDevice.AD_Unknown;
}
}
/// <summary>
/// Returns the Device Tag i.e. the single letter to mark a device in Actions
/// </summary>
/// <param name="device">The device name from the defaultProfile</param>
/// <returns>The single UCase device Tag letter</returns>
static public string DevTag( string device )
{
switch ( device.ToLower( ) ) {
case KeyboardCls.DeviceClass: return "K";
case JoystickCls.DeviceClass: return "J";
case GamepadCls.DeviceClass: return "X";
case MouseCls.DeviceClass: return "M"; // 20151220BM: add mouse device (from AC 2.0 defaultProfile usage)
case "ps3pad": return "P";
default: return "Z";
}
}
/// <summary>
/// Returns the Device name from the Device Tag
/// </summary>
/// <param name="device">The single UCase device Tag letter</param>
/// <returns>The device name from the defaultProfile</returns>
static public string DeviceClassFromTag( string devTag )
{
switch ( devTag ) {
case "K": return KeyboardCls.DeviceClass;
case "J": return JoystickCls.DeviceClass;
case "X": return GamepadCls.DeviceClass;
case "M": return MouseCls.DeviceClass; // 20151220BM: add mouse device (from AC 2.0 defaultProfile usage)
case "P": return "ps3pad";
default: return "unknown";
}
}
/// <summary>
/// Try to derive the device class from the devInput string (mo1_, kb1_, xi1_, jsN_)
/// </summary>
/// <param name="devInput">The input command string dev_input format</param>
/// <returns>A proper DeviceClass string</returns>
static public string DeviceClassFromInput( string devInput )
{
string deviceClass = DeviceCls.DeviceClass;
deviceClass = JoystickCls.DeviceClassFromInput( devInput );
if ( !DeviceCls.IsUndefined( deviceClass ) ) return deviceClass;
deviceClass = GamepadCls.DeviceClassFromInput( devInput );
if ( !DeviceCls.IsUndefined( deviceClass ) ) return deviceClass;
deviceClass = KeyboardCls.DeviceClassFromInput( devInput );
if ( !DeviceCls.IsUndefined( deviceClass ) ) return deviceClass;
deviceClass = MouseCls.DeviceClassFromInput( devInput );
if ( !DeviceCls.IsUndefined( deviceClass ) ) return deviceClass;
// others..
return deviceClass;
}
/// <summary>
/// Returns the ActionDevice from a deviceID (a trailing _ is added if not there)
/// </summary>
/// <param name="devID">DeviceID</param>
/// <returns>The ActionDevice</returns>
static public ActionDevice ADeviceFromDevID( string devID )
{
string val = devID;
if ( !devID.EndsWith( "_" ) ) val += "_";
return ADevice( DeviceClassFromInput( val ) );
}
/// <summary>
/// Returns the ActionDevice from the devInput string (mo1_, kb1_, xi1_, jsN_)
/// </summary>
/// <param name="devInput">The input command string dev_input format</param>
/// <returns>The ActionDevice</returns>
static public ActionDevice ADeviceFromInput( string devInput )
{
return ADevice( DeviceClassFromInput( devInput ) );
}
/// <summary>
/// Query the devices if the input is disabled
/// </summary>
/// <param name="input">The input command</param>
/// <returns>True if disabled input</returns>
static public bool IsDisabledInput( string input )
{
bool disabledInput = false;
disabledInput = DeviceCls.IsDisabledInput( input ); // generic
if ( disabledInput ) return disabledInput;
disabledInput = JoystickCls.IsDisabledInput( input );
if ( disabledInput ) return disabledInput;
disabledInput = GamepadCls.IsDisabledInput( input );
if ( disabledInput ) return disabledInput;
disabledInput = KeyboardCls.IsDisabledInput( input );
if ( disabledInput ) return disabledInput;
disabledInput = MouseCls.IsDisabledInput( input );
if ( disabledInput ) return disabledInput;
// others..
return disabledInput;
}
/// <summary>
/// Disable the input for a specific device - input is a generic Disabled Input
/// </summary>
/// <param name="input">An input (generic disable or a valid command)</param>
/// <param name="aDevice">A valid device</param>
/// <returns>A device diabled or the original input if it was not a disabled</returns>
static public string DisableInput( string input, ActionDevice aDevice )
{
if ( DeviceCls.IsDisabledInput( input ) ) {
// was generic blind - return a device specific disabled input
switch ( aDevice ) {
case ActionDevice.AD_Gamepad: return GamepadCls.DisabledInput;
case ActionDevice.AD_Joystick: return JoystickCls.DisabledInput;
case ActionDevice.AD_Keyboard: return KeyboardCls.DisabledInput;
case ActionDevice.AD_Mouse: return MouseCls.DisabledInput;
default: return "";
}
}
else {
return input; // not disabled - just return the input
}
}
/// <summary>
/// Extends the input to a device input if not already done
/// </summary>
/// <param name="input">An input</param>
/// <param name="aDevice">The ActionDevice</param>
/// <returns>A valid devInput (dev_input) format</returns>
static public string DevInput( string input, ActionDevice aDevice )
{
switch ( aDevice ) {
case ActionDevice.AD_Gamepad: return GamepadCls.DevInput( input );
case ActionDevice.AD_Joystick: return JoystickCls.DevInput( input );
case ActionDevice.AD_Keyboard: return KeyboardCls.DevInput( input );
case ActionDevice.AD_Mouse: return MouseCls.DevInput( input );
default: return input;
}
}
/// <summary>
/// Return the color of a device
/// </summary>
/// <param name="devInput">The devinput (determine JS colors)</param>
/// <param name="aDevice">The ActionDevice</param>
/// <returns>The device color</returns>
static public System.Drawing.Color DeviceColor( string devInput )
{
// background is along the input
ActionDevice aDevice = ADeviceFromInput( devInput );
switch ( aDevice ) {
case ActionDevice.AD_Gamepad: return GamepadCls.XiColor( );
case ActionDevice.AD_Joystick: return JoystickCls.JsNColor( JoystickCls.JSNum( devInput ) );// need to know which JS
case ActionDevice.AD_Keyboard: return KeyboardCls.KbdColor( );
case ActionDevice.AD_Mouse: return MouseCls.MouseColor( );
default: return MyColors.UnassignedColor;
}
}
#endregion
}
}

@ -18,8 +18,8 @@ namespace SCJMapper_V2.Devices
return ( deviceClass == DeviceClass );
}
public const string BlendedInput = "~"; // internal used only
static public bool IsBlendedInput( string input ) { return ( input == BlendedInput ); }
public const string DisabledInput = "~"; // internal used only
static public bool IsDisabledInput( string input ) { return ( input == DisabledInput ); }
static public bool IsDeviceClass( string deviceClass ) { return false; }
@ -62,15 +62,15 @@ namespace SCJMapper_V2.Devices
static public string toXML( string blendedInput )
{
return blendedInput.Replace( BlendedInput, " " ); // must make spaces (tilde is for internal processing only)
return blendedInput.Replace( DisabledInput, " " ); // must make spaces (tilde is for internal processing only)
}
static public string toXMLBlendExtension( string blendedInput )
{
return (IsBlendedInput(blendedInput) ? string.Format( "multiTap=\"1\"") : "" ); // blending needs to overwrite potential multitaps (2+)
return (IsDisabledInput(blendedInput) ? string.Format( "multiTap=\"1\"") : "" ); // blending needs to overwrite potential multitaps (2+)
}
static public string fromXML( string blendedInput )
{
return blendedInput.Replace( " ", BlendedInput ); // must make tilde (spaces is for external processing only)
return blendedInput.Replace( " ", DisabledInput ); // must make tilde (spaces is for external processing only)
}
}

@ -30,10 +30,10 @@ namespace SCJMapper_V2.Devices.Gamepad
public const string DevNameCIG = "Controller (Gamepad)"; // seems CIG names the Gamepad always like this - and not as the device replies
public const string JsUnknown = "xi_";
public new const string BlendedInput = DeviceID + DeviceCls.BlendedInput;
static public new bool IsBlendedInput( string input )
public new const string DisabledInput = DeviceID + DeviceCls.DisabledInput;
static public new bool IsDisabledInput( string input )
{
if ( input == BlendedInput ) return true;
if ( input == DisabledInput ) return true;
return false;
}
@ -116,7 +116,7 @@ namespace SCJMapper_V2.Devices.Gamepad
// 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_
string retVal = input.Replace( " ", "" );
if ( IsBlendedInput( input ) ) return input;
if ( IsDisabledInput( input ) ) return input;
if ( retVal.StartsWith( "xi_" ) )
retVal = retVal.Insert( 2, "1" );

@ -34,10 +34,10 @@ namespace SCJMapper_V2.Devices.Joystick
public const string JsUnknown = "jsx_";
public new const string BlendedInput = DeviceID + DeviceCls.BlendedInput; //AC2 ..
static public new bool IsBlendedInput( string input )
public new const string DisabledInput = DeviceID + DeviceCls.DisabledInput; //AC2 ..
static public new bool IsDisabledInput( string input )
{
if ( input == BlendedInput ) return true;
if ( input == DisabledInput ) return true;
return false;
}

@ -27,10 +27,10 @@ namespace SCJMapper_V2.Devices.Keyboard
public const string ClearMods = "escape";
public new const string BlendedInput = DeviceID + DeviceCls.BlendedInput;
static public new bool IsBlendedInput ( string input )
public new const string DisabledInput = DeviceID + DeviceCls.DisabledInput;
static public new bool IsDisabledInput( string input )
{
if ( input == BlendedInput ) return true;
if ( input == DisabledInput ) return true;
return false;
}
@ -101,7 +101,7 @@ namespace SCJMapper_V2.Devices.Keyboard
// input is something like a letter or a composition like lctrl+c
// try easy: add kb1_ at the beginning and before any +; first remove spaces
string retVal = input.Replace(" ","");
if ( IsBlendedInput( input ) ) return input;
if ( IsDisabledInput( input ) ) return input;
int plPos = retVal.IndexOf("+");
while (plPos>0) {

@ -28,10 +28,10 @@ namespace SCJMapper_V2.Devices.Mouse
public new const string DeviceID = "mo1_";
static public int RegisteredDevices = 0; // devices add here once they are created (though will not decrement as they are not deleted)
public new const string BlendedInput = DeviceID + DeviceCls.BlendedInput;
static public new bool IsBlendedInput( string input )
public new const string DisabledInput = DeviceID + DeviceCls.DisabledInput;
static public new bool IsDisabledInput( string input )
{
if ( input == BlendedInput ) return true;
if ( input == DisabledInput ) return true;
return false;
}
@ -103,7 +103,7 @@ namespace SCJMapper_V2.Devices.Mouse
// input is something like a mouse1 (TODO compositions like lctrl+mouse1 ??)
// try easy: add mo1_ at the beginning
string retVal = input.Replace(" ","");
if ( IsBlendedInput( input ) ) return input;
if ( IsDisabledInput( input ) ) return input;
return "mo1_" + retVal;
}

@ -1,7 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using SCJMapper_V2.Actions;
using SCJMapper_V2.Devices.Joystick;
@ -24,16 +25,16 @@ namespace SCJMapper_V2.Devices.Options
string m_option = ""; // the option name (level where it applies)
private string m_deviceName = "";
private bool m_isStrafe = false; // default
private bool m_isStrafe = false; // default
private bool m_expEnabled = false; // default
private bool m_expEnabled = false; // default
private string m_exponent = "1.000";
private bool m_ptsEnabled = false; // default
private bool m_ptsEnabled = false; // default
private List<string> m_PtsIn = new List<string>( );
private List<string> m_PtsOut = new List<string>( );
private bool m_invertEnabled = false; // default
private bool m_invertEnabled = false; // default
private DeviceCls m_deviceRef = null; // Ref
@ -44,9 +45,9 @@ namespace SCJMapper_V2.Devices.Options
/// Clone this object
/// </summary>
/// <returns>A deep Clone of this object</returns>
public object Clone( )
public object Clone()
{
var dt = (DeviceTuningParameter)this.MemberwiseClone(); // self and all value types
var dt = (DeviceTuningParameter)this.MemberwiseClone( ); // self and all value types
// more objects to deep copy
// --> NO cloning as this Ref will be overwritten when editing
dt.m_deviceoptionRef = null; // just reset
@ -207,7 +208,7 @@ namespace SCJMapper_V2.Devices.Options
/// Reset all items that will be assigned dynamically while scanning the actions
/// - currently DeviceoptionRef, NodeText
/// </summary>
public void ResetDynamicItems( )
public void ResetDynamicItems()
{
// using the public property to ensure the complete processing of the assignment
// GameDevice = null;
@ -215,7 +216,7 @@ namespace SCJMapper_V2.Devices.Options
NodeText = "";
}
public void AssignDynamicItems( DeviceCls dev, DeviceOptionParameter devOptionRef, string nodeText )
public void AssignDynamicItems( DeviceCls dev, DeviceOptionParameter devOptionRef, string nodeText )
{
// using the public property to ensure the complete processing of the assignment
NodeText = nodeText; // must be first - the content is used later for DeviceOptionRef assignment
@ -226,7 +227,7 @@ namespace SCJMapper_V2.Devices.Options
/// <summary>
/// Derive values from a command (e.g. v_pitch - js1_x)
/// </summary>
private void DecomposeCommand( )
private void DecomposeCommand()
{
// populate from input
// something like "v_pitch - js1_x" OR "v_pitch - xi_thumbl" OR "v_pitch - ximod+xi_thumbl+xi_mod"
@ -239,21 +240,24 @@ namespace SCJMapper_V2.Devices.Options
// gamepad
m_cmdCtrl = "xi_thumblx";
m_deviceName = m_deviceRef.DevName;
} else if ( cmd.Contains( "xi_thumbly" ) ) {
}
else if ( cmd.Contains( "xi_thumbly" ) ) {
// gamepad
m_cmdCtrl = "xi_thumbly";
m_deviceName = m_deviceRef.DevName;
} else if ( cmd.Contains( "xi_thumbrx" ) ) {
}
else if ( cmd.Contains( "xi_thumbrx" ) ) {
// gamepad
m_cmdCtrl = "xi_thumbrx";
m_deviceName = m_deviceRef.DevName;
} else if ( cmd.Contains( "xi_thumbry" ) ) {
}
else if ( cmd.Contains( "xi_thumbry" ) ) {
// gamepad
m_cmdCtrl = "xi_thumbry";
m_deviceName = m_deviceRef.DevName;
}
// assume joystick
else {
// assume joystick
else {
// get parts
m_cmdCtrl = JoystickCls.ActionFromJsCommand( cmd ); //js1_x -> x; js2_rotz -> rotz
m_deviceName = m_deviceRef.DevName;
@ -271,7 +275,8 @@ namespace SCJMapper_V2.Devices.Options
double d = 0;
if ( ( !string.IsNullOrEmpty( valString ) ) && double.TryParse( valString, out d ) ) {
return d.ToString( "0.000" );
} else {
}
else {
return valString;
}
}
@ -280,7 +285,7 @@ namespace SCJMapper_V2.Devices.Options
/// Format an XML -options- node from the tuning contents
/// </summary>
/// <returns>The XML string or an empty string</returns>
public string Options_toXML( )
public string Options_toXML()
{
if ( ( /*SensitivityUsed ||*/ ExponentUsed || InvertUsed || NonLinCurveUsed ) == false ) return ""; // not used
if ( DevInstanceNo < 1 ) return ""; // no device to assign it to..
@ -306,10 +311,12 @@ namespace SCJMapper_V2.Devices.Options
tmp += string.Format( "\t\t\t\t<point in=\"{0}\" out=\"{1}\"/>\n", m_PtsIn[2], m_PtsOut[2] );
tmp += string.Format( "\t\t\t</nonlinearity_curve>\n" );
tmp += string.Format( "\t\t</{0}> \n", m_option );
} else if ( ExponentUsed ) {
}
else if ( ExponentUsed ) {
// only exp used
tmp += string.Format( "exponent=\"{0}\" /> \n", Exponent );
} else {
}
else {
// neither exp or curve
tmp += string.Format( " /> \n" );// nothing...
}
@ -327,76 +334,61 @@ namespace SCJMapper_V2.Devices.Options
/// <param name="reader">A prepared XML reader</param>
/// <param name="instance">the Joystick instance number</param>
/// <returns></returns>
public Boolean Options_fromXML( XmlReader reader, string type, int instance )
public Boolean Options_fromXML( XElement option, string type, int instance )
{
/*
<flight_move_pitch exponent="1.00" >
<nonlinearity_curve>
<point in="0.182" out="0.028"/>
<point in="0.629" out="0.235"/>
<point in="0.895" out="0.629"/>
</nonlinearity_curve>
</flight_move_pitch>
*/
m_class = type;
string invert = "";
string exponent = "";
m_option = reader.Name;
m_devInstanceNo = instance;
m_option = option.Name.LocalName;
// derive from flight_move_pitch || flight_move_yaw || flight_move_roll (nothing bad should arrive here)
string[] e = m_option.ToLowerInvariant( ).Split( new char[] { '_' } );
if ( e.Length > 2 ) m_cmdCtrl = e[2]; // TODO - see if m_cmdCtrl is needed to be derived here
string invert = (string)option.Attribute( "invert" );
if ( !string.IsNullOrEmpty(invert) ) {
InvertUsed = false;
if ( invert == "1" ) InvertUsed = true;
}
if ( reader.HasAttributes ) {
invert = reader["invert"];
if ( !string.IsNullOrWhiteSpace( invert ) ) {
InvertUsed = false;
if ( invert == "1" ) InvertUsed = true;
}
/*
sensitivity = reader["sensitivity"];
if ( !string.IsNullOrWhiteSpace( sensitivity ) ) {
Sensitivity = sensitivity;
SensitivityUsed = true;
}
*/
exponent = reader["exponent"];
if ( !string.IsNullOrWhiteSpace( exponent ) ) {
Exponent = RoundString( exponent );
ExponentUsed = true;
}
string exponent = (string)option.Attribute( "exponent" );
if ( !string.IsNullOrEmpty( exponent ) ) {
Exponent = RoundString( exponent );
ExponentUsed = true;
}
// we may have a nonlin curve...
if ( !reader.IsEmptyElement ) {
reader.Read( );
if ( !reader.EOF ) {
if ( reader.Name.ToLowerInvariant( ) == "nonlinearity_curve" ) {
m_PtsIn.Clear( ); m_PtsOut.Clear( ); // reset pts
ExponentUsed = false; // NonLin Curve takes prio
reader.Read( );
while ( !reader.EOF ) {
string ptIn = "";
string ptOut = "";
if ( reader.Name.ToLowerInvariant( ) == "point" ) {
if ( reader.HasAttributes ) {
ptIn = RoundString( reader["in"] );
ptOut = RoundString( reader["out"] );
m_PtsIn.Add( ptIn ); m_PtsOut.Add( ptOut ); m_ptsEnabled = true;
}
}
reader.Read( );
}//while
// sanity check - we've have to have 3 pts here - else we subst
// add 2nd
if ( m_PtsIn.Count < 2 ) {
m_PtsIn.Add( "0.500" ); m_PtsOut.Add( "0.500" );
log.Info( "Options_fromXML: got only one nonlin point, added (0.5|0.5)" );
}
// add 3rd
if ( m_PtsIn.Count < 3 ) {
m_PtsIn.Add( "0.750" ); m_PtsOut.Add( "0.750" );
log.Info( "Options_fromXML: got only two nonlin points, added (0.75|0.75)" );
}
}
XElement nlc = option.Element( "nonlinearity_curve" );
if ( nlc != null ) {
m_PtsIn.Clear( ); m_PtsOut.Clear( ); // reset pts
IEnumerable<XElement> points = from x in nlc.Elements( )
where ( x.Name == "point" )
select x;
foreach ( XElement point in points ) {
string ptIn = RoundString( (string)point.Attribute( "in" ) );
string ptOut = RoundString( (string)point.Attribute( "out" ) );
m_PtsIn.Add( ptIn ); m_PtsOut.Add( ptOut ); m_ptsEnabled = true;
}
}
// sanity check - we've have to have 3 pts here - else we subst
// add 2nd
if ( m_PtsIn.Count < 2 ) {
m_PtsIn.Add( "0.500" ); m_PtsOut.Add( "0.500" );
log.Info( "Options_fromXML: got only one nonlin point, added (0.5|0.5)" );
}
// add 3rd
if ( m_PtsIn.Count < 3 ) {
m_PtsIn.Add( "0.750" ); m_PtsOut.Add( "0.750" );
log.Info( "Options_fromXML: got only two nonlin points, added (0.75|0.75)" );
}
return true;
}

@ -227,7 +227,8 @@ namespace SCJMapper_V2.Devices.Options
try {
XDocument doc = XDocument.Parse( xml );
return doc.ToString( ).Split( new string[] { string.Format( "\n" ) }, StringSplitOptions.RemoveEmptyEntries );
} catch ( Exception ) {
}
catch ( Exception ) {
return new string[] { xml };
}
}
@ -267,7 +268,7 @@ namespace SCJMapper_V2.Devices.Options
/// </summary>
/// <param name="xml">the XML action fragment</param>
/// <returns>True if an action was decoded</returns>
public Boolean fromXML( string xml )
public bool fromXML( XElement deviceOptions )
{
/*
* This can be a lot of the following options
@ -281,81 +282,41 @@ namespace SCJMapper_V2.Devices.Options
*
*/
XmlReaderSettings settings = new XmlReaderSettings( );
settings.ConformanceLevel = ConformanceLevel.Fragment;
settings.IgnoreWhitespace = true;
settings.IgnoreComments = true;
XmlReader reader = XmlReader.Create( new StringReader( xml ), settings );
reader.Read( );
string name = "";
if ( reader.HasAttributes ) {
name = reader["name"];
string devClass = ( name == GamepadCls.DevNameCIG ) ? GamepadCls.DeviceClass : JoystickCls.DeviceClass;// have to trick this one...
reader.Read( );
// try to disassemble the items
while ( !reader.EOF ) {
if ( reader.Name.ToLowerInvariant( ) == "option" ) {
if ( reader.HasAttributes ) {
string input = reader["input"];
string deadzone = RoundString( reader["deadzone"] );
string saturation = RoundString( reader["saturation"] );
if ( !string.IsNullOrWhiteSpace( input ) ) {
string doID = "";
doID = DevOptionID( devClass, name, input );
if ( !string.IsNullOrWhiteSpace( deadzone ) ) {
float testF;
if ( !float.TryParse( deadzone, out testF ) ) { // check for valid number in string
deadzone = "0.000";
}
if ( !this.ContainsKey( doID ) ) {
log.InfoFormat( "Cannot caputre Device Options for device <{0}> - unknown device!", name );
//this.Add( doID, new DeviceOptionParameter( devClass, name, input, deadzone, saturation ) );
}
else {
// add deadzone value tp existing
this[doID].DeadzoneUsed = true;
this[doID].Deadzone = deadzone;
}
}
if ( !string.IsNullOrWhiteSpace( saturation ) ) {
float testF;
if ( !float.TryParse( saturation, out testF ) ) { // check for valid number in string
saturation = "1.000";
}
if ( !this.ContainsKey( doID ) ) {
log.InfoFormat( "Cannot caputre Device Options for device <{0}> - unknown device!", name );
//this.Add( doID, new DeviceOptionParameter( devClass, name, input, deadzone, saturation ) ); // actually not supported..
}
else {
// add saturation value tp existing
this[doID].SaturationUsed = true;
this[doID].Saturation = saturation;
}
}
}
else {
//? option node has not the needed attributes
log.ErrorFormat( "Deviceoptions.fromXML: option node has not the needed attributes" );
}
}
else {
//?? option node has NO attributes
log.ErrorFormat( "Deviceoptions.fromXML: option node has NO attributes" );
}
string name = (string)deviceOptions.Attribute( "name" ); // mandadory
string devClass = ( name == GamepadCls.DevNameCIG ) ? GamepadCls.DeviceClass : JoystickCls.DeviceClass;// have to trick this one...
IEnumerable<XElement> options = from x in deviceOptions.Elements( )
where ( x.Name == "option" )
select x;
foreach ( XElement option in options ) {
string input = (string)option.Attribute( "input" ); // mandadory
string doID = DevOptionID( devClass, name, input );
string deadzone = RoundString( (string)option.Attribute( "deadzone" ));
if ( !string.IsNullOrEmpty(deadzone) ) {
if ( !this.ContainsKey( doID ) ) {
log.InfoFormat( "Cannot caputre Device Options for device <{0}> - unknown device!", name );
}
else {
// add deadzone value tp existing
this[doID].DeadzoneUsed = true;
this[doID].Deadzone = deadzone;
}
}
reader.Read( );
}//while
}
else {
//??
if ( !m_stringOptions.Contains( xml ) ) m_stringOptions.Add( xml );
}
string saturation = RoundString( (string)option.Attribute( "saturation" ) );
if ( !string.IsNullOrEmpty( saturation ) ) {
if ( !this.ContainsKey( doID ) ) {
log.InfoFormat( "Cannot caputre Device Options for device <{0}> - unknown device!", name );
}
else {
// add saturation value tp existing
this[doID].SaturationUsed = true;
this[doID].Saturation = saturation;
}
}
}
return true;
}

@ -157,7 +157,8 @@ namespace SCJMapper_V2.Devices.Options
try {
XDocument doc = XDocument.Parse( xml );
return doc.ToString( ).Split( new string[] { string.Format( "\n" ) }, StringSplitOptions.RemoveEmptyEntries );
} catch ( Exception ) {
}
catch ( Exception ) {
return new string[] { xml };
}
}
@ -197,7 +198,7 @@ namespace SCJMapper_V2.Devices.Options
/// </summary>
/// <param name="xml">the XML action fragment</param>
/// <returns>True if an action was decoded</returns>
public bool fromXML( string xml )
public bool fromXML( XElement options )
{
/*
* This can be a lot of the following options
@ -225,136 +226,96 @@ namespace SCJMapper_V2.Devices.Options
</options>
*/
XmlReaderSettings settings = new XmlReaderSettings( );
settings.ConformanceLevel = ConformanceLevel.Fragment;
settings.IgnoreWhitespace = true;
settings.IgnoreComments = true;
XmlReader reader = XmlReader.Create( new StringReader( xml ), settings );
reader.Read( );
string type = "";
string instance = ""; int nInstance = 0;
if ( reader.HasAttributes ) {
type = reader["type"];
if ( !( ( type.ToLowerInvariant( ) == "joystick" ) || ( type.ToLowerInvariant( ) == "xboxpad" ) ) ) {
// save as plain text
if ( !m_stringOptions.Contains( xml ) ) m_stringOptions.Add( xml );
return true;
string instance = (string)options.Attribute( "instance" ); // mandadory
string type = (string)options.Attribute( "type" ); // mandadory
if ( !int.TryParse( instance, out int nInstance ) ) nInstance = 0;
// try to disassemble the items
/*
* <flight> instance="0/1" sensitivity="n.nn" exponent="n.nn" (instance should be invert)
* <flight_move>
* <flight_move_pitch>
* <flight_move_yaw>
* <flight_move_roll>
* <flight_move_strafe_vertical>
* <flight_move_strafe_lateral>
* <flight_move_strafe_longitudinal>
* <flight_throttle> invert="0/1"
* <flight_throttle_abs>
* <flight_throttle_rel>
* <flight_aim>
* <flight_aim_pitch>
* <flight_aim_yaw>
* <flight_view>
* <flight_view_pitch>
* <flight_view_yaw>
*
*
<nonlinearity_curve>
<point in="0.1" out="0.001"/>
* ..
</nonlinearity_curve>
*
*
*
*/
foreach ( XElement item in options.Elements( ) ) {
if ( item.Name.LocalName == "flight_move_pitch" ) {
m_tuning["flight_move_pitch"].Options_fromXML( item, type, int.Parse( instance ) );
}
// further on..
instance = reader["instance"];
if ( !int.TryParse( instance, out nInstance ) ) nInstance = 0;
reader.Read( );
// try to disassemble the items
/*
* <flight> instance="0/1" sensitivity="n.nn" exponent="n.nn" (instance should be invert)
* <flight_move>
* <flight_move_pitch>
* <flight_move_yaw>
* <flight_move_roll>
* <flight_move_strafe_vertical>
* <flight_move_strafe_lateral>
* <flight_move_strafe_longitudinal>
* <flight_throttle> invert="0/1"
* <flight_throttle_abs>
* <flight_throttle_rel>
* <flight_aim>
* <flight_aim_pitch>
* <flight_aim_yaw>
* <flight_view>
* <flight_view_pitch>
* <flight_view_yaw>
*
*
<nonlinearity_curve>
<point in="0.1" out="0.001"/>
* ..
</nonlinearity_curve>
*
*
*
*/
while ( !reader.EOF ) {
if ( reader.Name.ToLowerInvariant( ) == "flight_move_pitch" ) {
m_tuning["flight_move_pitch"].Options_fromXML( reader, type, int.Parse( instance ) );
}
else if ( reader.Name.ToLowerInvariant( ) == "flight_move_yaw" ) {
m_tuning["flight_move_yaw"].Options_fromXML( reader, type, int.Parse( instance ) );
}
else if ( reader.Name.ToLowerInvariant( ) == "flight_move_roll" ) {
m_tuning["flight_move_roll"].Options_fromXML( reader, type, int.Parse( instance ) );
}
else if ( reader.Name.ToLowerInvariant( ) == "flight_move_strafe_vertical" ) {
m_tuning["flight_move_strafe_vertical"].Options_fromXML( reader, type, int.Parse( instance ) );
}
else if ( reader.Name.ToLowerInvariant( ) == "flight_move_strafe_lateral" ) {
m_tuning["flight_move_strafe_lateral"].Options_fromXML( reader, type, int.Parse( instance ) );
}
else if ( reader.Name.ToLowerInvariant( ) == "flight_move_strafe_longitudinal" ) {
m_tuning["flight_move_strafe_longitudinal"].Options_fromXML( reader, type, int.Parse( instance ) );
}
else if ( reader.Name.ToLowerInvariant( ) == "flight_throttle_abs" ) {
m_tuning["flight_throttle_abs"].Options_fromXML( reader, type, int.Parse( instance ) );
}
else if ( reader.Name.ToLowerInvariant( ) == "flight_throttle_rel" ) {
m_tuning["flight_throttle_rel"].Options_fromXML( reader, type, int.Parse( instance ) );
}
else if ( reader.Name.ToLowerInvariant( ) == "flight_aim_pitch" ) {
m_tuning["flight_aim_pitch"].Options_fromXML( reader, type, int.Parse( instance ) );
}
else if ( reader.Name.ToLowerInvariant( ) == "flight_aim_yaw" ) {
m_tuning["flight_aim_yaw"].Options_fromXML( reader, type, int.Parse( instance ) );
}
else if ( reader.Name.ToLowerInvariant( ) == "flight_view_pitch" ) {
m_tuning["flight_view_pitch"].Options_fromXML( reader, type, int.Parse( instance ) );
}
else if ( reader.Name.ToLowerInvariant( ) == "flight_view_yaw" ) {
m_tuning["flight_view_yaw"].Options_fromXML( reader, type, int.Parse( instance ) );
}
else if ( reader.NodeType != XmlNodeType.EndElement ) {
}
else if ( reader.Name.ToLowerInvariant( ) == "fps_view_pitch" ) {
m_tuning["fps_view_pitch"].Options_fromXML( reader, type, int.Parse( instance ) );
}
else if ( reader.Name.ToLowerInvariant( ) == "fps_view__yaw" ) {
m_tuning["fps_view__yaw"].Options_fromXML( reader, type, int.Parse( instance ) );
}
else if ( reader.NodeType != XmlNodeType.EndElement ) {
}
else if ( reader.Name.ToLowerInvariant( ) == "fps_move_lateral" ) {
m_tuning["fps_move_lateral"].Options_fromXML( reader, type, int.Parse( instance ) );
}
else if ( reader.Name.ToLowerInvariant( ) == "fps_move_longitudinal" ) {
m_tuning["fps_move_longitudinal"].Options_fromXML( reader, type, int.Parse( instance ) );
}
else if ( reader.NodeType != XmlNodeType.EndElement ) {
}
else if ( reader.Name.ToLowerInvariant( ) == "mgv_view_pitch" ) {
m_tuning["mgv_view_pitch"].Options_fromXML( reader, type, int.Parse( instance ) );
}
else if ( reader.Name.ToLowerInvariant( ) == "mgv_view_yaw" ) {
m_tuning["mgv_view_yaw"].Options_fromXML( reader, type, int.Parse( instance ) );
}
else if ( reader.NodeType != XmlNodeType.EndElement ) {
//??
log.InfoFormat( "Options.fromXML: unknown node - {0} - stored as is", reader.Name );
if ( !m_stringOptions.Contains( xml ) ) m_stringOptions.Add( xml );
}
else if ( item.Name.LocalName == "flight_move_yaw" ) {
m_tuning["flight_move_yaw"].Options_fromXML( item, type, int.Parse( instance ) );
}
else if ( item.Name.LocalName == "flight_move_roll" ) {
m_tuning["flight_move_roll"].Options_fromXML( item, type, int.Parse( instance ) );
}
else if ( item.Name.LocalName == "flight_move_strafe_vertical" ) {
m_tuning["flight_move_strafe_vertical"].Options_fromXML( item, type, int.Parse( instance ) );
}
else if ( item.Name.LocalName == "flight_move_strafe_lateral" ) {
m_tuning["flight_move_strafe_lateral"].Options_fromXML( item, type, int.Parse( instance ) );
}
else if ( item.Name.LocalName == "flight_move_strafe_longitudinal" ) {
m_tuning["flight_move_strafe_longitudinal"].Options_fromXML( item, type, int.Parse( instance ) );
}
else if ( item.Name.LocalName == "flight_throttle_abs" ) {
m_tuning["flight_throttle_abs"].Options_fromXML( item, type, int.Parse( instance ) );
}
else if ( item.Name.LocalName == "flight_throttle_rel" ) {
m_tuning["flight_throttle_rel"].Options_fromXML( item, type, int.Parse( instance ) );
reader.Read( );
}
else if ( item.Name.LocalName == "flight_aim_pitch" ) {
m_tuning["flight_aim_pitch"].Options_fromXML( item, type, int.Parse( instance ) );
}
else if ( item.Name.LocalName == "flight_aim_yaw" ) {
m_tuning["flight_aim_yaw"].Options_fromXML( item, type, int.Parse( instance ) );
}
else if ( item.Name.LocalName == "flight_view_pitch" ) {
m_tuning["flight_view_pitch"].Options_fromXML( item, type, int.Parse( instance ) );
}
else if ( item.Name.LocalName == "flight_view_yaw" ) {
m_tuning["flight_view_yaw"].Options_fromXML( item, type, int.Parse( instance ) );
}
else if ( item.Name.LocalName == "fps_view_pitch" ) {
m_tuning["fps_view_pitch"].Options_fromXML( item, type, int.Parse( instance ) );
}
else if ( item.Name.LocalName == "fps_view__yaw" ) {
m_tuning["fps_view__yaw"].Options_fromXML( item, type, int.Parse( instance ) );
}
else if ( item.Name.LocalName == "fps_move_lateral" ) {
m_tuning["fps_move_lateral"].Options_fromXML( item, type, int.Parse( instance ) );
}
else if ( item.Name.LocalName == "fps_move_longitudinal" ) {
m_tuning["fps_move_longitudinal"].Options_fromXML( item, type, int.Parse( instance ) );
}
else if ( item.Name.LocalName == "mgv_view_pitch" ) {
m_tuning["mgv_view_pitch"].Options_fromXML( item, type, int.Parse( instance ) );
}
else if ( item.Name.LocalName == "mgv_view_yaw" ) {
m_tuning["mgv_view_yaw"].Options_fromXML( item, type, int.Parse( instance ) );
}
}
return true;
}

@ -7,6 +7,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
namespace SCJMapper_V2.Devices.Options
{
@ -300,7 +301,7 @@ namespace SCJMapper_V2.Devices.Options
/// </summary>
/// <param name="xml">the XML action fragment</param>
/// <returns>True if an action was decoded</returns>
public bool fromXML( string xml )
public bool fromXML( XElement options )
{
/*
* This can be a lot of the following options
@ -316,43 +317,29 @@ namespace SCJMapper_V2.Devices.Options
</options>
*/
XmlReaderSettings settings = new XmlReaderSettings( );
settings.ConformanceLevel = ConformanceLevel.Fragment;
settings.IgnoreWhitespace = true;
settings.IgnoreComments = true;
XmlReader reader = XmlReader.Create( new StringReader( xml ), settings );
reader.Read( );
string type = "";
string instance = ""; int nInstance = 0;
if ( reader.HasAttributes ) {
instance = reader["instance"];
if ( !int.TryParse( instance, out nInstance ) ) nInstance = 0;
type = reader["type"];
// now dispatch to the instance to capture the content
if ( type.ToLowerInvariant( ) == "joystick" ) {
string toID = TuneOptionIDfromJsN( JoystickCls.DeviceClass, nInstance );
// now this might not be availabe if devices have been changed
if ( this.ContainsKey( toID ) ) {
this[toID].fromXML( xml );
}
else {
log.InfoFormat( "Read XML Options - joystick instance {0} is not available - dropped this content", nInstance );
}
string instance = (string)options.Attribute( "instance" ); // mandadory
string type = (string)options.Attribute( "type" ); // mandadory
if ( !int.TryParse( instance, out int nInstance ) ) nInstance = 0;
// now dispatch to the instance to capture the content
if ( JoystickCls.IsDeviceClass( type ) ) {
string toID = TuneOptionIDfromJsN( JoystickCls.DeviceClass, nInstance );
// now this might not be availabe if devices have been changed
if ( this.ContainsKey( toID ) ) {
this[toID].fromXML( options );
}
else if ( type.ToLowerInvariant( ) == "xboxpad" ) {
string toID = TuneOptionID( GamepadCls.DeviceClass, nInstance );
if ( this.ContainsKey( toID ) ) {// 20170513: bugfix if gamepad is in the XML but not connected right now - ignore
this[toID].fromXML( xml );
}
else {
log.InfoFormat( "Read XML Options - xboxpad instance {0} is not available - dropped this content", nInstance );
}
else {
log.InfoFormat( "Read XML Options - joystick instance {0} is not available - dropped this content", nInstance );
}
}
else if ( GamepadCls.IsDeviceClass( type ) ) {
string toID = TuneOptionID( GamepadCls.DeviceClass, nInstance );
if ( this.ContainsKey( toID ) ) {// 20170513: bugfix if gamepad is in the XML but not connected right now - ignore
this[toID].fromXML( options );
}
else {
log.InfoFormat( "Read XML Options - xboxpad instance {0} is not available - dropped this content", nInstance );
}
}
return true;
}

@ -6,7 +6,7 @@ using System.Xml;
using System.IO;
using System.Xml.Linq;
namespace SCJMapper_V2.Devices.Joystick
namespace SCJMapper_V2.Devices
{
/// <summary>
/// Maintains an CustomisationUIHeader - something like:
@ -28,10 +28,13 @@ namespace SCJMapper_V2.Devices.Joystick
List<string> m_stringOptions = new List<string>( );
public const string XmlName = "CustomisationUIHeader";
public struct DevRec : ICloneable
{
public string devType;
public int instNo;
public int instNo;
public object Clone()
{
@ -45,7 +48,7 @@ namespace SCJMapper_V2.Devices.Joystick
/// </summary>
/// <param name="clone"></param>
/// <returns>True if the clone is identical but not a shallow copy</returns>
public bool CheckClone(DevRec clone)
public bool CheckClone( DevRec clone )
{
bool ret = true;
ret &= ( this.devType == clone.devType ); // immutable string - shallow copy is OK
@ -64,11 +67,11 @@ namespace SCJMapper_V2.Devices.Joystick
/// Clone this object
/// </summary>
/// <returns>A deep Clone of this object</returns>
public object Clone( )
public object Clone()
{
var uic = (UICustHeader)this.MemberwiseClone();
var uic = (UICustHeader)this.MemberwiseClone( );
// more objects to deep copy
uic.m_devInstances = m_devInstances.Select( x => ( DevRec )x.Clone( ) ).ToList( );
uic.m_devInstances = m_devInstances.Select( x => (DevRec)x.Clone( ) ).ToList( );
#if DEBUG
// check cloned item
@ -82,7 +85,7 @@ namespace SCJMapper_V2.Devices.Joystick
/// </summary>
/// <param name="clone"></param>
/// <returns>True if the clone is identical but not a shallow copy</returns>
private bool CheckClone (UICustHeader clone )
private bool CheckClone( UICustHeader clone )
{
bool ret = true;
ret &= ( this.m_stringOptions == clone.m_stringOptions ); // immutable string list - shallow copy is OK
@ -91,7 +94,7 @@ namespace SCJMapper_V2.Devices.Joystick
ret &= ( this.m_image == clone.m_image ); // immutable string - shallow copy is OK
ret &= ( this.m_devInstances.Count == clone.m_devInstances.Count );
if (ret) {
if ( ret ) {
for ( int i = 0; i < this.m_devInstances.Count; i++ ) {
ret &= ( this.m_devInstances[i].CheckClone( clone.m_devInstances[i] ) );
}
@ -111,7 +114,7 @@ namespace SCJMapper_V2.Devices.Joystick
set { m_label = value; }
}
public void ClearInstances( )
public void ClearInstances()
{
m_devInstances.Clear( );
}
@ -136,7 +139,7 @@ namespace SCJMapper_V2.Devices.Joystick
/// Dump the CustomisationUIHeader as partial XML nicely formatted
/// </summary>
/// <returns>the action as XML fragment</returns>
public string toXML( )
public string toXML()
{
/*
<CustomisationUIHeader label="sdsd" description="" image="">
@ -155,7 +158,7 @@ namespace SCJMapper_V2.Devices.Joystick
string r = "";
r += string.Format( "\t<CustomisationUIHeader label=\"{0}\" description=\"{1}\" image=\"{2}\">\n", m_label, m_description, m_image );
r += string.Format( "\t<{0} label=\"{1}\" description=\"{2}\" image=\"{3}\">\n", XmlName, m_label, m_description, m_image );
if ( m_devInstances.Count > 0 ) {
r += string.Format( "\t\t<devices>\n" );
@ -191,16 +194,22 @@ namespace SCJMapper_V2.Devices.Joystick
/// </summary>
/// <param name="xml">the XML action fragment</param>
/// <returns>True if an action was decoded</returns>
private Boolean Instance_fromXML( XmlReader reader )
private bool Instance_fromXML( XElement devices )
{
reader.Read( );
while ( !reader.EOF ) {
string devType = reader.Name;
string instance = reader["instance"];
/*
<devices>
<keyboard instance="1"/>
<mouse instance="1"/>
<joystick instance="1"/>
<joystick instance="2"/>
</devices>
*/
foreach ( XElement dev in devices.Nodes( ) ) {
string devType = (string)dev.Name.LocalName;
int instNo = 0;
if ( !string.IsNullOrWhiteSpace( instance ) ) {
if ( !int.TryParse( instance, out instNo ) ) {
IEnumerable<XAttribute> attr = dev.Attributes( ).Where( _a => _a.Name == "instance" );
if ( attr.Count( ) > 0 ) {
if ( !int.TryParse( attr.ElementAt( 0 ).Value.ToString( ), out instNo ) ) {
instNo = 0;
}
else {
@ -210,10 +219,7 @@ namespace SCJMapper_V2.Devices.Joystick
m_devInstances.Add( dr );
}
}
reader.Read( );
if ( reader.NodeType == XmlNodeType.EndElement ) break; // expect end of <Devices> here
}//while
}
return true;
}
@ -223,49 +229,41 @@ namespace SCJMapper_V2.Devices.Joystick
/// </summary>
/// <param name="xml">the XML action fragment</param>
/// <returns>True if an action was decoded</returns>
public Boolean fromXML( string xml )
public bool fromXML( XElement cuiHeader )
{
XmlReaderSettings settings = new XmlReaderSettings( );
settings.ConformanceLevel = ConformanceLevel.Fragment;
settings.IgnoreWhitespace = true;
settings.IgnoreComments = true;
XmlReader reader = XmlReader.Create( new StringReader( xml ), settings );
reader.Read( );
if ( reader.HasAttributes ) {
m_label = reader["label"];
m_description = reader["description"];
if ( string.IsNullOrEmpty( m_description ) ) m_description = "@ui_JoystickDefaultDesc";
m_image = reader["image"];
if ( string.IsNullOrEmpty( m_image ) ) m_image = "JoystickDefault";
reader.Read( );
// try to disassemble the items
/*
* <Devices>
* <joystick instance="1" />
* <joystick instance="2" />
* </Devices>
*/
while ( !reader.EOF ) {
if ( reader.Name.ToLowerInvariant( ) == "devices" ) {
Instance_fromXML( reader );
}
else if ( reader.Name.ToLowerInvariant( ) == "categories" ) {
reader.ReadInnerXml( );
}
else {
//??
log.InfoFormat( "UICustHeader.fromXML: unknown node - {0} - stored as is", reader.Name );
if ( !m_stringOptions.Contains( xml ) ) m_stringOptions.Add( xml );
}
reader.Read( );
if ( reader.NodeType == XmlNodeType.EndElement ) break; // expect end of <CustomisationUIHeader> here
}
/*
<CustomisationUIHeader label="my_x55_65o" description="@@ui_JoystickSaitekX55Desc" image="JoystickSaitekX55">
<devices>
<keyboard instance="1"/>
<mouse instance="1"/>
<joystick instance="1"/>
<joystick instance="2"/>
</devices>
<categories>
<category label="@ui_CCSpaceFlight"/>
</categories>
</CustomisationUIHeader>
*/
m_label = (string)cuiHeader.Attributes( ).First( a => a.Name == "label" ); // mandadory - else Exception
IEnumerable<XAttribute> attr = cuiHeader.Attributes( ).Where( _a => _a.Name == "description" );
if ( attr.Count( ) > 0 )
m_description = attr.ElementAt( 0 ).Value.ToString( );
else
m_description = "@ui_JoystickDefaultDesc";
attr = cuiHeader.Attributes( ).Where( _a => _a.Name == "image" );
if ( attr.Count( ) > 0 )
m_image = attr.ElementAt( 0 ).Value.ToString( );
else
m_image = "JoystickDefault";
// try to disassemble the devices items
IEnumerable<XElement> elements = from x in cuiHeader.Elements( )
where ( x.Name == "devices" )
select x;
foreach ( XElement devices in elements ) {
Instance_fromXML( devices );
}
return true;

@ -84,22 +84,22 @@ namespace SCJMapper_V2
/// <summary>
/// Detects and returns the current Input device
/// </summary>
private ActionCls.ActionDevice InputMode
private Act.ActionDevice InputMode
{
get {
// take care of the sequence.. mouse overrides key but both override joy and game
if ( m_mouseIn ) { // 20151220BM: add mouse device (from AC 2.0 defaultProfile usage)
return ActionCls.ActionDevice.AD_Mouse;
return Act.ActionDevice.AD_Mouse;
}
else if ( m_keyIn ) {
return ActionCls.ActionDevice.AD_Keyboard;
return Act.ActionDevice.AD_Keyboard;
}
else {
if ( IsGamepadTab( tc1.SelectedTab ) ) {
return ActionCls.ActionDevice.AD_Gamepad;
return Act.ActionDevice.AD_Gamepad;
}
else {
return ActionCls.ActionDevice.AD_Joystick;
return Act.ActionDevice.AD_Joystick;
}
}
}
@ -798,7 +798,7 @@ namespace SCJMapper_V2
{
log.Debug( "btBlend_Click" );
if ( m_AT.CanBlendBinding ) {
m_AT.BlendBinding( );
m_AT.DisableBinding( );
UpdateTableSelectedItem( );
if ( m_AT.Dirty ) btDump.BackColor = MyColors.DirtyColor;
}
@ -1308,7 +1308,7 @@ namespace SCJMapper_V2
find = ActionTreeNode.ComposeNodeText( action, "js" );
nodeText = m_AT.FindText( actionmap, find ); // returns "" or a complete text ("action - command")
if ( !string.IsNullOrWhiteSpace( nodeText ) ) {
if ( !ActionCls.IsBlendedInput( ActionTreeNode.CommandFromNodeText( nodeText ) ) ) {
if ( !Act.IsDisabledInput( ActionTreeNode.CommandFromNodeText( nodeText ) ) ) {
dev = DeviceInst.JoystickListRef.Find_jsN( JoystickCls.JSNum( ActionTreeNode.CommandFromNodeText( nodeText ) ) );
if ( dev != null ) {
// find the tuning item of the action
@ -1324,7 +1324,7 @@ namespace SCJMapper_V2
find = ActionTreeNode.ComposeNodeText( action, "xi" );
nodeText = m_AT.FindText( actionmap, find );
if ( !string.IsNullOrWhiteSpace( nodeText ) ) {
if ( !ActionCls.IsBlendedInput( ActionTreeNode.CommandFromNodeText( nodeText ) ) ) {
if ( !Act.IsDisabledInput( ActionTreeNode.CommandFromNodeText( nodeText ) ) ) {
dev = DeviceInst.GamepadRef;
if ( dev != null ) {
// find the tuning item of the action
@ -1537,7 +1537,7 @@ namespace SCJMapper_V2
{
AutoTabXML_Assignment( EATabXML.Tab_Assignment );
string devInput = ActionCls.DevInput( lblLastJ.Text, InputMode );
string devInput = Act.DevInput( lblLastJ.Text, InputMode );
RTF.RTFformatter RTF = new RTF.RTFformatter( );
m_AT.FindAllActionsRTF( devInput, RTF );
// have to check if throttle is used and if - add those to the list
@ -1639,7 +1639,7 @@ namespace SCJMapper_V2
// only if needed
if ( ( FTAB != null ) && FTAB.Visible ) {
FTAB.SuspendDGV( );
m_AT.ActionMaps.toDataSet( FTAB.DS_AMaps );
m_AT.ActionMaps.ToDataSet( FTAB.DS_AMaps );
FTAB.ResumeDGV( );
FTAB.Populate( );
}
@ -1651,7 +1651,7 @@ namespace SCJMapper_V2
// only if needed
if ( ( FTAB != null ) && FTAB.Visible ) {
string actionID = m_AT.SelectedActionID;
m_AT.ActionMaps.updateDataSet( FTAB.DS_AMaps, actionID );
m_AT.ActionMaps.UpdateDataSet( FTAB.DS_AMaps, actionID );
// FTAB.UpdateRow( actionID ); seems not needed...
}
}

@ -1,10 +0,0 @@
spaceship_general;Kv_toggle_cabin_lights;Kv_toggle_running_lights;Kv_power_cycle_preset_fwd;Kv_power_cycle_preset_back;Xv_eject;;;;;;;;;;;;;;;;;;;;;;;
spaceship_view;Jv_view_yaw_left;Jv_view_yaw_right;Jv_view_yaw;Jv_view_yaw_1p;Kv_view_yaw_absolute;Jv_view_pitch_up;Jv_view_pitch_down;Jv_view_pitch;Jv_view_pitch_1p;Kv_view_pitch_absolute;Kv_view_roll_absolute;Jv_view_cycle_fwd;Kv_view_cycle_internal_fwd;Xv_view_option;Xv_view_mode;Jv_view_zoom_in;Jv_view_zoom_out;Kv_view_dynamic_focus_in;Kv_view_dynamic_focus_out;Jv_view_dynamic_focus_toggle;Kv_view_track_target;;;;;;;
spaceship_movement;Jv_pitch;Jv_yaw_left;Jv_yaw_right;Jv_yaw;Kv_roll_left;Kv_roll_right;Jv_roll;Jv_throttle;Kv_throttle_toggle_minmax;Xv_throttle_zero;Xv_throttle_up;Xv_throttle_down;Xv_brake;Jv_target_match_vel;Xv_ifcs_toggle_vector_decoupling;Kv_strafe_up;Kv_strafe_down;Kv_strafe_left;Kv_strafe_right;Xv_strafe_forward;Xv_strafe_back;Xv_strafe_horizontal;Xv_strafe_vertical;Jv_newtonian_yaw;Jv_newtonian_pitch;Xv_newtonian_brake;Xv_ifcs_toggle_safety;Jv_afterburner
spaceship_targeting;Jv_target_cycle_all_fwd;Jv_target_cycle_all_back;Kv_target_cycle_friendly_fwd;Kv_target_cycle_friendly_back;Xv_target_toggle_pinned_focused;Jv_target_missile_lock_focused;Jv_target_cycle_hostile_fwd;Kv_target_cycle_hostile_back;Jv_target_nearest_hostile;Kv_target_nearest_landzone;Kv_target_pin_reticule;Kv_target_cycle_subsystem_fwd;Kv_target_cycle_subsystem_back;;;;;;;;;;;;;;;
spaceship_weapons;Jv_attack1_group1;Jv_attack1_group2;Jv_attack1_group3;Jv_attack1_group4;;;;;;;;;;;;;;;;;;;;;;;;
spaceship_missiles;Jv_weapon_cycle_missile_fwd;Kv_weapon_cycle_missile_back;Xv_weapon_toggle_arm_missile;Jv_weapon_launch_missile;;;;;;;;;;;;;;;;;;;;;;;;
spaceship_defensive;Jv_weapon_launch_countermeasure;Jv_weapon_cycle_countermeasure_fwd;Kv_shield_raise_level_forward;Kv_shield_raise_level_back;Kv_shield_raise_level_left;Kv_shield_raise_level_right;Kv_shield_reset_level;Kv_shield_power_up;Kv_shield_power_down;Jv_shield_boost_recharge;Jv_shield_cycle_presets_fwd;Jv_shield_cycle_presets_back;;;;;;;;;;;;;;;;
spaceship_auto_weapons;Kv_weapon_toggle_ai;;;;;;;;;;;;;;;;;;;;;;;;;;;
spaceship_radar;Kv_radar_cycle_zoom_fwd;Kv_radar_cycle_focus_fwd;Kv_radar_cycle_focus_back;;;;;;;;;;;;;;;;;;;;;;;;;
spaceship_hud;Kv_hud_cycle_mode_fwd;Kv_hud_cycle_mode_back;Kv_comm_open_chat;Kv_comm_show_chat;Kv_comm_open_precanned;;;;;;;;;;;;;;;;;;;;;;;
1 spaceship_general Kv_toggle_cabin_lights Kv_toggle_running_lights Kv_power_cycle_preset_fwd Kv_power_cycle_preset_back Xv_eject
2 spaceship_view Jv_view_yaw_left Jv_view_yaw_right Jv_view_yaw Jv_view_yaw_1p Kv_view_yaw_absolute Jv_view_pitch_up Jv_view_pitch_down Jv_view_pitch Jv_view_pitch_1p Kv_view_pitch_absolute Kv_view_roll_absolute Jv_view_cycle_fwd Kv_view_cycle_internal_fwd Xv_view_option Xv_view_mode Jv_view_zoom_in Jv_view_zoom_out Kv_view_dynamic_focus_in Kv_view_dynamic_focus_out Jv_view_dynamic_focus_toggle Kv_view_track_target
3 spaceship_movement Jv_pitch Jv_yaw_left Jv_yaw_right Jv_yaw Kv_roll_left Kv_roll_right Jv_roll Jv_throttle Kv_throttle_toggle_minmax Xv_throttle_zero Xv_throttle_up Xv_throttle_down Xv_brake Jv_target_match_vel Xv_ifcs_toggle_vector_decoupling Kv_strafe_up Kv_strafe_down Kv_strafe_left Kv_strafe_right Xv_strafe_forward Xv_strafe_back Xv_strafe_horizontal Xv_strafe_vertical Jv_newtonian_yaw Jv_newtonian_pitch Xv_newtonian_brake Xv_ifcs_toggle_safety Jv_afterburner
4 spaceship_targeting Jv_target_cycle_all_fwd Jv_target_cycle_all_back Kv_target_cycle_friendly_fwd Kv_target_cycle_friendly_back Xv_target_toggle_pinned_focused Jv_target_missile_lock_focused Jv_target_cycle_hostile_fwd Kv_target_cycle_hostile_back Jv_target_nearest_hostile Kv_target_nearest_landzone Kv_target_pin_reticule Kv_target_cycle_subsystem_fwd Kv_target_cycle_subsystem_back
5 spaceship_weapons Jv_attack1_group1 Jv_attack1_group2 Jv_attack1_group3 Jv_attack1_group4
6 spaceship_missiles Jv_weapon_cycle_missile_fwd Kv_weapon_cycle_missile_back Xv_weapon_toggle_arm_missile Jv_weapon_launch_missile
7 spaceship_defensive Jv_weapon_launch_countermeasure Jv_weapon_cycle_countermeasure_fwd Kv_shield_raise_level_forward Kv_shield_raise_level_back Kv_shield_raise_level_left Kv_shield_raise_level_right Kv_shield_reset_level Kv_shield_power_up Kv_shield_power_down Jv_shield_boost_recharge Jv_shield_cycle_presets_fwd Jv_shield_cycle_presets_back
8 spaceship_auto_weapons Kv_weapon_toggle_ai
9 spaceship_radar Kv_radar_cycle_zoom_fwd Kv_radar_cycle_focus_fwd Kv_radar_cycle_focus_back
10 spaceship_hud Kv_hud_cycle_mode_fwd Kv_hud_cycle_mode_back Kv_comm_open_chat Kv_comm_show_chat Kv_comm_open_precanned

Binary file not shown.

@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion( "2.33.0.67" )]
[assembly: AssemblyFileVersion( "2.33.0.67" )]
[assembly: AssemblyVersion( "2.34.0.68" )]
[assembly: AssemblyFileVersion( "2.34.0.68" )]

@ -1,10 +1,10 @@
SC Joystick Mapper V 2.33 - Build 67 BETA
(c) Cassini, StandardToaster - 23-Dec-2017
SC Joystick Mapper V 2.34 - Build 68 BETA
(c) Cassini, StandardToaster - 26-Dec-2017
Contains 12 files + graphics:
SCJMapper.exe The program (V2.33)
SCJMapper.exe.config Program config (V2.33) - MUST be in the same folder as the Exe file
SCJMapper.exe The program (V2.34)
SCJMapper.exe.config Program config (V2.34) - MUST be in the same folder as the Exe file
SharpDX.DirectInput.dll Managed DirectInput Assembly - MUST be in the same folder as the Exe file
SharpDX.dll Managed DirectX Assembly - MUST be in the same folder as the Exe file
OpenTK.dll Managed OpenGL Assembly - MUST be in the same folder as the Exe file
@ -20,7 +20,7 @@ ReadMe.txt This file
graphics folder Skybox Images (V2.32) - graphics folder MUST be in the same folder as the Exe file
NOTE V 2.33:
NOTE V 2.34:
search order for defaultProfile.xml to build the action tree is:
1. directory where SCJMapper Exe is located
2. directory of <SC>\LIVE\USER
@ -40,6 +40,8 @@ Scanned for viruses before packing...
cassini@burri-web.org
Changelog:
V 2.34 - BETA Build 68
- improvement - complete rework of XML defaultProfile/mapping parsing
V 2.33 - BETA Build 67
- update for SC 3.0.0 Alpha public
- fix - finding SC game folder - may work automatically for 3.0 Alpha else define it in Settings

@ -5,6 +5,12 @@ using System.Xml;
using System.IO;
using SCJMapper_V2.Actions;
using System.Xml.Linq;
using System.Linq;
using SCJMapper_V2.Devices.Joystick;
using SCJMapper_V2.Devices.Keyboard;
using SCJMapper_V2.Devices.Mouse;
using SCJMapper_V2.Devices.Gamepad;
namespace SCJMapper_V2.SC
{
@ -19,40 +25,30 @@ namespace SCJMapper_V2.SC
public bool ValidContent { get; set; }
private Stack<string> m_nodeNameStack = null; // element name stack - keeping track where we are
// state for the parser
enum EState
{
idle = 0,
inActionMap,
}
private EState m_state = EState.idle;
// an action map and its actions
class ProfileAction
{
public string name { get; set; } // the action name
public string devID { get; set; } // the input method K,J,X,P
public string Name { get; set; } // the action name
public string DevID { get; set; } // the input method K,J,X,P
private string m_defBinding = ""; // NOTE: this is AC1 style in the Profile - need to conver later when dumping out
public string defBinding { get { return m_defBinding; } set { m_defBinding = value; } } // DONT! need to clean this one, found spaces...
public string DefBinding { get { return m_defBinding; } set { m_defBinding = value; } } // DONT! need to clean this one, found spaces...
private ActivationMode m_defActivationMode = ActivationMode.Default;
public ActivationMode defActivationMode { get { return m_defActivationMode; } set { m_defActivationMode = value; } }
public ActivationMode DefActivationMode { get { return m_defActivationMode; } set { m_defActivationMode = value; } }
public string keyName
{ get { return devID + name; } } // prep for TreView usage - create a key from input+name
public string KeyName
{ get { return DevID + Name; } } // prep for TreView usage - create a key from input+name
}
class ActionMap : List<ProfileAction> // carries the action list
{
public string name { get; set; } // the map name
public string Name { get; set; } // the map name
static int ContainsLoop( List<ProfileAction> list, string value )
{
for ( int i = 0; i < list.Count; i++ ) {
if ( list[i].keyName == value ) {
if ( list[i].KeyName == value ) {
return i;
}
}
@ -61,12 +57,12 @@ namespace SCJMapper_V2.SC
public new int IndexOf( ProfileAction pact )
{
return ContainsLoop( this, pact.keyName );
return ContainsLoop( this, pact.KeyName );
}
public new bool Contains( ProfileAction pact )
{
return ( ContainsLoop( this, pact.keyName ) >= 0 );
return ( ContainsLoop( this, pact.KeyName ) >= 0 );
}
public new void Add( ProfileAction pact )
@ -78,6 +74,8 @@ namespace SCJMapper_V2.SC
base.Add( pact );
}
};
Dictionary<string, ActionMap> m_aMap = null; // key would be the actionmap name
ActionMap m_currentMap = null;
@ -105,9 +103,9 @@ namespace SCJMapper_V2.SC
string buf = "";
foreach ( ActionMap am in m_aMap.Values ) {
buf += am.name + ";";
buf += am.Name + ";";
foreach ( ProfileAction a in am ) {
buf += a.keyName + ";" + a.defBinding + ";" + a.defActivationMode.Name + ";" + a.defActivationMode.MultiTap.ToString( ) + ";"; // add default binding + activation mode to the CSV
buf += a.KeyName + ";" + a.DefBinding + ";" + a.DefActivationMode.Name + ";" + a.DefActivationMode.MultiTap.ToString( ) + ";"; // add default binding + activation mode to the CSV
}
buf += string.Format( "\n" );
}
@ -116,413 +114,233 @@ namespace SCJMapper_V2.SC
}
/// <summary>
/// Assumes to be in an action element
/// retrieves the attributes and collects the various control=binding pairs
/// </summary>
/// <param name="xr">An XML reader @ StartElement</param>
private void CollectActions( Dictionary<string, string> attr )
// INPUT processing of the xml nodes
private void ActModeInput( ref ProfileAction pa, XElement xml )
{
//first find an ActivationMode if there is - applies to all actions
string actModeName = ActivationMode.Default.Name;
string multiTap = "0";
// this can be an Activation Mode OR a multitap
// if there is an activationMode the multiTap remains 0
// if no ActivationMode is given, multitap is 1 or may be 2...
if ( attr.ContainsKey( "ActivationMode" ) ) {
actModeName = attr["ActivationMode"];
multiTap = ActivationModes.Instance.MultiTapFor( actModeName ).ToString( ); // given by the already collected items
string actModeName = (string)xml.Attribute( "ActivationMode" );
string multiTap = (string)xml.Attribute( "multiTap" );
if ( string.IsNullOrEmpty( actModeName ) ) {
actModeName = pa.DefActivationMode.Name; // from store
}
else {
// name remains default - we handle multiTaps only here
multiTap = "1"; // default if not changed in the action to may be 2 or so..
if ( attr.ContainsKey( "multiTap" ) ) {
multiTap = attr["multiTap"];
}
}
ActivationMode actMode = new ActivationMode( actModeName, int.Parse( multiTap ) ); // should be a valid ActivationMode for this action
// we collect actions for each input ie for K,J,X and M
if ( attr.ContainsKey( "joystick" ) ) {
ProfileAction ac = new ProfileAction( );
ac.name = attr["name"];
ac.devID = "J";
ac.defBinding = attr["joystick"];
ac.defActivationMode = actMode;
if ( ac.defBinding == " " ) {
ac.defBinding = Devices.Joystick.JoystickCls.BlendedInput;
m_currentMap.Add( ac ); // finally add it to the current map if it was bound
}
else if ( !string.IsNullOrEmpty( ac.defBinding ) ) {
ac.defBinding = "js1_" + ac.defBinding;
m_currentMap.Add( ac ); // finally add it to the current map if it was bound
}
if ( string.IsNullOrEmpty( multiTap ) ) {
multiTap = ActivationModes.Instance.MultiTapFor( actModeName ).ToString( ); // given by the already collected items
}
pa.DefActivationMode = new ActivationMode( actModeName, int.Parse( multiTap ) ); // renew
}
if ( attr.ContainsKey( "keyboard" ) ) {
ProfileAction ac = new ProfileAction( );
ac.name = attr["name"];
ac.devID = "K";
ac.defBinding = attr["keyboard"];
ac.defActivationMode = actMode;
if ( ac.defBinding == " " ) {
ac.defBinding = Devices.Keyboard.KeyboardCls.BlendedInput;
m_currentMap.Add( ac ); // finally add it to the current map if it was bound
}
else if ( !string.IsNullOrEmpty( ac.defBinding ) ) {
ac.defBinding = "kb1_" + ac.defBinding;
m_currentMap.Add( ac ); // finally add it to the current map if it was bound
}
private void JInput( ref ProfileAction pa, XElement xml, string input )
{
ActModeInput( ref pa, xml );
if ( !string.IsNullOrEmpty( input ) ) {
pa.DefBinding = input;
if ( pa.DefBinding == " " )
pa.DefBinding = JoystickCls.DisabledInput;
else if ( !string.IsNullOrEmpty( pa.DefBinding ) )
pa.DefBinding = "js1_" + pa.DefBinding; // extend with device for mapping use
}
}
if ( attr.ContainsKey( "mouse" ) ) { // 20151220BM: add mouse device (from AC 2.0 defaultProfile usage)
ProfileAction ac = new ProfileAction( );
ac.name = attr["name"];
ac.devID = "M";
ac.defBinding = attr["mouse"];
ac.defActivationMode = actMode;
if ( ac.defBinding == " " ) {
ac.defBinding = Devices.Mouse.MouseCls.BlendedInput;
m_currentMap.Add( ac ); // finally add it to the current map if it was bound
}
else if ( !string.IsNullOrEmpty( ac.defBinding ) ) {
ac.defBinding = "mo1_" + ac.defBinding;
m_currentMap.Add( ac ); // finally add it to the current map if it was bound
}
private void KInput( ref ProfileAction pa, XElement xml, string input )
{
ActModeInput( ref pa, xml );
if ( !string.IsNullOrEmpty( input ) ) {
pa.DefBinding = input;
if ( pa.DefBinding == " " )
pa.DefBinding = KeyboardCls.DisabledInput;
else if ( !string.IsNullOrEmpty( pa.DefBinding ) )
pa.DefBinding = "kb1_" + pa.DefBinding; // extend with device for mapping use
}
}
if ( attr.ContainsKey( "xboxpad" ) ) {
ProfileAction ac = new ProfileAction( );
ac.name = attr["name"];
ac.devID = "X";
ac.defBinding = attr["xboxpad"];
ac.defActivationMode = actMode;
if ( ac.defBinding == " " ) {
ac.defBinding = Devices.Gamepad.GamepadCls.BlendedInput;
m_currentMap.Add( ac ); // finally add it to the current map if it was bound
}
else if ( !string.IsNullOrEmpty( ac.defBinding ) ) {
ac.defBinding = "xi1_" + ac.defBinding;
m_currentMap.Add( ac ); // finally add it to the current map if it was bound
}
}
if ( attr.ContainsKey( "ps3pad" ) ) {
// ignore
private void MInput( ref ProfileAction pa, XElement xml, string input )
{
ActModeInput( ref pa, xml );
if ( !string.IsNullOrEmpty( input ) ) {
pa.DefBinding = input;
if ( pa.DefBinding == " " )
pa.DefBinding = MouseCls.DisabledInput;
else if ( !string.IsNullOrEmpty( pa.DefBinding ) )
pa.DefBinding = "mo1_" + pa.DefBinding; // extend with device for mapping use
}
}
/// <summary>
/// Read one 'empty' XML element
///
/// <name [attr="" ..] />
///
/// </summary>
/// <param name="xr">An XML reader @ StartElement</param>
/// <returns>True if reading can continue</returns>
private bool ReadEmptyElement( XmlReader xr )
private void XInput( ref ProfileAction pa, XElement xml, string input )
{
Dictionary<string, string> attr = new Dictionary<string, string>( );
string eName = xr.Name;
switch ( xr.NodeType ) {
case XmlNodeType.Element:
//Console.Write( "<{0}", xr.Name );
while ( xr.MoveToNextAttribute( ) ) {
attr.Add( xr.Name, xr.Value ); // save the attributes
//Console.Write( " {0}='{1}'", xr.Name, xr.Value );
}
if ( m_state == EState.inActionMap ) {
// processing a valid action map - collect actions
if ( eName.ToLower( ) == "action" ) {
// this is an action.. - collect it
CollectActions( attr );
}
}// if inmap
//Console.Write( ">\n" );
break;
case XmlNodeType.Text:
//Console.Write( xr.Value );
break;
case XmlNodeType.EndElement:
//Console.Write( "</{0}>\n", xr.Name );
break;
ActModeInput( ref pa, xml );
if ( !string.IsNullOrEmpty( input ) ) {
pa.DefBinding = input;
if ( pa.DefBinding == " " )
pa.DefBinding = GamepadCls.DisabledInput;
else if ( !string.IsNullOrEmpty( pa.DefBinding ) )
pa.DefBinding = "xi1_" + pa.DefBinding; // extend with device for mapping use
}
return true;
}
/// <summary>
/// Reads an action sub element
/// Read all from an Action XElement
/// </summary>
/// <param name="xr">An XML reader @ StartElement</param>
private void ReadActionSub( XmlReader xr, string actionName, string device )
/// <param name="action">The action XElement</param>
/// <returns>True if successfull</returns>
private bool ReadAction( XElement action )
{
/* A variety exists here...
<action name="v_eject_cinematic" onPress="0" onHold="1" onRelease="1" keyboard="ralt+l" xboxpad="shoulderl+shoulderr+y" joystick=" " />
<action name="v_exit" onPress="1" onHold="0" onRelease="1" multiTap="1" multiTapBlock="1" pressTriggerThreshold="1.0" releaseTriggerThreshold="-1" releaseTriggerDelay="0" keyboard="f" xboxpad="y" UILabel="@ui_CIExit" UIDescription="@ui_CIExitDesc" >
<joystick ActivationMode="press" input=" " />
</action>
<action name="v_throttle_100" onPress="1" xboxpad=" " joystick=" " UILabel="@ui_CIThrottleMax" UIDescription="@ui_CIThrottleMaxDesc" >
<xboxpad multiTap="2" input="thumbl_up" />
<keyboard multiTap="2" input=" " />
</action>
<action name="v_target_deselect_component" ActivationMode="delayed_press" pressTriggerThreshold="0.75" joystick="" >
<keyboard >
<inputdata input="lbracket" />
<inputdata input="rbracket" />
</keyboard>
</action>
*/
log.Debug( "DProfileReader.ReadAction - Entry" );
// a complete actionmap arrives here
bool retVal = true;
/*
<action name = "v_throttle_100" onPress = "1" xboxpad = " " joystick = " " UILabel = "@ui_CIThrottleMax" UIDescription = "@ui_CIThrottleMaxDesc" >
<keyboard multiTap = "2" input = "w" />
</action >
or
<action name="v_brake" onPress="1" onHold="1" onRelease="1" keyboard="space" xboxpad="xi_shoulderl+xi_shoulderr">
<joystick input="js2_button7" />
<joystick input="js2_button8" />
</action>
or
<action name="v_hud_confirm" onPress="1" onRelease="1" xboxpad="xi_triggerL_btn+xi_a" joystick="js1_button19">
<keyboard>
<inputdata input="enter"/>
</keyboard>
</action>
or
<action name="ui_up" onPress="1" onHold="1" holdTriggerDelay="0.15" holdRepeatDelay="0.15" >
<keyboard>
<inputdata input="up" />
</keyboard>
<xboxpad>
<inputdata input="dpad_up" />
<inputdata input="thumbly" useAnalogCompare="1" analogCompareVal="0.5" analogCompareOp="GREATERTHAN" />
<inputdata input="thumbry" useAnalogCompare="1" analogCompareVal="0.5" analogCompareOp="GREATERTHAN" />
</xboxpad>
</action>
*/
bool done = false;
do {
xr.Read( ); // get next element
Dictionary<string, string> attr = new Dictionary<string, string>( );
// add what is not contained in the structure we are about to parse
attr.Add( "name", actionName ); // actionName is in the outer element
string eName = xr.Name; // this is either the device or inputdata if there are multiple entries
// read attributes if any
while ( xr.MoveToNextAttribute( ) ) {
attr.Add( xr.Name, xr.Value ); // save the attributes
//Console.Write( " {0}='{1}'", xr.Name, xr.Value );
}
xr.MoveToElement( ); // backup
// Have to add the device, otherwise the following does not work..
if ( attr.ContainsKey( "input" ) ) {
if ( !string.IsNullOrEmpty( device ) ) {
// device is given i.e. enclosing the input statements
// 20170512 - some keyboard entries are listed with mouse input ... ?!?
// we substitute and add such mouse entries - don't know what the game does later...
string ip = attr["input"];
if ( !string.IsNullOrEmpty( ip ) ) {
if ( ip.StartsWith( "mouse" ) ) {
attr.Add( "mouse", attr["input"] ); // override the device given
}
else {
attr.Add( device, attr["input"] ); // if the device is given, use it
string name = (string)action.Attribute( "name" );
// prep all kinds
var jAC = new ProfileAction( ) { Name = name, DevID = Act.DevTag( JoystickCls.DeviceClass ) };
var kAC = new ProfileAction( ) { Name = name, DevID = Act.DevTag( KeyboardCls.DeviceClass ) };
var mAC = new ProfileAction( ) { Name = name, DevID = Act.DevTag( MouseCls.DeviceClass ) };
var xAC = new ProfileAction( ) { Name = name, DevID = Act.DevTag( GamepadCls.DeviceClass ) };
// process element items
JInput( ref jAC, action, (string)action.Attribute( JoystickCls.DeviceClass ) );
KInput( ref kAC, action, (string)action.Attribute( KeyboardCls.DeviceClass ) );
MInput( ref mAC, action, (string)action.Attribute( MouseCls.DeviceClass ) );
XInput( ref xAC, action, (string)action.Attribute( GamepadCls.DeviceClass ) );
// then nested ones - they may or may not exist from the initial scan
foreach ( XElement l1action in action.Elements( ) ) {
// comes with the name of the device class
switch ( l1action.Name.LocalName ) {
case JoystickCls.DeviceClass: {
JInput( ref jAC, l1action, (string)l1action.Attribute( "input" ) ); // may have attributed ones
foreach ( XElement l2action in l1action.Elements( ) ) {
if ( l2action.Name.LocalName == "inputdata" ) {
JInput( ref jAC, l2action, (string)l2action.Attribute( "input" ) ); // or in the inputdata nesting
}
}
}
}
else {
string ip = attr["input"];
if ( !string.IsNullOrEmpty( ip ) ) {
attr.Add( eName, ip ); // else it should be the eName element
}
}
}
// the element name is a control
if ( xr.NodeType == XmlNodeType.EndElement ) {
done = ( xr.Name == m_nodeNameStack.Peek( ) ); // EXIT if the end element matches the entry
}
else if ( xr.IsEmptyElement ) {
// an attribute only element
CollectActions( attr );
}
else {
// one with subelements again
m_nodeNameStack.Push( xr.Name ); // recursive .. push element name to terminate later (this is i.e. keyboard)
ReadActionSub( xr, actionName, xr.Name );
}
} while ( !done );
break;
m_nodeNameStack.Pop( ); // action is finished
}
/// <summary>
/// Read one XML element
///
/// <name attr="">
/// [ Xelement ]
/// </name>
///
/// </summary>
/// <param name="xr">An XML reader @ StartElement</param>
/// <returns>True if reading can continue</returns>
private bool ReadElement( XmlReader xr )
{
Dictionary<string, string> attr = new Dictionary<string, string>( );
string eName = xr.Name;
switch ( xr.NodeType ) {
case XmlNodeType.Element:
//Console.Write( "<{0}", xr.Name );
while ( xr.MoveToNextAttribute( ) ) {
attr.Add( xr.Name, xr.Value ); // save the attributes
//Console.Write( " {0}='{1}'", xr.Name, xr.Value );
}
// now here we could have an actionmap start
if ( m_state == EState.idle ) {
if ( m_nodeNameStack.Peek( ).ToLower( ) == "actionmap" ) {
// check for a valid one
string mapName = attr["name"];
string item = Array.Find( ActionMapsCls.ActionMaps, delegate ( string sstr ) { return sstr == mapName; } );
if ( !string.IsNullOrEmpty( item ) ) {
// finally.... it is a valid actionmap
m_currentMap = new ActionMap( );
m_currentMap.name = mapName;
if ( !m_aMap.ContainsKey( mapName ) ) { //20170325 - fix multiple map names - don't add the second, third etc. (CIG bug..)
m_aMap.Add( mapName, m_currentMap ); // add to our inventory
case KeyboardCls.DeviceClass: {
KInput( ref kAC, l1action, (string)l1action.Attribute( "input" ) ); // may have attributed ones
foreach ( XElement l2action in l1action.Elements( ) ) {
if ( l2action.Name.LocalName == "inputdata" ) {
KInput( ref kAC, l2action, (string)l2action.Attribute( "input" ) ); // or in the inputdata nesting
}
else {
log.DebugFormat( "ReadElement: IGNORED duplicate map with name: {0}", mapName );
}
}
break;
case MouseCls.DeviceClass: {
MInput( ref mAC, l1action, (string)l1action.Attribute( "input" ) ); // may have attributed ones
foreach ( XElement l2action in l1action.Elements( ) ) {
if ( l2action.Name.LocalName == "inputdata" ) {
MInput( ref mAC, l2action, (string)l2action.Attribute( "input" ) ); // or in the inputdata nesting
}
m_state = EState.inActionMap; // now we are in and processing the map
}
}
}
else if ( m_state == EState.inActionMap ) {
// processing a valid action map - collect actions
if ( eName.ToLower( ) == "action" ) {
// this is an action.. - collect it
CollectActions( attr );
ReadActionSub( xr, attr["name"], "" ); // a non empty action element may have a sub element (but no device yet)
break;
case GamepadCls.DeviceClass: {
XInput( ref xAC, l1action, (string)l1action.Attribute( "input" ) ); // may have attributed ones
foreach ( XElement l2action in l1action.Elements( ) ) {
if ( l2action.Name.LocalName == "inputdata" ) {
XInput( ref xAC, l2action, (string)l2action.Attribute( "input" ) ); // or in the inputdata nesting
}
}
}
}
//Console.Write( ">\n" );
break;
case XmlNodeType.Text:
//Console.Write( xr.Value );
break;
case XmlNodeType.EndElement:
//Console.Write( "</{0}>\n", xr.Name );
break;
break;
default: break;
}
}
return true;
if ( !string.IsNullOrEmpty( jAC.DefBinding ) ) m_currentMap.Add( jAC ); // finally add it to the current map if it was bound
if ( !string.IsNullOrEmpty( kAC.DefBinding ) ) m_currentMap.Add( kAC ); // finally add it to the current map if it was bound
if ( !string.IsNullOrEmpty( mAC.DefBinding ) ) m_currentMap.Add( mAC ); // finally add it to the current map if it was bound
if ( !string.IsNullOrEmpty( xAC.DefBinding ) ) m_currentMap.Add( xAC ); // finally add it to the current map if it was bound
return retVal;
}
/// <summary>
/// Read the xml part
/// Read all from an Actionmap XElement
/// </summary>
/// <param name="xr"></param>
/// <returns></returns>
private bool ReadXML( XmlReader xr )
/// <param name="actionmap">The Actionmap XElement</param>
/// <returns>True if successfull</returns>
private bool ReadActionmap( XElement actionmap )
{
log.Debug( "DProfileReader.ReadXML - Entry" );
log.Debug( "DProfileReader.ReadActionmap - Entry" );
// a complete actionmap arrives here
bool retVal = true;
try {
do {
if ( xr.IsStartElement( ) ) {
m_nodeNameStack.Push( xr.Name );
if ( xr.IsEmptyElement ) {
retVal = retVal && ReadEmptyElement( xr );
m_nodeNameStack.Pop( ); // empty ones end inline
}
else {
retVal = retVal && ReadElement( xr );
}
// check for a valid one
string mapName = (string)actionmap.Attribute( "name" ); // mandatory
string item = Array.Find( ActionMapsCls.ActionMaps, delegate ( string sstr ) { return sstr == mapName; } );
if ( !string.IsNullOrEmpty( item ) ) {
// finally.... it is a valid actionmap
m_currentMap = new ActionMap( );
m_currentMap.Name = mapName;
if ( !m_aMap.ContainsKey( mapName ) ) { //20170325 - fix multiple map names - don't add the second, third etc. (CIG bug..)
m_aMap.Add( mapName, m_currentMap ); // add to our inventory
IEnumerable<XElement> actions = from x in actionmap.Elements( )
where ( x.Name == "action" )
select x;
foreach ( XElement action in actions ) {
// one action
retVal &= ReadAction( action );
}
else if ( xr.NodeType == XmlNodeType.EndElement ) {
//Console.Write( "</{0}>\n", xr.Name );
string exitElement = m_nodeNameStack.Pop( );
if ( m_state == EState.inActionMap )
if ( exitElement.ToLower( ) == "actionmap" ) m_state = EState.idle; // finished
}
} while ( xr.Read( ) );
if ( m_nodeNameStack.Count == 0 )
return retVal && true;
else
return false;
}
catch ( Exception ex ) {
// get any exceptions from reading
log.Error( "DProfileReader.ReadXML - unexpected", ex );
return false;
}
}
/*
//<ActivationModes >
// <ActivationMode name="tap" onPress="0" onHold="0" onRelease="1" multiTap="1" multiTapBlock="1" pressTriggerThreshold="-1" releaseTriggerThreshold="0.25" releaseTriggerDelay="0" />
...
//</ActivationModes>
*/
private bool ReadActivationModes( XmlReader xr )
{
log.Debug( "DProfileReader.ReadActivationModes - Entry" );
try {
xr.ReadToFollowing( "ActivationModes" );
xr.ReadToDescendant( "ActivationMode" );
do {
if ( xr.NodeType == XmlNodeType.EndElement ) {
xr.Read( );
break; // finished
}
string name = xr["name"];
string mTap = xr["multiTap"];
if ( !string.IsNullOrEmpty( name ) ) ActivationModes.Instance.Add( new ActivationMode( name, int.Parse( mTap ) ) );
} while ( xr.Read( ) );
}
else {
log.DebugFormat( "ReadActionmap: IGNORED duplicate map with name: {0}", mapName );
}
return true;
}
catch ( Exception ex ) {
// get any exceptions from reading
log.Error( "DProfileReader.ReadXML - unexpected", ex );
return false;
}
return retVal;
}
// Read modifiers
//<modifiers>
// <mod input = "xi_shoulderl" />
// <mod input ="xi_triggerl_btn" />
// <mod input = "xi_dpad_down" />
// <mod input ="xi_y" />
// <mod input = "kb_z" />
// <mod input ="kb_f3" />
// <mod input = "kb_lalt" />
// <mod input = "kb_lalt" />
// <mod input = "kb_f4" />
// <mod input = "kb_mouse2" />
// <mod input = "xi_dpad_down" />
// <mod input = "xi_shoulderl" />
// <mod input = "xi_triggerl_btn" />
//</ modifiers >
private bool ReadModifiers( XmlReader xr )
/// <summary>
/// Read all from ActivationMode XElement
/// </summary>
/// <param name="actmodes">The Activatiomodes XElement</param>
/// <returns>True if successfull</returns>
private bool ReadActivationModes( XElement actmodes )
{
log.Debug( "DProfileReader.ReadModifiers - Entry" );
/*
//<ActivationModes >
// <ActivationMode name="tap" onPress="0" onHold="0" onRelease="1" multiTap="1" multiTapBlock="1" pressTriggerThreshold="-1" releaseTriggerThreshold="0.25" releaseTriggerDelay="0" />
...
//</ActivationModes>
*/
log.Debug( "DProfileReader.ReadActivationModes - Entry" );
try {
xr.ReadToFollowing( "modifiers" );
return Modifiers.Instance.FromXML( xr.ReadOuterXml(), true );
}
catch ( Exception ex ) {
// get any exceptions from reading
log.Error( "DProfileReader.ReadXML - unexpected", ex );
return false;
IEnumerable<XElement> activationmodes = from x in actmodes.Elements( )
where ( x.Name == "ActivationMode" )
select x;
foreach ( XElement activationmode in activationmodes ) {
string name = (string)activationmode.Attribute( "name" );
string mTap = (string)activationmode.Attribute( "multiTap" );
if ( !string.IsNullOrEmpty( name ) ) ActivationModes.Instance.Add( new ActivationMode( name, int.Parse( mTap ) ) );
}
return true;
}
/// <summary>
/// Read the defaultProfile.xml - do some sanity check
/// </summary>
@ -532,32 +350,52 @@ namespace SCJMapper_V2.SC
{
log.Debug( "DProfileReader.fromXML - Entry" );
if ( ActionMapsCls.ActionMaps.Length == 0 ) ActionMapsCls.LoadSupportedActionMaps( ActionMapList( xml ) ); // make sure we have them loaded ( refactoring to get a singleton or so...)
// make sure we have them loaded ( refactoring to get a singleton or so...)
if ( ActionMapsCls.ActionMaps.Length == 0 ) ActionMapsCls.LoadSupportedActionMaps( ActionMapList( xml ) );
XmlReaderSettings settings = new XmlReaderSettings( );
settings.ConformanceLevel = ConformanceLevel.Fragment;
settings.IgnoreWhitespace = true;
settings.IgnoreComments = true;
XmlReader reader = XmlReader.Create( new StringReader( xml ), settings );
// read the content of the xml
XmlReaderSettings settings = new XmlReaderSettings {
ConformanceLevel = ConformanceLevel.Fragment,
IgnoreWhitespace = true,
IgnoreComments = true
};
using ( XmlReader reader = XmlReader.Create( new StringReader( xml ), settings ) ) {
m_aMap = new Dictionary<string, ActionMap>( );
// init the activation modes singleton
ActivationModes.Instance.Clear( );
ActivationModes.Instance.Add( ActivationMode.Default );
m_nodeNameStack = new Stack<string>( );
m_aMap = new Dictionary<string, ActionMap>( );
// init the activation modes singleton
ActivationModes.Instance.Clear( );
ActivationModes.Instance.Add( ActivationMode.Default );
ValidContent = true; // init
ValidContent = true; // init
reader.Read( );
ValidContent &= ReadActivationModes( reader );
reader.MoveToContent( );
if ( XNode.ReadFrom( reader ) is XElement el ) {
IEnumerable<XElement> activationModes = from x in el.Elements( )
where ( x.Name == "ActivationModes" )
select x;
foreach ( XElement activationMode in activationModes ) {
ValidContent &= ReadActivationModes( activationMode );
}
Modifiers.Instance.Clear( );
ValidContent &= ReadModifiers( reader );
m_nodeNameStack.Push( "profile" ); // we are already in the XML now
Modifiers.Instance.Clear( );
IEnumerable<XElement> modifiers = from x in el.Elements( )
where ( x.Name == "modifiers" )
select x;
foreach ( XElement modifier in modifiers ) {
ValidContent &= Modifiers.Instance.FromXML( modifier );
}
ValidContent &= ReadXML( reader );
IEnumerable<XElement> actionmaps = from x in el.Elements( )
where ( x.Name == "actionmap" )
select x;
foreach ( XElement actionmap in actionmaps ) {
ValidContent &= ReadActionmap( actionmap );
}
}
}
return ValidContent;
}
@ -568,24 +406,25 @@ namespace SCJMapper_V2.SC
/// <returns>A filled SCActionMapList object</returns>
public SCActionMapList ActionMapList( string xml )
{
SCActionMapList aml = new SCActionMapList( );
log.Debug( "DProfileReader.ActionMapList - Entry" );
XmlReaderSettings settings = new XmlReaderSettings( );
settings.ConformanceLevel = ConformanceLevel.Fragment;
settings.IgnoreWhitespace = true;
settings.IgnoreComments = true;
XmlReader reader = XmlReader.Create( new StringReader( xml ), settings );
reader.Read( );
if ( !reader.ReadToFollowing( "actionmap" ) ) return aml; // ERROR empty one..
do {
string attr = reader["name"];
if ( !string.IsNullOrEmpty( attr ) )
aml.AddActionMap( attr );
} while ( reader.ReadToFollowing( "actionmap" ) );
SCActionMapList aml = new SCActionMapList( );
XmlReaderSettings settings = new XmlReaderSettings {
ConformanceLevel = ConformanceLevel.Fragment,
IgnoreWhitespace = true,
IgnoreComments = true
};
using ( XmlReader reader = XmlReader.Create( new StringReader( xml ), settings ) ) {
reader.MoveToContent( );
if ( XNode.ReadFrom( reader ) is XElement el ) {
IEnumerable<XElement> actionmaps = from x in el.Elements( )
where ( x.Name == "actionmap" )
select x;
foreach ( XElement actionmap in actionmaps ) {
aml.AddActionMap( (string)actionmap.Attribute("name") );
}
}
}
return aml;
}

@ -5,6 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
namespace SCJMapper_V2.SC
{
@ -144,37 +145,26 @@ namespace SCJMapper_V2.SC
/// <param name="xml"></param>
/// <param name="defProfile"></param>
/// <returns></returns>
public bool FromXML( string xml, bool defProfile = false )
public bool FromXML( XElement modifiers, bool defProfile = false )
{
XmlReaderSettings settings = new XmlReaderSettings( );
settings.ConformanceLevel = ConformanceLevel.Fragment;
settings.IgnoreWhitespace = true;
settings.IgnoreComments = true;
XmlReader reader = XmlReader.Create( new StringReader( xml ), settings );
try {
reader.ReadToFollowing( "modifiers" );
reader.ReadToDescendant( "mod" );
do {
if ( reader.NodeType == XmlNodeType.EndElement ) {
reader.Read( );
break; // finished
}
string name = reader["input"];
if ( !string.IsNullOrEmpty( name ) ) {
var m = new Modifier( name, defProfile );
if ( !Contains( m ) )
Add( m );
}
} while ( reader.Read( ) );
return true;
}
catch ( Exception ex ) {
// get any exceptions from reading
return false;
/*
<modifiers >
<mod input="xi1_shoulderl" />
...
</modifiers>
*/
IEnumerable<XElement> mods = from x in modifiers.Elements( )
where ( x.Name == "mod" )
select x;
foreach ( XElement mod in mods ) {
string name = (string)mod.Attribute( "input" );
if ( !string.IsNullOrEmpty( name ) ) {
var m = new Modifier( name, defProfile );
if ( !Contains( m ) )
Add( m );
}
}
return true;
}

@ -27,8 +27,8 @@
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>67</ApplicationRevision>
<ApplicationVersion>2.33.0.%2a</ApplicationVersion>
<ApplicationRevision>68</ApplicationRevision>
<ApplicationVersion>2.34.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
@ -125,6 +125,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Actions\ActionCommandCls.cs" />
<Compile Include="Actions\Act.cs" />
<Compile Include="Actions\ActionTreeEventArgs.cs" />
<Compile Include="Actions\ActionTreeInputNode.cs" />
<Compile Include="Actions\ActionTreeNode.cs" />
@ -241,7 +242,7 @@
<Compile Include="SC\SCMappings.cs" />
<Compile Include="SC\SCPath.cs" />
<Compile Include="TheUser.cs" />
<Compile Include="Devices\Joystick\UICustHeader.cs" />
<Compile Include="Devices\UICustHeader.cs" />
<Compile Include="OGL\TriDiagonalMatrix.cs" />
<Compile Include="Devices\Joystick\xyPoints.cs" />
<Compile Include="Devices\Gamepad\UC_GpadPanel.cs">

@ -101,7 +101,7 @@ namespace SCJMapper_V2.Table
static public string DevInput ( DS_ActionMaps.T_ActionRow acr )
{
if ( acr.Disabled )
return DeviceCls.BlendedInput;
return DeviceCls.DisabledInput;
else
return acr.Usr_Binding;
}

@ -322,7 +322,7 @@ namespace SCJMapper_V2.Table
if ( e.ColumnIndex != DGV.Columns["Disabled"].Index ) return;
if ( ( bool )DGV.Rows[e.RowIndex].Cells[DGV.Columns["Disabled"].Index].Value == true )
DGV.Rows[e.RowIndex].Cells[DGV.Columns["Usr_Binding"].Index].Value = DeviceCls.BlendedInput;
DGV.Rows[e.RowIndex].Cells[DGV.Columns["Usr_Binding"].Index].Value = DeviceCls.DisabledInput;
else
DGV.Rows[e.RowIndex].Cells[DGV.Columns["Usr_Binding"].Index].Value = ""; // don't know anything else...

@ -12,7 +12,7 @@ using SCJMapper_V2.Devices.Keyboard;
using SCJMapper_V2.Devices.Mouse;
using SCJMapper_V2.Devices.Gamepad;
using SCJMapper_V2.Devices.Joystick;
using System.Xml.Linq;
namespace SCJMapper_V2.Actions
{
@ -46,217 +46,13 @@ namespace SCJMapper_V2.Actions
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod( ).DeclaringType );
/// <summary>
/// Device Enums
/// </summary>
public enum ActionDevice
{
AD_Unknown = -1,
AD_Joystick = 0,
AD_Gamepad,
AD_Keyboard,
AD_Mouse, // 20151220BM: add mouse device (from AC 2.0 defaultProfile usage)
}
#region Static Items
/// <summary>
/// Return the Device Enum from a DeviceClass string
/// </summary>
/// <param name="deviceClass">Device Class string</param>
/// <returns>Device Enum</returns>
static public ActionDevice ADevice( string deviceClass )
{
switch ( deviceClass.ToLower( ) ) {
case KeyboardCls.DeviceClass: return ActionDevice.AD_Keyboard;
case JoystickCls.DeviceClass: return ActionDevice.AD_Joystick;
case GamepadCls.DeviceClass: return ActionDevice.AD_Gamepad;
case MouseCls.DeviceClass: return ActionDevice.AD_Mouse; // 20151220BM: add mouse device (from AC 2.0 defaultProfile usage)
case "ps3pad": return ActionDevice.AD_Gamepad;
default: return ActionDevice.AD_Unknown;
}
}
// Static items to have this mapping in only one place
/// <summary>
/// Returns the Device Tag i.e. the single letter to mark a device in Actions
/// </summary>
/// <param name="device">The device name from the defaultProfile</param>
/// <returns>The single UCase device Tag letter</returns>
static public string DevTag( string device )
{
switch ( device.ToLower( ) ) {
case KeyboardCls.DeviceClass: return "K";
case JoystickCls.DeviceClass: return "J";
case GamepadCls.DeviceClass: return "X";
case MouseCls.DeviceClass: return "M"; // 20151220BM: add mouse device (from AC 2.0 defaultProfile usage)
case "ps3pad": return "P";
default: return "Z";
}
}
/// <summary>
/// Returns the Device name from the Device Tag
/// </summary>
/// <param name="device">The single UCase device Tag letter</param>
/// <returns>The device name from the defaultProfile</returns>
static public string DeviceClassFromTag( string devTag )
{
switch ( devTag ) {
case "K": return KeyboardCls.DeviceClass;
case "J": return JoystickCls.DeviceClass;
case "X": return GamepadCls.DeviceClass;
case "M": return MouseCls.DeviceClass; // 20151220BM: add mouse device (from AC 2.0 defaultProfile usage)
case "P": return "ps3pad";
default: return "unknown";
}
}
/// <summary>
/// Try to derive the device class from the devInput string (mo1_, kb1_, xi1_, jsN_)
/// </summary>
/// <param name="devInput">The input command string dev_input format</param>
/// <returns>A proper DeviceClass string</returns>
static public string DeviceClassFromInput( string devInput )
{
string deviceClass = DeviceCls.DeviceClass;
deviceClass = JoystickCls.DeviceClassFromInput( devInput );
if ( !DeviceCls.IsUndefined( deviceClass ) ) return deviceClass;
deviceClass = GamepadCls.DeviceClassFromInput( devInput );
if ( !DeviceCls.IsUndefined( deviceClass ) ) return deviceClass;
deviceClass = KeyboardCls.DeviceClassFromInput( devInput );
if ( !DeviceCls.IsUndefined( deviceClass ) ) return deviceClass;
deviceClass = MouseCls.DeviceClassFromInput( devInput );
if ( !DeviceCls.IsUndefined( deviceClass ) ) return deviceClass;
// others..
return deviceClass;
}
/// <summary>
/// Returns the ActionDevice from a deviceID (a trailing _ is added if not there)
/// </summary>
/// <param name="devID">DeviceID</param>
/// <returns>The ActionDevice</returns>
static public ActionDevice ADeviceFromDevID( string devID )
{
string val = devID;
if ( !devID.EndsWith( "_" ) ) val += "_";
return ADevice( DeviceClassFromInput( val ) );
}
/// <summary>
/// Returns the ActionDevice from the devInput string (mo1_, kb1_, xi1_, jsN_)
/// </summary>
/// <param name="devInput">The input command string dev_input format</param>
/// <returns>The ActionDevice</returns>
static public ActionDevice ADeviceFromInput( string devInput )
{
return ADevice( DeviceClassFromInput( devInput ) );
}
/// <summary>
/// Query the devices if the input is blended
/// </summary>
/// <param name="input">The input command</param>
/// <returns>True if blended input</returns>
static public Boolean IsBlendedInput( string input )
{
Boolean blendedInput = false;
blendedInput = DeviceCls.IsBlendedInput( input ); // generic
if ( blendedInput ) return blendedInput;
blendedInput = JoystickCls.IsBlendedInput( input );
if ( blendedInput ) return blendedInput;
blendedInput = GamepadCls.IsBlendedInput( input );
if ( blendedInput ) return blendedInput;
blendedInput = KeyboardCls.IsBlendedInput( input );
if ( blendedInput ) return blendedInput;
blendedInput = MouseCls.IsBlendedInput( input );
if ( blendedInput ) return blendedInput;
// others..
return blendedInput;
}
/// <summary>
/// Blend the input using the device specific format of the input is generic Blind
/// </summary>
/// <param name="input">An input (generic blend or a valid command)</param>
/// <param name="aDevice">A valid device</param>
/// <returns>A device blend or the original input if it was not a blend</returns>
static public string BlendInput( string input, ActionDevice aDevice )
{
if ( DeviceCls.IsBlendedInput( input ) ) {
// was generic blind
switch ( aDevice ) {
case ActionDevice.AD_Gamepad: return GamepadCls.BlendedInput;
case ActionDevice.AD_Joystick: return JoystickCls.BlendedInput;
case ActionDevice.AD_Keyboard: return KeyboardCls.BlendedInput;
case ActionDevice.AD_Mouse: return MouseCls.BlendedInput;
default: return "";
}
} else {
return input; // just return
}
}
/// <summary>
/// Extends the input to a device input if not already done
/// </summary>
/// <param name="input">An input</param>
/// <param name="aDevice">The ActionDevice</param>
/// <returns>A valid devInput (dev_input) format</returns>
static public string DevInput( string input, ActionDevice aDevice )
{
switch ( aDevice ) {
case ActionDevice.AD_Gamepad: return GamepadCls.DevInput( input );
case ActionDevice.AD_Joystick: return JoystickCls.DevInput( input );
case ActionDevice.AD_Keyboard: return KeyboardCls.DevInput( input );
case ActionDevice.AD_Mouse: return MouseCls.DevInput( input );
default: return input;
}
}
/// <summary>
/// Return the color of a device
/// </summary>
/// <param name="devInput">The devinput (determine JS colors)</param>
/// <param name="aDevice">The ActionDevice</param>
/// <returns>The device color</returns>
static public System.Drawing.Color DeviceColor( string devInput )
{
// background is along the input
ActionDevice aDevice = ADeviceFromInput( devInput );
switch ( aDevice ) {
case ActionDevice.AD_Gamepad: return GamepadCls.XiColor( );
case ActionDevice.AD_Joystick: {
int jNum = JoystickCls.JSNum( devInput ); // need to know which JS
return JoystickCls.JsNColor( jNum );
}
case ActionDevice.AD_Keyboard: return KeyboardCls.KbdColor( );
case ActionDevice.AD_Mouse: return MouseCls.MouseColor( );
default: return MyColors.UnassignedColor;
}
}
#endregion
// **************** Class items **********************
public string key { get; set; } // the key is the "Daction" formatted item (as we can have the same name multiple times)
public string name { get; set; } // the plain action name e.g. v_yaw
public ActionDevice actionDevice { get; set; } // the enum of the device
public string device { get; set; } // name of the device (uses DeviceClass)
public string defBinding { get; set; } // the default binding
public ActivationMode defActivationMode { get; set; } // the default binding ActivationMode
public List<ActionCommandCls> inputList { get; set; } // regular bind is the 0-element, addbinds are added to the list
public string Key { get; set; } // the key is the "Daction" formatted item (as we can have the same name multiple times)
public string Name { get; set; } // the plain action name e.g. v_yaw
public Act.ActionDevice ActionDevice { get; set; } // the enum of the device
public string Device { get; set; } // name of the device (uses DeviceClass)
public string DefBinding { get; set; } // the default binding
public ActivationMode DefActivationMode { get; set; } // the default binding ActivationMode
public List<ActionCommandCls> InputList { get; set; } // regular bind is the 0-element, addbinds are added to the list
/// <summary>
/// Clone this object
@ -266,8 +62,8 @@ namespace SCJMapper_V2.Actions
{
ActionCls newAc = (ActionCls)this.MemberwiseClone( );
// more objects to deep copy
newAc.defActivationMode = (ActivationMode)this.defActivationMode.Clone( );
newAc.inputList = this.inputList.Select( x => (ActionCommandCls)x.Clone( ) ).ToList( );
newAc.DefActivationMode = (ActivationMode)this.DefActivationMode.Clone( );
newAc.InputList = this.InputList.Select( x => (ActionCommandCls)x.Clone( ) ).ToList( );
return newAc;
}
@ -283,9 +79,9 @@ namespace SCJMapper_V2.Actions
ActionCls newAc = this.MyClone( );
// creates a copy of the list with reassigned jsN devs
newAc.inputList.Clear( ); // get rid of cloned list
foreach ( ActionCommandCls acc in inputList ) {
newAc.inputList.Add( acc.ReassignJsN( newJsList ) ); // creates the deep copy of the list
newAc.InputList.Clear( ); // get rid of cloned list
foreach ( ActionCommandCls acc in InputList ) {
newAc.InputList.Add( acc.ReassignJsN( newJsList ) ); // creates the deep copy of the list
}
return newAc;
@ -297,13 +93,13 @@ namespace SCJMapper_V2.Actions
/// </summary>
public ActionCls()
{
key = "";
actionDevice = ActionDevice.AD_Unknown;
device = JoystickCls.DeviceClass;
name = "";
defBinding = "";
defActivationMode = ActivationMode.Default;
inputList = new List<ActionCommandCls>( ); // empty list
Key = "";
ActionDevice = Act.ActionDevice.AD_Unknown;
Device = JoystickCls.DeviceClass;
Name = "";
DefBinding = "";
DefActivationMode = ActivationMode.Default;
InputList = new List<ActionCommandCls>( ); // empty list
}
@ -316,9 +112,9 @@ namespace SCJMapper_V2.Actions
/// <returns>Returns the ActionCommand created</returns>
public ActionCommandCls AddCommand( string devInput, ActivationMode activationMode )
{
ActionCommandCls acc = new ActionCommandCls( devInput, inputList.Count - 1 ); // starts from -1 ...
ActionCommandCls acc = new ActionCommandCls( devInput, InputList.Count - 1 ); // starts from -1 ...
acc.ActivationMode = new ActivationMode( activationMode );
inputList.Add( acc );
InputList.Add( acc );
return acc;
}
@ -333,7 +129,7 @@ namespace SCJMapper_V2.Actions
{
ActionCommandCls acc = new ActionCommandCls( devInput, index );
acc.ActivationMode = new ActivationMode( ActivationMode.Default );
inputList.Add( acc );
InputList.Add( acc );
return acc;
}
@ -341,11 +137,11 @@ namespace SCJMapper_V2.Actions
{
int removeIt = -1;
for ( int i = 0; i < inputList.Count; i++ ) {
if ( inputList[i].NodeIndex == index ) removeIt = i;
if ( inputList[i].NodeIndex > index ) inputList[i].NodeIndex -= 1; // reorder trailing ones
for ( int i = 0; i < InputList.Count; i++ ) {
if ( InputList[i].NodeIndex == index ) removeIt = i;
if ( InputList[i].NodeIndex > index ) InputList[i].NodeIndex -= 1; // reorder trailing ones
}
if ( removeIt >= 0 ) inputList.RemoveAt( removeIt );
if ( removeIt >= 0 ) InputList.RemoveAt( removeIt );
}
@ -355,9 +151,9 @@ namespace SCJMapper_V2.Actions
/// <param name="newAc"></param>
public void Merge( ActionCls newAc )
{
this.inputList.Clear( );
foreach ( ActionCommandCls acc in newAc.inputList ) {
this.inputList.Add( acc );
this.InputList.Clear( );
foreach ( ActionCommandCls acc in newAc.InputList ) {
this.InputList.Add( acc );
}
}
@ -367,14 +163,15 @@ namespace SCJMapper_V2.Actions
/// Updates an actionCommand with a new input (command)
/// </summary>
/// <param name="devInput">The input command</param>
/// <param name="accIndex">The input index to update</param>
public void UpdateCommandFromInput( string devInput, int accIndex ) // ActionCommandCls actionCmd )
{
//log.Debug( "UpdateCommandFromInput - Entry" );
if ( accIndex < 0 ) return;
// Apply the input to the ActionTree
this.inputList[accIndex].DevInput = BlendInput( devInput, this.actionDevice );
if ( IsBlendedInput( this.inputList[accIndex].DevInput ) || string.IsNullOrEmpty( devInput ) ) {
this.inputList[accIndex].ActivationMode = new ActivationMode( ActivationMode.Default ); // reset activation mode if the input is empty
this.InputList[accIndex].DevInput = Act.DisableInput( devInput, this.ActionDevice );
if ( Act.IsDisabledInput( this.InputList[accIndex].DevInput ) || string.IsNullOrEmpty( devInput ) ) {
this.InputList[accIndex].ActivationMode = new ActivationMode( ActivationMode.Default ); // reset activation mode if the input is empty
}
}
@ -388,7 +185,7 @@ namespace SCJMapper_V2.Actions
log.Debug( "FindActionInputObject - Entry" );
// Apply the input to the ActionTree
ActionCommandCls acc = null;
acc = this.inputList.Find( delegate ( ActionCommandCls _ACC ) { return _ACC.DevInput == devInput; } );
acc = this.InputList.Find( delegate ( ActionCommandCls _ACC ) { return _ACC.DevInput == devInput; } );
if ( acc == null ) {
log.Error( "FindActionInputObject - Action Input not found in Action" );
return null; // ERROR - Action Input not found in tree
@ -400,14 +197,14 @@ namespace SCJMapper_V2.Actions
/// <summary>
/// Find an ActionCommand with index in an Action
/// </summary>
/// <param name="input">The input</param>
/// <param name="index">The input index to find</param>
/// <returns>An actionCommand or null if not found</returns>
public ActionCommandCls FindActionInputObject( int index )
{
log.Debug( "FindActionInputObject - Entry" );
// Apply the input to the ActionTree
ActionCommandCls acc = null;
acc = this.inputList.Find( delegate ( ActionCommandCls _ACC ) { return _ACC.NodeIndex == index; } );
acc = this.InputList.Find( delegate ( ActionCommandCls _ACC ) { return _ACC.NodeIndex == index; } );
if ( acc == null ) {
log.Error( "FindActionInputObject - Action Input not found in Action" );
return null; // ERROR - Action Input not found in tree
@ -423,13 +220,12 @@ namespace SCJMapper_V2.Actions
public string toXML()
{
string r = ""; string
bindCmd = "rebind";
if ( inputList.Count > 0 ) {
if ( !string.IsNullOrEmpty( inputList[0].Input ) ) {
r = string.Format( "\t<action name=\"{0}\">\n", name );
foreach ( ActionCommandCls acc in inputList ) {
bindCmd = "rebind"; // first entry is rebind
if ( InputList.Count > 0 ) {
if ( !string.IsNullOrEmpty( InputList[0].Input ) ) {
r = string.Format( "\t<action name=\"{0}\">\n", Name );
foreach ( ActionCommandCls acc in InputList ) {
if ( !string.IsNullOrEmpty( acc.Input ) ) {
// r += string.Format( "\t\t\t<{0} device=\"{1}\" {2}", bindCmd, device, acc.toXML( ) ); // OLD style
r += string.Format( "\t\t\t<{0} {1}", bindCmd, acc.toXML( ) ); // 20151220BM: format for AC2 style
bindCmd = "addbind"; // switch to addbind
}
@ -442,106 +238,39 @@ namespace SCJMapper_V2.Actions
}
/// <summary>
/// Read an action from XML - do some sanity check
/// Read an action from XML - do some sanity checks
/// </summary>
/// <param name="xml">the XML action fragment</param>
/// <returns>True if an action was decoded</returns>
public Boolean fromXML( string xml )
public bool fromXML( XElement actionNode )
{
XmlReaderSettings settings = new XmlReaderSettings( );
settings.ConformanceLevel = ConformanceLevel.Fragment;
settings.IgnoreWhitespace = true;
settings.IgnoreComments = true;
XmlReader reader = XmlReader.Create( new StringReader( xml ), settings );
reader.Read( );
if ( reader.Name.ToLowerInvariant( ) == "action" ) {
if ( reader.HasAttributes ) {
name = reader["name"];
reader.ReadStartElement( "action" ); // Checks that the current content node is an element with the given Name and advances the reader to the next node
} else {
return false;
Name = (string)actionNode.Attribute( "name" ); // mandadory
foreach ( XElement bindingNode in actionNode.Nodes( ) ) {
string binding = bindingNode.Name.ToString( );
string input = "", actModeName = "", multi = "";
input = (string)bindingNode.Attribute( "input" ); // mandadory
if ( string.IsNullOrEmpty( input ) ) input = "";
actModeName = (string)bindingNode.Attribute( "ActivationMode" );
multi = (string)bindingNode.Attribute( "multiTap" );
//process
input = DeviceCls.fromXML( input ); // move from external to internal blend
Device = Act.DeviceClassFromInput( input );
ActivationMode actMode = null;
if ( !string.IsNullOrEmpty( actModeName ) ) {
actMode = ActivationModes.Instance.ActivationModeByName( actModeName ); // should be a valid ActivationMode for this action
}
}
do {
// support AC2 and AC1 i.e. without and with device attribute
if ( reader.Name.ToLowerInvariant( ) == "rebind" ) {
if ( reader.HasAttributes ) {
device = reader["device"];
string input = reader["input"];
if ( string.IsNullOrEmpty( input ) ) return false; // ERROR exit
input = DeviceCls.fromXML( input ); // move from external to internal blend
if ( string.IsNullOrEmpty( device ) ) {
// AC2 style - derive the device (Device.DeviceClass)
device = DeviceClassFromInput( input );
} else {
// AC1 style - need to reformat mouse and keyboard according to AC2 style now
if ( KeyboardCls.IsDeviceClass( device ) ) input = KeyboardCls.FromAC1( input );
else if ( MouseCls.IsDeviceClass( device ) ) input = MouseCls.FromAC1( input );
else if ( GamepadCls.IsDeviceClass( device ) ) input = GamepadCls.FromAC1( input );
}
//first find an ActivationMode if there is - applies to all actions
// this can be an Activation Mode OR a multitap
// if there is an activationMode - copy the one from our List
// if no ActivationMode is given, create one with multitap 1 or may be 2...
string actModeName = reader["ActivationMode"];
ActivationMode actMode = null;
if ( !string.IsNullOrEmpty( actModeName ) ) {
actMode = ActivationModes.Instance.ActivationModeByName( actModeName ); // should be a valid ActivationMode for this action
} else {
actMode = new ActivationMode( ActivationMode.Default ); // no specific name given, use default
string multiTap = reader["multiTap"];
if ( !string.IsNullOrEmpty( multiTap ) ) {
actMode.MultiTap = int.Parse( multiTap ); // modify with given multiTap
}
}
key = DevTag( device ) + name; // unique id of the action
actionDevice = ADevice( device ); // get the enum of the input device
AddCommand( input, actMode );
// advances the reader to the next node
reader.ReadStartElement( "rebind" );
else {
actMode = new ActivationMode( ActivationMode.Default ); // no specific name given, use default
if ( !string.IsNullOrEmpty( multi ) ) {
actMode.MultiTap = int.Parse( multi ); // modify with given multiTap
}
} else if ( reader.Name.ToLowerInvariant( ) == "addbind" ) {
if ( reader.HasAttributes ) {
device = reader["device"];
string input = reader["input"];
if ( string.IsNullOrEmpty( input ) ) return false; // ERROR exit
input = DeviceCls.fromXML( input ); // move from external to internal blend
if ( string.IsNullOrEmpty( device ) ) {
// AC2 style - derive the device (Device.DeviceClass)
device = DeviceClassFromInput( input );
} else {
// AC1 style - need to reformat according to AC2 style now
if ( KeyboardCls.IsDeviceClass( device ) ) input = KeyboardCls.FromAC1( input );
else if ( MouseCls.IsDeviceClass( device ) ) input = MouseCls.FromAC1( input );
else if ( GamepadCls.IsDeviceClass( device ) ) input = GamepadCls.FromAC1( input );
}
//first find an ActivationMode if there is - applies to all actions
// this can be an Activation Mode OR a multitap
// if there is an activationMode - copy the one from our List
// if no ActivationMode is given, create one with multitap 1 or may be 2...
string actModeName = reader["ActivationMode"];
ActivationMode actMode = null;
if ( !string.IsNullOrEmpty( actModeName ) ) {
actMode = ActivationModes.Instance.ActivationModeByName( actModeName ); // should be a valid ActivationMode for this action
} else {
actMode = new ActivationMode( ActivationMode.Default ); // no specific name given, use default
string multiTap = reader["multiTap"];
if ( !string.IsNullOrEmpty( multiTap ) ) {
actMode.MultiTap = int.Parse( multiTap ); // modify with given multiTap
}
}
AddCommand( input, actMode );
// advances the reader to the next node
reader.ReadStartElement( "addbind" );
}
} else {
return false;
}
} while ( reader.Name == "addbind" );
if ( binding == "rebind" ) {
Key = Act.DevTag( Device ) + Name; // unique id of the action
ActionDevice = Act.ADevice( Device ); // get the enum of the input device
}
AddCommand( input, actMode );
}//foreach
return true;
}

@ -166,11 +166,11 @@ namespace SCJMapper_V2.Actions
/// Updates an actionCommand with a new input (command)
/// </summary>
/// <param name="devInput">The input command</param>
public void UpdateCommandFromInput( string devInput, ActionCls.ActionDevice actionDevice) // ActionCommandCls actionCmd )
public void UpdateCommandFromInput( string devInput, Act.ActionDevice actionDevice) // ActionCommandCls actionCmd )
{
// Apply the input to the ActionTree
this.DevInput = ActionCls.BlendInput( devInput, actionDevice );
if ( ActionCls.IsBlendedInput( this.DevInput ) || string.IsNullOrEmpty( devInput ) ) {
this.DevInput = Act.DisableInput( devInput, actionDevice );
if ( Act.IsDisabledInput( this.DevInput ) || string.IsNullOrEmpty( devInput ) ) {
this.ActivationMode = new ActivationMode( ActivationMode.Default ); // reset activation mode if the input is empty
}
}

@ -6,6 +6,7 @@ using System.IO;
using SCJMapper_V2.Devices.Joystick;
using System.Linq;
using System.Xml.Linq;
namespace SCJMapper_V2.Actions
{
@ -25,7 +26,7 @@ namespace SCJMapper_V2.Actions
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod( ).DeclaringType );
public string name { get; set; }
public string Name { get; set; }
/// <summary>
/// Copy return the complete ActionMap while reassigning the JsN Tag
@ -34,7 +35,7 @@ namespace SCJMapper_V2.Actions
/// <returns>The ActionMap copy with reassigned input</returns>
public ActionMapCls ReassignJsN( JsReassingList newJsList )
{
var newMap = new ActionMapCls(this);
var newMap = new ActionMapCls( this );
foreach ( ActionCls ac in this ) {
newMap.Add( ac.ReassignJsN( newJsList ) ); // creates the deep copy of the tree
@ -46,11 +47,11 @@ namespace SCJMapper_V2.Actions
private ActionMapCls( ActionMapCls other )
{
this.name = other.name;
this.Name = other.Name;
// no deep copy of refs
}
public ActionMapCls( ) { }
public ActionMapCls() { }
/// <summary>
/// Merge the given Map with this Map
@ -61,12 +62,13 @@ namespace SCJMapper_V2.Actions
{
// do we find all actions in the new list that are like the new ones in our list ?
foreach ( ActionCls newAc in newAcm ) {
ActionCls AC = this.Find( delegate( ActionCls ac ) {
return ac.key == newAc.key;
ActionCls AC = this.Find( delegate ( ActionCls ac ) {
return ac.Key == newAc.Key;
} );
if ( AC == null ) {
; // this.Add( newAc ); // no, add it
} else {
}
else {
AC.Merge( newAc ); // yes, merge it
}
}
@ -77,15 +79,15 @@ namespace SCJMapper_V2.Actions
/// Dump the actionmap as partial XML nicely formatted
/// </summary>
/// <returns>the action as XML fragment</returns>
public string toXML( )
public string toXML()
{
string acs = "";
foreach ( ActionCls ac in this ) {
string x = ac.toXML( );
string x = ac.toXML( );
if ( !string.IsNullOrEmpty( x ) ) acs += string.Format( "\t{0}", x );
}
if ( !string.IsNullOrWhiteSpace( acs ) ) {
string r = string.Format( "\t<actionmap name=\"{0}\">\n", name );
string r = string.Format( "\t<actionmap name=\"{0}\">\n", Name );
r += acs;
r += string.Format( "\t</actionmap>\n" );
return r;
@ -100,33 +102,14 @@ namespace SCJMapper_V2.Actions
/// </summary>
/// <param name="xml">the XML action fragment</param>
/// <returns>True if an action was decoded</returns>
public Boolean fromXML( string xml )
public bool fromXML( XElement actionmap )
{
XmlReaderSettings settings = new XmlReaderSettings( );
settings.ConformanceLevel = ConformanceLevel.Fragment;
settings.IgnoreWhitespace = true;
settings.IgnoreComments = true;
XmlReader reader = XmlReader.Create( new StringReader( xml ), settings );
reader.Read( );
if ( reader.Name == "actionmap" ) {
if ( reader.HasAttributes ) {
name = reader["name"];
} else {
return false;
}
}
reader.Read( ); // move to next element
string x = reader.ReadOuterXml( );
while ( !string.IsNullOrEmpty( x ) ) {
Name = (string)actionmap.Attribute( "name" ); // mandadory
foreach ( XElement actionNode in actionmap.Nodes( ) ) {
ActionCls ac = new ActionCls( );
if ( ac.fromXML( x ) ) {
if ( ac.fromXML( actionNode ) ) {
this.Add( ac ); // add to list
}
x = reader.ReadOuterXml( );
}
return true;
}

@ -20,6 +20,7 @@ using SCJMapper_V2.Devices.Gamepad;
using SCJMapper_V2.Devices.Joystick;
using SCJMapper_V2.Devices.Options;
using System.Linq;
using System.Xml.Linq;
namespace SCJMapper_V2.Actions
{
@ -174,7 +175,7 @@ namespace SCJMapper_V2.Actions
// do we find an actionmap like the new one in our list ?
ActionMapCls ACM = this.Find( delegate ( ActionMapCls acm ) {
return acm.name == newAcm.name;
return acm.Name == newAcm.Name;
} );
if ( ACM == null ) {
; // this.Add( newAcm ); // no, add new
@ -187,7 +188,7 @@ namespace SCJMapper_V2.Actions
#if USE_DS_ACTIONMAPS // see and (un)define on top of file to allow for editing the DataSet entities
public void toDataSet( DS_ActionMaps dsa )
public void ToDataSet( DS_ActionMaps dsa )
{
dsa.Clear( );
if ( dsa.HasChanges( ) ) dsa.T_ActionMap.AcceptChanges( );
@ -195,25 +196,25 @@ namespace SCJMapper_V2.Actions
int AMcount = 1;
foreach ( ActionMapCls am in this ) {
DS_ActionMaps.T_ActionMapRow amr = dsa.T_ActionMap.NewT_ActionMapRow( );
string amShown = DS_ActionMap.ActionMapShown( am.name, AMcount++ );
string amShown = DS_ActionMap.ActionMapShown( am.Name, AMcount++ );
amr.ID_ActionMap = amShown;
dsa.T_ActionMap.AddT_ActionMapRow( amr );
foreach ( ActionCls ac in am ) {
int ilIndex = 0;
while ( ac.inputList.Count > ilIndex ) {
while ( ac.InputList.Count > ilIndex ) {
DS_ActionMaps.T_ActionRow ar = dsa.T_Action.NewT_ActionRow( );
ar.ID_Action = DS_ActionMap.ActionID( am.name, ac.key, ac.inputList[ilIndex].NodeIndex ); // make a unique key
ar.ID_Action = DS_ActionMap.ActionID( am.Name, ac.Key, ac.InputList[ilIndex].NodeIndex ); // make a unique key
ar.AddBind = ( ilIndex > 0 ); // all but the first are addbinds
ar.REF_ActionMap = amShown;
ar.ActionName = ac.name;
ar.Device = ac.device;
ar.Def_Binding = ac.defBinding;
ar.Def_Modifier = ac.defActivationMode.Name;
ar.Usr_Binding = ac.inputList[ilIndex].DevInput;
ar.Usr_Modifier = ac.inputList[ilIndex].ActivationMode.Name;
ar.Disabled = DeviceCls.IsBlendedInput( ac.inputList[ilIndex].Input );
ar.ActionName = ac.Name;
ar.Device = ac.Device;
ar.Def_Binding = ac.DefBinding;
ar.Def_Modifier = ac.DefActivationMode.Name;
ar.Usr_Binding = ac.InputList[ilIndex].DevInput;
ar.Usr_Modifier = ac.InputList[ilIndex].ActivationMode.Name;
ar.Disabled = DeviceCls.IsDisabledInput( ac.InputList[ilIndex].Input );
dsa.T_Action.AddT_ActionRow( ar );
ilIndex++;
@ -227,19 +228,19 @@ namespace SCJMapper_V2.Actions
dsa.AcceptChanges( );
}
public void updateDataSet( DS_ActionMaps dsa, string actionID )
public void UpdateDataSet( DS_ActionMaps dsa, string actionID )
{
foreach ( ActionMapCls am in this ) {
DS_ActionMaps.T_ActionMapRow amr = dsa.T_ActionMap.NewT_ActionMapRow( );
foreach ( ActionCls ac in am ) {
int ilIndex = 0;
while ( ac.inputList.Count > ilIndex ) {
if ( actionID == DS_ActionMap.ActionID( am.name, ac.key, ac.inputList[ilIndex].NodeIndex ) ) {
while ( ac.InputList.Count > ilIndex ) {
if ( actionID == DS_ActionMap.ActionID( am.Name, ac.Key, ac.InputList[ilIndex].NodeIndex ) ) {
DS_ActionMaps.T_ActionRow ar = dsa.T_Action.FindByID_Action( actionID );
ar.Usr_Binding = ac.inputList[ilIndex].DevInput;
ar.Usr_Modifier = ac.inputList[ilIndex].ActivationMode.Name;
ar.Disabled = DeviceCls.IsBlendedInput( ac.inputList[ilIndex].Input );
ar.Usr_Binding = ac.InputList[ilIndex].DevInput;
ar.Usr_Modifier = ac.InputList[ilIndex].ActivationMode.Name;
ar.Disabled = DeviceCls.IsDisabledInput( ac.InputList[ilIndex].Input );
ar.AcceptChanges( );
return;
}
@ -333,69 +334,81 @@ namespace SCJMapper_V2.Actions
{
log.Debug( "ActionMapsCls.fromXML - Entry" );
XmlReaderSettings settings = new XmlReaderSettings( );
settings.ConformanceLevel = ConformanceLevel.Fragment;
settings.IgnoreWhitespace = true;
settings.IgnoreComments = true;
XmlReader reader = XmlReader.Create( new StringReader( xml ), settings );
reader.Read( );
// read the header element
if ( reader.Name == "ActionMaps" ) {
if ( reader.HasAttributes ) {
version = reader["version"];
if ( version == "0" ) version = ACM_VERSION; // update from legacy to actual version
// get the joystick mapping if there is one
for ( int i = 0; i < JoystickCls.JSnum_MAX; i++ ) {
jsN[i] = reader[string.Format( "js{0}", i + 1 )];
jsNGUID[i] = reader[string.Format( "js{0}G", i + 1 )];
XmlReaderSettings settings = new XmlReaderSettings {
ConformanceLevel = ConformanceLevel.Fragment,
IgnoreWhitespace = true,
IgnoreComments = true
};
using ( XmlReader reader = XmlReader.Create( new StringReader( xml ), settings ) ) {
reader.MoveToContent( );
// read the header element
if ( reader.Name == "ActionMaps" ) {
if ( reader.HasAttributes ) {
version = reader["version"];
if ( version == "0" ) version = ACM_VERSION; // update from legacy to actual version
// get the joystick mapping if there is one
for ( int i = 0; i < JoystickCls.JSnum_MAX; i++ ) {
jsN[i] = reader[string.Format( "js{0}", i + 1 )];
jsNGUID[i] = reader[string.Format( "js{0}G", i + 1 )];
}
}
else {
return false;
}
}
else {
return false;
}
}
// now handle the js assignment from the map
// Reset with the found mapping
DeviceInst.JoystickListRef.ResetJsNAssignment( jsNGUID );
// Only now create the default optiontree for this map, containing included joysticks and the gamepad
CreateNewOptions( );
// now handle the js assignment from the map
// Reset with the found mapping
DeviceInst.JoystickListRef.ResetJsNAssignment( jsNGUID );
// Only now create the default optiontree for this map, containing included joysticks and the gamepad
CreateNewOptions( );
// now read the CIG content of the map
reader.MoveToContent( );
// could be actionmap OR (AC 0.9) deviceoptions OR options
if ( XNode.ReadFrom( reader ) is XElement el ) {
IEnumerable<XElement> actionmaps = from x in el.Elements( )
where ( x.Name == "actionmap" )
select x;
foreach ( XElement actionmap in actionmaps ) {
ActionMapCls acm = new ActionMapCls( );
if ( acm.fromXML( actionmap ) ) {
this.Merge( acm ); // merge list
}
}
// now read the CIG content of the map
reader.Read( ); // move to next element
IEnumerable<XElement> custHeaders = from x in el.Elements( )
where ( x.Name == UICustHeader.XmlName )
select x;
foreach ( XElement custHeader in custHeaders ) {
m_uiCustHeader.fromXML( custHeader );
}
// could be actionmap OR (AC 0.9) deviceoptions OR options
IEnumerable<XElement> deviceOptions = from x in el.Elements( )
where ( x.Name == "deviceoptions" )
select x;
foreach ( XElement deviceOption in deviceOptions ) {
m_deviceOptions.fromXML( deviceOption );
}
while ( !reader.EOF ) { //!string.IsNullOrEmpty( x ) ) {
IEnumerable<XElement> options = from x in el.Elements( )
where ( x.Name == "options" )
select x;
foreach ( XElement option in options ) {
m_tuningOptions.fromXML( option );
}
if ( reader.Name.ToLowerInvariant( ) == "actionmap" ) {
string x = reader.ReadOuterXml( );
ActionMapCls acm = new ActionMapCls( );
if ( acm.fromXML( x ) ) {
this.Merge( acm ); // merge list
IEnumerable<XElement> modifiers = from x in el.Elements( )
where ( x.Name == "modifiers" )
select x;
foreach ( XElement modifier in modifiers ) {
SC.Modifiers.Instance.FromXML( modifier );
}
}
else if ( reader.Name.ToLowerInvariant( ) == "customisationuiheader" ) {
string x = reader.ReadOuterXml( );
m_uiCustHeader.fromXML( x );
}
else if ( reader.Name.ToLowerInvariant( ) == "deviceoptions" ) {
string x = reader.ReadOuterXml( );
m_deviceOptions.fromXML( x );
}
else if ( reader.Name.ToLowerInvariant( ) == "options" ) {
string x = reader.ReadOuterXml( );
m_tuningOptions.fromXML( x );
}
else if ( reader.Name.ToLowerInvariant( ) == "modifiers" ) {
string x = reader.ReadOuterXml( );
SC.Modifiers.Instance.FromXML( x ); // add as 'non profile'
}
else {
reader.Read( );
}
}
return true;

@ -219,14 +219,14 @@ namespace SCJMapper_V2.Actions
}
public bool ShowAction( ActionCls.ActionDevice actDev, string input )
public bool ShowAction( Act.ActionDevice actDev, string input )
{
if ( ActionCls.IsBlendedInput( input ) && m_showMappedOnly ) return false;
if ( Act.IsDisabledInput( input ) && m_showMappedOnly ) return false;
switch ( actDev ) {
case ActionCls.ActionDevice.AD_Gamepad: return m_showGameP;
case ActionCls.ActionDevice.AD_Joystick: return m_showJoy;
case ActionCls.ActionDevice.AD_Keyboard: return m_showKbd;
case ActionCls.ActionDevice.AD_Mouse: return m_showMouse;
case Act.ActionDevice.AD_Gamepad: return m_showGameP;
case Act.ActionDevice.AD_Joystick: return m_showJoy;
case Act.ActionDevice.AD_Keyboard: return m_showKbd;
case Act.ActionDevice.AD_Mouse: return m_showMouse;
default: return false;
}
}
@ -245,7 +245,9 @@ namespace SCJMapper_V2.Actions
ActionTreeNode matn = FindMasterAction( (ActionTreeNode)Ctrl.SelectedNode );
ActionCls ac = FindActionObject( matn.Parent.Name, matn.Name ); // the related action
// make new items
ActionTreeInputNode matin = new ActionTreeInputNode( "UNDEF" ); matin.ImageKey = "Add";
ActionTreeInputNode matin = new ActionTreeInputNode( "UNDEF" ) {
ImageKey = "Add"
};
matn.Nodes.Add( matin ); // add to master tree
ActionCommandCls acc = ac.AddCommand( "", matin.Index );
// show stuff
@ -278,14 +280,14 @@ namespace SCJMapper_V2.Actions
}
public void BlendBinding()
public void DisableBinding()
{
UpdateSelectedItem( DeviceCls.BlendedInput, ActionCls.ActionDevice.AD_Unknown, false );
UpdateSelectedItem( DeviceCls.DisabledInput, Act.ActionDevice.AD_Unknown, false );
}
public void ClearBinding()
{
UpdateSelectedItem( "", ActionCls.ActionDevice.AD_Unknown, false );
UpdateSelectedItem( "", Act.ActionDevice.AD_Unknown, false );
}
@ -485,6 +487,8 @@ namespace SCJMapper_V2.Actions
txReader = new StringReader( dpReader.CSVMap );
}
// Input is a CSV formatted defaultprofile
// we assume no addbind items in the profile
// so all actions are shown in the ActionTreeNode and no ActionTreeNode childs must be created here
// however we create the ActionCommand for each entry that is supported - even if it is not mapped (input= "")
@ -496,8 +500,7 @@ namespace SCJMapper_V2.Actions
if ( !IgnoreMaps.Contains( "," + elem[0] + "," ) ) {
// must have 2 elements min
Array.Resize( ref cnl, 0 );
acm = new ActionMapCls( ); acm.name = elem[0]; // get actionmap name
// process items
acm = new ActionMapCls { Name = elem[0] }; // get actionmap name
for ( int ei = 1; ei < elem.Length; ei += 4 ) { // step 2 - action;defaultBinding;defaultActivationMode;defMultiTap come in as quadrupples
if ( !string.IsNullOrEmpty( elem[ei] ) ) {
// default assignments
@ -509,11 +512,13 @@ namespace SCJMapper_V2.Actions
ActivationMode defActivationMode = new ActivationMode( defActivationModeName, defMultiTap );
string devID = elem[ei].Substring( 0, 1 );
string device = ActionCls.DeviceClassFromTag( devID );
string device = Act.DeviceClassFromTag( devID );
// visual item for the action
cn = new ActionTreeNode( "UNDEF" ); cn.Name = elem[ei]; cn.Action = action; cn.BackColor = Color.White; // name with the key it to find it..
cn.ImageKey = devID; cn.BackColor = Color.White; // some stuff does not work properly...
cn = new ActionTreeNode( "UNDEF" ) {
Name = elem[ei], Action = action, BackColor = Color.White, ImageKey = devID // name with the key it to find it..
};
cn.BackColor = Color.White; // some stuff does not work properly...
if ( ActivationMode.IsDefault( defActivationModeName ) ) {
cn.NodeFont = FontAction;
}
@ -523,56 +528,60 @@ namespace SCJMapper_V2.Actions
Array.Resize( ref cnl, cnl.Length + 1 ); cnl[cnl.Length - 1] = cn;
// derive content tree
ac = new ActionCls( ); ac.key = cn.Name; ac.name = action; ac.device = device; ac.actionDevice = ActionCls.ADevice( device );
ac.defBinding = defBinding; ac.defActivationMode = defActivationMode;
ac = new ActionCls {
Key = cn.Name, Name = action, Device = device, ActionDevice = Act.ADevice( device ),
DefBinding = defBinding, DefActivationMode = defActivationMode
};
acm.Add( ac ); // add to our map
cn.ActionDevice = ac.actionDevice; // should be known now
cn.ActionDevice = ac.ActionDevice; // should be known now
// create just an unmapped ActionCommand item
acc = ac.AddCommand( "", -1 ); // profile items are shown in the ActionTreeNode (not in a child)
// init and apply the default mappings if requested
if ( ac.actionDevice == ActionCls.ActionDevice.AD_Joystick ) {
if ( ac.ActionDevice == Act.ActionDevice.AD_Joystick ) {
acc.DevID = JoystickCls.DeviceID;
int jNum = JoystickCls.JSNum( ac.defBinding );
int jNum = JoystickCls.JSNum( ac.DefBinding );
if ( applyDefaults ) {
if ( JoystickCls.IsJSValid( jNum ) ) {
acc.DevInput = ac.defBinding;
cn.Command = ac.defBinding; cn.BackColor = JoystickCls.JsNColor( jNum );
acc.DevInput = ac.DefBinding;
cn.Command = ac.DefBinding; cn.BackColor = JoystickCls.JsNColor( jNum );
}
}
}
else if ( ac.actionDevice == ActionCls.ActionDevice.AD_Gamepad ) {
else if ( ac.ActionDevice == Act.ActionDevice.AD_Gamepad ) {
acc.DevID = GamepadCls.DeviceID;
if ( applyDefaults ) {
if ( !string.IsNullOrEmpty( ac.defBinding ) ) {
acc.DevInput = ac.defBinding;
cn.Command = ac.defBinding; cn.BackColor = GamepadCls.XiColor( );
if ( !string.IsNullOrEmpty( ac.DefBinding ) ) {
acc.DevInput = ac.DefBinding;
cn.Command = ac.DefBinding; cn.BackColor = GamepadCls.XiColor( );
}
}
}
else if ( ac.actionDevice == ActionCls.ActionDevice.AD_Keyboard ) {
else if ( ac.ActionDevice == Act.ActionDevice.AD_Keyboard ) {
acc.DevID = KeyboardCls.DeviceID;
if ( applyDefaults ) {
if ( !string.IsNullOrEmpty( ac.defBinding ) ) {
acc.DevInput = ac.defBinding;
cn.Command = ac.defBinding; cn.BackColor = KeyboardCls.KbdColor( );
if ( !string.IsNullOrEmpty( ac.DefBinding ) ) {
acc.DevInput = ac.DefBinding;
cn.Command = ac.DefBinding; cn.BackColor = KeyboardCls.KbdColor( );
}
}
}
else if ( ac.actionDevice == ActionCls.ActionDevice.AD_Mouse ) { // 20151220BM: add mouse device (from AC 2.0 defaultProfile usage)
else if ( ac.ActionDevice == Act.ActionDevice.AD_Mouse ) { // 20151220BM: add mouse device (from AC 2.0 defaultProfile usage)
acc.DevID = MouseCls.DeviceID;
if ( applyDefaults ) {
if ( !string.IsNullOrEmpty( ac.defBinding ) ) {
acc.DevInput = ac.defBinding;
cn.Command = ac.defBinding; cn.BackColor = MouseCls.MouseColor( );
if ( !string.IsNullOrEmpty( ac.DefBinding ) ) {
acc.DevInput = ac.DefBinding;
cn.Command = ac.DefBinding; cn.BackColor = MouseCls.MouseColor( );
}
}
}
}
}//for
tn = new ActionTreeNode( acm.name, cnl ); tn.Name = acm.name; tn.Action = acm.name; // name it to find it..
tn.ImageIndex = 0; tn.NodeFont = FontActionmap; // new Font( m_MasterTree.Font, FontStyle.Bold );
tn = new ActionTreeNode( acm.Name, cnl ) {
Name = acm.Name, Action = acm.Name, // name it to find it..
ImageIndex = 0, NodeFont = FontActionmap // new Font( m_MasterTree.Font, FontStyle.Bold );
};
m_MasterTree.BackColor = Color.White; // fix for defect TreeView (cut off bold text)
m_MasterTree.Nodes.Add( tn ); // add to control
if ( topNode == null ) topNode = tn; // once to keep the start of list
@ -584,8 +593,9 @@ namespace SCJMapper_V2.Actions
}//while
}
// fix for defect TreeView (cut off bold text at last element -despite the BackColor fix) add another and delete it
tn = new ActionTreeNode( "DUMMY" ); tn.Name = "DUMMY";
tn.ImageIndex = 0; tn.NodeFont = FontActionmap; // new Font( m_MasterTree.Font, FontStyle.Bold );
tn = new ActionTreeNode( "DUMMY" ) {
Name = "DUMMY", ImageIndex = 0, NodeFont = FontActionmap // new Font( m_MasterTree.Font, FontStyle.Bold );
};
m_MasterTree.BackColor = m_MasterTree.BackColor; // fix for defect TreeView (cut off bold text)
m_MasterTree.Nodes.Add( tn ); // add to control
m_MasterTree.Nodes.RemoveByKey( "DUMMY" );
@ -617,7 +627,7 @@ namespace SCJMapper_V2.Actions
ActionTreeNode atn = ( Ctrl.SelectedNode as ActionTreeNode ); // the treenode from a level 1
ActionCls ac = FindActionObject( atn.Parent.Name, atn.Name ); if ( ac == null ) return am; // ERROR exit
ActionCommandCls acc = ac.FindActionInputObject( ActionTreeNode.CommandFromNodeText( atn.Text ) ); if ( acc == null ) return am; // ERROR exit
am = new ActivationModes( ac.defActivationMode, acc.ActivationMode ); // policy: get the default first, then the attached one
am = new ActivationModes( ac.DefActivationMode, acc.ActivationMode ); // policy: get the default first, then the attached one
return am;
}
else if ( Ctrl.SelectedNode.Level == 2 ) {
@ -627,7 +637,7 @@ namespace SCJMapper_V2.Actions
// the related action
ActionCls ac = FindActionObject( patn.Parent.Name, patn.Name ); if ( ac == null ) return am; // ERROR exit
ActionCommandCls acc = ac.FindActionInputObject( atn.Index ); if ( acc == null ) return am; // ERROR exit
am = new ActivationModes( ac.defActivationMode, acc.ActivationMode );// policy: get the default first, then the attached one
am = new ActivationModes( ac.DefActivationMode, acc.ActivationMode );// policy: get the default first, then the attached one
return am;
}
@ -690,7 +700,7 @@ namespace SCJMapper_V2.Actions
/// First apply to the GUI tree where the selection happend then copy it over to master tree
/// </summary>
/// <param name="input">The new Text property</param>
public bool UpdateSelectedItem( string input, ActionCls.ActionDevice inKind, bool checkKind )
public bool UpdateSelectedItem( string input, Act.ActionDevice inKind, bool checkKind )
{
if ( Ctrl.SelectedNode == null ) return false; // ERROR exit
if ( ( Ctrl.SelectedNode.Level == 0 ) || ( Ctrl.SelectedNode.Level > 2 ) ) return false; // ERROR exit
@ -702,11 +712,11 @@ namespace SCJMapper_V2.Actions
ActionTreeNode atn = ( Ctrl.SelectedNode as ActionTreeNode ); // the treenode from a level 1
ActionCls ac = FindActionObject( atn.Parent.Name, atn.Name ); // the related action in an actionmap
if ( ac == null ) return false; // ERROR exit
if ( checkKind && ( ac.actionDevice != inKind ) ) return false; // ERROR exit
if ( checkKind && ( ac.ActionDevice != inKind ) ) return false; // ERROR exit
ActionCommandCls acc = ac.FindActionInputObject( ActionTreeNode.CommandFromNodeText( atn.Text ) );
if ( acc == null ) return false; // ERROR exit
// have it - continue
ac.UpdateCommandFromInput( ActionCls.DevInput( input, inKind ), acc.NodeIndex + 1 );
ac.UpdateCommandFromInput( Act.DevInput( input, inKind ), acc.NodeIndex + 1 );
atn.UpdateAction( acc ); UpdateMasterNode( atn );
NodeSelected( ); // virtual event - as the selection does not change
Dirty = true;
@ -723,17 +733,17 @@ namespace SCJMapper_V2.Actions
ActionCls ac = FindActionObject( patn.Parent.Name, patn.Name ); // the related action in an actionmap
if ( ac == null ) return false; // ERROR exit
if ( checkKind ) {
if ( ac.actionDevice == ActionCls.ActionDevice.AD_Keyboard ) {
if ( ( inKind != ActionCls.ActionDevice.AD_Keyboard ) && ( inKind != ActionCls.ActionDevice.AD_Mouse ) ) return false; // ERROR exit
if ( ac.ActionDevice == Act.ActionDevice.AD_Keyboard ) {
if ( ( inKind != Act.ActionDevice.AD_Keyboard ) && ( inKind != Act.ActionDevice.AD_Mouse ) ) return false; // ERROR exit
}
else {
if ( ac.actionDevice != inKind ) return false; // ERROR exit
if ( ac.ActionDevice != inKind ) return false; // ERROR exit
}
}
ActionCommandCls acc = ac.FindActionInputObject( atn.Index );
if ( acc == null ) return false; // ERROR exit
// have it - continue
ac.UpdateCommandFromInput( ActionCls.DevInput( input, inKind ), acc.NodeIndex + 1 );
ac.UpdateCommandFromInput( Act.DevInput( input, inKind ), acc.NodeIndex + 1 );
atn.UpdateAction( acc ); UpdateMasterNode( atn );
NodeSelected( ); // virtual event - as the selection does not change
Dirty = true;
@ -753,9 +763,9 @@ namespace SCJMapper_V2.Actions
//log.Debug( "FindActionInputObject - Entry" );
// Apply the input to the ActionTree
ActionCls ac = null; ActionCommandCls acc = null;
ActionMapCls ACM = ActionMaps.Find( delegate ( ActionMapCls _ACM ) { return _ACM.name == actionMap; } );
if ( ACM != null ) ac = ACM.Find( delegate ( ActionCls _AC ) { return _AC.key == actionKey; } );
if ( ac != null ) acc = ac.inputList.Find( delegate ( ActionCommandCls _ACC ) { return _ACC.DevInput == devInput; } );
ActionMapCls ACM = ActionMaps.Find( delegate ( ActionMapCls _ACM ) { return _ACM.Name == actionMap; } );
if ( ACM != null ) ac = ACM.Find( delegate ( ActionCls _AC ) { return _AC.Key == actionKey; } );
if ( ac != null ) acc = ac.InputList.Find( delegate ( ActionCommandCls _ACC ) { return _ACC.DevInput == devInput; } );
if ( acc == null ) {
log.Error( "FindActionInputObject - Action Input not found in tree" );
return null; // ERROR - Action Input not found in tree
@ -775,9 +785,9 @@ namespace SCJMapper_V2.Actions
//log.Debug( "FindActionInputObject - Entry" );
// Apply the input to the ActionTree
ActionCls ac = null; ActionCommandCls acc = null;
ActionMapCls ACM = tree.ActionMaps.Find( delegate ( ActionMapCls _ACM ) { return _ACM.name == actionMap; } );
if ( ACM != null ) ac = ACM.Find( delegate ( ActionCls _AC ) { return _AC.key == actionKey; } );
if ( ac != null ) acc = ac.inputList.Find( delegate ( ActionCommandCls _ACC ) { return _ACC.NodeIndex == index; } );
ActionMapCls ACM = tree.ActionMaps.Find( delegate ( ActionMapCls _ACM ) { return _ACM.Name == actionMap; } );
if ( ACM != null ) ac = ACM.Find( delegate ( ActionCls _AC ) { return _AC.Key == actionKey; } );
if ( ac != null ) acc = ac.InputList.Find( delegate ( ActionCommandCls _ACC ) { return _ACC.NodeIndex == index; } );
if ( acc == null ) {
log.Error( "FindActionInputObject - Action Input not found in tree" );
return null; // ERROR - Action Input not found in tree
@ -785,9 +795,6 @@ namespace SCJMapper_V2.Actions
return acc;
}
/// <summary>
/// Find an action with name in a actionmap
/// </summary>
@ -799,8 +806,8 @@ namespace SCJMapper_V2.Actions
//log.Debug( "FindActionObject - Entry" );
// Apply the input to the ActionTree
ActionCls ac = null;
ActionMapCls ACM = ActionMaps.Find( delegate ( ActionMapCls acm ) { return acm.name == actionMap; } );
if ( ACM != null ) ac = ACM.Find( delegate ( ActionCls _AC ) { return _AC.key == action; } );
ActionMapCls ACM = ActionMaps.Find( delegate ( ActionMapCls acm ) { return acm.Name == actionMap; } );
if ( ACM != null ) ac = ACM.Find( delegate ( ActionCls _AC ) { return _AC.Key == action; } );
if ( ac == null ) {
log.Error( "FindActionObject - Action Not found in tree" );
return null; // ERROR - Action Not found in tree
@ -808,7 +815,6 @@ namespace SCJMapper_V2.Actions
return ac;
}
/// <summary>
/// Defines what to show in the tree
/// </summary>
@ -835,15 +841,15 @@ namespace SCJMapper_V2.Actions
log.DebugFormat( "ReloadTreeView - Entry {0}", m_MasterTree.GetHashCode( ).ToString( ) );
foreach ( ActionMapCls acm in ActionMaps ) {
if ( IgnoreMaps.Contains( "," + acm.name + "," ) ) break; // next
if ( IgnoreMaps.Contains( "," + acm.Name + "," ) ) break; // next
try {
ActionTreeNode mtn = (ActionTreeNode)m_MasterTree.Nodes[acm.name]; // get the map node
ActionTreeNode mtn = (ActionTreeNode)m_MasterTree.Nodes[acm.Name]; // get the map node
// find the item to reload into the treeview
foreach ( ActionCls ac in acm ) {
ActionTreeNode matn = (ActionTreeNode)mtn.Nodes[ac.key]; // get the action node
ActionTreeNode matn = (ActionTreeNode)mtn.Nodes[ac.Key]; // get the action node
bool first = true;
// refresh commands
foreach ( ActionCommandCls acc in ac.inputList ) {
foreach ( ActionCommandCls acc in ac.InputList ) {
try {
ac.UpdateCommandFromInput( acc.DevInput, acc.NodeIndex + 1 ); // this may apply (un)Blending if needed
// the first one goes into the node, further must be created if not existing
@ -855,7 +861,7 @@ namespace SCJMapper_V2.Actions
else {
// have to recreate the action child nodes
//ActionTreeInputNode matin = new ActionTreeInputNode( "UNDEF" ); matin.ImageKey = "Add";
ActionTreeInputNode matin = new ActionTreeInputNode( ac.name ); matin.ImageKey = "Add";
ActionTreeInputNode matin = new ActionTreeInputNode( ac.Name ); matin.ImageKey = "Add";
matin.Name = matn.Name + "_" + matin.Index; // unique name needed
acc.NodeIndex = matin.Index; // assign visual reference
matn.Nodes.Add( matin ); // add to master tree
@ -871,7 +877,6 @@ namespace SCJMapper_V2.Actions
log.DebugFormat( "ReloadTreeView - Exception in loading Treevie\n{0}", e.Message ); // map key not found ??
}
}
// finally apply the filter and make it visible
FilterTree( );
}
@ -990,7 +995,7 @@ namespace SCJMapper_V2.Actions
{
List<string> ret = new List<string>( );
if ( string.IsNullOrEmpty( input ) ) return ret; // nothing to find here...
if ( ActionCls.IsBlendedInput( input ) ) return ret; // nothing to find here...
if ( Act.IsDisabledInput( input ) ) return ret; // nothing to find here...
ret.Add( "Actions listed for Input: " + input );
ret.Add( "" );
@ -1001,18 +1006,18 @@ namespace SCJMapper_V2.Actions
// have to search Actions in Maps
foreach ( ActionCls ac in acm ) {
string l = ""; // return line composition
if ( ac.defBinding == input ) {
if ( ac.DefBinding == input ) {
ret.Add( "" );
aMode = string.Format( "{0};{1}", ac.defActivationMode.Name, ac.defActivationMode.MultiTap );
l = string.Format( "{0} - {1} - {2} - {3}", "profile", ac.name, acm.name, aMode );
aMode = string.Format( "{0};{1}", ac.DefActivationMode.Name, ac.DefActivationMode.MultiTap );
l = string.Format( "{0} - {1} - {2} - {3}", "profile", ac.Name, acm.Name, aMode );
ret.Add( l );
}
foreach ( ActionCommandCls acc in ac.inputList ) {
foreach ( ActionCommandCls acc in ac.InputList ) {
if ( acc.DevInput == input ) {
aMode = string.Format( "modified;{0};{1}", acc.ActivationMode.Name, acc.ActivationMode.MultiTap );
if ( acc.ActivationMode == ActivationMode.Default )
aMode = string.Format( "default" );
l = string.Format( "{0} - {1} - {2} - {3}", "mapped ", ac.name, acm.name, aMode );
l = string.Format( "{0} - {1} - {2} - {3}", "mapped ", ac.Name, acm.Name, aMode );
ret.Add( l );
}
}
@ -1029,7 +1034,7 @@ namespace SCJMapper_V2.Actions
public void FindAllActionsRTF( string input, RTF.RTFformatter rtf )
{
if ( string.IsNullOrEmpty( input ) ) return; // nothing to find here...
if ( ActionCls.IsBlendedInput( input ) ) return; // nothing to find here...
if ( Act.IsDisabledInput( input ) ) return; // nothing to find here...
rtf.FontSize( 12 );
rtf.Write( "Actions listed for input: " );
rtf.RBold = true; rtf.WriteLn( input ); rtf.RBold = false;
@ -1046,18 +1051,18 @@ namespace SCJMapper_V2.Actions
foreach ( ActionMapCls acm in ActionMaps ) {
// have to search Actions in Maps
foreach ( ActionCls ac in acm ) {
if ( ac.defBinding == input ) {
aMode = string.Format( "{0};{1}", ac.defActivationMode.Name, ac.defActivationMode.MultiTap );
rtf.Write( "profile" ); rtf.WriteTab( ac.name ); rtf.WriteTab( acm.name ); rtf.WriteTab( aMode ); rtf.WriteLn( );
if ( ac.DefBinding == input ) {
aMode = string.Format( "{0};{1}", ac.DefActivationMode.Name, ac.DefActivationMode.MultiTap );
rtf.Write( "profile" ); rtf.WriteTab( ac.Name ); rtf.WriteTab( acm.Name ); rtf.WriteTab( aMode ); rtf.WriteLn( );
rtf.WriteLn( );
}
foreach ( ActionCommandCls acc in ac.inputList ) {
foreach ( ActionCommandCls acc in ac.InputList ) {
if ( acc.DevInput == input ) {
aMode = string.Format( "modified;{0};{1}", acc.ActivationMode.Name, acc.ActivationMode.MultiTap );
if ( acc.ActivationMode == ActivationMode.Default )
aMode = string.Format( "default" );
rtf.RHighlightColor = RTF.RTFformatter.ERColor.ERC_Green;
rtf.Write( "mapped" ); rtf.WriteTab( ac.name ); rtf.WriteTab( acm.name ); rtf.WriteTab( aMode.PadRight( 80 ) ); rtf.WriteLn( );
rtf.Write( "mapped" ); rtf.WriteTab( ac.Name ); rtf.WriteTab( acm.Name ); rtf.WriteTab( aMode.PadRight( 80 ) ); rtf.WriteLn( );
rtf.RHighlightColor = RTF.RTFformatter.ERColor.ERC_Black;
rtf.WriteLn( );
}
@ -1178,7 +1183,7 @@ namespace SCJMapper_V2.Actions
ActionCommandCls acc = ac.FindActionInputObject( ActionTreeNode.CommandFromNodeText( atn.Text ) );
if ( acc == null ) return ""; // ERROR exit
// have it - continue
string actionID = DS_ActionMap.ActionID( atn.Parent.Name, ac.key, acc.NodeIndex );
string actionID = DS_ActionMap.ActionID( atn.Parent.Name, ac.Key, acc.NodeIndex );
return actionID;
}
@ -1191,7 +1196,7 @@ namespace SCJMapper_V2.Actions
ActionCommandCls acc = ac.FindActionInputObject( atn.Index );
if ( acc == null ) return ""; // ERROR exit
// have it - continue
string actionID = DS_ActionMap.ActionID( atn.Parent.Name, ac.key, acc.NodeIndex );
string actionID = DS_ActionMap.ActionID( atn.Parent.Name, ac.Key, acc.NodeIndex );
return actionID;
}
@ -1219,7 +1224,7 @@ namespace SCJMapper_V2.Actions
countChanges++;
ActionCommandCls acc = FindActionInputObject( nTree, DS_ActionMap.ActionMap( ar ), DS_ActionMap.ActionKey( ar ), DS_ActionMap.ActionCommandIndex( ar ) );
if ( acc != null ) {
acc.UpdateCommandFromInput( ActionCls.DevInput( DS_ActionMap.DevInput( ar ), ActionCls.ADevice( ar.Device ) ), ActionCls.ADevice( ar.Device ) );
acc.UpdateCommandFromInput( Act.DevInput( DS_ActionMap.DevInput( ar ), Act.ADevice( ar.Device ) ), Act.ADevice( ar.Device ) );
ar.Usr_Binding = acc.DevInput; // feedback the right one
}
else {
@ -1266,20 +1271,20 @@ namespace SCJMapper_V2.Actions
repList += string.Format( " {0}+- {1} _ {2}#-[{4}] {3}\n\n", "Action".PadRight( padAction ), "Dev".PadRight( padDevice ), "Binding".PadRight( padInput ), "Activation", "T" ); // col description line
foreach ( ActionMapCls acm in ActionMaps ) {
string rep = string.Format( "*** {0}\n", acm.name );
string rep = string.Format( "*** {0}\n", acm.Name );
repList += rep;
foreach ( ActionCls ac in acm ) {
foreach ( ActionCommandCls acc in ac.inputList ) {
if ( ShowAction( ac.actionDevice, acc.Input ) ) {
foreach ( ActionCommandCls acc in ac.InputList ) {
if ( ShowAction( ac.ActionDevice, acc.Input ) ) {
if ( !string.IsNullOrEmpty( acc.Input ) /* && !( acc.Input == DeviceCls.BlendedInput )*/ ) {
if ( acc.DevInput == ac.defBinding ) {
rep = string.Format( " {0} . {1} _ {2}", ac.name.PadRight( padAction ), acc.DevID.PadRight( padDevice ), acc.Input.PadRight( padInput ) );
if ( acc.DevInput == ac.DefBinding ) {
rep = string.Format( " {0} . {1} _ {2}", ac.Name.PadRight( padAction ), acc.DevID.PadRight( padDevice ), acc.Input.PadRight( padInput ) );
}
else {
rep = string.Format( " {0} + {1} _ {2}", ac.name.PadRight( padAction ), acc.DevID.PadRight( padDevice ), acc.Input.PadRight( padInput ) ); // my binding
rep = string.Format( " {0} + {1} _ {2}", ac.Name.PadRight( padAction ), acc.DevID.PadRight( padDevice ), acc.Input.PadRight( padInput ) ); // my binding
}
if ( acc.ActivationMode == ActivationMode.Default ) {
rep += string.Format( " . [{1}] {0}\n", ac.defActivationMode.Name, ac.defActivationMode.MultiTap );
rep += string.Format( " . [{1}] {0}\n", ac.DefActivationMode.Name, ac.DefActivationMode.MultiTap );
}
else {
rep += string.Format( " # [{1}] {0}\n", acc.ActivationMode.Name, acc.ActivationMode.MultiTap );
@ -1340,7 +1345,7 @@ namespace SCJMapper_V2.Actions
foreach ( ActionCls ac in acm ) {
// we get an action for each device class here - sort it out
if ( ac.name != action ) {
if ( ac.Name != action ) {
// dump if not empty
if ( !string.IsNullOrEmpty( action ) ) {
// compose one action
@ -1348,8 +1353,8 @@ namespace SCJMapper_V2.Actions
repList += string.Format( "{0}", rep ); // add to list
}
// action changed - restart collection
action = ac.name;
rep = string.Format( "{0};{1};", acm.name, ac.name ); // actionmap; action
action = ac.Name;
rep = string.Format( "{0};{1};", acm.Name, ac.Name ); // actionmap; action
// note: don't add trailing semicolons as the are applied in the output formatting
if ( listModifiers ) {
kbA = "n.a.;;;;"; // defaults tag;input;mod-tag;mod-name;mod-mult
@ -1361,35 +1366,35 @@ namespace SCJMapper_V2.Actions
jsA = new string[] { kbA, kbA, kbA, kbA };
}
foreach ( ActionCommandCls acc in ac.inputList ) {
foreach ( ActionCommandCls acc in ac.InputList ) {
// this is for add binds
if ( ShowAction( ac.actionDevice, acc.Input ) ) {
if ( ShowAction( ac.ActionDevice, acc.Input ) ) {
if ( !string.IsNullOrEmpty( acc.Input ) ) {
// set modified - note: don't add trailing semicolons as the are applied in the output formatting
string aTag = "modified"; //default or modified
string aMode = string.Format( "modified;{0};{1}", acc.ActivationMode.Name, acc.ActivationMode.MultiTap );
// change if they are default mappings
if ( acc.DevInput == ac.defBinding ) aTag = "default";
if ( acc.ActivationMode == ActivationMode.Default ) aMode = string.Format( "default;{0};{1}", ac.defActivationMode.Name, ac.defActivationMode.MultiTap );
if ( acc.DevInput == ac.DefBinding ) aTag = "default";
if ( acc.ActivationMode == ActivationMode.Default ) aMode = string.Format( "default;{0};{1}", ac.DefActivationMode.Name, ac.DefActivationMode.MultiTap );
if ( listModifiers ) {
switch ( ActionCls.ADeviceFromDevID( acc.DevID ) ) {
case ActionCls.ActionDevice.AD_Keyboard: kbA = string.Format( "{0};{1};{2}", aTag, acc.Input, aMode ); break;
case ActionCls.ActionDevice.AD_Mouse: moA = string.Format( "{0};{1};{2}", aTag, acc.Input, aMode ); break;
case ActionCls.ActionDevice.AD_Joystick:
switch ( Act.ADeviceFromDevID( acc.DevID ) ) {
case Act.ActionDevice.AD_Keyboard: kbA = string.Format( "{0};{1};{2}", aTag, acc.Input, aMode ); break;
case Act.ActionDevice.AD_Mouse: moA = string.Format( "{0};{1};{2}", aTag, acc.Input, aMode ); break;
case Act.ActionDevice.AD_Joystick:
int jsNum = JoystickCls.JSNum( acc.DevInput ) - 1;
if ( jsNum >= 0 ) jsA[jsNum] = string.Format( "{0};{1};{2}", aTag, acc.Input, aMode ); break;
case ActionCls.ActionDevice.AD_Gamepad: xbA = string.Format( "{0};{1};{2}", aTag, acc.Input, aMode ); break;
case Act.ActionDevice.AD_Gamepad: xbA = string.Format( "{0};{1};{2}", aTag, acc.Input, aMode ); break;
default: break;
}//switch
}
else {
switch ( ActionCls.ADeviceFromDevID( acc.DevID ) ) {
case ActionCls.ActionDevice.AD_Keyboard: kbA = string.Format( "{0};{1}", aTag, acc.Input ); break;
case ActionCls.ActionDevice.AD_Mouse: moA = string.Format( "{0};{1}", aTag, acc.Input ); break;
case ActionCls.ActionDevice.AD_Joystick:
switch ( Act.ADeviceFromDevID( acc.DevID ) ) {
case Act.ActionDevice.AD_Keyboard: kbA = string.Format( "{0};{1}", aTag, acc.Input ); break;
case Act.ActionDevice.AD_Mouse: moA = string.Format( "{0};{1}", aTag, acc.Input ); break;
case Act.ActionDevice.AD_Joystick:
int jsNum = JoystickCls.JSNum( acc.DevInput ) - 1;
if ( jsNum >= 0 ) jsA[jsNum] = string.Format( "{0};{1}", aTag, acc.Input ); break;
case ActionCls.ActionDevice.AD_Gamepad: xbA = string.Format( "{0};{1}", aTag, acc.Input ); break;
case Act.ActionDevice.AD_Gamepad: xbA = string.Format( "{0};{1}", aTag, acc.Input ); break;
default: break;
}//switch
}

@ -7,7 +7,7 @@ using System.Windows.Forms;
namespace SCJMapper_V2.Actions
{
/// <summary>
/// Our INPUT TreeNode - inherits a regular one and adds some functionality
/// Our INPUT TreeNode - inherits a ActionTreeNode one and adds some functionality
///
/// contains the input command i.e. - js2_button3 OR ! js1_x (MODs applies at the very beginning of the string)
/// </summary>
@ -61,8 +61,7 @@ namespace SCJMapper_V2.Actions
/// <returns>the command part or an empty string</returns>
public new static string CommandFromNodeText( string nodeText )
{
string cmd;
ActionTreeInputNode.DecompNodeText( nodeText, out cmd );
ActionTreeInputNode.DecompNodeText( nodeText, out string cmd );
return cmd;
}
@ -81,24 +80,12 @@ namespace SCJMapper_V2.Actions
public ActionTreeInputNode( ActionTreeInputNode srcNode )
: base( srcNode )
{
if ( srcNode == null ) return;
/*
this.Name = srcNode.Name;
this.Text = srcNode.Text;
this.BackColor = srcNode.BackColor;
this.ForeColor = srcNode.ForeColor;
this.NodeFont = srcNode.NodeFont;
this.ImageKey = srcNode.ImageKey;
this.Tag = srcNode.Tag;
this.m_command = srcNode.m_command;
*/
}
// ctor
public ActionTreeInputNode( string text )
: base ( text )
{
//this.Text = text;
}
// ctor
@ -108,20 +95,24 @@ namespace SCJMapper_V2.Actions
}
//private string m_command ="";
/// <summary>
/// Property Text of an Input node
/// </summary>
public new string Text
{
get { return base.Text; }
set
{
ActionTreeInputNode.DecompNodeText( value, out m_command );
base.Text = ActionTreeInputNode.ComposeNodeText( "$" + m_command, m_modified ); // tag for the node processing
base.Text = ActionTreeInputNode.ComposeNodeText( AddDiv + m_command, m_modified ); // tag for the node processing
}
}
public new string Command
/// <summary>
/// Property Command of an Input node
/// </summary>
{
get { return m_command; }
set

@ -10,24 +10,25 @@ using SCJMapper_V2.Devices;
namespace SCJMapper_V2.Actions
{
/// <summary>
/// Our TreeNode - inherits a regular one and adds some functionality
/// Our TreeNode - inherits a regular TreeNode one and adds some functionality
/// </summary>
class ActionTreeNode : TreeNode
{
#region Static items
public const char RegDiv = '-';
public const char ModDiv = '#';
public const char RegDiv = '-'; // action, cmd separator tag
public const char ModDiv = '#'; // modified tag
public const string AddDiv = "$"; // addbind tag
// Handle all text label composition and extraction here
public static String ComposeNodeText( String action, String cmd, Boolean modified = false )
public static string ComposeNodeText( string action, string cmd, bool modified = false )
{
if ( String.IsNullOrEmpty( cmd ) ) {
if ( string.IsNullOrEmpty( cmd ) ) {
return action; // v_eject
}
else if ( String.IsNullOrEmpty( action ) ) {
else if ( string.IsNullOrEmpty( action ) ) {
return cmd; // js1_button1
}
else {
@ -38,14 +39,20 @@ namespace SCJMapper_V2.Actions
}
}
public static void DecompNodeText( String nodeText, out String action, out String cmd )
/// <summary>
/// Decompose from node.Text to the individual parts
/// e.g. v_eject - js1_button1 # => v_eject, js1_button1
/// </summary>
/// <param name="nodeText">The node Text</param>
/// <param name="action">The action</param>
/// <param name="cmd">The device command</param>
public static void DecompNodeText( string nodeText, out string action, out string cmd )
{
action = ""; cmd = "";
String[] e = nodeText.Split( new char[] { RegDiv, ModDiv }, StringSplitOptions.RemoveEmptyEntries );
string[] e = nodeText.Split( new char[] { RegDiv, ModDiv }, StringSplitOptions.RemoveEmptyEntries );
if ( e.Length > 1 ) {
action = e[0].TrimEnd( );
if ( e[1].Trim() == DeviceCls.BlendedInput ) {
if ( e[1].Trim() == DeviceCls.DisabledInput ) {
cmd = e[1];
}
else {
@ -53,11 +60,12 @@ namespace SCJMapper_V2.Actions
}
}
else if ( e.Length > 0 ) {
// action part only - i.e. not bound node
action = e[0].TrimEnd( );
cmd = "";
// consider if the single item is not an action but a command (from ActionTreeInputNode)
// it is then starting with the tag $ (that must be removed)
if ( action.StartsWith( "$" ) ) {
if ( action.StartsWith( AddDiv ) ) {
cmd = action.Substring( 1 );
action = "";
}
@ -72,10 +80,9 @@ namespace SCJMapper_V2.Actions
/// </summary>
/// <param name="nodeText">The node text in 'action - command' notation</param>
/// <returns>the action part or an empty string</returns>
public static String ActionFromNodeText( String nodeText )
public static string ActionFromNodeText( string nodeText )
{
String action, cmd;
ActionTreeNode.DecompNodeText( nodeText, out action, out cmd );
ActionTreeNode.DecompNodeText( nodeText, out string action, out string cmd );
return action;
}
@ -85,10 +92,9 @@ namespace SCJMapper_V2.Actions
/// </summary>
/// <param name="nodeText">The node text in 'action - command' notation</param>
/// <returns>the command part or an empty string</returns>
public static String CommandFromNodeText( String nodeText )
public static string CommandFromNodeText( string nodeText )
{
String action, cmd;
ActionTreeNode.DecompNodeText( nodeText, out action, out cmd );
ActionTreeNode.DecompNodeText( nodeText, out string action, out string cmd );
return cmd;
}
@ -135,10 +141,10 @@ namespace SCJMapper_V2.Actions
}
// our own properties
private String m_action = "";
protected String m_command ="";
private string m_action = "";
protected string m_command ="";
protected bool m_modified = false; // any modifier applied? (ActivationMode)
private ActionCls.ActionDevice m_actionDevice = ActionCls.ActionDevice.AD_Unknown;
private Act.ActionDevice m_actionDevice = Act.ActionDevice.AD_Unknown;
/// <summary>
@ -165,28 +171,30 @@ namespace SCJMapper_V2.Actions
if ( actionCmd == null ) return;
// input is either "" or a valid mapping or a blended mapping
if ( String.IsNullOrEmpty( actionCmd.Input ) ) {
if ( string.IsNullOrEmpty( actionCmd.Input ) ) {
// new unmapped
this.Command = ""; this.BackColor = MyColors.UnassignedColor;
if ( this.Level == 2 ) this.Action = "UNDEF"; // apply UNDEF - 20160525 fix addbind not showing UNDEF if assigned
}
// blended mapped ones - can only get a Blend Background
else if ( actionCmd.Input == DeviceCls.BlendedInput ) {
else if ( actionCmd.Input == DeviceCls.DisabledInput ) {
this.Command = actionCmd.DevInput; this.BackColor = MyColors.BlendedColor;
}
else {
// mapped ( regular ones )
this.Command = actionCmd.DevInput;
//if ( this.Level == 2 ) this.Action = ""; // remove UNDEF - 20160525 fix addbind not showing UNDEF if assigned
// background is along the input
this.BackColor = ActionCls.DeviceColor( actionCmd.DevInput );
this.BackColor = Act.DeviceColor( actionCmd.DevInput );
}
this.Modified = !actionCmd.DefaultActivationMode; // apply modifier visual
}
public new String Text
/// <summary>
/// Property Text of an Action node
/// </summary>
public new string Text
{
get { return base.Text; }
set
@ -197,7 +205,10 @@ namespace SCJMapper_V2.Actions
}
public String Action
/// <summary>
/// Property Action of an Action node
/// </summary>
public string Action
{
get { return m_action; }
set
@ -207,7 +218,10 @@ namespace SCJMapper_V2.Actions
}
}
public String Command
/// <summary>
/// Property Command of an Action node
/// </summary>
public string Command
{
get { return m_command; }
set
@ -217,7 +231,10 @@ namespace SCJMapper_V2.Actions
}
}
public ActionCls.ActionDevice ActionDevice
/// <summary>
/// Property ActionDevice of an Action node
/// </summary>
public Act.ActionDevice ActionDevice
{
get { return m_actionDevice; }
set
@ -226,7 +243,10 @@ namespace SCJMapper_V2.Actions
}
}
public Boolean Modified
/// <summary>
/// Property Modified of an Action node
/// </summary>
public bool Modified
{
get { return m_modified; }
set
@ -237,43 +257,55 @@ namespace SCJMapper_V2.Actions
}
public Boolean IsJoystickAction
/// <summary>
/// Property IsJoystickAction of an Action node
/// </summary>
public bool IsJoystickAction
{
get { return ( m_actionDevice == ActionCls.ActionDevice.AD_Joystick ); }
get { return ( m_actionDevice == Act.ActionDevice.AD_Joystick ); }
}
public Boolean IsGamepadAction
/// <summary>
/// Property IsGamepadAction of an Action node
/// </summary>
public bool IsGamepadAction
{
get { return ( m_actionDevice == ActionCls.ActionDevice.AD_Gamepad ); }
get { return ( m_actionDevice == Act.ActionDevice.AD_Gamepad ); }
}
public Boolean IsKeyboardAction
/// <summary>
/// Property IsKeyboardAction of an Action node
/// </summary>
public bool IsKeyboardAction
{
get { return ( m_actionDevice == ActionCls.ActionDevice.AD_Keyboard ); }
get { return ( m_actionDevice == Act.ActionDevice.AD_Keyboard ); }
}
public Boolean IsMouseAction // 20151220BM: add mouse device (from AC 2.0 defaultProfile usage)
/// <summary>
/// Property IsMouseAction of an Action node
/// </summary>
public bool IsMouseAction // 20151220BM: add mouse device (from AC 2.0 defaultProfile usage)
{
get { return ( m_actionDevice == ActionCls.ActionDevice.AD_Mouse ); }
get { return ( m_actionDevice == Act.ActionDevice.AD_Mouse ); }
}
/// <summary>
/// Returns true if the action is mapped
/// </summary>
public Boolean IsMappedAction
public bool IsMappedAction
{
get {
return !( string.IsNullOrEmpty( m_command ) || ActionCls.IsBlendedInput( m_command ) );
return !( string.IsNullOrEmpty( m_command ) || Act.IsDisabledInput( m_command ) );
}
}
/// <summary>
/// Returns true if the action is disabled
/// </summary>
public Boolean IsDisabledAction
public bool IsDisabledAction
{
get {
return ActionCls.IsBlendedInput( m_command );
return Act.IsDisabledInput( m_command );
}
}

Loading…
Cancel
Save