diff --git a/Actions/Act.cs b/Actions/Act.cs new file mode 100644 index 0000000..0a781ba --- /dev/null +++ b/Actions/Act.cs @@ -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 +{ + /// + /// Common Device Handling items for Action Classes + /// + public class Act + { + /// + /// Device Enums to be used within Action Classes + /// + 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_ + + /// + /// Return the Device Enum from a DeviceClass string + /// + /// Device Class string + /// Device Enum + 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; + } + } + + /// + /// Returns the Device Tag i.e. the single letter to mark a device in Actions + /// + /// The device name from the defaultProfile + /// The single UCase device Tag letter + 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"; + } + } + + /// + /// Returns the Device name from the Device Tag + /// + /// The single UCase device Tag letter + /// The device name from the defaultProfile + 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"; + } + } + + + /// + /// Try to derive the device class from the devInput string (mo1_, kb1_, xi1_, jsN_) + /// + /// The input command string dev_input format + /// A proper DeviceClass string + 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; + } + + /// + /// Returns the ActionDevice from a deviceID (a trailing _ is added if not there) + /// + /// DeviceID + /// The ActionDevice + static public ActionDevice ADeviceFromDevID( string devID ) + { + string val = devID; + if ( !devID.EndsWith( "_" ) ) val += "_"; + return ADevice( DeviceClassFromInput( val ) ); + } + + /// + /// Returns the ActionDevice from the devInput string (mo1_, kb1_, xi1_, jsN_) + /// + /// The input command string dev_input format + /// The ActionDevice + static public ActionDevice ADeviceFromInput( string devInput ) + { + return ADevice( DeviceClassFromInput( devInput ) ); + } + + /// + /// Query the devices if the input is disabled + /// + /// The input command + /// True if disabled input + 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; + } + + /// + /// Disable the input for a specific device - input is a generic Disabled Input + /// + /// An input (generic disable or a valid command) + /// A valid device + /// A device diabled or the original input if it was not a disabled + 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 + } + } + + /// + /// Extends the input to a device input if not already done + /// + /// An input + /// The ActionDevice + /// A valid devInput (dev_input) format + 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; + } + } + + /// + /// Return the color of a device + /// + /// The devinput (determine JS colors) + /// The ActionDevice + /// The device color + 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 + + } +} diff --git a/Devices/DeviceCls.cs b/Devices/DeviceCls.cs index 6ef4a65..1354ee9 100644 --- a/Devices/DeviceCls.cs +++ b/Devices/DeviceCls.cs @@ -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) } } diff --git a/Devices/Gamepad/GamepadCls.cs b/Devices/Gamepad/GamepadCls.cs index ea9aa7a..f73a6f3 100644 --- a/Devices/Gamepad/GamepadCls.cs +++ b/Devices/Gamepad/GamepadCls.cs @@ -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" ); diff --git a/Devices/Joystick/JoystickCls.cs b/Devices/Joystick/JoystickCls.cs index c74f1b7..7658033 100644 --- a/Devices/Joystick/JoystickCls.cs +++ b/Devices/Joystick/JoystickCls.cs @@ -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; } diff --git a/Devices/Keyboard/KeyboardCls.cs b/Devices/Keyboard/KeyboardCls.cs index d630427..6a5b38d 100644 --- a/Devices/Keyboard/KeyboardCls.cs +++ b/Devices/Keyboard/KeyboardCls.cs @@ -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) { diff --git a/Devices/Mouse/MouseCls.cs b/Devices/Mouse/MouseCls.cs index 15e94aa..cb0d2ea 100644 --- a/Devices/Mouse/MouseCls.cs +++ b/Devices/Mouse/MouseCls.cs @@ -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; } diff --git a/Devices/Options/DeviceTuningParameter.cs b/Devices/Options/DeviceTuningParameter.cs index 4135eab..5686445 100644 --- a/Devices/Options/DeviceTuningParameter.cs +++ b/Devices/Options/DeviceTuningParameter.cs @@ -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 m_PtsIn = new List( ); private List m_PtsOut = new List( ); - 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 /// /// A deep Clone of this object - 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 /// - 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 /// /// Derive values from a command (e.g. v_pitch - js1_x) /// - 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 /// /// The XML string or an empty string - 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\n", m_PtsIn[2], m_PtsOut[2] ); tmp += string.Format( "\t\t\t\n" ); tmp += string.Format( "\t\t \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 /// A prepared XML reader /// the Joystick instance number /// - public Boolean Options_fromXML( XmlReader reader, string type, int instance ) + public Boolean Options_fromXML( XElement option, string type, int instance ) { + /* + + + + + + + + */ 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 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; } diff --git a/Devices/Options/Deviceoptions.cs b/Devices/Options/Deviceoptions.cs index f7a0d2b..4fde804 100644 --- a/Devices/Options/Deviceoptions.cs +++ b/Devices/Options/Deviceoptions.cs @@ -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 /// /// the XML action fragment /// True if an action was decoded - 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 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; } diff --git a/Devices/Options/OptionTree.cs b/Devices/Options/OptionTree.cs index 2c5139e..22ec2a3 100644 --- a/Devices/Options/OptionTree.cs +++ b/Devices/Options/OptionTree.cs @@ -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 /// /// the XML action fragment /// True if an action was decoded - 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 */ - 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 + /* + * instance="0/1" sensitivity="n.nn" exponent="n.nn" (instance should be invert) + * + * + * + * + * + * + * + * invert="0/1" + * + * + * + * + * + * + * + * + * + * + + + * .. + + * + * + * + */ + 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 - /* - * instance="0/1" sensitivity="n.nn" exponent="n.nn" (instance should be invert) - * - * - * - * - * - * - * - * invert="0/1" - * - * - * - * - * - * - * - * - * - * - - - * .. - - * - * - * - */ - 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; } diff --git a/Devices/Options/Tuningoptions.cs b/Devices/Options/Tuningoptions.cs index 79c7d27..bb1d198 100644 --- a/Devices/Options/Tuningoptions.cs +++ b/Devices/Options/Tuningoptions.cs @@ -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 /// /// the XML action fragment /// True if an action was decoded - 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 */ - 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; } diff --git a/Devices/Joystick/UICustHeader.cs b/Devices/UICustHeader.cs similarity index 69% rename from Devices/Joystick/UICustHeader.cs rename to Devices/UICustHeader.cs index f382a63..0aaf524 100644 --- a/Devices/Joystick/UICustHeader.cs +++ b/Devices/UICustHeader.cs @@ -6,7 +6,7 @@ using System.Xml; using System.IO; using System.Xml.Linq; -namespace SCJMapper_V2.Devices.Joystick +namespace SCJMapper_V2.Devices { /// /// Maintains an CustomisationUIHeader - something like: @@ -28,10 +28,13 @@ namespace SCJMapper_V2.Devices.Joystick List m_stringOptions = new List( ); + 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 /// /// /// True if the clone is identical but not a shallow copy - 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 /// /// A deep Clone of this object - 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 /// /// /// True if the clone is identical but not a shallow copy - 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 /// /// the action as XML fragment - public string toXML( ) + public string toXML() { /* @@ -155,7 +158,7 @@ namespace SCJMapper_V2.Devices.Joystick string r = ""; - r += string.Format( "\t\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\n" ); @@ -191,16 +194,22 @@ namespace SCJMapper_V2.Devices.Joystick /// /// the XML action fragment /// True if an action was decoded - 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"]; + /* + + + + + + + */ + 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 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 here - }//while - + } return true; } @@ -223,49 +229,41 @@ namespace SCJMapper_V2.Devices.Joystick /// /// the XML action fragment /// True if an action was decoded - 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 - /* - * - * - * - * - */ - 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 here - } - + /* + + + + + + + + + + + + + */ + m_label = (string)cuiHeader.Attributes( ).First( a => a.Name == "label" ); // mandadory - else Exception + IEnumerable 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 elements = from x in cuiHeader.Elements( ) + where ( x.Name == "devices" ) + select x; + foreach ( XElement devices in elements ) { + Instance_fromXML( devices ); } return true; diff --git a/FormMain.cs b/FormMain.cs index ab1c6e2..5ddf01c 100644 --- a/FormMain.cs +++ b/FormMain.cs @@ -84,22 +84,22 @@ namespace SCJMapper_V2 /// /// Detects and returns the current Input device /// - 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... } } diff --git a/MappingVars.csv b/MappingVars.csv deleted file mode 100644 index 833b2fe..0000000 --- a/MappingVars.csv +++ /dev/null @@ -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;;;;;;;;;;;;;;;;;;;;;;; diff --git a/MappingVars.xlsx b/MappingVars.xlsx deleted file mode 100644 index 12f1605..0000000 Binary files a/MappingVars.xlsx and /dev/null differ diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs index 248c591..8908bb5 100644 --- a/Properties/AssemblyInfo.cs +++ b/Properties/AssemblyInfo.cs @@ -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" )] diff --git a/ReadMe.txt b/ReadMe.txt index ca7667b..9a935c1 100644 --- a/ReadMe.txt +++ b/ReadMe.txt @@ -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 \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 diff --git a/SC/DProfileReader.cs b/SC/DProfileReader.cs index 30d5b50..c3cf6c3 100644 --- a/SC/DProfileReader.cs +++ b/SC/DProfileReader.cs @@ -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 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 // carries the action list { - public string name { get; set; } // the map name + public string Name { get; set; } // the map name static int ContainsLoop( List 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 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 } - /// - /// Assumes to be in an action element - /// retrieves the attributes and collects the various control=binding pairs - /// - /// An XML reader @ StartElement - private void CollectActions( Dictionary 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 } } - - /// - /// Read one 'empty' XML element - /// - /// - /// - /// - /// An XML reader @ StartElement - /// True if reading can continue - private bool ReadEmptyElement( XmlReader xr ) + private void XInput( ref ProfileAction pa, XElement xml, string input ) { - Dictionary attr = new Dictionary( ); - 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( "\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; } /// - /// Reads an action sub element + /// Read all from an Action XElement /// - /// An XML reader @ StartElement - private void ReadActionSub( XmlReader xr, string actionName, string device ) + /// The action XElement + /// True if successfull + private bool ReadAction( XElement action ) { + /* A variety exists here... + + + + + + + + + + + + + + + + + */ + log.Debug( "DProfileReader.ReadAction - Entry" ); + // a complete actionmap arrives here + bool retVal = true; - /* - - - - or - - - - - or - - - - - - or - - - - - - - - - - - - */ - bool done = false; - do { - xr.Read( ); // get next element - Dictionary attr = new Dictionary( ); - // 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 - } - - /// - /// Read one XML element - /// - /// - /// [ Xelement ] - /// - /// - /// - /// An XML reader @ StartElement - /// True if reading can continue - private bool ReadElement( XmlReader xr ) - { - Dictionary attr = new Dictionary( ); - 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( "\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; } /// - /// Read the xml part + /// Read all from an Actionmap XElement /// - /// - /// - private bool ReadXML( XmlReader xr ) + /// The Actionmap XElement + /// True if successfull + 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 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( "\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; - } - } - - /* - // - // - ... - // - */ - 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 - - // - // - // - // - // - // - // - // - - // - // - // - - // - // - // - - // - - private bool ReadModifiers( XmlReader xr ) + /// + /// Read all from ActivationMode XElement + /// + /// The Activatiomodes XElement + /// True if successfull + private bool ReadActivationModes( XElement actmodes ) { - log.Debug( "DProfileReader.ReadModifiers - Entry" ); + /* + // + // + ... + // + */ + 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 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; } - /// /// Read the defaultProfile.xml - do some sanity check /// @@ -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( ); + // init the activation modes singleton + ActivationModes.Instance.Clear( ); + ActivationModes.Instance.Add( ActivationMode.Default ); - m_nodeNameStack = new Stack( ); - m_aMap = new Dictionary( ); - // 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 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 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 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 /// A filled SCActionMapList object 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 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; } diff --git a/SC/Modifiers.cs b/SC/Modifiers.cs index 828ad4d..7372b74 100644 --- a/SC/Modifiers.cs +++ b/SC/Modifiers.cs @@ -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 /// /// /// - 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; + /* + + + ... + + */ + IEnumerable 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; } diff --git a/SCJMapper-V2.csproj b/SCJMapper-V2.csproj index 80479ed..30b37b4 100644 --- a/SCJMapper-V2.csproj +++ b/SCJMapper-V2.csproj @@ -27,8 +27,8 @@ false false true - 67 - 2.33.0.%2a + 68 + 2.34.0.%2a false true @@ -125,6 +125,7 @@ + @@ -241,7 +242,7 @@ - + diff --git a/Table/DS_ActionMap.cs b/Table/DS_ActionMap.cs index ee9dc9e..9ecb11c 100644 --- a/Table/DS_ActionMap.cs +++ b/Table/DS_ActionMap.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; } diff --git a/Table/FormTable.cs b/Table/FormTable.cs index e241e94..da57d6a 100644 --- a/Table/FormTable.cs +++ b/Table/FormTable.cs @@ -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... diff --git a/actions/ActionCls.cs b/actions/ActionCls.cs index dad6623..eb187ae 100644 --- a/actions/ActionCls.cs +++ b/actions/ActionCls.cs @@ -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 ); - /// - /// Device Enums - /// - 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 - - /// - /// Return the Device Enum from a DeviceClass string - /// - /// Device Class string - /// Device Enum - 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 - - /// - /// Returns the Device Tag i.e. the single letter to mark a device in Actions - /// - /// The device name from the defaultProfile - /// The single UCase device Tag letter - 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"; - } - } - - /// - /// Returns the Device name from the Device Tag - /// - /// The single UCase device Tag letter - /// The device name from the defaultProfile - 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"; - } - } - - - /// - /// Try to derive the device class from the devInput string (mo1_, kb1_, xi1_, jsN_) - /// - /// The input command string dev_input format - /// A proper DeviceClass string - 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; - } - - /// - /// Returns the ActionDevice from a deviceID (a trailing _ is added if not there) - /// - /// DeviceID - /// The ActionDevice - static public ActionDevice ADeviceFromDevID( string devID ) - { - string val = devID; - if ( !devID.EndsWith( "_" ) ) val += "_"; - return ADevice( DeviceClassFromInput( val ) ); - } - - /// - /// Returns the ActionDevice from the devInput string (mo1_, kb1_, xi1_, jsN_) - /// - /// The input command string dev_input format - /// The ActionDevice - static public ActionDevice ADeviceFromInput( string devInput ) - { - return ADevice( DeviceClassFromInput( devInput ) ); - } - - /// - /// Query the devices if the input is blended - /// - /// The input command - /// True if blended input - 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; - } - - /// - /// Blend the input using the device specific format of the input is generic Blind - /// - /// An input (generic blend or a valid command) - /// A valid device - /// A device blend or the original input if it was not a blend - 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 - } - } - - /// - /// Extends the input to a device input if not already done - /// - /// An input - /// The ActionDevice - /// A valid devInput (dev_input) format - 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; - } - } - - /// - /// Return the color of a device - /// - /// The devinput (determine JS colors) - /// The ActionDevice - /// The device color - 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 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 InputList { get; set; } // regular bind is the 0-element, addbinds are added to the list /// /// 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 /// public ActionCls() { - key = ""; - actionDevice = ActionDevice.AD_Unknown; - device = JoystickCls.DeviceClass; - name = ""; - defBinding = ""; - defActivationMode = ActivationMode.Default; - inputList = new List( ); // empty list + Key = ""; + ActionDevice = Act.ActionDevice.AD_Unknown; + Device = JoystickCls.DeviceClass; + Name = ""; + DefBinding = ""; + DefActivationMode = ActivationMode.Default; + InputList = new List( ); // empty list } @@ -316,9 +112,9 @@ namespace SCJMapper_V2.Actions /// Returns the ActionCommand created 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 /// 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) /// /// The input command + /// The input index to update 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 /// /// Find an ActionCommand with index in an Action /// - /// The input + /// The input index to find /// An actionCommand or null if not found 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\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\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 } /// - /// Read an action from XML - do some sanity check + /// Read an action from XML - do some sanity checks /// /// the XML action fragment /// True if an action was decoded - 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; } diff --git a/actions/ActionCommandCls.cs b/actions/ActionCommandCls.cs index 11e1cd3..6fc570d 100644 --- a/actions/ActionCommandCls.cs +++ b/actions/ActionCommandCls.cs @@ -166,11 +166,11 @@ namespace SCJMapper_V2.Actions /// Updates an actionCommand with a new input (command) /// /// The input command - 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 } } diff --git a/actions/ActionMapCls.cs b/actions/ActionMapCls.cs index 5ce17f1..1c07340 100644 --- a/actions/ActionMapCls.cs +++ b/actions/ActionMapCls.cs @@ -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; } /// /// Copy return the complete ActionMap while reassigning the JsN Tag @@ -34,7 +35,7 @@ namespace SCJMapper_V2.Actions /// The ActionMap copy with reassigned input 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() { } /// /// 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 /// /// the action as XML fragment - 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\n", name ); + string r = string.Format( "\t\n", Name ); r += acs; r += string.Format( "\t\n" ); return r; @@ -100,33 +102,14 @@ namespace SCJMapper_V2.Actions /// /// the XML action fragment /// True if an action was decoded - 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; } diff --git a/actions/ActionMapsCls.cs b/actions/ActionMapsCls.cs index bf49e20..7921a70 100644 --- a/actions/ActionMapsCls.cs +++ b/actions/ActionMapsCls.cs @@ -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 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 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 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 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 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; diff --git a/actions/ActionTree.cs b/actions/ActionTree.cs index 1a1d2f3..65cfea4 100644 --- a/actions/ActionTree.cs +++ b/actions/ActionTree.cs @@ -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 /// /// The new Text property - 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; } - - - /// /// Find an action with name in a actionmap /// @@ -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; } - /// /// Defines what to show in the tree /// @@ -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 ret = new List( ); 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 } diff --git a/actions/ActionTreeInputNode.cs b/actions/ActionTreeInputNode.cs index 2c1601d..3be52bd 100644 --- a/actions/ActionTreeInputNode.cs +++ b/actions/ActionTreeInputNode.cs @@ -7,7 +7,7 @@ using System.Windows.Forms; namespace SCJMapper_V2.Actions { /// - /// 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) /// @@ -61,8 +61,7 @@ namespace SCJMapper_V2.Actions /// the command part or an empty string 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 =""; - + /// + /// Property Text of an Input node + /// 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 + /// + /// Property Command of an Input node + /// { get { return m_command; } set diff --git a/actions/ActionTreeNode.cs b/actions/ActionTreeNode.cs index 6cc5fcb..1b3640c 100644 --- a/actions/ActionTreeNode.cs +++ b/actions/ActionTreeNode.cs @@ -10,24 +10,25 @@ using SCJMapper_V2.Devices; namespace SCJMapper_V2.Actions { /// - /// Our TreeNode - inherits a regular one and adds some functionality + /// Our TreeNode - inherits a regular TreeNode one and adds some functionality /// 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 ) + /// + /// Decompose from node.Text to the individual parts + /// e.g. v_eject - js1_button1 # => v_eject, js1_button1 + /// + /// The node Text + /// The action + /// The device command + 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 /// /// The node text in 'action - command' notation /// the action part or an empty string - 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 /// /// The node text in 'action - command' notation /// the command part or an empty string - 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; /// @@ -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 + /// + /// Property Text of an Action node + /// + public new string Text { get { return base.Text; } set @@ -197,7 +205,10 @@ namespace SCJMapper_V2.Actions } - public String Action + /// + /// Property Action of an Action node + /// + public string Action { get { return m_action; } set @@ -207,7 +218,10 @@ namespace SCJMapper_V2.Actions } } - public String Command + /// + /// Property Command of an Action node + /// + public string Command { get { return m_command; } set @@ -217,7 +231,10 @@ namespace SCJMapper_V2.Actions } } - public ActionCls.ActionDevice ActionDevice + /// + /// Property ActionDevice of an Action node + /// + public Act.ActionDevice ActionDevice { get { return m_actionDevice; } set @@ -226,7 +243,10 @@ namespace SCJMapper_V2.Actions } } - public Boolean Modified + /// + /// Property Modified of an Action node + /// + public bool Modified { get { return m_modified; } set @@ -237,43 +257,55 @@ namespace SCJMapper_V2.Actions } - public Boolean IsJoystickAction + /// + /// Property IsJoystickAction of an Action node + /// + public bool IsJoystickAction { - get { return ( m_actionDevice == ActionCls.ActionDevice.AD_Joystick ); } + get { return ( m_actionDevice == Act.ActionDevice.AD_Joystick ); } } - public Boolean IsGamepadAction + /// + /// Property IsGamepadAction of an Action node + /// + public bool IsGamepadAction { - get { return ( m_actionDevice == ActionCls.ActionDevice.AD_Gamepad ); } + get { return ( m_actionDevice == Act.ActionDevice.AD_Gamepad ); } } - public Boolean IsKeyboardAction + /// + /// Property IsKeyboardAction of an Action node + /// + 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) + /// + /// Property IsMouseAction of an Action node + /// + 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 ); } } /// /// Returns true if the action is mapped /// - 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 ) ); } } /// /// Returns true if the action is disabled /// - public Boolean IsDisabledAction + public bool IsDisabledAction { get { - return ActionCls.IsBlendedInput( m_command ); + return Act.IsDisabledInput( m_command ); } }