From ffe5005c2b27b0d688405ef0d3c33f509b72a717 Mon Sep 17 00:00:00 2001 From: bm98 Date: Sat, 15 Apr 2017 00:33:21 +0200 Subject: [PATCH] PreRelease Build 62 saved on git updates of dev tuning for strafe #48 improvement of control and selection #49 fix exception for multiple actionmaps #51 improvement for collapsing the treeview added Options dialog for all items in one window some minor fixes/refacturings on the way --- CloneableItems.cs | 33 ++ DeviceCls.cs | 20 + DeviceInst.cs | 100 +++++ FormMain.Designer.cs | 4 +- FormMain.cs | 494 ++++++++++-------------- Gamepad/GamepadCls.cs | 87 +++-- Joystick/FormReassign.cs | 5 +- Joystick/JoystickCls.cs | 58 ++- Joystick/JoystickList.cs | 86 ++++- Joystick/JsReassingList.cs | 2 +- Joystick/UICustHeader.cs | 127 +++++-- Keyboard/KeyboardCls.cs | 56 +-- Mouse/MouseCls.cs | 48 ++- OGL/FormJSCalCurve.cs | 73 ++-- Options/DeviceOptionParameter.cs | 119 +++++- Options/DeviceTuningParameter.cs | 128 +++++-- Options/Deviceoptions.cs | 125 ++++++- Options/FormOptions.Designer.cs | 45 +-- Options/FormOptions.cs | 622 +++++++++++++++++++------------ Options/OptionTree.cs | 117 ++++-- Options/Tuningoptions.cs | 331 ++++++++++++++++ README.md | 1 + SC/ActivationModes.cs | 23 +- SC/DProfileReader.cs | 67 ++-- SC/SCDefaultProfile.cs | 4 +- SCJMapper-V2.csproj | 3 + SCJMapper-V2.sln | 2 +- actions/ActionCls.cs | 111 +++--- actions/ActionCommandCls.cs | 102 ++--- actions/ActionMapCls.cs | 43 ++- actions/ActionMapsCls.cs | 155 ++++---- actions/ActionTree.cs | 112 +++--- actions/MyColors.cs | 30 +- defaultProfile.xml | 575 ++++++++++++++-------------- 34 files changed, 2460 insertions(+), 1448 deletions(-) create mode 100644 CloneableItems.cs create mode 100644 DeviceInst.cs create mode 100644 Options/Tuningoptions.cs diff --git a/CloneableItems.cs b/CloneableItems.cs new file mode 100644 index 0000000..d3be3bf --- /dev/null +++ b/CloneableItems.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SCJMapper_V2 +{ + public class CloneableDictionary : Dictionary where TValue : ICloneable + { + public virtual object Clone( ) + { + CloneableDictionary clone = new CloneableDictionary(); + foreach ( KeyValuePair kvp in this ) { + clone.Add( kvp.Key, ( TValue )kvp.Value.Clone( ) ); + } + return clone; + } + } + + public class CloneableList : List where TValue : ICloneable + { + public virtual CloneableList Clone( ) + { + CloneableList clone = new CloneableList(); + foreach ( TValue kvp in this ) { + clone.Add( ( TValue )kvp.Clone( ) ); + } + return clone; + } + } + +} diff --git a/DeviceCls.cs b/DeviceCls.cs index 41df763..95847df 100644 --- a/DeviceCls.cs +++ b/DeviceCls.cs @@ -27,8 +27,28 @@ namespace SCJMapper_V2 static public string DevInput( string input ) { return input; } static public bool DevMatch( string devInput ) { return false; } + /// + /// Return the CIG instance number (which is the jsN number) - 1 based + /// + public abstract int XmlInstance { get; } // holds the CIG instance to be used throughout + /// + /// The DeviceClass of this instance + /// public abstract string DevClass { get; } + /// + /// The DX ProductName property + /// public abstract string DevName { get; } + + /// + /// The DX instance number of the object (from enum) - 0 based + /// + public abstract int DevInstance { get; } + /// + /// The DX GUID of the device + /// + public abstract string DevInstanceGUID { get; } + public abstract System.Drawing.Color MapColor { get; } public virtual List AnalogCommands { get { return new List( ); } } // just return an empty one if not implemented diff --git a/DeviceInst.cs b/DeviceInst.cs new file mode 100644 index 0000000..de210dc --- /dev/null +++ b/DeviceInst.cs @@ -0,0 +1,100 @@ +using SCJMapper_V2.Gamepad; +using SCJMapper_V2.Joystick; +using SCJMapper_V2.Keyboard; +using SCJMapper_V2.Mouse; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SCJMapper_V2 +{ + /// + /// Collects and provides the device instances throughout the application + /// Remark: pls use the ..Ref properties unless assiging the instance + /// + public sealed class DeviceInst + { + /// + /// Holds the DXInput Joystick List + /// + static private JoystickList m_Joystick = new JoystickList( ); + static public JoystickList JoystickListInst + { + get => m_Joystick; + } + /// + /// Provides the JoystickList of instances found in this system + /// + static public JoystickList JoystickListRef + { + get => m_Joystick; + } + + /// + /// Holds the DXInput Joystick List + /// + static private JoystickCls m_curJoystick = null; + static public JoystickCls JoystickInst + { + set => m_curJoystick = value; + } + /// + /// Provides the 'current' Joystick instance + /// + static public JoystickCls JoystickRef + { + get => m_curJoystick; + } + + /// + /// Holds the DXInput keyboard + /// + static private GamepadCls m_Gamepad = null; + static public GamepadCls GamepadInst + { + set => m_Gamepad = value; + } + /// + /// Provides the first Gamepad instance found in this system + /// + static public GamepadCls GamepadRef + { + get => m_Gamepad; + } + + /// + /// Holds the DXInput keyboard + /// + static private KeyboardCls m_Keyboard = null; + static public KeyboardCls KeyboardInst + { + set => m_Keyboard = value; + } + /// + /// Provides the first Keyboard instance found in this system + /// + static public KeyboardCls KeyboardRef + { + get => m_Keyboard; + } + + /// + /// Holds the DXInput mouse + /// + static private MouseCls m_Mouse = null; + static public MouseCls MouseInst + { + set => m_Mouse = value; + } + /// + /// Provides the first Mouse instance found in this system + /// + static public MouseCls MouseRef + { + get => m_Mouse; + } + + } +} diff --git a/FormMain.Designer.cs b/FormMain.Designer.cs index 1d76027..c6dc0f3 100644 --- a/FormMain.Designer.cs +++ b/FormMain.Designer.cs @@ -15,8 +15,8 @@ { timer1.Stop( ); // Unacquire all DirectInput objects. - foreach ( Joystick.JoystickCls js in m_Joystick ) js.FinishDX( ); - m_Joystick.Clear( ); + foreach ( Joystick.JoystickCls js in DeviceInst.JoystickListRef ) js.FinishDX( ); + DeviceInst.JoystickListRef.Clear( ); if ( disposing && ( components != null ) ) { components.Dispose( ); diff --git a/FormMain.cs b/FormMain.cs index bf49b1f..026cd73 100644 --- a/FormMain.cs +++ b/FormMain.cs @@ -27,49 +27,27 @@ namespace SCJMapper_V2 private const string c_GithubLink = @"https://github.com/SCToolsfactory/SCJMapper-V2/releases"; private AppSettings m_AppSettings = new AppSettings( ); - private Boolean m_appLoading = true; // used to detect if we are loading (or running) + private bool m_appLoading = true; // used to detect if we are loading (or running) // keyboard modifier handling variables private string m_persistentMods = ""; private const int c_modifierTime = 3500; // msec time before a modifier times out and will be removed private int m_modifierTimeout = 0; - - /// - /// Holds the DXInput Joystick List - /// - private JoystickList m_Joystick = new JoystickList( ); - - /// - /// Holds the currently selected Joystick - /// - private JoystickCls m_curJoystick = null; - - /// - /// Holds the DXInput keyboard - /// - private GamepadCls m_Gamepad = null; - /// - /// Holds the DXInput keyboard + /// Holds the ActionTree that manages the TreeView and the action lists /// - private KeyboardCls m_Keyboard = null; + private ActionTree m_AT = null; /// - /// Holds the DXInput mouse + /// Holds the Tuning Form /// - private MouseCls m_Mouse = null; - + private OGL.FormJSCalCurve JSCAL = null; /// - /// Holds the ActionTree that manages the TreeView and the action lists + /// Holds the Table Form /// - private ActionTree m_AT = null; - - - private OGL.FormJSCalCurve JSCAL = null; - private FormTable FTAB = null; #region Tools section @@ -90,11 +68,11 @@ namespace SCJMapper_V2 /// /// The tab page /// True if it is the Gamepad Tab - private Boolean IsGamepadTab( TabPage page ) + private bool IsGamepadTab( TabPage page ) { // catch if the Tag is not an int... try { - return ( ( int )page.Tag == ID_GAMEPAD_TAB ); + return ( (int)page.Tag == ID_GAMEPAD_TAB ); } catch { return false; } @@ -126,9 +104,9 @@ namespace SCJMapper_V2 /// Get the current JsN string for the active device tab /// /// The jsN string - can be jsx, js1..jsN - private string JSStr( ) + private string JSStr() { - UC_JoyPanel jp = ( UC_JoyPanel )( tc1.SelectedTab.Controls["UC_JoyPanel"] ); + UC_JoyPanel jp = (UC_JoyPanel)( tc1.SelectedTab.Controls["UC_JoyPanel"] ); return jp.JsName; } @@ -138,13 +116,13 @@ namespace SCJMapper_V2 #region Main Form Handling - public MainForm( ) + public MainForm() { try { // Load the icon from our resources System.Resources.ResourceManager resources = new System.Resources.ResourceManager( this.GetType( ) ); - this.Icon = ( ( System.Drawing.Icon )( resources.GetObject( "$this.Icon" ) ) ); + this.Icon = ( (System.Drawing.Icon)( resources.GetObject( "$this.Icon" ) ) ); } catch { ; // well... } @@ -156,19 +134,19 @@ namespace SCJMapper_V2 private void MainForm_Deactivate( object sender, EventArgs e ) { timer1.Enabled = false; - if ( m_Joystick != null ) m_Joystick.Deactivate( ); - if ( m_Keyboard != null ) m_Keyboard.Deactivate( ); + if ( DeviceInst.JoystickListRef != null ) DeviceInst.JoystickListRef.Deactivate( ); + if ( DeviceInst.KeyboardRef != null ) DeviceInst.KeyboardRef.Deactivate( ); } private void MainForm_Activated( object sender, EventArgs e ) { timer1.Enabled = true; - if ( m_Joystick != null ) m_Joystick.Activate( ); - if ( m_Keyboard != null ) m_Keyboard.Activate( ); + if ( DeviceInst.JoystickListRef != null ) DeviceInst.JoystickListRef.Activate( ); + if ( DeviceInst.KeyboardRef != null ) DeviceInst.KeyboardRef.Activate( ); } - private void LoadMappingDD( ) + private void LoadMappingDD() { SCMappings.UpdateMappingNames( ); tsDDbtMappings.DropDownItems.Clear( ); @@ -180,7 +158,7 @@ namespace SCJMapper_V2 /// /// Indicates if the SC directory is a valid one /// - private void SCFileIndication( ) + private void SCFileIndication() { if ( string.IsNullOrEmpty( SCPath.SCClientMappingPath ) ) tsDDbtMappings.BackColor = MyColors.InvalidColor; else tsDDbtMappings.BackColor = MyColors.MappingColor; @@ -258,9 +236,9 @@ namespace SCJMapper_V2 } // load Mouse menu strip - if ( m_Mouse != null ) { - for ( int i = 0; i < m_Mouse.NumberOfButtons; i++ ) { - ToolStripMenuItem ts = new ToolStripMenuItem("Button " + ( i + 1 ).ToString( ), null, new EventHandler( tmeItem_Click )); + if ( DeviceInst.MouseRef != null ) { + for ( int i = 0; i < DeviceInst.MouseRef.NumberOfButtons; i++ ) { + ToolStripMenuItem ts = new ToolStripMenuItem( "Button " + ( i + 1 ).ToString( ), null, new EventHandler( tmeItem_Click ) ); ts.Tag = ( i + 1 ).ToString( ); cmMouseEntry.Items.Add( ts ); } @@ -275,8 +253,8 @@ namespace SCJMapper_V2 cbxShowMappedOnly.Checked = m_AppSettings.ShowMapped; // init current Joystick - int jsIndex = ( int )tc1.SelectedTab.Tag; // gets the index into the JS list - if ( jsIndex >= 0 ) m_curJoystick = m_Joystick[jsIndex]; + int jsIndex = (int)tc1.SelectedTab.Tag; // gets the index into the JS list + if ( jsIndex >= 0 ) DeviceInst.JoystickInst = DeviceInst.JoystickListRef[jsIndex]; // init PTU folder usage sign lblPTU.Visible = m_AppSettings.UsePTU; @@ -293,7 +271,7 @@ namespace SCJMapper_V2 /// /// Handles the Exit button /// - private void buttonExit_Click( object sender, System.EventArgs e ) + private void buttonExit_Click( object sender, EventArgs e ) { log.Debug( "Shutting down now..." ); Close( ); @@ -305,25 +283,25 @@ namespace SCJMapper_V2 private void tc1_Selected( object sender, TabControlEventArgs e ) { // init current Joystick - int jsIndex = ( int )tc1.SelectedTab.Tag; // gets the index into the JS list + int jsIndex = (int)tc1.SelectedTab.Tag; // gets the index into the JS list if ( jsIndex >= 0 ) - m_curJoystick = m_Joystick[jsIndex]; + DeviceInst.JoystickInst = DeviceInst.JoystickListRef[jsIndex]; else - m_curJoystick = null; + DeviceInst.JoystickInst = null; } /// /// Fancy tab coloring with ownerdraw to paint the callout buttons /// - private void tc1_DrawItem( object sender, System.Windows.Forms.DrawItemEventArgs e ) + private void tc1_DrawItem( object sender, DrawItemEventArgs e ) { try { //This line of code will help you to change the apperance like size,name,style. Font f; //For background color - Brush backBrush = new System.Drawing.SolidBrush( MyColors.TabColor[e.Index] ); + Brush backBrush = new SolidBrush( MyColors.TabColor[e.Index] ); //For forground color - Brush foreBrush = new SolidBrush( System.Drawing.Color.Black ); + Brush foreBrush = new SolidBrush( Color.Black ); //This construct will hell you to deside which tab page have current focus @@ -380,13 +358,13 @@ namespace SCJMapper_V2 /// /// Resets the Action Tree /// - private void InitActionTree( Boolean addDefaultBinding ) + private void InitActionTree( bool addDefaultBinding ) { log.Debug( "InitActionTree - Entry" ); // build TreeView and the ActionMaps if ( m_AT != null ) m_AT.NodeSelectedEvent -= M_AT_NodeSelectedEvent; // disconnect the Event - m_AT = new ActionTree( m_Joystick, m_Gamepad ); + m_AT = new ActionTree( ); m_AT.NodeSelectedEvent += M_AT_NodeSelectedEvent; // connect the Event m_AT.Ctrl = treeView1; // the ActionTree owns the TreeView control @@ -404,18 +382,18 @@ namespace SCJMapper_V2 // apply a default JS to Joystick mapping - can be changed and reloaded from XML mappings // must take care of Gamepads if there are (but we take care of one only...) - + //@@@@@@@ int joyStickIndex = 0; // Joystick List Index for ( int deviceTabIndex = 0; deviceTabIndex < JoystickCls.JSnum_MAX; deviceTabIndex++ ) { if ( tc1.TabPages.Count > deviceTabIndex ) { // valid Device Tab if ( IsGamepadTab( tc1.TabPages[deviceTabIndex] ) ) { ; // ignore gamepads - } else if ( m_Joystick.Count > joyStickIndex ) { + } else if ( DeviceInst.JoystickListRef.Count > joyStickIndex ) { // there is a joystick device left.. - m_Joystick[joyStickIndex].JSAssignment = joyStickIndex + 1; // assign number 1.. - m_AT.ActionMaps.jsN[deviceTabIndex] = m_Joystick[joyStickIndex].DevName; - m_AT.ActionMaps.jsNGUID[deviceTabIndex] = m_Joystick[joyStickIndex].DevInstanceGUID; + DeviceInst.JoystickListRef[joyStickIndex].JSAssignment = joyStickIndex + 1; // assign number 1.. + m_AT.ActionMaps.jsN[deviceTabIndex] = DeviceInst.JoystickListRef[joyStickIndex].DevName; + m_AT.ActionMaps.jsNGUID[deviceTabIndex] = DeviceInst.JoystickListRef[joyStickIndex].DevInstanceGUID; joyStickIndex++; } } @@ -425,16 +403,22 @@ namespace SCJMapper_V2 + // Helper: collect the joysticks here + struct myDxJoystick + { + public SharpDX.DirectInput.Joystick js; + public string prodName; + } + /// /// Aquire the DInput joystick devices /// /// - public bool InitDirectInput( ) + public bool InitDirectInput() { log.Debug( "Entry" ); - // Enumerate joysticks in the system. - int tabs = 0; + // Enumerate gamepads in the system. SharpDX.XInput.UserIndex gpDeviceIndex = SharpDX.XInput.UserIndex.Any; // Initialize DirectInput @@ -443,109 +427,106 @@ namespace SCJMapper_V2 try { log.Debug( "Get Keyboard device" ); - m_Keyboard = new KeyboardCls( new SharpDX.DirectInput.Keyboard( directInput ), this ); + DeviceInst.KeyboardInst = new KeyboardCls( new SharpDX.DirectInput.Keyboard( directInput ), this ); log.Debug( "Get Mouse device" ); - m_Mouse = new MouseCls( new SharpDX.DirectInput.Mouse( directInput ), this ); + DeviceInst.MouseInst = new MouseCls( new SharpDX.DirectInput.Mouse( directInput ), this ); } catch ( Exception ex ) { log.Debug( "InitDirectInput phase 1 failed unexpectedly", ex ); return false; } + + List dxJoysticks = new List( ); + SharpDX.XInput.Controller dxGamepad = null; + try { // scan the Input for attached devices log.Debug( "Scan GameControl devices" ); - int nJs = 1; // number the Joystick Tabs foreach ( DeviceInstance instance in directInput.GetDevices( DeviceClass.GameControl, DeviceEnumerationFlags.AttachedOnly ) ) { - - log.InfoFormat( "GameControl: #{0} Type:{1} Device:{2}", tabs, instance.Type.ToString( ), instance.ProductName ); + log.InfoFormat( "GameControl: Type:{0} Device:{1}", instance.Type.ToString( ), instance.ProductName ); // Create the device interface log.Debug( "Create the device interface" ); - SharpDX.DirectInput.Joystick jsDevice = null; - SharpDX.XInput.Controller gpDevice = null; - JoystickCls js = null; GamepadCls gs = null; if ( m_AppSettings.DetectGamepad && ( instance.Usage == SharpDX.Multimedia.UsageId.GenericGamepad ) ) { // detect Gamepad only if the user wishes to do so for ( SharpDX.XInput.UserIndex i = SharpDX.XInput.UserIndex.One; i < SharpDX.XInput.UserIndex.Four; i++ ) { - gpDevice = new SharpDX.XInput.Controller( i ); - if ( gpDevice.IsConnected ) { - log.InfoFormat( "Scan Input {0} for gamepad - {1}", i, gpDevice.GetCapabilities( SharpDX.XInput.DeviceQueryType.Gamepad ).ToString( ) ); + dxGamepad = new SharpDX.XInput.Controller( i ); + if ( dxGamepad.IsConnected ) { + log.InfoFormat( "Scan Input {0} for gamepad - {1}", i, dxGamepad.GetCapabilities( SharpDX.XInput.DeviceQueryType.Gamepad ).ToString( ) ); gpDeviceIndex = i; - break; + break; // get only the first one } } } else { - jsDevice = new SharpDX.DirectInput.Joystick( directInput, instance.InstanceGuid ); - log.DebugFormat( "Create the device interface for: {0}", jsDevice.Information.ProductName ); + myDxJoystick myJs = new myDxJoystick( ); + myJs.js = new SharpDX.DirectInput.Joystick( directInput, instance.InstanceGuid ); + myJs.prodName = instance.ProductName; + dxJoysticks.Add( myJs ); + log.DebugFormat( "Create the device interface for: {0}", myJs.prodName ); } - - // we have the first tab made as reference so TabPage[0] already exists - if ( tabs == 0 ) { - // first panel - The Tab content exists already - if ( gpDevice != null ) { - log.Debug( "Add first Gamepad panel" ); - tc1.TabPages[tabs].Text = "Gamepad "; - UC_GpadPanel uUC_GpadPanelNew = new UC_GpadPanel( ); tc1.TabPages[tabs].Controls.Add( uUC_GpadPanelNew ); - uUC_GpadPanelNew.Size = UC_JoyPanel.Size; uUC_GpadPanelNew.Location = UC_JoyPanel.Location; - UC_JoyPanel.Enabled = false; UC_JoyPanel.Visible = false; // don't use this one - log.Debug( "Create Gamepad instance" ); - gs = new GamepadCls( gpDevice, uUC_GpadPanelNew, tabs ); // does all device related activities for that particular item - gs.SetDeviceName( instance.ProductName ); - tc1.TabPages[tabs].ToolTipText = string.Format( "{0}\n{1}", gs.DevName, " " ); - toolTip1.SetToolTip( tc1.TabPages[tabs], tc1.TabPages[tabs].ToolTipText ); - } else { - log.Debug( "Add first Joystick panel" ); - log.Debug( "Create Joystick instance" ); - tc1.TabPages[tabs].Text = string.Format( "Joystick {0}", nJs++ ); - js = new JoystickCls( jsDevice, this, tabs + 1, UC_JoyPanel, tabs ); // does all device related activities for that particular item - tc1.TabPages[tabs].ToolTipText = string.Format( "{0}\n{1}", js.DevName, js.DevInstanceGUID ); - toolTip1.SetToolTip( tc1.TabPages[tabs], tc1.TabPages[tabs].ToolTipText ); - } - } else { - if ( gpDevice != null ) { - log.Debug( "Add next Gamepad panel" ); - tc1.TabPages.Add( "Gamepad " ); - UC_GpadPanel uUC_GpadPanelNew = new UC_GpadPanel( ); tc1.TabPages[tabs].Controls.Add( uUC_GpadPanelNew ); - uUC_GpadPanelNew.Size = UC_JoyPanel.Size; uUC_GpadPanelNew.Location = UC_JoyPanel.Location; - log.Debug( "Create Gamepad instance" ); - gs = new GamepadCls( gpDevice, uUC_GpadPanelNew, tabs ); // does all device related activities for that particular item - gs.SetDeviceName( instance.ProductName ); - tc1.TabPages[tabs].ToolTipText = string.Format( "{0}\n{1}", gs.DevName, " " ); - toolTip1.SetToolTip( tc1.TabPages[tabs], tc1.TabPages[tabs].ToolTipText ); - } else { - log.Debug( "Add next Joystick panel" ); - // setup the further tab contents along the reference one in TabPage[0] (the control named UC_JoyPanel) - tc1.TabPages.Add( string.Format( "Joystick {0}", nJs++ ) ); - UC_JoyPanel uUC_JoyPanelNew = new UC_JoyPanel( ); tc1.TabPages[tabs].Controls.Add( uUC_JoyPanelNew ); - uUC_JoyPanelNew.Size = UC_JoyPanel.Size; uUC_JoyPanelNew.Location = UC_JoyPanel.Location; - log.Debug( "Create Joystick instance" ); - js = new JoystickCls( jsDevice, this, tabs + 1, uUC_JoyPanelNew, tabs ); // does all device related activities for that particular item - tc1.TabPages[tabs].ToolTipText = string.Format( "{0}\n{1}", js.DevName, js.DevInstanceGUID ); - toolTip1.SetToolTip( tc1.TabPages[tabs], tc1.TabPages[tabs].ToolTipText ); - } - } - - if ( gpDevice != null ) { - m_Gamepad = gs; - SetGamepadTab( tc1.TabPages[tabs] ); // indicates the gamepad tab (murks..) - MyColors.GamepadColor = MyColors.TabColor[tabs]; // save it for future use - } else if ( js != null ) { - m_Joystick.Add( js ); // add to joystick list - tc1.TabPages[tabs].Tag = ( m_Joystick.Count - 1 ); // used to find the tab for polling - } - tc1.TabPages[tabs].BackColor = MyColors.TabColor[tabs]; // each tab has its own color - - // next tab - tabs++; - if ( tabs >= JoystickCls.JSnum_MAX ) break; // cannot load more JSticks than predefined Tabs } - log.DebugFormat( "Added {0} GameControl devices", tabs ); } catch ( Exception ex ) { log.Debug( "InitDirectInput phase 2 failed unexpectedly", ex ); return false; } + + int tabs = 0; + // make the GP the first device if there is one. + if ( dxGamepad != null ) { + log.Debug( "Add first Gamepad panel" ); + tc1.TabPages[tabs].Text = "Gamepad "; + UC_GpadPanel uUC_GpadPanelNew = new UC_GpadPanel( ); tc1.TabPages[tabs].Controls.Add( uUC_GpadPanelNew ); + uUC_GpadPanelNew.Size = UC_JoyPanel.Size; uUC_GpadPanelNew.Location = UC_JoyPanel.Location; + UC_JoyPanel.Enabled = false; UC_JoyPanel.Visible = false; // don't use this one + log.Debug( "Create Gamepad instance" ); + DeviceInst.GamepadInst = new GamepadCls( dxGamepad, uUC_GpadPanelNew, tabs ); // does all device related activities for that particular item + DeviceInst.GamepadRef.SetDeviceName( GamepadCls.DevNameCIG ); // this is fixed ... + tc1.TabPages[tabs].ToolTipText = string.Format( "{0}\n{1}", DeviceInst.GamepadRef.DevName, " " ); + toolTip1.SetToolTip( tc1.TabPages[tabs], tc1.TabPages[tabs].ToolTipText ); + + SetGamepadTab( tc1.TabPages[tabs] ); // indicates the gamepad tab (murks..) + MyColors.TabColor[tabs] = MyColors.GamepadColor; // save it for future use of tab coloring (drawing) + tc1.TabPages[tabs].BackColor = MyColors.TabColor[tabs]; + + tabs++; // next tab + } + + // do all joysticks + int nJs = 0; // number the Joystick Tabs + foreach ( myDxJoystick myJs in dxJoysticks ) { + // we have the first tab made as reference so TabPage[0] already exists + JoystickCls js = null; UC_JoyPanel uUC_JoyPanelNew = null; + if ( tabs == 0 ) { + // first panel - The Tab content exists already + log.Debug( "Add first Joystick panel" ); + uUC_JoyPanelNew = UC_JoyPanel; + } else { + log.Debug( "Add next Joystick panel" ); + // setup the further tab contents along the reference one in TabPage[0] (the control named UC_JoyPanel) + tc1.TabPages.Add( "" ); // numbering is 1 based for the user + uUC_JoyPanelNew = new UC_JoyPanel( ); tc1.TabPages[tabs].Controls.Add( uUC_JoyPanelNew ); + uUC_JoyPanelNew.Size = UC_JoyPanel.Size; uUC_JoyPanelNew.Location = UC_JoyPanel.Location; + } + // common part + tc1.TabPages[tabs].Text = string.Format( "Joystick {0}", nJs + 1 ); // numbering is 1 based for the user + log.Debug( "Create Joystick instance " + nJs.ToString( ) ); + js = new JoystickCls( myJs.js, this, nJs, uUC_JoyPanelNew, tabs ); // does all device related activities for that particular item + DeviceInst.JoystickListRef.Add( js ); // add to joystick list + tc1.TabPages[tabs].ToolTipText = string.Format( "{0}\n{1}", js.DevName, js.DevInstanceGUID ); + toolTip1.SetToolTip( tc1.TabPages[tabs], tc1.TabPages[tabs].ToolTipText ); + tc1.TabPages[tabs].BackColor = MyColors.TabColor[tabs]; + tc1.TabPages[tabs].Tag = js.DevInstance; // used to find the tab for polling + + nJs++; // next joystick + // next Joystick tab + tabs++; + if ( tabs >= JoystickCls.JSnum_MAX ) break; // cannot load more JSticks than predefined Tabs + } + + log.DebugFormat( "Added {0} GameControl devices", tabs ); + if ( tabs == 0 ) { log.Warn( "Unable to find and/or create any joystick devices." ); MessageBox.Show( "Unable to create a joystick device. Program will exit.", "No joystick found", MessageBoxButtons.OK, MessageBoxIcon.Information ); @@ -556,7 +537,6 @@ namespace SCJMapper_V2 log.Debug( "Init ActionTree" ); InitActionTree( true ); - return true; } @@ -568,12 +548,12 @@ namespace SCJMapper_V2 /// /// Grab the rtb data and load them into config /// - private void Grab( ) + private void Grab() { log.Debug( "Grab - Entry" ); - m_Joystick.ResetJsNAssignment( ); m_AT.ActionMaps.fromXML( rtb.Text ); + // Collect modifiers - simply overwrite existing ones as we deal with THIS file now tdiAddMod1.Visible = false; tdiAddMod2.Visible = false; tdiAddMod3.Visible = false; // make context menu invisible tdiAddMod1.Text = ""; tdiAddMod2.Text = ""; tdiAddMod3.Text = ""; // and clear @@ -601,37 +581,6 @@ namespace SCJMapper_V2 } */ - // JS mapping for js1 .. js8 can be changed and reloaded from XML - // note - unmapped ones remain what they were - // This is includes similar procedures as reassigning of the jsN items - JoystickCls j = null; - - m_Joystick.ClearJsNAssignment( ); - // for all supported jsN - for ( int i = 0; i < JoystickCls.JSnum_MAX; i++ ) { - j = null; - if ( !string.IsNullOrEmpty( m_AT.ActionMaps.jsNGUID[i] ) ) j = m_Joystick.Find_jsInstance( m_AT.ActionMaps.jsNGUID[i] ); - else if ( !string.IsNullOrEmpty( m_AT.ActionMaps.jsN[i] ) ) j = m_Joystick.Find_jsDev( m_AT.ActionMaps.jsN[i] ); - - if ( j != null ) { - m_AT.ActionMaps.jsNGUID[i] = j.DevInstanceGUID; // subst for missing one (version up etc.) - j.JSAssignment = i + 1; // i is 0 based ; jsN is 1 based - } else { - // a valid but unknown GUID - - m_AT.ActionMaps.Clear_jsEntry( i ); - } - } - - - // maintain the new JsN assignment and update the colorlist - List newL = new List( ); - foreach ( TabPage tp in tc1.TabPages ) { - if ( IsGamepadTab( tp ) ) newL.Add( 0 ); - else newL.Add( m_Joystick[( int )tp.Tag].JSAssignment ); - } - JoystickCls.ReassignJsColor( newL ); - m_AT.DefineShowOptions( cbxShowJoystick.Checked, cbxShowGamepad.Checked, cbxShowKeyboard.Checked, cbxShowMouse.Checked, cbxShowMappedOnly.Checked ); m_AT.ReloadTreeView( ); // finally reload things into the tree @@ -651,7 +600,7 @@ namespace SCJMapper_V2 /// /// Dump Config into rtb /// - private void Dump( ) + private void Dump() { log.Debug( "Dump - Entry" ); @@ -703,24 +652,24 @@ namespace SCJMapper_V2 if ( m_keyIn || tc1.SelectedTab.Tag == null ) return; // don't handle those string ctrl = ""; - if ( m_curJoystick == null ) { + if ( DeviceInst.JoystickRef == null ) { // no active joystick - may be a gamepad - if ( m_Gamepad != null ) { + if ( DeviceInst.GamepadRef != null ) { // poll Gamepad if active - m_Gamepad.GetData( ); - ctrl = m_Gamepad.GetLastChange( ); + DeviceInst.GamepadRef.GetData( ); + ctrl = DeviceInst.GamepadRef.GetLastChange( ); timer1.Interval = 750; // allow more time to release buttons [msec] } } else { // poll active Joystick - m_curJoystick.GetData( ); // poll the device + DeviceInst.JoystickRef.GetData( ); // poll the device // add keyboard modifier - if there are .. - if ( m_Keyboard == null ) { + if ( DeviceInst.KeyboardRef == null ) { // no keyboard => no modifier - ctrl = JSStr( ) + m_curJoystick.GetLastChange( ); // show last handled JS control + ctrl = JSStr( ) + DeviceInst.JoystickRef.GetLastChange( ); // show last handled JS control } else { UpdateModifiers( ); // get the last keyboard modifer to compose the command, also handles the modifier lifetime - ctrl = JSStr( ) + m_persistentMods + m_curJoystick.GetLastChange( ); // show last handled JS control + ctrl = JSStr( ) + m_persistentMods + DeviceInst.JoystickRef.GetLastChange( ); // show last handled JS control } timer1.Interval = 150; // standard polling [msec] } @@ -809,66 +758,13 @@ namespace SCJMapper_V2 // possibly obsolete - we dont support to make own modifiers - button is invisible private void btMakeMod_Click( object sender, EventArgs e ) { - if ( m_AT.ActionMaps.Modifiers.Contains( lblLastJ.Text ) ) return; // have it already - if ( m_AT.ActionMaps.Modifiers.Count > 2 ) return; // can max 3 ... - - // make a new one - CheckBox cbx = new CheckBox(); - cbx.Text = lblLastJ.Text; - cbx.Checked = true; - cbx.CheckedChanged += Cbx_CheckedChanged; - //flpExtensions.Controls.Add( cbx ); - m_AT.ActionMaps.Modifiers.Add( lblLastJ.Text ); - // maintain context menu - quick and d.. version - if ( string.IsNullOrEmpty( tdiAddMod1.Text ) ) { - tdiAddMod1.Text = string.Format( "MOD: {0}", lblLastJ.Text ); - tdiAddMod1.Visible = true; - m_curJoystick.UpdateModifier( lblLastJ.Text, true ); - m_AT.Dirty = true; if ( m_AT.Dirty ) btDump.BackColor = MyColors.DirtyColor; - } else if ( string.IsNullOrEmpty( tdiAddMod2.Text ) ) { - tdiAddMod2.Text = string.Format( "MOD: {0}", lblLastJ.Text ); - tdiAddMod2.Visible = true; - m_curJoystick.UpdateModifier( lblLastJ.Text, true ); - m_AT.Dirty = true; if ( m_AT.Dirty ) btDump.BackColor = MyColors.DirtyColor; - } else if ( string.IsNullOrEmpty( tdiAddMod3.Text ) ) { - tdiAddMod3.Text = string.Format( "MOD: {0}", lblLastJ.Text ); - tdiAddMod3.Visible = true; - m_curJoystick.UpdateModifier( lblLastJ.Text, true ); - m_AT.Dirty = true; if ( m_AT.Dirty ) btDump.BackColor = MyColors.DirtyColor; - } } - - - - //TODO // possibly obsolete - we dont support to make own modifiers private void Cbx_CheckedChanged( object sender, EventArgs e ) { - /* - * int i = flpExtensions.Controls.IndexOf( (Control)sender ); - if ( i >= 0 ) { - string my = ( sender as CheckBox).Text; - int m = m_AT.ActionMaps.Modifiers.IndexOf(my); - if ( m >= 0 ) m_AT.ActionMaps.Modifiers.RemoveAt( m ); - // maintain context menu - quick and d.. version - if ( tdiAddMod1.Text.EndsWith( my ) ) { - tdiAddMod1.Text = ""; tdiAddMod1.Visible = false; - } - if ( tdiAddMod2.Text.EndsWith( my ) ) { - tdiAddMod2.Text = ""; tdiAddMod2.Visible = false; - } - if ( tdiAddMod3.Text.EndsWith( my ) ) { - tdiAddMod3.Text = ""; tdiAddMod3.Visible = false; - } - // remove from joystick - but this applies to one of all - may be not the current - foreach ( JoystickCls j in m_Joystick ) { j.UpdateModifier( my, false ); } // send it to all - // finally remove the checkbox - //flpExtensions.Controls.RemoveAt( i ); - m_AT.Dirty = true; if ( m_AT.Dirty ) btDump.BackColor = MyColors.DirtyColor; - } - */ } + // General Area Items private void btDump_Click( object sender, EventArgs e ) @@ -1045,9 +941,9 @@ namespace SCJMapper_V2 { // note: the right click selected the node ContextMenuStrip cts = ( sender as ContextMenuStrip ); - Boolean any2 = false; // Group 2 - Boolean any3 = false; // Group 3 - Boolean any4 = false; // Group 4 + bool any2 = false; // Group 2 + bool any3 = false; // Group 3 + bool any4 = false; // Group 4 m_prevActivationMode = ActivationMode.Default; // switch Closing handling OFF in case we don't show anything @@ -1096,7 +992,7 @@ namespace SCJMapper_V2 private void tdiCollapseAll_Click( object sender, EventArgs e ) { TreeNode selNodeActionMap = treeView1.SelectedNode; - TreeNode selNodeParent = selNodeActionMap; + TreeNode selNodeParent = selNodeActionMap; // see if we have a parent.. if ( selNodeActionMap.Level > 1 ) selNodeParent = selNodeActionMap.Parent; @@ -1117,8 +1013,8 @@ namespace SCJMapper_V2 private void tdiCbxActivation_Click( object sender, EventArgs e ) { cmAddDel.Close( ToolStripDropDownCloseReason.ItemClicked ); - if ( !string.IsNullOrEmpty( m_prevActivationMode.Name ) && ( m_prevActivationMode.Name != ( string )tdiCbxActivation.SelectedItem ) ) { - tdiCbxActivation.Text = ( string )tdiCbxActivation.SelectedItem; + if ( !string.IsNullOrEmpty( m_prevActivationMode.Name ) && ( m_prevActivationMode.Name != (string)tdiCbxActivation.SelectedItem ) ) { + tdiCbxActivation.Text = (string)tdiCbxActivation.SelectedItem; // seems to have changed - evaluate // it is either one of the ActivationModes, or profile default m_AT.UpdateActivationModeSelectedItem( tdiCbxActivation.Text ); @@ -1200,7 +1096,7 @@ namespace SCJMapper_V2 // XML load and save private void btSaveMyMapping_Click( object sender, EventArgs e ) { - Boolean cancel = false; + bool cancel = false; if ( SCMappings.IsValidMappingName( txMappingName.Text ) ) { Dump( ); if ( SCMappings.MappingFileExists( txMappingName.Text ) ) { @@ -1259,7 +1155,7 @@ namespace SCJMapper_V2 SCFileIndication( ); // now update the contents according to new settings - foreach ( JoystickCls j in m_Joystick ) j.ApplySettings( ); // update Seetings + foreach ( JoystickCls j in DeviceInst.JoystickListRef ) j.ApplySettings( ); // update Seetings m_AT.IgnoreMaps = m_AppSettings.IgnoreActionmaps; // and start over with an empty tree InitActionTree( false ); @@ -1273,15 +1169,15 @@ namespace SCJMapper_V2 { // have to stop polling while the Reassign window is open timer1.Enabled = false; - if ( m_Joystick.ShowReassign( ) != System.Windows.Forms.DialogResult.Cancel ) { + if ( DeviceInst.JoystickListRef.ShowReassign( ) != DialogResult.Cancel ) { // copy the action tree while reassigning the jsN mappings from OLD to NEW - ActionTree newTree = m_AT.ReassignJsN( m_Joystick.JsReassingList ); + ActionTree newTree = m_AT.ReassignJsN( DeviceInst.JoystickListRef.JsReassingList ); // we have still the old assignment in the ActionMap - change it here (map does not know about the devices) JoystickCls j = null; // for all supported jsN devices for ( int i = 0; i < JoystickCls.JSnum_MAX; i++ ) { - j = m_Joystick.Find_jsN( i + 1 ); + j = DeviceInst.JoystickListRef.Find_jsN( i + 1 ); if ( j != null ) { newTree.ActionMaps.jsN[i] = j.DevName; newTree.ActionMaps.jsNGUID[i] = j.DevInstanceGUID; } else { @@ -1324,25 +1220,43 @@ namespace SCJMapper_V2 // attach Yaw command DeviceTuningParameter tuning = null; - DeviceCls dev = null; + DeviceCls dev = null; string find = ""; // find action item for yaw - tuning = m_AT.ActionMaps.OptionTree.TuningItem( optionName ); // set defaults find = ActionTreeNode.ComposeNodeText( action, "js" ); nodeText = m_AT.FindText( actionmap, find ); // returns "" or a complete text ("action - command") if ( !string.IsNullOrWhiteSpace( nodeText ) ) { - dev = m_Joystick.Find_jsN( JoystickCls.JSNum( ActionTreeNode.CommandFromNodeText( nodeText ) ) ); - } else { + if ( !ActionCls.IsBlendedInput( ActionTreeNode.CommandFromNodeText( nodeText ) ) ) { + dev = DeviceInst.JoystickListRef.Find_jsN( JoystickCls.JSNum( ActionTreeNode.CommandFromNodeText( nodeText ) ) ); + string toID = Tuningoptions.TuneOptionIDfromJsN( JoystickCls.DeviceClass, dev.XmlInstance ); + OptionTree ot = m_AT.ActionMaps.TuningOptions.OptionTreeFromToID( toID ); + if ( ot != null ) tuning = + ot.TuningItem( optionName ); // set defaults + } + } + if ( dev == null ) { find = ActionTreeNode.ComposeNodeText( action, "xi" ); nodeText = m_AT.FindText( actionmap, find ); if ( !string.IsNullOrWhiteSpace( nodeText ) ) { - dev = m_Gamepad; + if ( !ActionCls.IsBlendedInput( ActionTreeNode.CommandFromNodeText( nodeText ) ) ) { + dev = DeviceInst.GamepadRef; + string toID = Tuningoptions.TuneOptionIDfromJsN( GamepadCls.DeviceClass, dev.XmlInstance ); + OptionTree ot = m_AT.ActionMaps.TuningOptions.OptionTreeFromToID( toID ); + if ( ot != null ) tuning = + ot.TuningItem( optionName ); // set defaults + } } } + // dev might be null here if no device for the action was found + // tuning might be null here if no tuningitem for the device action was found (which should not happen !!) + if ( ( dev != null ) && ( tuning == null ) ) { + log.ErrorFormat( "UpdateOptionItem - Tuning item for device not found - dev: {0} - option: {1}", dev.DevName, optionName ); + return; // ERROR EXIT + } - tuning.Reset( ); if ( dev != null ) { + tuning.Reset( ); // JS commands that are supported if ( nodeText.ToLowerInvariant( ).EndsWith( "_x" ) || nodeText.ToLowerInvariant( ).EndsWith( "_rotx" ) || nodeText.ToLowerInvariant( ).EndsWith( "_throttlex" ) || nodeText.ToLowerInvariant( ).EndsWith( "_y" ) || nodeText.ToLowerInvariant( ).EndsWith( "_roty" ) || nodeText.ToLowerInvariant( ).EndsWith( "_throttley" ) @@ -1350,9 +1264,9 @@ namespace SCJMapper_V2 || nodeText.ToLowerInvariant( ).EndsWith( "_slider1" ) || nodeText.ToLowerInvariant( ).EndsWith( "_slider2" ) ) { tuning.GameDevice = dev; tuning.NodeText = nodeText; - string doID = Deviceoptions.DevOptionID( dev.DevName, nodeText ); + string doID = Deviceoptions.DevOptionID( dev.DevClass, dev.DevName, nodeText ); if ( m_AT.ActionMaps.DeviceOptions.ContainsKey( doID ) ) { - tuning.Deviceoption = m_AT.ActionMaps.DeviceOptions[doID]; + tuning.DeviceoptionRef = m_AT.ActionMaps.DeviceOptions[doID]; } } // GP commands that are supported @@ -1360,18 +1274,18 @@ namespace SCJMapper_V2 || nodeText.ToLowerInvariant( ).Contains( "_thumbly" ) || nodeText.ToLowerInvariant( ).Contains( "_thumbry" ) ) { tuning.GameDevice = dev; tuning.NodeText = nodeText; - string doID = Deviceoptions.DevOptionID( dev.DevName, nodeText ); + string doID = Deviceoptions.DevOptionID( dev.DevClass, dev.DevName, nodeText ); if ( m_AT.ActionMaps.DeviceOptions.ContainsKey( doID ) ) { - tuning.Deviceoption = m_AT.ActionMaps.DeviceOptions[doID]; + tuning.DeviceoptionRef = m_AT.ActionMaps.DeviceOptions[doID]; } } - } else if ( tuning.DevInstanceNo > 0 ) { + } else if ( tuning != null && tuning.DevInstanceNo > 0 ) { // a device was assigned but the action is not mapped // try to find the gamedevice here if ( JoystickCls.IsDeviceClass( tuning.DeviceClass ) ) { - tuning.GameDevice = m_Joystick.Find_jsN( tuning.DevInstanceNo ); + tuning.GameDevice = DeviceInst.JoystickListRef.Find_jsN( tuning.DevInstanceNo ); } else if ( GamepadCls.IsDeviceClass( tuning.DeviceClass ) ) { - tuning.GameDevice = m_Gamepad; + tuning.GameDevice = DeviceInst.GamepadRef; } } @@ -1381,7 +1295,7 @@ namespace SCJMapper_V2 /// Get the assigned controls for some commands used in Tuning Yaw,Pitch,Roll and the Strafe ones /// Connect deviceOption if known /// - private void UpdateTuningItems( ) + private void UpdateTuningItems() { // cleanup - Actions will be assigned new in below calls m_AT.ActionMaps.DeviceOptions.ResetActions( ); @@ -1400,7 +1314,7 @@ namespace SCJMapper_V2 /// /// Get the assigned controls for other Options - if available... /// - private void UpdateMoreOptionItems( ) + private void UpdateMoreOptionItems() { // get current mapping from ActionMaps UpdateOptionItem( "flight_throttle_abs", "v_throttle_abs", "spaceship_movement" ); @@ -1427,7 +1341,7 @@ namespace SCJMapper_V2 // Have to attach here to capture the currently valid settings UpdateTuningItems( ); // run - JSCAL.OptionTree = m_AT.ActionMaps.OptionTree; // assign tuning values + JSCAL.TuningOptions = m_AT.ActionMaps.TuningOptions; JSCAL.ShowDialog( this ); m_AT.Dirty = true; @@ -1442,20 +1356,20 @@ namespace SCJMapper_V2 { timer1.Enabled = false; // must be off while a modal window is shown, else DX gets crazy - FormOptions OPT = new FormOptions(); + FormOptions OPT = new FormOptions( ); // Have to attach here to capture the currently valid settings UpdateTuningItems( ); UpdateMoreOptionItems( ); - DeviceList devlist = new DeviceList(); - if ( m_AppSettings.DetectGamepad && m_Gamepad != null ) { - devlist.Add( m_Gamepad ); + DeviceList devlist = new DeviceList( ); + if ( m_AppSettings.DetectGamepad && (DeviceInst.GamepadRef != null) ) { + devlist.Add( DeviceInst.GamepadRef ); } - devlist.AddRange( m_Joystick ); + devlist.AddRange( DeviceInst.JoystickListRef ); - OPT.OptionTree = m_AT.ActionMaps.OptionTree; + OPT.TuningOptions = m_AT.ActionMaps.TuningOptions; OPT.DeviceOptions = m_AT.ActionMaps.DeviceOptions; OPT.Devicelist = devlist; @@ -1474,8 +1388,8 @@ namespace SCJMapper_V2 // Keyboard Input - Boolean m_keyIn = false; - Boolean m_mouseIn = false; + bool m_keyIn = false; + bool m_mouseIn = false; private void btJsKbd_Click( object sender, EventArgs e ) @@ -1483,7 +1397,7 @@ namespace SCJMapper_V2 m_keyIn = ( !m_keyIn ); if ( m_keyIn ) { cbxThrottle.Checked = false; cbxThrottle.Enabled = false; // must be disabled.. - if ( m_Keyboard == null ) { + if ( DeviceInst.KeyboardRef == null ) { m_keyIn = false; btJsKbd.ImageKey = "J"; return; @@ -1492,8 +1406,8 @@ namespace SCJMapper_V2 lblLastJ.BackColor = MyColors.KeyboardColor; btJsKbd.ImageKey = "K"; lblLastJ.Focus( ); - m_Keyboard.Activate( ); - m_Keyboard.GetData( ); // poll to aquire once + DeviceInst.KeyboardRef.Activate( ); + DeviceInst.KeyboardRef.GetData( ); // poll to aquire once } else { m_mouseIn = false; // not longer lblLastJ.BackColor = MyColors.ValidColor; @@ -1507,14 +1421,14 @@ namespace SCJMapper_V2 private void lblLastJ_KeyDown( object sender, KeyEventArgs e ) { if ( m_keyIn ) { - m_Keyboard.GetData( ); - string modS = m_Keyboard.GetLastChange( false ); // modifiers only - string keyModS = m_Keyboard.GetLastChange( true ); // modifiers+keyboard input + DeviceInst.KeyboardRef.GetData( ); + string modS = DeviceInst.KeyboardRef.GetLastChange( false ); // modifiers only + string keyModS = DeviceInst.KeyboardRef.GetLastChange( true ); // modifiers+keyboard input // don't override modifiers when we are in mouse mode and the mod is the same and there is no kbd entry.... if ( m_mouseIn && ( keyModS == modS ) && ( m_persistentMods == ( modS + "+" ) ) ) { ; // nothing here - } else { - lblLastJ.Text = m_Keyboard.GetLastChange( true ); + lblLastJ.Text = DeviceInst.KeyboardRef.GetLastChange( true ); m_mouseIn = false; // clear on kbd input } // also maintain persistent mods @@ -1528,12 +1442,12 @@ namespace SCJMapper_V2 // maintain the global modifier store - private void UpdateModifiers( ) + private void UpdateModifiers() { - if ( m_Keyboard == null ) return; + if ( DeviceInst.KeyboardRef == null ) return; - m_Keyboard.GetData( ); - string modS = m_Keyboard.GetLastChange( false ); + DeviceInst.KeyboardRef.GetData( ); + string modS = DeviceInst.KeyboardRef.GetLastChange( false ); if ( !string.IsNullOrEmpty( modS ) ) { if ( modS.Contains( KeyboardCls.ClearMods ) ) { // allow to cancel modifiers @@ -1562,24 +1476,24 @@ namespace SCJMapper_V2 private void tmeItem_Click( object sender, EventArgs e ) { ToolStripMenuItem ts = (ToolStripMenuItem)sender; - if ( string.IsNullOrEmpty( ( string )ts.Tag ) ) return; + if ( string.IsNullOrEmpty( (string)ts.Tag ) ) return; string item = ""; string device = MouseCls.DeviceClass; int btNum = 0; - if ( int.TryParse( ( string )ts.Tag, out btNum ) ) { + if ( int.TryParse( (string)ts.Tag, out btNum ) ) { // got a button (most likely..) item = "mouse" + btNum.ToString( ); - } else if ( ( string )ts.Tag == "X" ) + } else if ( (string)ts.Tag == "X" ) item = "maxis_x"; - else if ( ( string )ts.Tag == "Y" ) + else if ( (string)ts.Tag == "Y" ) item = "maxis_y"; - else if ( ( string )ts.Tag == "U" ) + else if ( (string)ts.Tag == "U" ) item = "mwheel_up"; - else if ( ( string )ts.Tag == "D" ) + else if ( (string)ts.Tag == "D" ) item = "mwheel_down"; - else if ( ( string )ts.Tag == "K_Tab" ) { + else if ( (string)ts.Tag == "K_Tab" ) { item = "tab"; device = KeyboardCls.DeviceClass; } @@ -1587,7 +1501,7 @@ namespace SCJMapper_V2 string ctrl = ""; // have to handle the two devices if ( MouseCls.IsDeviceClass( device ) ) { - if ( m_Keyboard == null ) { + if ( DeviceInst.KeyboardRef == null ) { // no keyboard = no modifier ctrl = MouseCls.MakeCtrl( item, "" ); // show last handled JS control } else { @@ -1607,7 +1521,7 @@ namespace SCJMapper_V2 // Called when the table must be rebuild - private void UpdateTable( ) + private void UpdateTable() { // only if needed if ( ( FTAB != null ) && FTAB.Visible ) { @@ -1619,7 +1533,7 @@ namespace SCJMapper_V2 } // Called when an entry has been modified - private void UpdateTableSelectedItem( ) + private void UpdateTableSelectedItem() { // only if needed if ( ( FTAB != null ) && FTAB.Visible ) { diff --git a/Gamepad/GamepadCls.cs b/Gamepad/GamepadCls.cs index a989bbf..844deb4 100644 --- a/Gamepad/GamepadCls.cs +++ b/Gamepad/GamepadCls.cs @@ -22,13 +22,14 @@ namespace SCJMapper_V2.Gamepad #region Static Items - public new const String DeviceClass = "xboxpad"; // the device name used throughout this app - public new const String DeviceID = "xi1_"; + public new const string DeviceClass = "xboxpad"; // the device name used throughout this app + public new const string DeviceID = "xi1_"; static public int RegisteredDevices = 0; + 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 Boolean IsBlendedInput( String input ) + public const string JsUnknown = "xi_"; + public new const string BlendedInput = DeviceID + DeviceCls.BlendedInput; + static public new bool IsBlendedInput( string input ) { if ( input == BlendedInput ) return true; return false; @@ -49,7 +50,7 @@ namespace SCJMapper_V2.Gamepad /// /// /// - static public new Boolean IsDeviceClass( String deviceClass ) + static public new bool IsDeviceClass( string deviceClass ) { return ( deviceClass == DeviceClass ); } @@ -59,7 +60,7 @@ namespace SCJMapper_V2.Gamepad /// /// /// - static public new String DeviceClassFromInput( String devInput ) + static public new string DeviceClassFromInput( string devInput ) { if ( DevMatch( devInput ) ) return DeviceClass; // this @@ -72,7 +73,7 @@ namespace SCJMapper_V2.Gamepad /// /// A gamepad input /// DevInput - static public new String DevInput( String input ) + static public new string DevInput( string input ) { if ( DevMatch( input ) ) return input; // already @@ -85,7 +86,7 @@ namespace SCJMapper_V2.Gamepad /// /// A devInput string /// True for a match - static public new Boolean DevMatch( String devInput ) + static public new bool DevMatch( string devInput ) { return devInput.StartsWith( DeviceID ); } @@ -98,7 +99,7 @@ namespace SCJMapper_V2.Gamepad /// /// /// - static public Boolean CanInvert( String control ) + static public bool CanInvert( string control ) { return rgx_xil.IsMatch( control ); } @@ -108,11 +109,11 @@ namespace SCJMapper_V2.Gamepad /// /// The AC1 input string /// An AC2 style input string - static public String FromAC1( String input ) + static public string FromAC1( string input ) { // 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(" ",""); + string retVal = input.Replace(" ",""); if ( IsBlendedInput( input ) ) return input; if ( retVal.StartsWith( "xi_" ) ) @@ -128,13 +129,13 @@ namespace SCJMapper_V2.Gamepad #endregion private Controller m_device; - private String m_devName = "Generic Gamepad"; + private string m_devName = DevNameCIG; private Capabilities m_gpCaps = new Capabilities( ); private State m_state = new State( ); private State m_prevState = new State( ); - private String m_lastItem = ""; + private string m_lastItem = ""; private int m_senseLimit = 500; // axis jitter avoidance... private bool m_activated = false; @@ -142,22 +143,34 @@ namespace SCJMapper_V2.Gamepad internal int MyTabPageIndex = -1; + /// + /// Return the device instance number (which is always 1) + /// + public override int XmlInstance { get { return 1; } } // const for Gamepad + /// + /// Return the DX device instance number (which is always 0) + /// + public override int DevInstance { get { return 0; } } /// /// The DeviceClass of this instance /// - public override String DevClass { get { return GamepadCls.DeviceClass; } } + public override string DevClass { get { return GamepadCls.DeviceClass; } } /// - /// The JS ProductName property + /// The Gamepad ProductName property /// - public override String DevName { get { return m_devName; } } + public override string DevName { get { return m_devName; } } /// - public void SetDeviceName( String devName ) + public void SetDeviceName( string devName ) { - m_devName = devName; + m_devName = DevNameCIG; // hard override ... m_gPanel.Caption = DevName; } + /// + /// The JS Instance GUID for multiple device support (VJoy gets 2 of the same name) + /// + public override string DevInstanceGUID { get { return "17809207-4663-4629-b5f8-26cc6afa0e70"; } } // artifical GUID - DX does not maintain one /// /// Returns the mapping color for this device @@ -167,7 +180,27 @@ namespace SCJMapper_V2.Gamepad get { return MyColors.GamepadColor; } } - public override Boolean Activated + + // Note: GP has deadzone on left and right thumb only + public override List AnalogCommands + { + get { + List cmds = new List(); + + try { + // Enumerate all the objects on the device. + if ( ( m_gpCaps.Gamepad.LeftThumbX != 0 ) || ( m_gpCaps.Gamepad.LeftThumbY != 0 ) ) { cmds.Add( "thumbl" ); } + if ( ( m_gpCaps.Gamepad.RightThumbX != 0 ) || ( m_gpCaps.Gamepad.RightThumbY != 0 ) ) { cmds.Add( "thumbr" ); } + } catch ( Exception ex ) { + log.Error( "AnalogCommands - Get Gamepad Objects failed", ex ); + } + cmds.Sort( ); + return cmds; + } + } + + + public override bool Activated { get { return m_activated; } set @@ -176,7 +209,7 @@ namespace SCJMapper_V2.Gamepad } } - private Boolean Bit( GamepadButtonFlags set, GamepadButtonFlags check ) + private bool Bit( GamepadButtonFlags set, GamepadButtonFlags check ) { Int32 s = ( Int32 )set; Int32 c = ( Int32 )check; return ( ( s & c ) == c ); @@ -189,7 +222,7 @@ namespace SCJMapper_V2.Gamepad /// A DXInput device /// The WinHandle of the main window /// The respective JS panel to show the properties - public GamepadCls( SharpDX.XInput.Controller device, UC_GpadPanel panel, int tabIndex ) + public GamepadCls( Controller device, UC_GpadPanel panel, int tabIndex ) { log.DebugFormat( "GamepadCls ctor - Entry with index {0}", device.ToString( ) ); @@ -270,9 +303,9 @@ namespace SCJMapper_V2.Gamepad /// Returns true if a modifer button is pressed /// /// - private Boolean ModButtonPressed( ) + private bool ModButtonPressed( ) { - Boolean retVal = m_state.Gamepad.Buttons != GamepadButtonFlags.None; + bool retVal = m_state.Gamepad.Buttons != GamepadButtonFlags.None; retVal = ( retVal || ( Math.Abs( ( Int32 )m_state.Gamepad.LeftTrigger ) > 0 ) ); retVal = ( retVal || ( Math.Abs( ( Int32 )m_state.Gamepad.RightTrigger ) > 0 ) ); return retVal; @@ -283,7 +316,7 @@ namespace SCJMapper_V2.Gamepad /// Find the last change the user did on that device /// /// The last action as CryEngine compatible string - public override String GetLastChange( ) + public override string GetLastChange( ) { if ( ModButtonPressed() ) { m_lastItem = ""; @@ -410,7 +443,7 @@ namespace SCJMapper_V2.Gamepad m_gPanel.Back = ( ( m_state.Gamepad.Buttons & GamepadButtonFlags.Back ) > 0 ) ? "pressed" : "_"; - String buttons = ""; + string buttons = ""; buttons += ( Bit( m_state.Gamepad.Buttons, GamepadButtonFlags.A ) ) ? "A" : "_"; buttons += ( Bit( m_state.Gamepad.Buttons, GamepadButtonFlags.B ) ) ? "B" : "_"; buttons += ( Bit( m_state.Gamepad.Buttons, GamepadButtonFlags.X ) ) ? "X" : "_"; @@ -422,7 +455,7 @@ namespace SCJMapper_V2.Gamepad /// /// Collect the current data from the device /// - public override void GetCmdData( String cmd, out int data ) + public override void GetCmdData( string cmd, out int data ) { // Make sure there is a valid device. if ( m_device == null ) { diff --git a/Joystick/FormReassign.cs b/Joystick/FormReassign.cs index 8e00cad..5d1e7b6 100644 --- a/Joystick/FormReassign.cs +++ b/Joystick/FormReassign.cs @@ -16,7 +16,7 @@ namespace SCJMapper_V2.Joystick private ComboBox[] m_cb = new ComboBox[] { null, null, null, null, null, null, null, null, null, null, null, null, }; - public Boolean Canceled { get; set; } + public bool Canceled { get; set; } /// /// ctor - gets the owning class instance @@ -65,6 +65,7 @@ namespace SCJMapper_V2.Joystick { int textIdx = 0; m_owner.JsReassingList.Clear( ); + // one entry for all joysticks defined - sequ is the DX enum (the list) foreach ( JoystickCls j in m_owner ) { try { m_owner.JsReassingList.Add( m_owner.NewJsList[textIdx], m_cb[textIdx].SelectedIndex ); @@ -77,7 +78,7 @@ namespace SCJMapper_V2.Joystick } } - private Boolean IsOK( ) + private bool IsOK( ) { int[] jsx = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; foreach ( ComboBox cb in m_cb ) { diff --git a/Joystick/JoystickCls.cs b/Joystick/JoystickCls.cs index e94559a..9186f3d 100644 --- a/Joystick/JoystickCls.cs +++ b/Joystick/JoystickCls.cs @@ -17,7 +17,7 @@ namespace SCJMapper_V2.Joystick /// public class JoystickCls : DeviceCls { - private static readonly log4net.ILog log = log4net.LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod( ).DeclaringType ); + private static readonly log4net.ILog log = log4net.LogManager.GetLogger( MethodBase.GetCurrentMethod( ).DeclaringType ); private static readonly AppSettings appSettings = new AppSettings( ); #region Static Items @@ -40,26 +40,6 @@ namespace SCJMapper_V2.Joystick } - /// - /// Reassigns the mapping color based on the jsAssignment list given - /// i.e. prepare the mapping colors for a given jsN assignment - /// - /// List of 0.. tabs where the value is the jsN number - static public void ReassignJsColor( List newJsList ) - { - // the default colors are aligned with the tabs - the tabs color is never changed but the jsN may - // i.e. if the first Tab is assigned as js2 then the second MapColor must get the color of the first Tab - int idx = 0; - foreach ( int i in newJsList ) { - // walk through the tabs - if ( i > 0 ) { - // this is the jsN for the tab indexed (make it 0 based) - MyColors.MapColor[i - 1] = MyColors.TabColor[idx]; - } - idx++; - } - } - /// /// Returns the currently valid color for a jsN assignment /// @@ -71,7 +51,7 @@ namespace SCJMapper_V2.Joystick if ( jsN < 1 ) return MyColors.ErrorColor; if ( jsN > JoystickCls.JSnum_MAX ) return MyColors.ErrorColor; - return MyColors.MapColor[jsN - 1]; // jsN is 1 based, color array is 0 based + return MyColors.JsMapColor[jsN - 1]; // jsN is 1 based, color array is 0 based } @@ -327,14 +307,15 @@ namespace SCJMapper_V2.Joystick private int m_sliderCount = 0; // static counter for UpdateControls private string m_lastItem = ""; private int m_senseLimit = 150; // axis jitter avoidance... - private int m_joystickNumber = 0; // seq number of the enumerated joystick + private int m_joystickNumber = 0; // 0..n-1 seq number of the enumerated joystick - assigned in Ctor - remains fixed + private int m_xmlInstance = 0; // The CIG instance number (may change through property JSAssignment) private bool[] m_ignoreButtons; private bool m_activated = false; private bool[] m_modifierButtons; private UC_JoyPanel m_jPanel = null; // the GUI panel - internal int MyTabPageIndex = -1; + internal int MyTabPageIndex = -1; /// /// Returns a CryEngine compatible hat direction @@ -351,7 +332,14 @@ namespace SCJMapper_V2.Joystick return ""; } - + /// + /// Return the CIG instance number (which is the jsN number) + /// + public override int XmlInstance { get { return m_xmlInstance; } } + /// + /// Return the DX device instance number (0..n-1) + /// + public override int DevInstance { get { return m_joystickNumber; } } /// /// The DeviceClass of this instance /// @@ -363,18 +351,17 @@ namespace SCJMapper_V2.Joystick /// /// The JS Instance GUID for multiple device support (VJoy gets 2 of the same name) /// - public string DevInstanceGUID { get { return m_device.Information.InstanceGuid.ToString( ); } } + public override string DevInstanceGUID { get { return m_device.Information.InstanceGuid.ToString( ); } } /// - /// The sequence number of the enumerated devices - /// - public int DevNumber { get { return m_joystickNumber; } } - /// - /// The assigned jsN number for this device + /// The assigned jsN number for this device (1..n) /// public int JSAssignment { - get { return m_jPanel.JsAssignment; } - set { m_jPanel.JsAssignment = value; } + get { return m_xmlInstance; } + set { + m_xmlInstance = value; + m_jPanel.JsAssignment = m_xmlInstance; + } } /// @@ -441,14 +428,17 @@ namespace SCJMapper_V2.Joystick /// /// A DXInput device /// The WinHandle of the main window + /// The 0.. n-1 Joystick from DX enum /// The respective JS panel to show the properties + /// The Tab index in the GUI public JoystickCls( SharpDX.DirectInput.Joystick device, Control hwnd, int joystickNum, UC_JoyPanel panel, int tabIndex ) { log.DebugFormat( "JoystickCls ctor - Entry with {0}", device.Information.ProductName ); m_device = device; m_hwnd = hwnd; - m_joystickNumber = joystickNum; + m_joystickNumber = joystickNum; // this remains fixed + m_xmlInstance = joystickNum+1; // initial assignment (is 1 based..) m_jPanel = panel; MyTabPageIndex = tabIndex; Activated = false; diff --git a/Joystick/JoystickList.cs b/Joystick/JoystickList.cs index 6c72972..df6f786 100644 --- a/Joystick/JoystickList.cs +++ b/Joystick/JoystickList.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; @@ -13,14 +14,61 @@ namespace SCJMapper_V2.Joystick public JsReassingList JsReassingList { get; set; } // index - oldJs, newJs public List NewJsList { get; set; } // index is this[idx] + /// + /// Reassigns the mapping color based on the jsAssignment list given + /// i.e. prepare the mapping colors for a given jsN assignment + /// + /// List of 0.. tabs where the value is the jsN number + static public void ReassignJsColor( List newJsList ) + { + // the default colors are aligned with the tabs - the tabs color is never changed but the jsN may + // i.e. if the first Tab is assigned as js2 then the second MapColor must get the color of the first Tab + int idx = 0; + foreach ( int i in newJsList ) { + if ( MyColors.TabColor[idx] == MyColors.GamepadColor ) { + ; // skip the gamepad for joystick coloring + } else { + // walk through the tabs + if ( i > 0 ) { + // this is the jsN for the tab indexed (make it 0 based) + MyColors.JsMapColor[i - 1] = MyColors.TabColor[idx]; + } + } + idx++; + } + } + + + static private Color DeviceColor( int dxnumber ) + { + int devNumber = 0; // this runs asynch due to the gamepad tab somewhere inbetween.. + for ( int mapIndex = 0; mapIndex < MyColors.TabColor.Length; mapIndex++ ) { + if ( MyColors.TabColor[mapIndex] == MyColors.GamepadColor ) { + ; // skip the gamepad for joystick coloring + } else if ( dxnumber == devNumber) { + return MyColors.TabColor[mapIndex]; + } else { + devNumber++;// not found but advance the device + } + } + return Color.Pink; // error but we should see the pink... + } + + /// + /// Deactivate all joysticks + /// public void Deactivate( ) { foreach ( JoystickCls j in this ) j.Activated = false; } + + /// + /// Activate all joysticks + /// public void Activate( ) { - foreach ( JoystickCls j in this ) j.Activated =true; + foreach ( JoystickCls j in this ) j.Activated = true; } /// @@ -37,24 +85,46 @@ namespace SCJMapper_V2.Joystick if ( FR.Canceled == false ) { int jIdx = 0; // update the new js indication in the tabs - foreach ( JoystickCls j in this ) j.JSAssignment = NewJsList[jIdx++]; - JoystickCls.ReassignJsColor( NewJsList ); + foreach ( JoystickCls js in this ) { + js.JSAssignment = NewJsList[jIdx++]; + if ( js.XmlInstance > 0 ) + MyColors.JsMapColor[js.XmlInstance - 1] = DeviceColor( js.DevInstance ); + } } return ( FR.Canceled ) ? DialogResult.Cancel : DialogResult.OK; } - public void ResetJsNAssignment( ) + /// + /// Reset the Js Assingment to the new mapping provided + /// index of the map is the jsNumber (0 based - i.e. js1 ==> index 0) + /// + public void ResetJsNAssignment( string[] jsNGUID ) { ClearJsNAssignment( ); - foreach ( JoystickCls j in this ) j.JSAssignment = 0; - if ( this.Count > 0 ) this[0].JSAssignment = this[0].MyTabPageIndex + 1; - if ( this.Count > 1 ) this[1].JSAssignment = this[1].MyTabPageIndex + 1; + // for all supported jsN + for ( int i = 0; i < JoystickCls.JSnum_MAX; i++ ) { + JoystickCls js = null; + if ( !string.IsNullOrEmpty( jsNGUID[i] ) ) js = Find_jsInstance( jsNGUID[i] ); + if ( js != null ) { + js.JSAssignment = i + 1; // i is 0 based ; jsN is 1 based + if ( js.XmlInstance > 0 ) + MyColors.JsMapColor[js.XmlInstance - 1] = DeviceColor( js.DevInstance ); + } + } } + /// + /// Set JsN to zero + /// public void ClearJsNAssignment( ) { - foreach ( JoystickCls j in this ) j.JSAssignment = 0; + int devNum = 0; + foreach ( JoystickCls js in this ) { + js.JSAssignment = 0; + MyColors.JsMapColor[devNum] = DeviceColor( devNum ); + devNum++; + } } diff --git a/Joystick/JsReassingList.cs b/Joystick/JsReassingList.cs index 0919833..4b99de6 100644 --- a/Joystick/JsReassingList.cs +++ b/Joystick/JsReassingList.cs @@ -15,7 +15,7 @@ namespace SCJMapper_V2.Joystick public class JsReassingList : List { - public Boolean ContainsOldJs( int oldJs ) + public bool ContainsOldJs( int oldJs ) { foreach ( JsReassingR jr in this ) { if ( jr.oldJs == oldJs ) return true; diff --git a/Joystick/UICustHeader.cs b/Joystick/UICustHeader.cs index 5b1e64c..7a809f1 100644 --- a/Joystick/UICustHeader.cs +++ b/Joystick/UICustHeader.cs @@ -22,22 +22,82 @@ namespace SCJMapper_V2.Joystick /// /// /// - public class UICustHeader + public class UICustHeader : ICloneable { private static readonly log4net.ILog log = log4net.LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod( ).DeclaringType ); - List m_stringOptions = new List( ); + List m_stringOptions = new List( ); - public struct DevRec + public struct DevRec : ICloneable { - public String devType; + public string devType; public int instNo; + + public object Clone() + { + var dr = (DevRec)this.MemberwiseClone( ); + + return dr; + } + + /// + /// Check clone against This + /// + /// + /// True if the clone is identical but not a shallow copy + public bool CheckClone(DevRec clone) + { + bool ret = true; + ret &= ( this.devType == clone.devType ); // immutable string - shallow copy is OK + ret &= ( this.instNo == clone.instNo ); // value type + return ret; + } } List m_devInstances = new List( ); - private String m_label = ""; - private String m_description = ""; - private String m_image = ""; + private string m_label = ""; + private string m_description = ""; + private string m_image = ""; + + + /// + /// Clone this object + /// + /// A deep Clone of this object + public object Clone( ) + { + var uic = (UICustHeader)this.MemberwiseClone(); + // more objects to deep copy + uic.m_devInstances = m_devInstances.Select( x => ( DevRec )x.Clone( ) ).ToList( ); + +#if DEBUG + // check cloned item + System.Diagnostics.Debug.Assert( CheckClone( uic ) ); +#endif + return uic; + } + + /// + /// Check clone against This + /// + /// + /// True if the clone is identical but not a shallow copy + private bool CheckClone (UICustHeader clone ) + { + bool ret = true; + ret &= ( this.m_stringOptions == clone.m_stringOptions ); // immutable string list - shallow copy is OK + ret &= ( this.m_label == clone.m_label ); // immutable string - shallow copy is OK + ret &= ( this.m_description == clone.m_description ); // immutable string - shallow copy is OK + ret &= ( this.m_image == clone.m_image ); // immutable string - shallow copy is OK + + ret &= ( this.m_devInstances.Count == clone.m_devInstances.Count ); + if (ret) { + for ( int i = 0; i < this.m_devInstances.Count; i++ ) { + ret &= ( this.m_devInstances[i].CheckClone( clone.m_devInstances[i] ) ); + } + } + return ret; + } public int Count @@ -45,7 +105,7 @@ namespace SCJMapper_V2.Joystick get { return ( m_stringOptions.Count + m_devInstances.Count ); } } - public String Label + public string Label { get { return m_label; } set { m_label = value; } @@ -61,14 +121,14 @@ namespace SCJMapper_V2.Joystick } - private String[] FormatXml( string xml ) + private string[] FormatXml( string xml ) { try { XDocument doc = XDocument.Parse( xml ); - return doc.ToString( ).Split( new String[] { String.Format( "\n" ) }, StringSplitOptions.RemoveEmptyEntries ); + return doc.ToString( ).Split( new string[] { string.Format( "\n" ) }, StringSplitOptions.RemoveEmptyEntries ); } catch ( Exception ) { - return new String[] { xml }; + return new string[] { xml }; } } @@ -76,7 +136,7 @@ namespace SCJMapper_V2.Joystick /// Dump the CustomisationUIHeader as partial XML nicely formatted /// /// the action as XML fragment - public String toXML( ) + public string toXML( ) { /* @@ -93,34 +153,34 @@ namespace SCJMapper_V2.Joystick */ - String r = ""; + string r = ""; - r += String.Format( "\t\n", m_label, m_description, m_image ); + r += string.Format( "\t\n", m_label, m_description, m_image ); if ( m_devInstances.Count > 0 ) { - r += String.Format( "\t\t\n" ); + r += string.Format( "\t\t\n" ); foreach ( DevRec dr in m_devInstances ) { - r += String.Format( "\t\t\t<{0} instance=\"{1}\"/>\n", dr.devType, dr.instNo.ToString( ) ); + r += string.Format( "\t\t\t<{0} instance=\"{1}\"/>\n", dr.devType, dr.instNo.ToString( ) ); } - r += String.Format( "\t\t\n" ); + r += string.Format( "\t\t\n" ); } // CIG adds them to export - so can we ... - r += String.Format( "\t\t\n" ); - r += String.Format( "\t\t\n" ); - r += String.Format( "\t\t\n" ); + r += string.Format( "\t\t\n" ); + r += string.Format( "\t\t\n" ); + r += string.Format( "\t\t\n" ); - r += String.Format( "\t\n" ); + r += string.Format( "\t\n" ); // and dump the plain contents if needed - foreach ( String x in m_stringOptions ) { - if ( !String.IsNullOrWhiteSpace( x ) ) { - foreach ( String line in FormatXml( x ) ) { - r += String.Format( "\t{0}", line ); + foreach ( string x in m_stringOptions ) { + if ( !string.IsNullOrWhiteSpace( x ) ) { + foreach ( string line in FormatXml( x ) ) { + r += string.Format( "\t{0}", line ); } } } - r += String.Format( "\n" ); + r += string.Format( "\n" ); return r; } @@ -136,10 +196,10 @@ namespace SCJMapper_V2.Joystick reader.Read( ); while ( !reader.EOF ) { - String devType = reader.Name; - String instance = reader["instance"]; + string devType = reader.Name; + string instance = reader["instance"]; int instNo = 0; - if ( !String.IsNullOrWhiteSpace( instance ) ) { + if ( !string.IsNullOrWhiteSpace( instance ) ) { if ( !int.TryParse( instance, out instNo ) ) { instNo = 0; } @@ -163,7 +223,7 @@ namespace SCJMapper_V2.Joystick /// /// the XML action fragment /// True if an action was decoded - public Boolean fromXML( String xml ) + public Boolean fromXML( string xml ) { XmlReaderSettings settings = new XmlReaderSettings( ); settings.ConformanceLevel = ConformanceLevel.Fragment; @@ -176,9 +236,9 @@ namespace SCJMapper_V2.Joystick if ( reader.HasAttributes ) { m_label = reader["label"]; m_description = reader["description"]; - if ( String.IsNullOrEmpty( m_description ) ) m_description = "@ui_JoystickDefaultDesc"; + if ( string.IsNullOrEmpty( m_description ) ) m_description = "@ui_JoystickDefaultDesc"; m_image = reader["image"]; - if ( String.IsNullOrEmpty( m_image ) ) m_image = "JoystickDefault"; + if ( string.IsNullOrEmpty( m_image ) ) m_image = "JoystickDefault"; reader.Read( ); // try to disassemble the items @@ -211,8 +271,5 @@ namespace SCJMapper_V2.Joystick return true; } - - - } } diff --git a/Keyboard/KeyboardCls.cs b/Keyboard/KeyboardCls.cs index 45df264..d9ed57c 100644 --- a/Keyboard/KeyboardCls.cs +++ b/Keyboard/KeyboardCls.cs @@ -19,14 +19,14 @@ namespace SCJMapper_V2.Keyboard #region Static Items - public new const String DeviceClass = "keyboard"; // the device name used throughout this app - public new const String DeviceID = "kb1_"; + public new const string DeviceClass = "keyboard"; // the device name used throughout this app + public new const string DeviceID = "kb1_"; static public int RegisteredDevices = 0; // devices add here once they are created (though will not decrement as they are not deleted) - public const String ClearMods = "escape"; + public const string ClearMods = "escape"; - public new const String BlendedInput = DeviceID + DeviceCls.BlendedInput; - static public new Boolean IsBlendedInput ( String input ) + public new const string BlendedInput = DeviceID + DeviceCls.BlendedInput; + static public new bool IsBlendedInput ( string input ) { if ( input == BlendedInput ) return true; return false; @@ -47,7 +47,7 @@ namespace SCJMapper_V2.Keyboard /// /// /// - static public new Boolean IsDeviceClass( String deviceClass ) + static public new bool IsDeviceClass( string deviceClass ) { return ( deviceClass == DeviceClass ); } @@ -57,7 +57,7 @@ namespace SCJMapper_V2.Keyboard /// /// /// - static public new String DeviceClassFromInput( String devInput ) + static public new string DeviceClassFromInput( string devInput ) { if ( DevMatch( devInput ) ) return DeviceClass; // this @@ -70,7 +70,7 @@ namespace SCJMapper_V2.Keyboard /// /// A keyboard input /// DevInput - static public new String DevInput( String input ) + static public new string DevInput( string input ) { if ( DevMatch( input ) ) return input; // already @@ -83,7 +83,7 @@ namespace SCJMapper_V2.Keyboard /// /// A devInput string /// True for a match - static public new Boolean DevMatch( String devInput ) + static public new bool DevMatch( string devInput ) { return devInput.StartsWith( DeviceID ); } @@ -94,11 +94,11 @@ namespace SCJMapper_V2.Keyboard /// /// The AC1 input string /// An AC2 style input string - static public String FromAC1( String input ) + static public string FromAC1( string input ) { // 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(" ",""); + string retVal = input.Replace(" ",""); if ( IsBlendedInput( input ) ) return input; int plPos = retVal.IndexOf("+"); @@ -121,12 +121,12 @@ namespace SCJMapper_V2.Keyboard /// /// The list of pressed DX keys /// The SC keycode string - public static String DXKeyboardCmd( List pressedKeys, Boolean modAndKey ) + public static string DXKeyboardCmd( List pressedKeys, bool modAndKey ) { - String altMod = ""; - String shiftMod = ""; - String ctrlMod = ""; - String key = ""; + string altMod = ""; + string shiftMod = ""; + string ctrlMod = ""; + string key = ""; foreach ( Key k in pressedKeys ) { switch ( ( int )k ) { @@ -236,7 +236,7 @@ namespace SCJMapper_V2.Keyboard /// The input by the user /// Modifiers to be applied /// - static public String MakeCtrl( String input, String modifiers ) + static public string MakeCtrl( string input, string modifiers ) { return DeviceID + modifiers + input; } @@ -251,18 +251,26 @@ namespace SCJMapper_V2.Keyboard private bool m_activated = false; + /// + /// Return the device instance number (which is always 1) + /// + public override int XmlInstance { get { return 1; } } // const for keyboard + /// + /// Return the DX device instance number (which is always 0) + /// + public override int DevInstance { get { return 0; } } /// /// The DeviceClass of this instance /// - public override String DevClass { get { return KeyboardCls.DeviceClass; } } + public override string DevClass { get { return KeyboardCls.DeviceClass; } } /// /// The JS ProductName property /// - public override String DevName { get { return m_device.Properties.ProductName; } } + public override string DevName { get { return m_device.Properties.ProductName; } } /// /// The JS Instance GUID for multiple device support (VJoy gets 2 of the same name) /// - public String DevInstanceGUID { get { return m_device.Information.InstanceGuid.ToString( ); } } + public override string DevInstanceGUID { get { return m_device.Information.InstanceGuid.ToString( ); } } /// /// Returns the mapping color for this device @@ -273,7 +281,7 @@ namespace SCJMapper_V2.Keyboard } - public override Boolean Activated + public override bool Activated { get { return m_activated; } set @@ -331,7 +339,7 @@ namespace SCJMapper_V2.Keyboard /// Find the last change the user did on that device /// /// The last action as CryEngine compatible string - public override String GetLastChange( ) + public override string GetLastChange( ) { return DXKeyboardCmd( m_state.PressedKeys, true ); } @@ -341,7 +349,7 @@ namespace SCJMapper_V2.Keyboard /// Find the last change the user did on that device /// /// The last action as CryEngine compatible string - public String GetLastChange( Boolean modAndKey ) + public string GetLastChange( bool modAndKey ) { return DXKeyboardCmd( m_state.PressedKeys, modAndKey ); } @@ -350,7 +358,7 @@ namespace SCJMapper_V2.Keyboard /// /// Collect the current data from the device (DUMMY for Kbd) /// - public override void GetCmdData( String cmd, out int data ) + public override void GetCmdData( string cmd, out int data ) { // Make sure there is a valid device. data = 0; diff --git a/Mouse/MouseCls.cs b/Mouse/MouseCls.cs index b6634ef..a2d7914 100644 --- a/Mouse/MouseCls.cs +++ b/Mouse/MouseCls.cs @@ -22,12 +22,12 @@ namespace SCJMapper_V2.Mouse #region Static Items - public new const String DeviceClass = "mouse"; // the device name used throughout this app - public new const String DeviceID = "mo1_"; + public new const string DeviceClass = "mouse"; // the device name used throughout this app + 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 Boolean IsBlendedInput( String input ) + public new const string BlendedInput = DeviceID + DeviceCls.BlendedInput; + static public new bool IsBlendedInput( string input ) { if ( input == BlendedInput ) return true; return false; @@ -49,7 +49,7 @@ namespace SCJMapper_V2.Mouse /// /// /// - static new public Boolean IsDeviceClass( String deviceClass ) + static new public bool IsDeviceClass( string deviceClass ) { return ( deviceClass == DeviceClass ); } @@ -59,7 +59,7 @@ namespace SCJMapper_V2.Mouse /// /// /// - static public new String DeviceClassFromInput( String devInput ) + static public new string DeviceClassFromInput( string devInput ) { if ( DevMatch( devInput ) ) return DeviceClass; // this @@ -72,7 +72,7 @@ namespace SCJMapper_V2.Mouse /// /// A mouse input /// DevInput - static public new String DevInput( String input ) + static public new string DevInput( string input ) { if ( DevMatch( input ) ) return input; // already @@ -85,7 +85,7 @@ namespace SCJMapper_V2.Mouse /// /// A devInput string /// True for a match - static public new Boolean DevMatch( String devInput ) + static public new bool DevMatch( string devInput ) { return devInput.StartsWith( DeviceID ); } @@ -96,11 +96,11 @@ namespace SCJMapper_V2.Mouse /// /// The AC1 input string /// An AC2 style input string - static public String FromAC1( String input ) + static public string FromAC1( string input ) { // input is something like a mouse1 (TODO compositions like lctrl+mouse1 ??) // try easy: add mo1_ at the beginning - String retVal = input.Replace(" ",""); + string retVal = input.Replace(" ",""); if ( IsBlendedInput( input ) ) return input; return "mo1_" + retVal; @@ -113,7 +113,7 @@ namespace SCJMapper_V2.Mouse /// The input by the user /// Modifiers to be applied /// - static public String MakeCtrl( String input, String modifiers ) + static public string MakeCtrl( string input, string modifiers ) { return DeviceID + modifiers + input; } @@ -127,21 +127,29 @@ namespace SCJMapper_V2.Mouse private Control m_hwnd; private bool m_activated = false; - private String m_lastItem = ""; + private string m_lastItem = ""; private int m_senseLimit = 150; // axis jitter avoidance... + /// + /// Return the device instance number (which is always 1) + /// + public override int XmlInstance { get { return 1; } } // const 1 for mouse + /// + /// Return the DX device instance number (which is always 0) + /// + public override int DevInstance { get { return 0; } } /// /// The DeviceClass of this instance /// - public override String DevClass { get { return MouseCls.DeviceClass; } } + public override string DevClass { get { return MouseCls.DeviceClass; } } /// /// The JS ProductName property /// - public override String DevName { get { return m_device.Properties.ProductName; } } + public override string DevName { get { return m_device.Properties.ProductName; } } /// /// The JS Instance GUID for multiple device support (VJoy gets 2 of the same name) /// - public String DevInstanceGUID { get { return m_device.Information.InstanceGuid.ToString( ); } } + public override string DevInstanceGUID { get { return m_device.Information.InstanceGuid.ToString( ); } } /// /// Returns the mapping color for this device @@ -152,7 +160,7 @@ namespace SCJMapper_V2.Mouse } - public override Boolean Activated + public override bool Activated { get { return m_activated; } set @@ -218,7 +226,7 @@ namespace SCJMapper_V2.Mouse /// Z-axis, typically a wheel. If the mouse does not have a z-axis, the value is 0. /// /// The last action as CryEngine compatible string - public override String GetLastChange( ) + public override string GetLastChange( ) { // TODO: Expand this out into a joystick class (see commit for details) Dictionary axies = new Dictionary( ) @@ -279,7 +287,7 @@ namespace SCJMapper_V2.Mouse /// /// Collect the current data from the device (DUMMY for Mouse) /// - public override void GetCmdData( String cmd, out int data ) + public override void GetCmdData( string cmd, out int data ) { // Make sure there is a valid device. data = 0; @@ -347,9 +355,9 @@ namespace SCJMapper_V2.Mouse // mwheel_up, mwheel_down - public static String MouseCmd( MouseEventArgs e ) + public static string MouseCmd( MouseEventArgs e ) { - String mbs = ""; + string mbs = ""; switch ( e.Button ) { case MouseButtons.Left: { mbs = "mouse1"; diff --git a/OGL/FormJSCalCurve.cs b/OGL/FormJSCalCurve.cs index 0935644..3350ebe 100644 --- a/OGL/FormJSCalCurve.cs +++ b/OGL/FormJSCalCurve.cs @@ -172,10 +172,10 @@ namespace SCJMapper_V2.OGL command = dp.CommandCtrl; // the option data invertUsed = dp.InvertUsed; - deadzoneUsed = dp.Deviceoption.DeadzoneUsed; - deadzoneS = dp.Deviceoption.Deadzone; - saturationUsed = dp.Deviceoption.SaturationUsed; - saturationS = dp.Deviceoption.Saturation; + deadzoneUsed = dp.DeviceoptionRef.DeadzoneUsed; + deadzoneS = dp.DeviceoptionRef.Deadzone; + saturationUsed = dp.DeviceoptionRef.SaturationUsed; + saturationS = dp.DeviceoptionRef.Saturation; exponentUsed = dp.ExponentUsed; exponentS = dp.Exponent; nonLinCurveUsed = dp.NonLinCurveUsed; @@ -196,10 +196,10 @@ namespace SCJMapper_V2.OGL if ( !used ) return; // don't return strings to control the device dp.InvertUsed = invertUsed; - dp.Deviceoption.DeadzoneUsed = deadzoneUsed; - dp.Deviceoption.Deadzone = deadzoneS; - dp.Deviceoption.SaturationUsed = saturationUsed; - dp.Deviceoption.Saturation = saturationS; + dp.DeviceoptionRef.DeadzoneUsed = deadzoneUsed; + dp.DeviceoptionRef.Deadzone = deadzoneS; + dp.DeviceoptionRef.SaturationUsed = saturationUsed; + dp.DeviceoptionRef.Saturation = saturationS; dp.ExponentUsed = exponentUsed; dp.Exponent = exponentS; dp.NonLinCurveUsed = nonLinCurveUsed; @@ -316,26 +316,25 @@ namespace SCJMapper_V2.OGL - private OptionTree m_tuningRef = null; // will get the current optiontree on call - public OptionTree OptionTree + private Tuningoptions m_tuningOptions = null; // will get the current optiontree on call + public Tuningoptions TuningOptions { get { - return m_tuningRef; + return m_tuningOptions; } set { - m_tuningRef = value; - if ( m_tuningRef == null ) { - log.Error( "- OptionTree: m_tuningRef not assigned" ); + m_tuningOptions = value; + if ( m_tuningOptions == null ) { + log.Error( "- TuningOptions: m_tuningRef not assigned" ); return; } + YawTuning = m_tuningOptions.FirstTuningItem( "flight_move_yaw" ); + PitchTuning = m_tuningOptions.FirstTuningItem( "flight_move_pitch" ); + RollTuning = m_tuningOptions.FirstTuningItem( "flight_move_roll" ); - YawTuning = m_tuningRef.TuningItem( "flight_move_yaw" ); - PitchTuning = m_tuningRef.TuningItem( "flight_move_pitch" ); - RollTuning = m_tuningRef.TuningItem( "flight_move_roll" ); - - StrafeLatTuning = m_tuningRef.TuningItem( "flight_move_strafe_lateral" ); - StrafeVertTuning = m_tuningRef.TuningItem( "flight_move_strafe_vertical" ); - StrafeLonTuning = m_tuningRef.TuningItem( "flight_move_strafe_longitudinal" ); + StrafeLatTuning = m_tuningOptions.FirstTuningItem( "flight_move_strafe_lateral" ); + StrafeVertTuning = m_tuningOptions.FirstTuningItem( "flight_move_strafe_vertical" ); + StrafeLonTuning = m_tuningOptions.FirstTuningItem( "flight_move_strafe_longitudinal" ); } } @@ -1035,18 +1034,22 @@ namespace SCJMapper_V2.OGL { Vector3d m = Vector3d.Zero; ; + bool lat = (m_StrafeLatTuning != null) && ( m_StrafeLatTuning.GameDevice != null ); + bool vert = (m_StrafeVertTuning != null) && ( m_StrafeVertTuning.GameDevice != null ); + bool lon = (m_StrafeLonTuning != null) && ( m_StrafeLonTuning.GameDevice != null ); + int i_x = 0, i_y = 0, i_z = 0; // Joystick Input int x = 0; int y = 0; int z = 0; // retain real input as i_xyz - if ( m_StrafeLatTuning.GameDevice != null ) m_StrafeLatTuning.GameDevice.GetCmdData( m_liveStrafeLat.command, out i_x ); // + = right - if ( m_StrafeVertTuning.GameDevice != null ) m_StrafeVertTuning.GameDevice.GetCmdData( m_liveStrafeVert.command, out i_y ); // + = up - if ( m_StrafeLonTuning.GameDevice != null ) m_StrafeLonTuning.GameDevice.GetCmdData( m_liveStrafeLon.command, out i_z ); // += twist right + if ( lat ) m_StrafeLatTuning.GameDevice.GetCmdData( m_liveStrafeLat.command, out i_x ); // + = right + if ( vert ) m_StrafeVertTuning.GameDevice.GetCmdData( m_liveStrafeVert.command, out i_y ); // + = up + if ( lon ) m_StrafeLonTuning.GameDevice.GetCmdData( m_liveStrafeLon.command, out i_z ); // += twist right // apply the modifications of the control (deadzone, shape, sensitivity) x = i_x; y = i_y; z = i_z; // retain real input as i_xyz m_flightModel.Velocity = Vector3d.Zero; // Lateral - if ( m_StrafeLatTuning.GameDevice != null ) { + if ( lat ) { double fout = m_liveStrafeLat.ScaledOut( x ); // 0 .. 1000.0 lblYInput.Text = ( i_x / 1000.0 ).ToString( "0.00" ); lblYOutput.Text = ( fout ).ToString( "0.00" ); // calculate new direction vector @@ -1054,7 +1057,7 @@ namespace SCJMapper_V2.OGL } // Vertical - if ( m_StrafeVertTuning.GameDevice != null ) { + if ( vert ) { double fout = m_liveStrafeVert.ScaledOut( y ); // 0 .. 1000.0 lblPInput.Text = ( i_y / 1000.0 ).ToString( "0.00" ); lblPOutput.Text = ( fout ).ToString( "0.00" ); // calculate new direction vector @@ -1062,7 +1065,7 @@ namespace SCJMapper_V2.OGL } // Longitudinal - if ( m_StrafeLonTuning.GameDevice != null ) { + if ( lon ) { double fout = m_liveStrafeLon.ScaledOut( z ); // 0 .. 1000.0 lblRInput.Text = ( i_z / 1000.0 ).ToString( "0.00" ); lblROutput.Text = ( fout ).ToString( "0.00" ); // calculate new direction vector @@ -1079,19 +1082,23 @@ namespace SCJMapper_V2.OGL { Vector3d m = Vector3d.Zero; ; + bool yaw = (m_YawTuning != null) && ( m_YawTuning.GameDevice != null ); + bool pitch = (m_PitchTuning != null) && ( m_PitchTuning.GameDevice != null ); + bool roll = (m_RollTuning != null) && ( m_RollTuning.GameDevice != null ); + int i_x = 0, i_y = 0, i_z = 0; // Joystick Input int x = 0; int y = 0; int z = 0; // retain real input as i_xyz - if ( m_YawTuning.GameDevice != null ) m_YawTuning.GameDevice.GetCmdData( m_liveYaw.command, out i_x ); // + = right - if ( m_PitchTuning.GameDevice != null ) m_PitchTuning.GameDevice.GetCmdData( m_livePitch.command, out i_y ); // + = up - if ( m_RollTuning.GameDevice != null ) m_RollTuning.GameDevice.GetCmdData( m_liveRoll.command, out i_z ); // += twist right + if ( yaw ) m_YawTuning.GameDevice.GetCmdData( m_liveYaw.command, out i_x ); // + = right + if ( pitch ) m_PitchTuning.GameDevice.GetCmdData( m_livePitch.command, out i_y ); // + = up + if ( roll ) m_RollTuning.GameDevice.GetCmdData( m_liveRoll.command, out i_z ); // += twist right // apply the modifications of the control (deadzone, shape, sensitivity) x = i_x; y = i_y; z = i_z; // retain real input as i_xyz m_flightModel.Velocity = Vector3d.Zero; // Yaw - if ( m_YawTuning.GameDevice != null ) { + if ( yaw ) { double fout = m_liveYaw.ScaledOut( x ); // 0 .. 1000.0 lblYInput.Text = ( i_x / 1000.0 ).ToString( "0.00" ); lblYOutput.Text = ( fout ).ToString( "0.00" ); // calculate new direction vector @@ -1099,7 +1106,7 @@ namespace SCJMapper_V2.OGL } // Pitch - if ( m_PitchTuning.GameDevice != null ) { + if ( pitch ) { double fout = m_livePitch.ScaledOut( y ); // 0 .. 1000.0 lblPInput.Text = ( i_y / 1000.0 ).ToString( "0.00" ); lblPOutput.Text = ( fout ).ToString( "0.00" ); // calculate new direction vector @@ -1107,7 +1114,7 @@ namespace SCJMapper_V2.OGL } // Roll - if ( m_RollTuning.GameDevice != null ) { + if ( roll ) { double fout = m_liveRoll.ScaledOut( z ); // 0 .. 1000.0 lblRInput.Text = ( i_z / 1000.0 ).ToString( "0.00" ); lblROutput.Text = ( fout ).ToString( "0.00" ); // calculate new direction vector diff --git a/Options/DeviceOptionParameter.cs b/Options/DeviceOptionParameter.cs index 8463819..ee4ed70 100644 --- a/Options/DeviceOptionParameter.cs +++ b/Options/DeviceOptionParameter.cs @@ -1,26 +1,73 @@  +using System; + namespace SCJMapper_V2.Options { - public class DeviceOptionParameter + public class DeviceOptionParameter : ICloneable { private static readonly log4net.ILog log = log4net.LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod( ).DeclaringType ); private string m_deviceName = ""; + private string m_deviceGUID = ""; // identify the beast! + private string m_deviceClass = ""; + private int m_deviceNumber = 0; private string m_cmdCtrl = ""; // x, y, rotz ... private string m_doID = ""; private string m_action =""; // v_pitch .. assigned if known only private bool m_deadzoneEnabled = false; // default - private string m_deadzone = "0.000"; + private string m_deadzone = "0.000"; + private bool m_saturationSupported = false; // supported for Joystick only private bool m_saturationEnabled = false; // default private string m_saturation = "1.000"; + /// + /// Clone this object + /// + /// A deep Clone of this object + public object Clone( ) + { + var dop = (DeviceOptionParameter)this.MemberwiseClone(); + // more objects to deep copy + + return dop; + } + + /// + /// Check clone against This + /// + /// + /// True if the clone is identical but not a shallow copy + internal bool CheckClone( DeviceOptionParameter clone ) + { + bool ret = true; + // object vars first + ret &= ( this.m_deviceName == clone.m_deviceName ); // immutable string - shallow copy is OK + ret &= ( this.m_deviceGUID == clone.m_deviceGUID ); // immutable string - shallow copy is OK + ret &= ( this.m_deviceClass == clone.m_deviceClass );// immutable string - shallow copy is OK + ret &= ( this.m_deviceNumber == clone.m_deviceNumber ); + ret &= ( this.m_cmdCtrl == clone.m_cmdCtrl ); // immutable string - shallow copy is OK + ret &= ( this.m_doID == clone.m_doID ); // immutable string - shallow copy is OK + ret &= ( this.m_action == clone.m_action ); // immutable string - shallow copy is OK + ret &= ( this.m_deadzoneEnabled == clone.m_deadzoneEnabled ); + ret &= ( this.m_deadzone == clone.m_deadzone ); // immutable string - shallow copy is OK + ret &= ( this.m_saturationSupported == clone.m_saturationSupported ); + ret &= ( this.m_saturationEnabled == clone.m_saturationEnabled ); + ret &= ( this.m_saturation == clone.m_saturation ); // immutable string - shallow copy is OK + return ret; + } + + + + /// + /// cTor : empty + /// public DeviceOptionParameter( ) { } @@ -32,36 +79,62 @@ namespace SCJMapper_V2.Options /// The command e.g. x,y, rotz etc /// The deadzone value as string (empty string disables) /// The saturation value as string (empty string disables) - public DeviceOptionParameter(string deviceName, string cmdCtrl, string dz, string sa ) + public DeviceOptionParameter( DeviceCls device, string cmdCtrl, string dz, string sa ) { - m_deviceName = deviceName; - m_doID = Deviceoptions.DevOptionID( deviceName, cmdCtrl ); + m_deviceClass = device.DevClass; + m_deviceName = device.DevName; + m_deviceGUID = device.DevInstanceGUID; + m_deviceNumber = device.DevInstance; + + m_doID = Deviceoptions.DevOptionID( m_deviceClass, m_deviceName, cmdCtrl ); m_cmdCtrl = cmdCtrl; - if ( string.IsNullOrEmpty( dz ) ) { - m_deadzone = "0.000"; - m_deadzoneEnabled = false; - } else { + + m_deadzone = "0.000"; + m_deadzoneEnabled = false; + if ( ! string.IsNullOrEmpty( dz ) ) { m_deadzone = dz; m_deadzoneEnabled = true; } - if ( string.IsNullOrEmpty(sa)) { - m_saturation = "1.000"; - m_saturationEnabled = false; - } else { - m_saturation = sa; - m_saturationEnabled = true; + + m_saturationSupported = false; + m_saturation = "1.000"; + m_saturationEnabled = false; + if ( Joystick.JoystickCls.IsDeviceClass( m_deviceClass ) ) { + m_saturationSupported = true; + if ( ! string.IsNullOrEmpty( sa ) ) { + m_saturation = sa; + m_saturationEnabled = true; + } } } #region Properties - public string DeviceName + public string DevClass + { + get { return m_deviceClass; } + } + + public string DevName { get { return m_deviceName; } - set { m_deviceName = value; } } + /// + /// Returns the dx device number of the item + /// + public int DevInstance + { + get { return m_deviceNumber; } + } + + public string DevInstanceGUID + { + get { return m_deviceGUID; } + } + + public string DoID { get { return m_doID; } @@ -95,6 +168,14 @@ namespace SCJMapper_V2.Options set { m_deadzone = value; } } + public bool SaturationSupported + { + get { + return m_saturationSupported; + } + set { m_saturationSupported = value; } + } + public bool SaturationUsed { get { @@ -131,13 +212,11 @@ namespace SCJMapper_V2.Options if ( DeadzoneUsed || SaturationUsed ) { tmp += string.Format( "\t\n", m_deviceName ); if ( DeadzoneUsed ) tmp += string.Format( "\t\t\n \n" ); } return tmp; } - - } } diff --git a/Options/DeviceTuningParameter.cs b/Options/DeviceTuningParameter.cs index 7716169..814c5f4 100644 --- a/Options/DeviceTuningParameter.cs +++ b/Options/DeviceTuningParameter.cs @@ -9,10 +9,11 @@ namespace SCJMapper_V2.Options /// /// set of parameters to tune the Joystick /// - public class DeviceTuningParameter + public class DeviceTuningParameter : ICloneable { private static readonly log4net.ILog log = log4net.LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod( ).DeclaringType ); + private string m_nodetext = ""; // v_pitch - js1_x private string m_action = ""; // v_pitch private string m_cmdCtrl = ""; // js1_x, js1_y, js1_rotz ... @@ -24,9 +25,6 @@ namespace SCJMapper_V2.Options private string m_deviceName = ""; private bool m_isStrafe = false; // default - // private bool m_senseEnabled = false; // default - // private string m_sense = "1.00"; - private bool m_expEnabled = false; // default private string m_exponent = "1.000"; @@ -36,33 +34,82 @@ namespace SCJMapper_V2.Options private bool m_invertEnabled = false; // default - private DeviceCls m_device = null; + private DeviceCls m_deviceRef = null; // Ref + + private DeviceOptionParameter m_deviceoptionRef = null; // will be used only while editing the Options !! + + + /// + /// Clone this object + /// + /// A deep Clone of this object + public object Clone( ) + { + 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 + + return dt; + } + + /// + /// Check clone against This + /// + /// + /// True if the clone is identical but not a shallow copy + internal bool CheckClone( DeviceTuningParameter clone ) + { + bool ret = true; + // object vars first + ret &= ( this.m_nodetext == clone.m_nodetext ); // immutable string - shallow copy is OK + ret &= ( this.m_action == clone.m_action ); // immutable string - shallow copy is OK + ret &= ( this.m_cmdCtrl == clone.m_cmdCtrl );// immutable string - shallow copy is OK + ret &= ( this.m_class == clone.m_class ); // immutable string - shallow copy is OK + ret &= ( this.m_devInstanceNo == clone.m_devInstanceNo ); + ret &= ( this.m_option == clone.m_option ); + ret &= ( this.m_deviceName == clone.m_deviceName ); + ret &= ( this.m_isStrafe == clone.m_isStrafe ); + ret &= ( this.m_expEnabled == clone.m_expEnabled ); + ret &= ( this.m_exponent == clone.m_exponent ); + ret &= ( this.m_ptsEnabled == clone.m_ptsEnabled ); + ret &= ( this.m_PtsIn == clone.m_PtsIn ); + ret &= ( this.m_PtsOut == clone.m_PtsOut ); + ret &= ( this.m_invertEnabled == clone.m_invertEnabled ); + ret &= ( this.m_deviceRef == clone.m_deviceRef ); + + // check m_deviceoptionRef + // --> NO check as this is assigned and used only while editing the Options + + return ret; + } + - private DeviceOptionParameter m_deviceoption = null; public DeviceTuningParameter( string optName ) { m_option = optName; } + public DeviceTuningParameter( string optName, DeviceCls device ) + { + m_option = optName; + GameDevice = device; + } + #region Properties public DeviceCls GameDevice { - get { return m_device; } + get { return m_deviceRef; } set { - m_device = value; + m_deviceRef = value; m_class = ""; m_devInstanceNo = -1; - if ( m_device == null ) return; // got a null device - - if ( JoystickCls.IsDeviceClass( m_device.DevClass ) ) { - m_class = m_device.DevClass; - m_devInstanceNo = ( m_device as JoystickCls ).JSAssignment; - } else if ( GamepadCls.IsDeviceClass( m_device.DevClass ) ) { - m_class = m_device.DevClass; - m_devInstanceNo = 1; // supports ONE gamepad - } + if ( m_deviceRef == null ) return; // got a null device + + m_class = m_deviceRef.DevClass; + m_devInstanceNo = m_deviceRef.XmlInstance; } } @@ -107,13 +154,13 @@ namespace SCJMapper_V2.Options set { m_isStrafe = value; } } - public DeviceOptionParameter Deviceoption + public DeviceOptionParameter DeviceoptionRef { - get { return m_deviceoption; } + get { return m_deviceoptionRef; } set { - m_deviceoption = value; - if ( m_deviceoption != null ) - m_deviceoption.Action = m_action; + m_deviceoptionRef = value; + if ( m_deviceoptionRef != null ) + m_deviceoptionRef.Action = m_action; } } @@ -159,7 +206,7 @@ namespace SCJMapper_V2.Options public void Reset( ) { //GameDevice = null; - Deviceoption = null; + DeviceoptionRef = null; NodeText = ""; } @@ -179,29 +226,43 @@ namespace SCJMapper_V2.Options if ( cmd.Contains( "xi_thumblx" ) ) { // gamepad m_cmdCtrl = "xi_thumblx"; - m_deviceName = m_device.DevName; + m_deviceName = m_deviceRef.DevName; } else if ( cmd.Contains( "xi_thumbly" ) ) { // gamepad m_cmdCtrl = "xi_thumbly"; - m_deviceName = m_device.DevName; + m_deviceName = m_deviceRef.DevName; } else if ( cmd.Contains( "xi_thumbrx" ) ) { // gamepad m_cmdCtrl = "xi_thumbrx"; - m_deviceName = m_device.DevName; + m_deviceName = m_deviceRef.DevName; } else if ( cmd.Contains( "xi_thumbry" ) ) { // gamepad m_cmdCtrl = "xi_thumbry"; - m_deviceName = m_device.DevName; + m_deviceName = m_deviceRef.DevName; } // assume joystick else { // get parts m_cmdCtrl = JoystickCls.ActionFromJsCommand( cmd ); //js1_x -> x; js2_rotz -> rotz - m_deviceName = m_device.DevName; + m_deviceName = m_deviceRef.DevName; } } } + /// + /// Rounds a string to 3 decimals (if it is a number..) + /// + /// A value string + /// A rounded value string - or the string if not a number + private string RoundString( string valString ) + { + double d = 0; + if ( ( !string.IsNullOrEmpty( valString ) ) && double.TryParse( valString, out d ) ) { + return d.ToString( "0.000" ); + } else { + return valString; + } + } /// /// Format an XML -options- node from the tuning contents @@ -285,7 +346,7 @@ namespace SCJMapper_V2.Options */ exponent = reader["exponent"]; if ( !string.IsNullOrWhiteSpace( exponent ) ) { - Exponent = exponent; + Exponent = RoundString( exponent ); ExponentUsed = true; } } @@ -303,8 +364,8 @@ namespace SCJMapper_V2.Options string ptOut = ""; if ( reader.Name.ToLowerInvariant( ) == "point" ) { if ( reader.HasAttributes ) { - ptIn = reader["in"]; - ptOut = reader["out"]; + ptIn = RoundString( reader["in"] ); + ptOut = RoundString( reader["out"] ); m_PtsIn.Add( ptIn ); m_PtsOut.Add( ptOut ); m_ptsEnabled = true; } } @@ -313,12 +374,12 @@ namespace SCJMapper_V2.Options // sanity check - we've have to have 3 pts here - else we subst // add 2nd if ( m_PtsIn.Count < 2 ) { - m_PtsIn.Add( "0.5" ); m_PtsOut.Add( "0.5" ); + 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.75" ); m_PtsOut.Add( "0.75" ); + m_PtsIn.Add( "0.750" ); m_PtsOut.Add( "0.750" ); log.Info( "Options_fromXML: got only two nonlin points, added (0.75|0.75)" ); } } @@ -328,6 +389,5 @@ namespace SCJMapper_V2.Options return true; } - } } diff --git a/Options/Deviceoptions.cs b/Options/Deviceoptions.cs index a25a0bb..0643092 100644 --- a/Options/Deviceoptions.cs +++ b/Options/Deviceoptions.cs @@ -4,6 +4,8 @@ using System.Xml; using System.IO; using System.Xml.Linq; using SCJMapper_V2.Joystick; +using SCJMapper_V2.Gamepad; +using System.Linq; namespace SCJMapper_V2.Options { @@ -22,10 +24,13 @@ namespace SCJMapper_V2.Options /// Saitek X52 Pro Flight Controller /// /// - public class Deviceoptions : Dictionary + public class Deviceoptions : CloneableDictionary { private static readonly log4net.ILog log = log4net.LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod( ).DeclaringType ); + + #region Static parts + private static char ID_Delimiter = '⁞'; /// /// Create a DeviceOption ID from dev Name and the command @@ -33,7 +38,7 @@ namespace SCJMapper_V2.Options /// The game device name as retrieved from XInput /// A device control that supports devOptions (all ananlog controls) /// - public static string DevOptionID( string devName, string cmdCtrl ) + public static string DevOptionID( string deviceClass, string devName, string cmdCtrl ) { // cmdCtrl can be anything // v_flight_throttle_abs - js1_throttlez @@ -41,11 +46,10 @@ namespace SCJMapper_V2.Options // v_strafe_longitudinal - js1_roty // v_strafe_longitudinal - xi1_shoulderl+thumbly // v_strafe_longitudinal - xi1_thumbly + string cmd = cmdCtrl.Trim(); // messy... if ( cmd.Contains( "throttle" ) ) cmd = cmd.Replace( "throttle", "" ); // this is not suitable for the devOption - if ( cmd.Contains( "throttle" ) ) cmd = cmd.Replace( "thumbl", "" ); // this is not suitable for the devOption - if ( cmd.Contains( "throttle" ) ) cmd = cmd.Replace( "thumbr", "" ); // this is not suitable for the devOption if ( cmd.Contains( "_" ) ) { int l = cmd.LastIndexOf("_"); cmd = cmd.Substring( l + 1 ); // assuming it is never the last one.. @@ -54,24 +58,91 @@ namespace SCJMapper_V2.Options int l = cmd.LastIndexOf("+"); cmd = cmd.Substring( l + 1 ); // assuming it is never the last one.. } - return string.Format( "{0}{1}{2}", devName, ID_Delimiter, cmd ); + // we have to trick the gamepad name here to CIG generic + return string.Format( "{0}{1}{2}", ( GamepadCls.IsDeviceClass( deviceClass ) ) ? GamepadCls.DevNameCIG : devName, ID_Delimiter, cmd ); } + #endregion + private List m_stringOptions = new List( ); // collected options from XML that are not parsed + + /// + /// Clone this object + /// + /// A deep Clone of this object + public new object Clone( ) + { + var dop = new Deviceoptions((CloneableDictionary)base.Clone()); + // more objects to deep copy + dop.m_stringOptions = new List( m_stringOptions ); + +#if DEBUG + // check cloned item + System.Diagnostics.Debug.Assert( CheckClone( dop ) ); +#endif + return dop; + } + + /// + /// Check clone against This + /// + /// + /// True if the clone is identical but not a shallow copy + private bool CheckClone( Deviceoptions clone ) + { + bool ret = true; + // object vars first + ret &= ( !object.ReferenceEquals( this.m_stringOptions, clone.m_stringOptions ) ); // shall not be the same object !! + + // check THIS Dictionary + ret &= ( this.Count == clone.Count ); + if ( ret ) { + for ( int i = 0; i < this.Count; i++ ) { + ret &= ( this.ElementAt( i ).Key == clone.ElementAt( i ).Key ); + + ret &= ( !object.ReferenceEquals( this.ElementAt( i ).Value, clone.ElementAt( i ).Value ) ); // shall not be the same object !! + ret &= ( this.ElementAt( i ).Value.CheckClone( clone.ElementAt( i ).Value ) ); // sub check + } + } + return ret; + } + + + + private Deviceoptions( CloneableDictionary init ) + { + foreach ( KeyValuePair kvp in init ) { + this.Add( kvp.Key, kvp.Value ); + } + } + + // ctor - public Deviceoptions( JoystickList jsList ) + public Deviceoptions( ) { // create all devOptions for all devices found (they may or may no be used) - foreach ( JoystickCls js in jsList ) { + foreach ( JoystickCls js in DeviceInst.JoystickListRef ) { foreach ( string input in js.AnalogCommands ) { - string doid = DevOptionID(js.DevName, input); - if ( ! this.ContainsKey(doid)) { - this.Add( doid, new DeviceOptionParameter( js.DevName, input, "", "" ) ); // init with disabled defaults + string doid = DevOptionID(JoystickCls.DeviceClass, js.DevName, input); + if ( !this.ContainsKey( doid ) ) { + this.Add( doid, new DeviceOptionParameter( js, input, "", "" ) ); // init with disabled defaults + } else { + log.WarnFormat( "cTor - Joystick DO_ID {0} exists (likely a duplicate device name e,g, vJoy ??)", doid ); + } + } + } + + // add gamepad if there is any + if ( DeviceInst.GamepadRef != null ) { + foreach ( string input in DeviceInst.GamepadRef.AnalogCommands ) { + string doid = DevOptionID(GamepadCls.DeviceClass, DeviceInst.GamepadRef.DevName, input); + if ( !this.ContainsKey( doid ) ) { + this.Add( doid, new DeviceOptionParameter( DeviceInst.GamepadRef, input, "", "" ) ); // init with disabled defaults } else { - log.WarnFormat( "cTor - DO_ID {0} exists (likely a duplicate device name e,g, vJoy ??)", doid ); + log.WarnFormat( "cTor - Gamepad DO_ID {0} exists", doid ); } } } @@ -88,12 +159,28 @@ namespace SCJMapper_V2.Options /// public void ResetActions( ) { - foreach (KeyValuePair kv in this ) { + foreach ( KeyValuePair kv in this ) { kv.Value.Action = ""; } } + /// + /// Rounds a string to 3 decimals (if it is a number..) + /// + /// A value string + /// A rounded value string - or the string if not a number + private string RoundString( string valString ) + { + double d = 0; + if ( ( !string.IsNullOrEmpty( valString ) ) && double.TryParse( valString, out d ) ) { + return d.ToString( "0.000" ); + } else { + return valString; + } + } + + private string[] FormatXml( string xml ) { try { @@ -165,6 +252,7 @@ namespace SCJMapper_V2.Options 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 @@ -172,17 +260,19 @@ namespace SCJMapper_V2.Options if ( reader.Name.ToLowerInvariant( ) == "option" ) { if ( reader.HasAttributes ) { string input = reader["input"]; - string deadzone = reader["deadzone"]; - string saturation = reader["saturation"]; + string deadzone = RoundString( reader["deadzone"] ); + string saturation = RoundString( reader["saturation"] ); if ( !string.IsNullOrWhiteSpace( input ) ) { - string doID = DevOptionID(name, 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 ) ) { - this.Add( doID, new DeviceOptionParameter( name, input, deadzone, saturation ) ); + 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; @@ -195,7 +285,8 @@ namespace SCJMapper_V2.Options saturation = "1.000"; } if ( !this.ContainsKey( doID ) ) { - this.Add( doID, new DeviceOptionParameter( name, input, deadzone, saturation ) ); + 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; diff --git a/Options/FormOptions.Designer.cs b/Options/FormOptions.Designer.cs index 99f6dc3..5485868 100644 --- a/Options/FormOptions.Designer.cs +++ b/Options/FormOptions.Designer.cs @@ -35,7 +35,6 @@ this.tabOptions = new System.Windows.Forms.TabPage(); this.lvOptionTree = new System.Windows.Forms.ListView(); this.tabDevOption = new System.Windows.Forms.TabPage(); - this.lvDevOptions = new System.Windows.Forms.ListView(); this.pnlOptionInput = new System.Windows.Forms.Panel(); this.rbUsePts = new System.Windows.Forms.RadioButton(); this.rbUseExpo = new System.Windows.Forms.RadioButton(); @@ -72,12 +71,9 @@ this.btDebugStop = new System.Windows.Forms.Button(); this.panel4 = new System.Windows.Forms.Panel(); this.btExit = new System.Windows.Forms.Button(); - this.cobDevices = new System.Windows.Forms.ComboBox(); - this.label1 = new System.Windows.Forms.Label(); this.tableLayoutPanel1.SuspendLayout(); this.tabC.SuspendLayout(); this.tabOptions.SuspendLayout(); - this.tabDevOption.SuspendLayout(); this.pnlOptionInput.SuspendLayout(); this.panel2.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.chart1)).BeginInit(); @@ -148,31 +144,18 @@ // // tabDevOption // - this.tabDevOption.Controls.Add(this.lvDevOptions); this.tabDevOption.Location = new System.Drawing.Point(4, 22); this.tabDevOption.Name = "tabDevOption"; this.tabDevOption.Padding = new System.Windows.Forms.Padding(3); - this.tabDevOption.Size = new System.Drawing.Size(656, 607); + this.tabDevOption.Size = new System.Drawing.Size(656, 635); this.tabDevOption.TabIndex = 1; this.tabDevOption.Text = "Device Options"; this.tabDevOption.UseVisualStyleBackColor = true; // - // lvDevOptions - // - this.lvDevOptions.Dock = System.Windows.Forms.DockStyle.Fill; - this.lvDevOptions.Location = new System.Drawing.Point(3, 3); - this.lvDevOptions.Name = "lvDevOptions"; - this.lvDevOptions.Size = new System.Drawing.Size(650, 601); - this.lvDevOptions.TabIndex = 0; - this.lvDevOptions.UseCompatibleStateImageBehavior = false; - this.lvDevOptions.SelectedIndexChanged += new System.EventHandler(this.lvDevOptions_SelectedIndexChanged); - // // pnlOptionInput // this.pnlOptionInput.BackColor = System.Drawing.Color.WhiteSmoke; - this.pnlOptionInput.Controls.Add(this.label1); this.pnlOptionInput.Controls.Add(this.rbUsePts); - this.pnlOptionInput.Controls.Add(this.cobDevices); this.pnlOptionInput.Controls.Add(this.rbUseExpo); this.pnlOptionInput.Controls.Add(this.rbUseNone); this.pnlOptionInput.Controls.Add(this.panel2); @@ -216,7 +199,7 @@ this.rbUseNone.AutoSize = true; this.rbUseNone.Checked = true; this.rbUseNone.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.rbUseNone.Location = new System.Drawing.Point(13, 455); + this.rbUseNone.Location = new System.Drawing.Point(13, 482); this.rbUseNone.Name = "rbUseNone"; this.rbUseNone.Size = new System.Drawing.Size(55, 17); this.rbUseNone.TabIndex = 56; @@ -612,25 +595,6 @@ this.btExit.UseVisualStyleBackColor = true; this.btExit.Click += new System.EventHandler(this.btExit_Click); // - // cobDevices - // - this.cobDevices.DropDownWidth = 220; - this.cobDevices.FormattingEnabled = true; - this.cobDevices.Location = new System.Drawing.Point(103, 482); - this.cobDevices.Name = "cobDevices"; - this.cobDevices.Size = new System.Drawing.Size(220, 21); - this.cobDevices.TabIndex = 55; - this.cobDevices.SelectedIndexChanged += new System.EventHandler(this.cobDevices_SelectedIndexChanged); - // - // label1 - // - this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(10, 485); - this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(44, 13); - this.label1.TabIndex = 56; - this.label1.Text = "Device:"; - // // FormOptions // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); @@ -648,7 +612,6 @@ this.tableLayoutPanel1.PerformLayout(); this.tabC.ResumeLayout(false); this.tabOptions.ResumeLayout(false); - this.tabDevOption.ResumeLayout(false); this.pnlOptionInput.ResumeLayout(false); this.pnlOptionInput.PerformLayout(); this.panel2.ResumeLayout(false); @@ -674,7 +637,7 @@ private System.Windows.Forms.TabControl tabC; private System.Windows.Forms.TabPage tabOptions; private System.Windows.Forms.TabPage tabDevOption; - private System.Windows.Forms.ListView lvDevOptions; + private System.Windows.Forms.ListView lviewlvDevOptions; private System.Windows.Forms.Panel pnlOptionInput; private System.Windows.Forms.RadioButton rbUsePts; private System.Windows.Forms.RadioButton rbUseExpo; @@ -710,7 +673,5 @@ private System.Windows.Forms.Panel pnlPreview; private System.Windows.Forms.Panel panel4; private System.Windows.Forms.Button btExit; - private System.Windows.Forms.Label label1; - private System.Windows.Forms.ComboBox cobDevices; } } \ No newline at end of file diff --git a/Options/FormOptions.cs b/Options/FormOptions.cs index 18e221d..6339815 100644 --- a/Options/FormOptions.cs +++ b/Options/FormOptions.cs @@ -1,4 +1,5 @@ -using SCJMapper_V2.Joystick; +using SCJMapper_V2.Gamepad; +using SCJMapper_V2.Joystick; using SCJMapper_V2.OGL; using System; using System.Collections.Generic; @@ -21,6 +22,42 @@ namespace SCJMapper_V2.Options private Label[] lblOut = null; private bool m_formLoaded = false; + // Col Index of the ListView items + private const int LV_DevCtrl = 1; + private const int LV_Saturation = LV_DevCtrl+1; + private const int LV_Deadzone = LV_Saturation+1; + private const int LV_Invert = LV_Deadzone+1; + private const int LV_Expo = LV_Invert+1; + private const int LV_Pt1 = LV_Expo+1; + private const int LV_Pt2 = LV_Pt1+1; + private const int LV_Pt3 = LV_Pt2+1; + + // allow access by index - index is tabpage index + private TabPage[] tabs = null; // Tag = DeviceName + private ListView [] lviews = null; // Tag = ToID + + // search the LV with the corresponding Tag + private ListView FindLV( string toID ) + { + foreach ( TabPage tp in tabC.TabPages ) { + if ( toID == ( string )tp.Controls["LV"].Tag ) { + return ( ListView )tp.Controls["LV"]; + } + } + return null; + } + + // search the LV with the corresponding Tag + private ListView FindLVbyGUID( string guid ) + { + foreach ( TabPage tp in tabC.TabPages ) { + if ( guid == ( string )tp.Tag ) { + return ( ListView )tp.Controls["LV"]; + } + } + return null; + } + private BezierSeries m_bSeries = new BezierSeries( ); private enum ESubItems @@ -35,14 +72,17 @@ namespace SCJMapper_V2.Options ESubItems_LAST } - private OptionTree m_tuningRef = null; // will get the current optiontree on call - public OptionTree OptionTree { get { return m_tuningRef; } set { m_tuningRef = value; } } + + private Tuningoptions m_tuningRef = null; // will get the current optiontree on call + public Tuningoptions TuningOptions { get { return m_tuningRef; } set { m_tuningRef = value; } } private Deviceoptions m_devOptRef = null; // will get the current device options on call public Deviceoptions DeviceOptions { get { return m_devOptRef; } set { m_devOptRef = value; } } private DeviceList m_devListRef = null; // will get the current devices on call - public DeviceList Devicelist { get { return m_devListRef; } + public DeviceList Devicelist + { + get { return m_devListRef; } set { m_devListRef = value; } @@ -90,16 +130,7 @@ namespace SCJMapper_V2.Options private void FormOptions_Load( object sender, EventArgs e ) { log.Debug( "Load - Entry" ); - cobDevices.Items.Add( "Unassigned" ); // beware this makes the index of the combo one more than the Devlist !! - if ( Devicelist != null ) { - foreach (DeviceCls dev in Devicelist ) { - cobDevices.Items.Add( dev.DevName ); - } - } - cobDevices.SelectedIndex = 0; - - OptionTreeSetup( ); - DevOptionsSetup( ); + DeviceTabsSetup( ); PrepOptionsTab( ); m_formLoaded = true; @@ -109,7 +140,17 @@ namespace SCJMapper_V2.Options private void FormOptions_FormClosing( object sender, FormClosingEventArgs e ) { log.Debug( "FormClosing - Entry" ); - UpdateLiveTuning( ); + // have to carry on current edits - NO ListView SelectionChange Event happens + try { + if ( ( (ListView)tabC.SelectedTab.Controls["LV"]).SelectedItems.Count > 0 ) { + // we push the current one back to tuning and the list view + UpdateLiveTuning( ); + UpdateLiveDevOption( ); + } + } catch { + ; + } + log.Info( "Closed now" ); } @@ -118,187 +159,279 @@ namespace SCJMapper_V2.Options #region Setup - private void OptionTreeSetup( ) + // setup all device tabs + private void DeviceTabsSetup( ) + { + tabs = new TabPage[] { }; + lviews = new ListView[] { }; + + tabC.TabPages.Clear( ); + for ( int idx = 0; idx < m_devListRef.Count; idx++ ) { + if ( m_devListRef[idx].XmlInstance > 0 ) { + // only with mapped devices + ListView lview = new ListView(); + Array.Resize( ref lviews, lviews.Length + 1 ); lviews[lviews.Length - 1] = lview; + // copied from Designer.cs + lview.Dock = DockStyle.Fill; + lview.Location = new Point( 3, 3 ); + lview.Name = "LV"; + lview.Size = new Size( 650, 629 ); + lview.TabIndex = 0; + lview.UseCompatibleStateImageBehavior = false; + lview.View = View.Details; + lview.SelectedIndexChanged += new EventHandler( this.lvOptionTree_SelectedIndexChanged ); + + lview.Tag = Tuningoptions.TuneOptionIDfromJsN( m_devListRef[idx].DevClass, m_devListRef[idx].XmlInstance ); + //m_devListRef[idx].DevInstanceGUID; // find an LV + + TabPage tab = new TabPage(m_devListRef[idx].DevName); + Array.Resize( ref tabs, tabs.Length + 1 ); tabs[tabs.Length - 1] = tab; + + // copied from Designer.cs + tab.Controls.Add( lview ); + tab.Location = new Point( 4, 22 ); + tab.Name = "Tab"; + tab.Padding = new Padding( 3 ); + tab.Size = new Size( 656, 635 ); + tab.TabIndex = 0; + tab.UseVisualStyleBackColor = true; + + tab.Tag = m_devListRef[idx].DevInstanceGUID; // find a device Tab + tabC.TabPages.Add( tab ); + + DeviceTabSetup( tabC.TabPages.Count - 1 ); // last added + } + } + } + + // setup one device tab with index + private void DeviceTabSetup( int tabIndex ) + { + if ( tabIndex < 0 ) return; + + TabPage tab = tabs[tabIndex]; + ListView lview = lviews[tabIndex]; + + ListViewSetup( lview ); + + OptionTreeSetup( lview, ( string )tabs[tabIndex].Tag ); + + } + + // Basic list view setup + private void ListViewSetup( ListView lview ) + { + if ( lview == null ) return; + + lview.Clear( ); + lview.View = View.Details; + lview.LabelEdit = false; + lview.AllowColumnReorder = false; + lview.FullRowSelect = true; + lview.GridLines = true; + lview.CheckBoxes = false; + lview.MultiSelect = false; + lview.HideSelection = false; + + string instText = " - instance=" + Tuningoptions.XmlInstanceFromID((string)lview.Tag); + lview.Columns.Add( "Option" + instText, 180, HorizontalAlignment.Left ); + lview.Columns.Add( "Dev Control", 80, HorizontalAlignment.Left ); + lview.Columns.Add( "Saturation", 80, HorizontalAlignment.Center ); + lview.Columns.Add( "Deadzone", 80, HorizontalAlignment.Center ); + lview.Columns.Add( "Invert", 50, HorizontalAlignment.Center ); + lview.Columns.Add( "Expo.", 50, HorizontalAlignment.Center ); + lview.Columns.Add( "Curve P1", 90, HorizontalAlignment.Center ); + lview.Columns.Add( "Curve P2", 90, HorizontalAlignment.Center ); + lview.Columns.Add( "Curve P3", 90, HorizontalAlignment.Center ); + + lview.ShowGroups = true; + } + + // make this in one contained function - easier to maintain + private void ListViewItemSetup( ListViewItem lvi ) + { + lvi.SubItems.Add( "" ); // dev control + lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); // saturation + deadzone + lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); // invert + expo + lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); // 3 points + } + + + // Setup the listview for a particular Device Tab + private void OptionTreeSetup( ListView lview, string devGUID ) { log.Debug( "OptionTreeSetup - Entry" ); if ( m_tuningRef == null ) { log.Error( "- OptionTreeSetup: m_tuningRef not assigned" ); return; } - - lvOptionTree.Clear( ); - lvOptionTree.View = View.Details; - lvOptionTree.LabelEdit = false; - lvOptionTree.AllowColumnReorder = false; - lvOptionTree.FullRowSelect = true; - lvOptionTree.GridLines = true; - lvOptionTree.CheckBoxes = false; - lvOptionTree.MultiSelect = false; - lvOptionTree.HideSelection = false; + if ( m_devOptRef == null ) { + log.Error( "- OptionTreeSetup: m_devOptRef not assigned" ); + return; + } DeviceTuningParameter tuning = null; string option = ""; - ListViewGroup lvg; + ListViewGroup lvg = null; ListViewItem lvi; + List devNamesDone = new List(); + + // first the analog controls for the device + string gpGUID = ""; + foreach ( KeyValuePair kv in m_devOptRef ) { + if ( GamepadCls.IsDeviceClass( kv.Value.DevClass ) ) + gpGUID = kv.Value.DevInstanceGUID; // save for later below + + if ( kv.Value.DevInstanceGUID == devGUID ) { + if ( !devNamesDone.Contains( kv.Value.DevName ) ) { + lvg = new ListViewGroup( "Device Options" ); lview.Groups.Add( lvg ); + devNamesDone.Add( kv.Value.DevName ); + } + lvi = new ListViewItem( kv.Value.CommandCtrl, lvg ); lvi.Name = kv.Value.DoID; lview.Items.Add( lvi ); + ListViewItemSetup( lvi ); + UpdateLvDevOptionFromLiveValues( kv.Value ); + } + } - lvg = new ListViewGroup( "0", "flight_move" ); lvOptionTree.Groups.Add( lvg ); + // then the functions + lvg = new ListViewGroup( "0", "flight_move " ); lview.Groups.Add( lvg ); { - option = "flight_move_pitch"; tuning = m_tuningRef.TuningItem( option ); m_live.Load( tuning ); + option = "flight_move_pitch"; tuning = m_tuningRef.TuningItem( ( string )lview.Tag, option ); m_live.Load( tuning ); if ( m_live.used ) { - lvi = new ListViewItem( option, lvg ); lvi.Name = option; lvi.Name = option; lvOptionTree.Items.Add( lvi ); - lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); + lvi = new ListViewItem( option, lvg ); lvi.Name = option; lvi.Name = option; lview.Items.Add( lvi ); ListViewItemSetup( lvi ); UpdateLvOptionFromLiveValues( m_live ); } - option = "flight_move_yaw"; tuning = m_tuningRef.TuningItem( option ); m_live.Load( tuning ); + option = "flight_move_yaw"; tuning = m_tuningRef.TuningItem( ( string )lview.Tag, option ); m_live.Load( tuning ); if ( m_live.used ) { - lvi = new ListViewItem( option, lvg ); lvi.Name = option; lvOptionTree.Items.Add( lvi ); - lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); + lvi = new ListViewItem( option, lvg ); lvi.Name = option; lview.Items.Add( lvi ); ListViewItemSetup( lvi ); UpdateLvOptionFromLiveValues( m_live ); } - option = "flight_move_roll"; tuning = m_tuningRef.TuningItem( option ); m_live.Load( tuning ); + option = "flight_move_roll"; tuning = m_tuningRef.TuningItem( ( string )lview.Tag, option ); m_live.Load( tuning ); if ( m_live.used ) { - lvi = new ListViewItem( option, lvg ); lvi.Name = option; lvOptionTree.Items.Add( lvi ); - lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); + lvi = new ListViewItem( option, lvg ); lvi.Name = option; lview.Items.Add( lvi ); ListViewItemSetup( lvi ); UpdateLvOptionFromLiveValues( m_live ); } - option = "flight_move_strafe_vertical"; tuning = m_tuningRef.TuningItem( option ); m_live.Load( tuning ); + option = "flight_move_strafe_vertical"; tuning = m_tuningRef.TuningItem( ( string )lview.Tag, option ); m_live.Load( tuning ); if ( m_live.used ) { - lvi = new ListViewItem( option, lvg ); lvi.Name = option; lvOptionTree.Items.Add( lvi ); - lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); + lvi = new ListViewItem( option, lvg ); lvi.Name = option; lview.Items.Add( lvi ); ListViewItemSetup( lvi ); UpdateLvOptionFromLiveValues( m_live ); } - option = "flight_move_strafe_lateral"; tuning = m_tuningRef.TuningItem( option ); m_live.Load( tuning ); + option = "flight_move_strafe_lateral"; tuning = m_tuningRef.TuningItem( ( string )lview.Tag, option ); m_live.Load( tuning ); if ( m_live.used ) { - lvi = new ListViewItem( option, lvg ); lvi.Name = option; lvOptionTree.Items.Add( lvi ); - lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); + lvi = new ListViewItem( option, lvg ); lvi.Name = option; lview.Items.Add( lvi ); ListViewItemSetup( lvi ); UpdateLvOptionFromLiveValues( m_live ); } - option = "flight_move_strafe_longitudinal"; tuning = m_tuningRef.TuningItem( option ); m_live.Load( tuning ); + option = "flight_move_strafe_longitudinal"; tuning = m_tuningRef.TuningItem( ( string )lview.Tag, option ); m_live.Load( tuning ); if ( m_live.used ) { - lvi = new ListViewItem( option, lvg ); lvi.Name = option; lvOptionTree.Items.Add( lvi ); - lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); + lvi = new ListViewItem( option, lvg ); lvi.Name = option; lview.Items.Add( lvi ); ListViewItemSetup( lvi ); UpdateLvOptionFromLiveValues( m_live ); } } - lvg = new ListViewGroup( "1", "flight_throttle" ); lvOptionTree.Groups.Add( lvg ); + lvg = new ListViewGroup( "1", "flight_throttle" ); lview.Groups.Add( lvg ); { - option = "flight_throttle_abs"; tuning = m_tuningRef.TuningItem( option ); m_live.Load( tuning ); + option = "flight_throttle_abs"; tuning = m_tuningRef.TuningItem( ( string )lview.Tag, option ); m_live.Load( tuning ); if ( m_live.used ) { - lvi = new ListViewItem( option, lvg ); lvi.Name = option; lvOptionTree.Items.Add( lvi ); - lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); + lvi = new ListViewItem( option, lvg ); lvi.Name = option; lview.Items.Add( lvi ); ListViewItemSetup( lvi ); UpdateLvOptionFromLiveValues( m_live ); } - option = "flight_throttle_rel"; tuning = m_tuningRef.TuningItem( option ); m_live.Load( tuning ); + option = "flight_throttle_rel"; tuning = m_tuningRef.TuningItem( ( string )lview.Tag, option ); m_live.Load( tuning ); if ( m_live.used ) { - lvi = new ListViewItem( option, lvg ); lvi.Name = option; lvOptionTree.Items.Add( lvi ); - lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); + lvi = new ListViewItem( option, lvg ); lvi.Name = option; lview.Items.Add( lvi ); ListViewItemSetup( lvi ); UpdateLvOptionFromLiveValues( m_live ); } } - lvg = new ListViewGroup( "2", "flight_aim" ); lvOptionTree.Groups.Add( lvg ); + lvg = new ListViewGroup( "2", "flight_aim" ); lview.Groups.Add( lvg ); { - option = "flight_aim_pitch"; tuning = m_tuningRef.TuningItem( option ); m_live.Load( tuning ); + option = "flight_aim_pitch"; tuning = m_tuningRef.TuningItem( ( string )lview.Tag, option ); m_live.Load( tuning ); if ( m_live.used ) { - lvi = new ListViewItem( option, lvg ); lvi.Name = option; lvOptionTree.Items.Add( lvi ); - lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); + lvi = new ListViewItem( option, lvg ); lvi.Name = option; lview.Items.Add( lvi ); ListViewItemSetup( lvi ); UpdateLvOptionFromLiveValues( m_live ); } - option = "flight_aim_yaw"; tuning = m_tuningRef.TuningItem( option ); m_live.Load( tuning ); + option = "flight_aim_yaw"; tuning = m_tuningRef.TuningItem( ( string )lview.Tag, option ); m_live.Load( tuning ); if ( m_live.used ) { - lvi = new ListViewItem( option, lvg ); lvi.Name = option; lvOptionTree.Items.Add( lvi ); - lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); + lvi = new ListViewItem( option, lvg ); lvi.Name = option; lview.Items.Add( lvi ); ListViewItemSetup( lvi ); UpdateLvOptionFromLiveValues( m_live ); } } - lvg = new ListViewGroup( "3", "flight_view" ); lvOptionTree.Groups.Add( lvg ); + lvg = new ListViewGroup( "3", "flight_view" ); lview.Groups.Add( lvg ); { - option = "flight_view_pitch"; tuning = m_tuningRef.TuningItem( option ); m_live.Load( tuning ); + option = "flight_view_pitch"; tuning = m_tuningRef.TuningItem( ( string )lview.Tag, option ); m_live.Load( tuning ); if ( m_live.used ) { - lvi = new ListViewItem( option, lvg ); lvi.Name = option; lvOptionTree.Items.Add( lvi ); - lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); + lvi = new ListViewItem( option, lvg ); lvi.Name = option; lview.Items.Add( lvi ); ListViewItemSetup( lvi ); UpdateLvOptionFromLiveValues( m_live ); } - option = "flight_view_yaw"; tuning = m_tuningRef.TuningItem( option ); m_live.Load( tuning ); + option = "flight_view_yaw"; tuning = m_tuningRef.TuningItem( ( string )lview.Tag, option ); m_live.Load( tuning ); if ( m_live.used ) { - lvi = new ListViewItem( option, lvg ); lvi.Name = option; lvOptionTree.Items.Add( lvi ); - lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); + lvi = new ListViewItem( option, lvg ); lvi.Name = option; lview.Items.Add( lvi ); ListViewItemSetup( lvi ); UpdateLvOptionFromLiveValues( m_live ); } } - lvg = new ListViewGroup( "4", "Turret_aim" ); lvOptionTree.Groups.Add( lvg ); + lvg = new ListViewGroup( "4", "Turret_aim" ); lview.Groups.Add( lvg ); { - option = "turret_aim_pitch"; tuning = m_tuningRef.TuningItem( option ); m_live.Load( tuning ); + option = "turret_aim_pitch"; tuning = m_tuningRef.TuningItem( ( string )lview.Tag, option ); m_live.Load( tuning ); if ( m_live.used ) { - lvi = new ListViewItem( option, lvg ); lvi.Name = option; lvOptionTree.Items.Add( lvi ); - lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); + lvi = new ListViewItem( option, lvg ); lvi.Name = option; lview.Items.Add( lvi ); ListViewItemSetup( lvi ); UpdateLvOptionFromLiveValues( m_live ); } - option = "turret_aim_yaw"; tuning = m_tuningRef.TuningItem( option ); m_live.Load( tuning ); + option = "turret_aim_yaw"; tuning = m_tuningRef.TuningItem( ( string )lview.Tag, option ); m_live.Load( tuning ); if ( m_live.used ) { - lvi = new ListViewItem( option, lvg ); lvi.Name = option; lvOptionTree.Items.Add( lvi ); - lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); + lvi = new ListViewItem( option, lvg ); lvi.Name = option; lview.Items.Add( lvi ); ListViewItemSetup( lvi ); UpdateLvOptionFromLiveValues( m_live ); } } + // GP only + if ( devGUID == gpGUID ) { // now this selector is murks but then it works... + lvg = new ListViewGroup( "5", "fps_view" ); lview.Groups.Add( lvg ); + { + option = "fps_view_pitch"; tuning = m_tuningRef.TuningItem( ( string )lview.Tag, option ); m_live.Load( tuning ); + if ( m_live.used ) { + lvi = new ListViewItem( option, lvg ); lvi.Name = option; lview.Items.Add( lvi ); ListViewItemSetup( lvi ); + UpdateLvOptionFromLiveValues( m_live ); + } + option = "fps_view_yaw"; tuning = m_tuningRef.TuningItem( ( string )lview.Tag, option ); m_live.Load( tuning ); + if ( m_live.used ) { + lvi = new ListViewItem( option, lvg ); lvi.Name = option; lview.Items.Add( lvi ); ListViewItemSetup( lvi ); + UpdateLvOptionFromLiveValues( m_live ); + } + } + lvg = new ListViewGroup( "6", "fps_move" ); lview.Groups.Add( lvg ); + { + option = "fps_move_lateral"; tuning = m_tuningRef.TuningItem( ( string )lview.Tag, option ); m_live.Load( tuning ); + if ( m_live.used ) { + lvi = new ListViewItem( option, lvg ); lvi.Name = option; lview.Items.Add( lvi ); ListViewItemSetup( lvi ); + UpdateLvOptionFromLiveValues( m_live ); + } + option = "fps_move_longitudinal"; tuning = m_tuningRef.TuningItem( ( string )lview.Tag, option ); m_live.Load( tuning ); + if ( m_live.used ) { + lvi = new ListViewItem( option, lvg ); lvi.Name = option; lview.Items.Add( lvi ); ListViewItemSetup( lvi ); + UpdateLvOptionFromLiveValues( m_live ); + } + } - lvOptionTree.Columns.Add( "Option", 180, HorizontalAlignment.Left ); - lvOptionTree.Columns.Add( "Dev Control", 80, HorizontalAlignment.Left ); - lvOptionTree.Columns.Add( "Invert", 50, HorizontalAlignment.Center ); - lvOptionTree.Columns.Add( "Expo.", 50, HorizontalAlignment.Center ); - lvOptionTree.Columns.Add( "Curve P1", 90, HorizontalAlignment.Center ); - lvOptionTree.Columns.Add( "Curve P2", 90, HorizontalAlignment.Center ); - lvOptionTree.Columns.Add( "Curve P3", 90, HorizontalAlignment.Center ); - - lvOptionTree.ShowGroups = true; - - log.Debug( "OptionTreeSetup - Exit" ); - } - - private void DevOptionsSetup( ) - { - log.Debug( "DevOptionsSetup - Entry" ); - if ( m_devOptRef == null ) { - log.Error( "- DevOptionsSetup: m_devOptRef not assigned" ); - return; - } - - lvDevOptions.Clear( ); - lvDevOptions.View = View.Details; - lvDevOptions.LabelEdit = false; - lvDevOptions.AllowColumnReorder = false; - lvDevOptions.FullRowSelect = true; - lvDevOptions.GridLines = true; - lvDevOptions.CheckBoxes = false; - lvDevOptions.MultiSelect = false; - lvDevOptions.HideSelection = false; - - ListViewGroup lvg=null; - ListViewItem lvi; - List devNamesDone = new List(); - - foreach ( KeyValuePair kv in m_devOptRef ) { - if ( !devNamesDone.Contains( kv.Value.DeviceName ) ) { - lvg = new ListViewGroup( string.Format( "{0} - {1}", "jsN", kv.Value.DeviceName ) ); lvDevOptions.Groups.Add( lvg ); - devNamesDone.Add( kv.Value.DeviceName ); + lvg = new ListViewGroup( "7", "manned_ground_vehicle" ); lview.Groups.Add( lvg ); + { + option = "mgv_view_pitch"; tuning = m_tuningRef.TuningItem( ( string )lview.Tag, option ); m_live.Load( tuning ); + if ( m_live.used ) { + lvi = new ListViewItem( option, lvg ); lvi.Name = option; lview.Items.Add( lvi ); ListViewItemSetup( lvi ); + UpdateLvOptionFromLiveValues( m_live ); + } + option = "mgv_view_yaw"; tuning = m_tuningRef.TuningItem( ( string )lview.Tag, option ); m_live.Load( tuning ); + if ( m_live.used ) { + lvi = new ListViewItem( option, lvg ); lvi.Name = option; lview.Items.Add( lvi ); ListViewItemSetup( lvi ); + UpdateLvOptionFromLiveValues( m_live ); + } } - lvi = new ListViewItem( kv.Value.CommandCtrl, lvg ); lvi.Name = kv.Value.DoID; lvDevOptions.Items.Add( lvi ); - lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); lvi.SubItems.Add( "" ); - UpdateLvDevOptionFromLiveValues( kv.Value ); - } + }// if GP + - lvDevOptions.Columns.Add( "Dev Control", 40, HorizontalAlignment.Left ); - lvDevOptions.Columns.Add( "Action", 140, HorizontalAlignment.Left ); - lvDevOptions.Columns.Add( "Saturation", 80, HorizontalAlignment.Center ); - lvDevOptions.Columns.Add( "Deadzone", 80, HorizontalAlignment.Center ); - lvDevOptions.ShowGroups = true; - log.Debug( "DevOptionsSetup - Exit" ); + log.Debug( "OptionTreeSetup - Exit" ); } @@ -329,31 +462,41 @@ namespace SCJMapper_V2.Options Reset( ); used = true; // always + isTuningItem = true; + isDevOptionItem = false; + gameDeviceRef = dp.GameDevice; nodetext = dp.NodeText; - if ( ! string.IsNullOrEmpty( dp.NodeText ) ) { + if ( !string.IsNullOrEmpty( dp.NodeText ) ) { string[] e = nodetext.Split( new char[] { ActionTreeInputNode.RegDiv, ActionTreeInputNode.ModDiv }, StringSplitOptions.RemoveEmptyEntries ); if ( e.Length > 0 ) control = e[1].TrimEnd( ); else control = dp.NodeText; - }else if ( gameDeviceRef != null ) { - control = gameDeviceRef.DevName; - }else { + } else if ( gameDeviceRef != null ) { + //control = gameDeviceRef.DevName; + } else { control = "n.a."; } command = dp.CommandCtrl; - // the option data - if ( dp.Deviceoption != null ) { - deadzoneUsed = dp.Deviceoption.DeadzoneUsed; - deadzoneS = dp.Deviceoption.Deadzone; - saturationUsed = dp.Deviceoption.SaturationUsed; - saturationS = dp.Deviceoption.Saturation; + + // the device option data if available + if ( dp.DeviceoptionRef != null ) { + isDevOptionItem = true; + + deadzoneUsed = dp.DeviceoptionRef.DeadzoneUsed; + deadzoneS = dp.DeviceoptionRef.Deadzone; + + saturationSupported = dp.DeviceoptionRef.SaturationSupported; + saturationUsed = dp.DeviceoptionRef.SaturationUsed; + saturationS = dp.DeviceoptionRef.Saturation; } else { deadzoneUsed = false; + saturationSupported = false; saturationUsed = false; } + // the tuning data invertUsed = dp.InvertUsed; exponentUsed = dp.ExponentUsed; exponentS = dp.Exponent; @@ -378,15 +521,21 @@ namespace SCJMapper_V2.Options Reset( ); used = true; + isTuningItem = false; + isDevOptionItem = true; + nodetext = dp.CommandCtrl; control = dp.CommandCtrl; command = dp.CommandCtrl; - // the option data + // the device option data deadzoneUsed = dp.DeadzoneUsed; deadzoneS = dp.Deadzone; + + saturationSupported = dp.SaturationSupported; saturationUsed = dp.SaturationUsed; saturationS = dp.Saturation; + // tuning data us not used here invertUsed = false; exponentUsed = false; nonLinCurveUsed = false; @@ -398,17 +547,25 @@ namespace SCJMapper_V2.Options { if ( !used ) return; // don't return strings to control the device + /* This is preassigned now - delete if finished if ( AcceptGameDevice ) { dp.GameDevice = gameDeviceRef; } - + */ dp.InvertUsed = invertUsed; - if ( dp.Deviceoption != null ) { - dp.Deviceoption.DeadzoneUsed = deadzoneUsed; - dp.Deviceoption.Deadzone = deadzoneS; - dp.Deviceoption.SaturationUsed = saturationUsed; - dp.Deviceoption.Saturation = saturationS; + + // update device options + if ( dp.DeviceoptionRef != null ) { + dp.DeviceoptionRef.DeadzoneUsed = deadzoneUsed; + dp.DeviceoptionRef.Deadzone = deadzoneS; + if ( saturationSupported ) { + dp.DeviceoptionRef.SaturationUsed = saturationUsed; + dp.DeviceoptionRef.Saturation = saturationS; + } else { + dp.DeviceoptionRef.SaturationUsed = false; + } } + // update tuning dp.ExponentUsed = exponentUsed; dp.Exponent = exponentS; dp.NonLinCurveUsed = nonLinCurveUsed; @@ -420,17 +577,22 @@ namespace SCJMapper_V2.Options dp.NonLinCurvePtsOut = pts; } - // update the TuningParameters + // update the DeviceOptions public void Update( ref DeviceOptionParameter dp ) { if ( !used ) return; // don't return strings to control the device - dp.DeadzoneUsed = deadzoneUsed; - dp.Deadzone = deadzoneS; + dp.DeadzoneUsed = deadzoneUsed; + dp.Deadzone = deadzoneS; + if ( saturationSupported ) { dp.SaturationUsed = saturationUsed; dp.Saturation = saturationS; + } else { + dp.SaturationUsed = false; + } } + // reset the live parameters public void Reset( ) { used = false; @@ -438,7 +600,7 @@ namespace SCJMapper_V2.Options m_range = 1000.0; m_sign = 1.0; invertUsed = false; deadzoneUsed = false; deadzone = 0.0; - saturationUsed = false; saturation = 1000.0; + saturationSupported = false; saturationUsed = false; saturation = 1000.0; exponentUsed = false; exponent = 1.0; nonLinCurveUsed = false; } @@ -454,6 +616,9 @@ namespace SCJMapper_V2.Options public bool AcceptGameDevice { get { return string.IsNullOrEmpty( nodetext ); } } // this is how we do it.. public DeviceCls gameDeviceRef = null; + public bool isTuningItem = false; + public bool isDevOptionItem = false; + // calc values private const double MAX_DZ = 160.0; // avoid range issues and silly values.. private const double MIN_SAT = 200.0; // avoid range issues and silly values.. @@ -498,6 +663,7 @@ namespace SCJMapper_V2.Options } } + public bool saturationSupported = false; public bool saturationUsed = false; private double m_saturation = 1000.0;// stores 1000 * set value public double saturation { get { return m_saturation; } set { m_saturation = ( value < MIN_SAT ) ? MIN_SAT : value; m_range = m_saturation - m_deadzone; } } @@ -595,7 +761,7 @@ namespace SCJMapper_V2.Options lblLiveNodetext.Text = "---"; cbxLiveInvert.Checked = false; lblLiveOutDeadzone.Text = "0.000"; cbxUseDeadzone.Checked = false; tbDeadzone.Enabled = false; - lblLiveOutSaturation.Text = "1.000"; cbxUseSaturation.Checked = false; tbSaturation.Enabled = false; + lblLiveOutSaturation.Text = "1.000"; cbxUseSaturation.Checked = false; tbSaturation.Enabled = false; cbxUseSaturation.Enabled = false; lblLiveOutExponent.Text = "1.000"; rbLivePtExponent.Checked = false; lblLiveIn1.Text = "0.250"; lblLiveOut1.Text = "0.250"; lblLiveIn2.Text = "0.500"; lblLiveOut2.Text = "0.500"; lblLiveIn3.Text = "0.750"; lblLiveOut3.Text = "0.750"; rbLivePt1.Checked = false; rbLivePt2.Checked = false; rbLivePt3.Checked = false; @@ -604,27 +770,23 @@ namespace SCJMapper_V2.Options m_updatingPts--; // end guard log.Debug( "UpdateGUIFromLiveValues - Exit 'not used'" ); - return; + return; // EXIT } + // get values from Live storage - pnlOptionInput.Enabled = true; + pnlOptionInput.Visible = lv.isTuningItem; + pnlDevOptionInput.Visible = lv.isDevOptionItem; + // pnlDevOptionInput.Visible = !lv.AcceptGameDevice; // cannot assign DevOptions to Tuning parameters without Action (will just dumped the Option only) + lblLiveNodetext.Text = lv.nodetext; - pnlDevOptionInput.Visible = ! lv.AcceptGameDevice; // cannot assign DevOptions to Tuning parameters without Action (will just dumped the Option only) - cobDevices.Enabled = lv.AcceptGameDevice; - if ( m_live.gameDeviceRef != null ) { - int idx = cobDevices.Items.IndexOf( m_live.gameDeviceRef.DevName ); - if ( idx >= 0 ) - cobDevices.SelectedIndex = idx; - } - else { - cobDevices.SelectedIndex = 0; // unassigned - } if ( lv.deadzoneUsed ) lblLiveOutDeadzone.Text = lv.deadzoneS; cbxUseDeadzone.Checked = lv.deadzoneUsed; - if ( lv.saturationUsed ) lblLiveOutSaturation.Text = lv.saturationS; - cbxUseSaturation.Checked = lv.saturationUsed; + + if ( lv.saturationSupported && lv.saturationUsed ) lblLiveOutSaturation.Text = lv.saturationS; + cbxUseSaturation.Enabled = lv.saturationSupported; + cbxUseSaturation.Checked = ( lv.saturationSupported && lv.saturationUsed ); cbxLiveInvert.Enabled = true; cbxLiveInvert.Checked = lv.invertUsed; @@ -648,32 +810,39 @@ namespace SCJMapper_V2.Options } - private void UpdateLvOptionFromLiveValues( LiveValues lv ) + private void UpdateLvOptionFromLiveValues( LiveValues lval ) { log.Debug( "UpdateLvOptionFromLiveValues - Entry" ); - if ( !lvOptionTree.Items.ContainsKey( lv.optionName ) ) { - log.Error( "ERROR: UpdateLvOptionFromLiveValues - Did not found Option: " + lv.optionName ); + if ( lval.gameDeviceRef == null ) + return; // should finally not happen.. + + // find the row entry + ListView lv = FindLVbyGUID( lval.gameDeviceRef.DevInstanceGUID ); + if ( lv == null ) return; // happens at startup when not all are created yet + + if ( !lv.Items.ContainsKey( lval.optionName ) ) { + log.Error( "ERROR: UpdateLvOptionFromLiveValues - Did not found Option: " + lval.optionName ); log.Debug( "UpdateLvOptionFromLiveValues - Exit 'not used'" ); return; } - ListViewItem lvi = lvOptionTree.Items[lv.optionName]; - if ( !lv.used ) { + ListViewItem lvi = lv.Items[lval.optionName]; + if ( !lval.used ) { // leave alone.. for next time enabling it - lvi.SubItems[1].Text = m_live.control; // js4_x - lvi.SubItems[2].Text = "---"; lvi.SubItems[3].Text = "---"; // inverted .. expo + lvi.SubItems[LV_DevCtrl].Text = m_live.control; // js4_x + lvi.SubItems[LV_Invert].Text = "---"; lvi.SubItems[LV_Expo].Text = "---"; // inverted .. expo lvi.SubItems[4].Text = "--- / ---"; lvi.SubItems[5].Text = "--- / ---"; lvi.SubItems[6].Text = "--- / ---"; // pt1..3 } else { - lvi.SubItems[1].Text = m_live.control; // js4_x - lvi.SubItems[2].Text = m_live.invertS; + lvi.SubItems[LV_DevCtrl].Text = m_live.control; // js4_x + lvi.SubItems[LV_Invert].Text = m_live.invertS; if ( m_live.exponentUsed ) - lvi.SubItems[3].Text = m_live.exponentS; // inverted .. expo + lvi.SubItems[LV_Expo].Text = m_live.exponentS; // inverted .. expo else - lvi.SubItems[3].Text = "---"; // inverted .. expo + lvi.SubItems[LV_Expo].Text = "---"; // inverted .. expo if ( m_live.nonLinCurveUsed ) { - lvi.SubItems[4].Text = m_live.PtS( 1 ); lvi.SubItems[5].Text = m_live.PtS( 2 ); lvi.SubItems[6].Text = m_live.PtS( 3 ); // pt1..3 + lvi.SubItems[LV_Pt1].Text = m_live.PtS( 1 ); lvi.SubItems[LV_Pt2].Text = m_live.PtS( 2 ); lvi.SubItems[LV_Pt3].Text = m_live.PtS( 3 ); // pt1..3 } else { - lvi.SubItems[4].Text = "--- / ---"; lvi.SubItems[5].Text = "--- / ---"; lvi.SubItems[6].Text = "--- / ---"; // pt1..3 + lvi.SubItems[LV_Pt1].Text = "--- / ---"; lvi.SubItems[LV_Pt2].Text = "--- / ---"; lvi.SubItems[LV_Pt3].Text = "--- / ---"; // pt1..3 } } @@ -684,22 +853,26 @@ namespace SCJMapper_V2.Options private void UpdateLvDevOptionFromLiveValues( DeviceOptionParameter dp ) { log.Debug( "UpdateLvDevOptionFromLiveValues - Entry" ); - if ( !lvDevOptions.Items.ContainsKey( dp.DoID ) ) { + ListView lv = FindLVbyGUID( dp.DevInstanceGUID ); + if ( !lv.Items.ContainsKey( dp.DoID ) ) { log.Error( "ERROR: UpdateLvDevOptionFromLiveValues - Did not found Option: " + dp.DoID ); log.Debug( "UpdateLvDevOptionFromLiveValues - Exit 'not used'" ); return; } - ListViewItem lvi = lvDevOptions.Items[dp.DoID]; - lvi.SubItems[1].Text = dp.Action; // Action - if ( dp.SaturationUsed ) - lvi.SubItems[2].Text = dp.Saturation; // saturation + ListViewItem lvi = lv.Items[dp.DoID]; + lvi.SubItems[LV_DevCtrl].Text = dp.Action; // Action + if ( dp.SaturationSupported && dp.SaturationUsed ) + lvi.SubItems[LV_Saturation].Text = dp.Saturation; // saturation + else if ( dp.SaturationSupported ) + lvi.SubItems[LV_Saturation].Text = "---"; else - lvi.SubItems[2].Text = "---"; + lvi.SubItems[LV_Saturation].Text = "n.a."; + if ( dp.DeadzoneUsed ) - lvi.SubItems[3].Text = dp.Deadzone; // deadzone + lvi.SubItems[LV_Deadzone].Text = dp.Deadzone; // deadzone else - lvi.SubItems[3].Text = "---"; + lvi.SubItems[LV_Deadzone].Text = "---"; log.Debug( "UpdateLvDevOptionFromLiveValues - Exit" ); } @@ -828,14 +1001,16 @@ namespace SCJMapper_V2.Options bool deadzoneUsed = true; bool satUsed = true; + bool satSupp = true; bool expUsed = true; bool ptsUsed = true; // see what is on display.. // Yaw - deadzoneUsed = ( m_live.deadzoneUsed == true ); - satUsed = ( m_live.saturationUsed == true ); - expUsed = ( m_live.exponentUsed == true ); - ptsUsed = ( m_live.nonLinCurveUsed == true ); + deadzoneUsed = m_live.deadzoneUsed; + satSupp = m_live.saturationSupported; + satUsed = ( satSupp && m_live.saturationUsed ); + expUsed = m_live.exponentUsed; + ptsUsed = m_live.nonLinCurveUsed; lblGraphDeadzone.Text = m_live.deadzoneS; lblGraphSaturation.Text = m_live.saturationS; @@ -1066,13 +1241,6 @@ namespace SCJMapper_V2.Options lvOptionTree.Items[0].Selected = true; } - private void PrepDevOptionsTab( ) - { - pnlOptionInput.Visible = false; - if ( lvDevOptions.Items.Count > 0 ) - lvDevOptions.Items[0].Selected = true; - } - // get the Live Item updated private void lvOptionTree_SelectedIndexChanged( object sender, EventArgs e ) @@ -1080,32 +1248,28 @@ namespace SCJMapper_V2.Options log.Debug( "lvOptionTree_SelectedIndexChanged - Entry" ); try { if ( ( sender as ListView ).SelectedItems.Count > 0 ) { - // before loading a new one we push the current one back to tuning and the list view - UpdateLiveTuning( ); - ListViewItem lvi = ( sender as ListView ).SelectedItems[0]; - m_liveTuning = m_tuningRef.TuningItem( lvi.Name ); - m_live.Load( m_liveTuning ); - UpdateGUIFromLiveValues( m_live ); - UpdateChartItems( ); - } - } catch { - ; - } - log.Debug( "lvOptionTree_SelectedIndexChanged - Exit" ); - } - - - private void lvDevOptions_SelectedIndexChanged( object sender, EventArgs e ) - { - log.Debug( "lvDevOptions_SelectedIndexChanged - Entry" ); - try { - if ( ( sender as ListView ).SelectedItems.Count > 0 ) { // before loading a new one we push the current one back to tuning and the list view + UpdateLiveTuning( ); UpdateLiveDevOption( ); + ListViewItem lvi = ( sender as ListView ).SelectedItems[0]; - m_liveDevOption = m_devOptRef[lvi.Name]; - m_live.Load( m_liveDevOption ); + // get the associated parameter - either DevOptions for the first part or Tuning for 2nd and on + m_liveTuning = m_tuningRef.TuningItem( ( string )( sender as ListView ).Tag, lvi.Name ); + if ( m_liveTuning == null ) { + // try devOptions only + if ( m_devOptRef.ContainsKey( lvi.Name ) ) { + m_liveDevOption = m_devOptRef[lvi.Name]; + m_live.Load( m_liveDevOption ); + } else { + m_liveDevOption = null; + } + + } else { + // valid tuning item + m_liveDevOption = m_liveTuning.DeviceoptionRef; // also connect the DevOptions here + m_live.Load( m_liveTuning ); + } UpdateGUIFromLiveValues( m_live ); UpdateChartItems( ); @@ -1113,30 +1277,23 @@ namespace SCJMapper_V2.Options } catch { ; } - log.Debug( "lvDevOptions_SelectedIndexChanged - Exit" ); + log.Debug( "lvOptionTree_SelectedIndexChanged - Exit" ); } + // handles Selecting AND Deselecting private void tabC_Selecting( object sender, TabControlCancelEventArgs e ) { log.Debug( "tabC_Selecting - Entry" ); - if ( ( e.TabPageIndex == 0 ) && ( e.Action == TabControlAction.Deselecting ) ) { + if ( e.Action == TabControlAction.Deselecting ) { // before leaving the Tab we push the current one back to tuning and the list view UpdateLiveTuning( ); + UpdateLiveDevOption( ); m_liveTuning = null; m_live.Reset( ); - } else - if ( ( e.TabPageIndex == 0 ) && ( e.Action == TabControlAction.Selecting ) ) { + } else if ( e.Action == TabControlAction.Selecting ) { PrepOptionsTab( ); - } else - if ( ( e.TabPageIndex == 1 ) && ( e.Action == TabControlAction.Deselecting ) ) { - UpdateLiveDevOption( ); - m_liveDevOption = null; - m_live.Reset( ); - } else - if ( ( e.TabPageIndex == 1 ) && ( e.Action == TabControlAction.Selecting ) ) { - PrepDevOptionsTab( ); - } else { } + } e.Cancel = false; // let it change log.Debug( "tabC_Selecting - Exit" ); @@ -1147,19 +1304,6 @@ namespace SCJMapper_V2.Options // It ai setup as OK button - nothing here so far... } - private void cobDevices_SelectedIndexChanged( object sender, EventArgs e ) - { - - if ( m_live.AcceptGameDevice ) { - if ( cobDevices.SelectedIndex <= 0 ) { - m_live.gameDeviceRef = null; - m_live.control = "n.a."; - } else { - m_live.gameDeviceRef = m_devListRef[cobDevices.SelectedIndex-1]; // we have the empty element on top in the combo - m_live.control = m_live.gameDeviceRef.DevName; - } - } - } } diff --git a/Options/OptionTree.cs b/Options/OptionTree.cs index d5cb2f5..6bd54bc 100644 --- a/Options/OptionTree.cs +++ b/Options/OptionTree.cs @@ -30,49 +30,93 @@ namespace SCJMapper_V2.Options /// /// options are given per deviceClass and instance - it seems /// - public class OptionTree + public class OptionTree : ICloneable { private static readonly log4net.ILog log = log4net.LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod( ).DeclaringType ); + // Support only one set of independent options (string storage) List m_stringOptions = new List( ); // bag for all tuning items - key is the option name - Dictionary m_tuning = new Dictionary(); + CloneableDictionary m_tuning = new CloneableDictionary(); + + + + /// + /// Clone this object + /// + /// A deep Clone of this object + public object Clone( ) + { + var ot = (OptionTree)this.MemberwiseClone(); + // more objects to deep copy + ot.m_stringOptions = new List( m_stringOptions ); + if ( this.m_tuning != null ) ot.m_tuning = ( CloneableDictionary )this.m_tuning.Clone( ); + + return ot; + } + + /// + /// Check clone against This + /// + /// + /// True if the clone is identical but not a shallow copy + internal bool CheckClone( OptionTree clone ) + { + bool ret = true; + // object vars first + ret &= ( !object.ReferenceEquals( this.m_stringOptions, clone.m_stringOptions ) ); // shall not be the same object !! + + // check m_tuning Dictionary + ret &= ( this.m_tuning.Count == clone.m_tuning.Count ); + if ( ret ) { + for ( int i = 0; i < this.m_tuning.Count; i++ ) { + ret &= ( this.m_tuning.ElementAt( i ).Key == clone.m_tuning.ElementAt( i ).Key ); + + ret &= ( !object.ReferenceEquals( this.m_tuning.ElementAt( i ).Value, clone.m_tuning.ElementAt( i ).Value ) ); // shall not be the same object !! + ret &= ( this.m_tuning.ElementAt( i ).Value.CheckClone( clone.m_tuning.ElementAt( i ).Value ) ); + } + } + return ret; + } + + + // ctor - public OptionTree( ) + public OptionTree( DeviceCls device ) { - m_tuning.Add( "flight_move_pitch", new DeviceTuningParameter( "flight_move_pitch" ) ); - m_tuning.Add( "flight_move_yaw", new DeviceTuningParameter( "flight_move_yaw" ) ); - m_tuning.Add( "flight_move_roll", new DeviceTuningParameter( "flight_move_roll" ) ); - m_tuning.Add( "flight_move_strafe_vertical", new DeviceTuningParameter( "flight_move_strafe_vertical" ) ); - m_tuning.Add( "flight_move_strafe_lateral", new DeviceTuningParameter( "flight_move_strafe_lateral" ) ); - m_tuning.Add( "flight_move_strafe_longitudinal", new DeviceTuningParameter( "flight_move_strafe_longitudinal" ) ); + m_tuning.Add( "flight_move_pitch", new DeviceTuningParameter( "flight_move_pitch", device ) ); + m_tuning.Add( "flight_move_yaw", new DeviceTuningParameter( "flight_move_yaw", device ) ); + m_tuning.Add( "flight_move_roll", new DeviceTuningParameter( "flight_move_roll", device ) ); + m_tuning.Add( "flight_move_strafe_vertical", new DeviceTuningParameter( "flight_move_strafe_vertical", device ) ); + m_tuning.Add( "flight_move_strafe_lateral", new DeviceTuningParameter( "flight_move_strafe_lateral", device ) ); + m_tuning.Add( "flight_move_strafe_longitudinal", new DeviceTuningParameter( "flight_move_strafe_longitudinal", device ) ); - m_tuning.Add( "flight_throttle_abs", new DeviceTuningParameter( "flight_throttle_abs" ) ); - m_tuning.Add( "flight_throttle_rel", new DeviceTuningParameter( "flight_throttle_rel" ) ); + m_tuning.Add( "flight_throttle_abs", new DeviceTuningParameter( "flight_throttle_abs", device ) ); + m_tuning.Add( "flight_throttle_rel", new DeviceTuningParameter( "flight_throttle_rel", device ) ); - m_tuning.Add( "flight_aim_pitch", new DeviceTuningParameter( "flight_aim_pitch" ) ); - m_tuning.Add( "flight_aim_yaw", new DeviceTuningParameter( "flight_aim_yaw" ) ); + m_tuning.Add( "flight_aim_pitch", new DeviceTuningParameter( "flight_aim_pitch", device ) ); + m_tuning.Add( "flight_aim_yaw", new DeviceTuningParameter( "flight_aim_yaw", device ) ); - m_tuning.Add( "flight_view_pitch", new DeviceTuningParameter( "flight_view_pitch" ) ); - m_tuning.Add( "flight_view_yaw", new DeviceTuningParameter( "flight_view_yaw" ) ); + m_tuning.Add( "flight_view_pitch", new DeviceTuningParameter( "flight_view_pitch", device ) ); + m_tuning.Add( "flight_view_yaw", new DeviceTuningParameter( "flight_view_yaw", device ) ); - m_tuning.Add( "turret_aim_pitch", new DeviceTuningParameter( "turret_aim_pitch" ) ); - m_tuning.Add( "turret_aim_yaw", new DeviceTuningParameter( "turret_aim_yaw" ) ); + m_tuning.Add( "turret_aim_pitch", new DeviceTuningParameter( "turret_aim_pitch", device ) ); + m_tuning.Add( "turret_aim_yaw", new DeviceTuningParameter( "turret_aim_yaw", device ) ); // Gamepad specific - /* Cannot find out to what actions they relate to - left alone for now - m_tuning.Add( "fps_view_pitch", new DeviceTuningParameter( "fps_view_pitch" ) ); - m_tuning.Add( "fps_view_yaw", new DeviceTuningParameter( "fps_view_yaw" ) ); + if ( Gamepad.GamepadCls.IsDeviceClass( device.DevClass ) ) { + m_tuning.Add( "fps_view_pitch", new DeviceTuningParameter( "fps_view_pitch", device ) ); + m_tuning.Add( "fps_view_yaw", new DeviceTuningParameter( "fps_view_yaw", device ) ); - m_tuning.Add( "fps_move_lateral", new DeviceTuningParameter( "fps_move_lateral" ) ); - m_tuning.Add( "fps_move_longitudinal", new DeviceTuningParameter( "fps_move_longitudinal" ) ); + m_tuning.Add( "fps_move_lateral", new DeviceTuningParameter( "fps_move_lateral", device ) ); + m_tuning.Add( "fps_move_longitudinal", new DeviceTuningParameter( "fps_move_longitudinal", device ) ); - m_tuning.Add( "mgv_view_pitch", new DeviceTuningParameter( "mgv_view_pitch" ) ); - m_tuning.Add( "mgv_view_yaw", new DeviceTuningParameter( "mgv_view_yaw" ) ); - */ + m_tuning.Add( "mgv_view_pitch", new DeviceTuningParameter( "mgv_view_pitch", device ) ); + m_tuning.Add( "mgv_view_yaw", new DeviceTuningParameter( "mgv_view_yaw", device ) ); + } } @@ -84,6 +128,7 @@ namespace SCJMapper_V2.Options // provide access to Tuning items + /// /// Returns a tuning item for the asked option /// @@ -142,7 +187,7 @@ namespace SCJMapper_V2.Options /// /// the XML action fragment /// True if an action was decoded - public Boolean fromXML( string xml ) + public bool fromXML( string xml ) { /* * This can be a lot of the following options @@ -253,6 +298,24 @@ namespace SCJMapper_V2.Options } 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 ); @@ -265,7 +328,5 @@ namespace SCJMapper_V2.Options return true; } - - } } diff --git a/Options/Tuningoptions.cs b/Options/Tuningoptions.cs new file mode 100644 index 0000000..784f86c --- /dev/null +++ b/Options/Tuningoptions.cs @@ -0,0 +1,331 @@ +using SCJMapper_V2.Gamepad; +using SCJMapper_V2.Joystick; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml; + +namespace SCJMapper_V2.Options +{ + public class Tuningoptions : CloneableDictionary , ICloneable + { + + #region Static parts + + private static readonly log4net.ILog log = log4net.LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod( ).DeclaringType ); + + private static char ID_Delimiter = '⁞'; + + // Translate toID keys to the proper OptionTree.. (reassing stuff) + // index is the DevNumber (DX enum) - value is the JsN/XmlInstance from reassign + private static int[] m_jsMap = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; // Max joysticks + + private static string TuneOptionID( string deviceClass, int dxNumber ) + { + return string.Format( "{0}{1}{2}", deviceClass, ID_Delimiter, dxNumber.ToString( ) ); + } + + + /// + /// Create a tuningOptionID from devClass and xmlInstance (jsN for joysticks, 1 for gamepad) + /// + /// Joysstick or Gamepad class name + /// The xml instance number or 1 for gamepad + /// An ID or a dummy ID if the instance is not found + public static string TuneOptionIDfromJsN( string deviceClass, int instance ) + { + // only search for joysticks + if ( JoystickCls.IsDeviceClass( deviceClass ) ) { + for ( int i = 0; i < m_jsMap.Length; i++ ) { + if ( m_jsMap[i] == instance ) { + return string.Format( "{0}{1}{2}", deviceClass, ID_Delimiter, i.ToString( ) ); + } + } + // not found return + return string.Format( "{0}{1}{2}", deviceClass, ID_Delimiter, -1 ); // will not be found in the collection + + } else { + // gamepad + return string.Format( "{0}{1}{2}", deviceClass, ID_Delimiter, instance ); + } + } + + + // translate a ToID built from JsN into the internal collection key + private static string ToIDfromJsToID( string toIDjs ) + { + string deviceClass = ClassFromID(toIDjs); + // only search for joysticks + if ( JoystickCls.IsDeviceClass( deviceClass ) ) { + string[] e = toIDjs.Split (ID_Delimiter); + if ( e.Length > 1 ) { + int i = int.Parse( e[1] ); + return TuneOptionIDfromJsN( e[0], i ); + } else + return ""; + } else { + // gamepad + return toIDjs; + } + } + + + /// + /// Returns the instance part of an ID + /// + /// A tuningOptionID + /// The instance part + public static int InstanceFromID( string TO_ID ) + { + string[] e = TO_ID.Split (ID_Delimiter); + if ( e.Length > 1 ) + return int.Parse( e[1] ); + else + return 0; + } + + /// + /// Returns the xml instance (jsN) part of an ID + /// + /// A tuningOptionID + /// The xml instance part + public static int XmlInstanceFromID( string TO_ID ) + { + int inst = 0; + string[] e = TO_ID.Split (ID_Delimiter); + if ( e.Length > 1 ) { + inst = int.Parse( e[1] ); + if ( inst >= 0 ) + return m_jsMap[inst]; + else + return inst; + } + else { + return -1; + } + } + + /// + /// Returns the device class part of an ID + /// + /// A tuningOptionID + /// The device class part + public static string ClassFromID( string TO_ID ) + { + string[] e = TO_ID.Split (ID_Delimiter); + if ( e.Length > 0 ) + return e[0]; + else + return DeviceCls.DeviceClass; + } + + #endregion + + + /// + /// Clone this object + /// + /// A deep Clone of this object + public override object Clone( ) + { + var to = new Tuningoptions((CloneableDictionary)base.Clone()); + // more objects to deep copy + +#if DEBUG + // check cloned item + System.Diagnostics.Debug.Assert( CheckClone( to ) ); +#endif + return to; + } + + /// + /// Check clone against This + /// + /// + /// True if the clone is identical but not a shallow copy + private bool CheckClone( Tuningoptions clone ) + { + bool ret = true; + // object vars first + + // check THIS Dictionary + ret &= ( this.Count == clone.Count ); + if ( ret ) { + for ( int i = 0; i < this.Count; i++ ) { + ret &= ( this.ElementAt( i ).Key == clone.ElementAt( i ).Key ); + + ret &= ( !object.ReferenceEquals( this.ElementAt( i ).Value, clone.ElementAt( i ).Value ) ); // shall not be the same object !! + ret &= ( this.ElementAt( i ).Value.CheckClone( clone.ElementAt( i ).Value ) ); // sub check + } + } + return ret; + } + + + /// + /// cTor: Copy - Initializes the tuning options with the given one + /// + /// + private Tuningoptions( CloneableDictionary init) + { + foreach ( KeyValuePair kvp in init ) { + this.Add( kvp.Key, kvp.Value ); + } + } + + /// + /// ctor: Create tuning options for each device + /// access via ToID + /// + public Tuningoptions( ) + { + // init reassign map + m_jsMap = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; // Max joysticks + + // create all Options for all devices found (they may or may no be used) + foreach ( JoystickCls js in DeviceInst.JoystickListRef ) { + string toid = TuneOptionID(JoystickCls.DeviceClass, js.DevInstance ); // initial is the XInput enumeration + + if ( !this.ContainsKey( toid ) ) { + this.Add( toid, new OptionTree( js ) ); // init with disabled defaults + // update map + m_jsMap[js.DevInstance] = js.XmlInstance; + } else { + log.WarnFormat( "cTor - Joystick DO_ID {0} exists (likely a duplicate device name", toid ); + } + } + + // add gamepad if there is any + if ( DeviceInst.GamepadRef != null ) { + string toid = TuneOptionID(GamepadCls.DeviceClass, 1 );// const - + if ( !this.ContainsKey( toid ) ) { + this.Add( toid, new OptionTree( DeviceInst.GamepadRef ) ); // init with disabled defaults + } else { + log.WarnFormat( "cTor - Gamepad DO_ID {0} exists", toid ); + } + } + } + + + /// + /// Remaps the tuning options (jsN numbers) + /// + /// A reassign list + public void ReassignJsN( JsReassingList newJsList ) + { + // reassign the N part for Joystick commands + int[] jsMapNew = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // Max joysticks - all n.a. assigned + + // walk the complete list - it is along the DX enum - so copy should work + for ( int i = 0; i < newJsList.Count; i++ ) { + jsMapNew[i] = newJsList[i].newJs; + } + m_jsMap = ( int[] )jsMapNew.Clone( ); // make it live + } + + /// + /// Returns a DevTuning item from the sought parameter + /// as the device is not given it looks for the first one that implements it + /// Note: this prefers devices that are listed early (usually a gamepad is before the joysticks) + /// + /// The tuning parameter + /// The sought item or null if not found + public DeviceTuningParameter FirstTuningItem( string option ) + { + foreach ( KeyValuePair kv in this ) { + DeviceTuningParameter item = kv.Value.TuningItem(option); + if ( ( item != null ) && !string.IsNullOrEmpty( item.NodeText ) ) + return item; + } + // not found in any device + return null; + } + + /// + /// Returns a DevTuning item from the sought parameters + /// + /// A Tuningoption ID (device) + /// The tuning parameter + /// The sought item or null if not found + public DeviceTuningParameter TuningItem( string toID, string option ) + { + if ( this.ContainsKey( toID ) ) { + return this[toID].TuningItem( option ); + } + return null; + } + + /// + /// Returns the OptionTree for a ToID or null - if not found + /// + /// A ToID + /// The OptionTree or null if not found + public OptionTree OptionTreeFromToID( string toID ) + { + if ( this.ContainsKey( toID ) ) { + return this[toID]; + } + return null; + } + + + /// + /// Read an Options from XML - do some sanity check + /// + /// the XML action fragment + /// True if an action was decoded + public bool fromXML( string xml ) + { + /* + * This can be a lot of the following options + * try to do our best.... + * + * + * .. + + + * + + .. + + + */ + 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 - instance {0} is not available - dropped this content", nInstance ); + } + } else if ( type.ToLowerInvariant( ) == "xboxpad" ) { + string toID = TuneOptionID(GamepadCls.DeviceClass, nInstance ); + this[toID].fromXML( xml ); + } + + } + return true; + } + + } +} diff --git a/README.md b/README.md index cc2e136..e010b72 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ NET40\OpenTK.GLControl.dll
NET20\Ionic.Zip.Reduced.dll
net40-full\log4net.dll

+Built with VisualStudio 2017 Community free version

DDS Skydome Images:

diff --git a/SC/ActivationModes.cs b/SC/ActivationModes.cs index e702938..56c2775 100644 --- a/SC/ActivationModes.cs +++ b/SC/ActivationModes.cs @@ -8,10 +8,13 @@ namespace SCJMapper_V2.SC /// /// Defines a single activation mode /// - public class ActivationMode + public class ActivationMode : ICloneable { + private const string c_DefaultActModeName = "Use Profile"; + #region Static parts + /// /// The default ActivationMode /// @@ -22,11 +25,12 @@ namespace SCJMapper_V2.SC /// /// Name to test /// True if the name matches the default name - static public Boolean IsDefault( string activationName ) + static public bool IsDefault( string activationName ) { return ( activationName == Default.Name ); } + #endregion /// /// The name of the ActivationMode @@ -38,6 +42,19 @@ namespace SCJMapper_V2.SC public int MultiTap { get; set; } + /// + /// Clone this object + /// + /// A deep Clone of this object + public object Clone( ) + { + var am = (ActivationMode)this.MemberwiseClone(); + // more objects to deep copy + + return am; + } + + /// /// cTor: empty constructor /// @@ -94,7 +111,7 @@ namespace SCJMapper_V2.SC /// /// Returns true if multiTap is more than 1 /// - public Boolean IsDoubleTap { get { return ( MultiTap > 1 ); } } + public bool IsDoubleTap { get { return ( MultiTap > 1 ); } } diff --git a/SC/DProfileReader.cs b/SC/DProfileReader.cs index e8f5bc2..2de3e34 100644 --- a/SC/DProfileReader.cs +++ b/SC/DProfileReader.cs @@ -70,7 +70,7 @@ namespace SCJMapper_V2.SC public new void Add( ProfileAction pact ) { // only get the latest .. - if ( this.Contains( pact ) ) + if ( this.Contains( pact ) ) this.RemoveAt( IndexOf( pact ) ); base.Add( pact ); @@ -78,7 +78,7 @@ namespace SCJMapper_V2.SC }; Dictionary m_aMap = null; // key would be the actionmap name ActionMap m_currentMap = null; - + // ****************** CLASS ********************** @@ -86,7 +86,7 @@ namespace SCJMapper_V2.SC /// /// cTor /// - public DProfileReader( ) + public DProfileReader() { ValidContent = false; // default } @@ -98,15 +98,14 @@ namespace SCJMapper_V2.SC /// public String CSVMap { - get - { + get { log.Debug( "DProfileReader.CSVMap - Entry" ); String buf = ""; foreach ( ActionMap am in m_aMap.Values ) { 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" ); } @@ -132,15 +131,14 @@ namespace SCJMapper_V2.SC if ( attr.ContainsKey( "ActivationMode" ) ) { actModeName = attr["ActivationMode"]; multiTap = ActivationModes.Instance.MultiTapFor( actModeName ).ToString( ); // given by the already collected items - } - else { + } 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 + 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" ) ) { @@ -152,8 +150,7 @@ namespace SCJMapper_V2.SC if ( ac.defBinding == " " ) { ac.defBinding = Joystick.JoystickCls.BlendedInput; m_currentMap.Add( ac ); // finally add it to the current map if it was bound - } - else if ( !String.IsNullOrEmpty( ac.defBinding ) ) { + } 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 } @@ -168,8 +165,7 @@ namespace SCJMapper_V2.SC if ( ac.defBinding == " " ) { ac.defBinding = Keyboard.KeyboardCls.BlendedInput; m_currentMap.Add( ac ); // finally add it to the current map if it was bound - } - else if ( !String.IsNullOrEmpty( ac.defBinding ) ) { + } 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 } @@ -184,8 +180,7 @@ namespace SCJMapper_V2.SC if ( ac.defBinding == " " ) { ac.defBinding = Mouse.MouseCls.BlendedInput; m_currentMap.Add( ac ); // finally add it to the current map if it was bound - } - else if ( !String.IsNullOrEmpty( ac.defBinding ) ) { + } 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 } @@ -200,8 +195,7 @@ namespace SCJMapper_V2.SC if ( ac.defBinding == " " ) { ac.defBinding = Gamepad.GamepadCls.BlendedInput; m_currentMap.Add( ac ); // finally add it to the current map if it was bound - } - else if ( !String.IsNullOrEmpty( ac.defBinding ) ) { + } 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 } @@ -314,12 +308,10 @@ namespace SCJMapper_V2.SC // 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 ) { + } else if ( xr.IsEmptyElement ) { // an attribute only element CollectActions( attr ); - } - else { + } 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 ); @@ -355,19 +347,20 @@ namespace SCJMapper_V2.SC 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; - } ); + 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; - m_aMap.Add( mapName, m_currentMap ); // add to our inventory + 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 + }else { + log.DebugFormat( "ReadElement: IGNORED duplicate map with name: {0}", mapName ); + } m_state = EState.inActionMap; // now we are in and processing the map } } - } - else if ( m_state == EState.inActionMap ) { + } else if ( m_state == EState.inActionMap ) { // processing a valid action map - collect actions if ( eName.ToLower( ) == "action" ) { // this is an action.. - collect it @@ -406,12 +399,10 @@ namespace SCJMapper_V2.SC if ( xr.IsEmptyElement ) { retVal = retVal && ReadEmptyElement( xr ); m_nodeNameStack.Pop( ); // empty ones end inline - } - else { + } else { retVal = retVal && ReadElement( xr ); } - } - else if ( xr.NodeType == XmlNodeType.EndElement ) { + } else if ( xr.NodeType == XmlNodeType.EndElement ) { //Console.Write( "\n", xr.Name ); String exitElement = m_nodeNameStack.Pop( ); if ( m_state == EState.inActionMap ) @@ -425,8 +416,7 @@ namespace SCJMapper_V2.SC else return false; - } - catch ( Exception ex ) { + } catch ( Exception ex ) { // get any exceptions from reading log.Error( "DProfileReader.ReadXML - unexpected", ex ); return false; @@ -434,7 +424,7 @@ namespace SCJMapper_V2.SC } - private Boolean ReadActivationModes ( XmlReader xr ) + private Boolean ReadActivationModes( XmlReader xr ) { log.Debug( "DProfileReader.ReadActivationModes - Entry" ); @@ -448,12 +438,11 @@ namespace SCJMapper_V2.SC } String name = xr["name"]; String mTap = xr["multiTap"]; - if ( ! string.IsNullOrEmpty(name)) ActivationModes.Instance.Add( new ActivationMode( name, int.Parse(mTap) ) ); + if ( !string.IsNullOrEmpty( name ) ) ActivationModes.Instance.Add( new ActivationMode( name, int.Parse( mTap ) ) ); } while ( xr.Read( ) ); return true; - } - catch ( Exception ex ) { + } catch ( Exception ex ) { // get any exceptions from reading log.Error( "DProfileReader.ReadXML - unexpected", ex ); return false; @@ -501,9 +490,9 @@ namespace SCJMapper_V2.SC /// /// A default profile XML string /// A filled SCActionMapList object - public SCActionMapList ActionMapList(string xml ) + public SCActionMapList ActionMapList( string xml ) { - SCActionMapList aml = new SCActionMapList(); + SCActionMapList aml = new SCActionMapList( ); log.Debug( "DProfileReader.ActionMapList - Entry" ); diff --git a/SC/SCDefaultProfile.cs b/SC/SCDefaultProfile.cs index 1c88b03..fb39278 100644 --- a/SC/SCDefaultProfile.cs +++ b/SC/SCDefaultProfile.cs @@ -46,8 +46,8 @@ namespace SCJMapper_V2.SC String retVal = ""; // first choice a defaultProfile.xml in the app dir distributed with the application ??? to be deleted ??? - if ( File.Exists( SCPath.DefaultProfileName ) ) { - using ( StreamReader sr = new StreamReader( SCPath.DefaultProfileName ) ) { + if ( File.Exists( defaultProfileName ) ) { // 20170404 - use the given name, not the one from SCPATH... + using ( StreamReader sr = new StreamReader( defaultProfileName ) ) { retVal = sr.ReadToEnd( ); UsedDefProfile = "AppDirectory defaultProfile"; log.InfoFormat( "- Use {0}", UsedDefProfile ); diff --git a/SCJMapper-V2.csproj b/SCJMapper-V2.csproj index df92a78..e4fa632 100644 --- a/SCJMapper-V2.csproj +++ b/SCJMapper-V2.csproj @@ -126,7 +126,9 @@ + + Form @@ -134,6 +136,7 @@ FormOptions.cs + diff --git a/SCJMapper-V2.sln b/SCJMapper-V2.sln index 8df0fde..f1a544e 100644 --- a/SCJMapper-V2.sln +++ b/SCJMapper-V2.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.25123.0 +VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SCJMapper-V2", "SCJMapper-V2.csproj", "{B5F8B339-E02E-4F6D-BF62-D776F165910F}" EndProject diff --git a/actions/ActionCls.cs b/actions/ActionCls.cs index 1e63593..738f7f3 100644 --- a/actions/ActionCls.cs +++ b/actions/ActionCls.cs @@ -9,6 +9,7 @@ using SCJMapper_V2.Keyboard; using SCJMapper_V2.Mouse; using SCJMapper_V2.Gamepad; using SCJMapper_V2.Joystick; +using System.Linq; namespace SCJMapper_V2 { @@ -61,7 +62,7 @@ namespace SCJMapper_V2 /// /// Device Class string /// Device Enum - static public ActionDevice ADevice( String deviceClass ) + static public ActionDevice ADevice( string deviceClass ) { switch ( deviceClass.ToLower( ) ) { case KeyboardCls.DeviceClass: return ActionDevice.AD_Keyboard; @@ -80,7 +81,7 @@ namespace SCJMapper_V2 /// /// The device name from the defaultProfile /// The single UCase device Tag letter - static public String DevTag( String device ) + static public string DevTag( string device ) { switch ( device.ToLower( ) ) { case KeyboardCls.DeviceClass: return "K"; @@ -97,7 +98,7 @@ namespace SCJMapper_V2 /// /// The single UCase device Tag letter /// The device name from the defaultProfile - static public String DeviceClassFromTag( String devTag ) + static public string DeviceClassFromTag( string devTag ) { switch ( devTag ) { case "K": return KeyboardCls.DeviceClass; @@ -115,9 +116,9 @@ namespace SCJMapper_V2 /// /// The input command string dev_input format /// A proper DeviceClass string - static public String DeviceClassFromInput( String devInput ) + static public string DeviceClassFromInput( string devInput ) { - String deviceClass = DeviceCls.DeviceClass; + string deviceClass = DeviceCls.DeviceClass; deviceClass = JoystickCls.DeviceClassFromInput( devInput ); if ( !DeviceCls.IsUndefined( deviceClass ) ) return deviceClass; @@ -158,7 +159,7 @@ namespace SCJMapper_V2 /// /// The input command /// True if blended input - static public Boolean IsBlendedInput( String input ) + static public Boolean IsBlendedInput( string input ) { Boolean blendedInput = false; @@ -183,7 +184,7 @@ namespace SCJMapper_V2 /// 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 ) + static public string BlendInput( string input, ActionDevice aDevice ) { if ( DeviceCls.IsBlendedInput( input ) ) { // was generic blind @@ -206,7 +207,7 @@ namespace SCJMapper_V2 /// An input /// The ActionDevice /// A valid devInput (dev_input) format - static public String DevInput( string input, ActionDevice aDevice ) + static public string DevInput( string input, ActionDevice aDevice ) { switch ( aDevice ) { case ActionDevice.AD_Gamepad: return GamepadCls.DevInput( input ); @@ -245,26 +246,28 @@ namespace SCJMapper_V2 // **************** 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 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 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 + + /// - /// ctor + /// Clone this object /// - public ActionCls( ) + /// A deep Clone of this object + private ActionCls MyClone( ) { - key = ""; - actionDevice = ActionDevice.AD_Unknown; - device = JoystickCls.DeviceClass; - name = ""; - defBinding = ""; - defActivationMode = ActivationMode.Default; - inputList = new List( ); // empty list + 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( ); + + return newAc; } @@ -275,24 +278,33 @@ namespace SCJMapper_V2 /// The action copy with reassigned input public ActionCls ReassignJsN( JsReassingList newJsList ) { - ActionCls newAc = new ActionCls( ); - // full copy from 'this' - newAc.key = this.key; - newAc.actionDevice = this.actionDevice; - newAc.device = this.device; - newAc.name = this.name; - newAc.defBinding = this.defBinding; - newAc.defActivationMode = this.defActivationMode; + 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 ) ); + newAc.inputList.Add( acc.ReassignJsN( newJsList ) ); // creates the deep copy of the list } return newAc; } + /// + /// ctor + /// + public ActionCls( ) + { + key = ""; + actionDevice = ActionDevice.AD_Unknown; + device = JoystickCls.DeviceClass; + name = ""; + defBinding = ""; + defActivationMode = ActivationMode.Default; + inputList = new List( ); // empty list + } + + /// /// Creates and adds the inputCommand list with given input string /// AC2 style input is used i.e. with device tag in front @@ -300,7 +312,7 @@ namespace SCJMapper_V2 /// /// /// Returns the ActionCommand created - public ActionCommandCls AddCommand( String devInput, ActivationMode activationMode ) + public ActionCommandCls AddCommand( string devInput, ActivationMode activationMode ) { ActionCommandCls acc = new ActionCommandCls( devInput, inputList.Count - 1 ); // starts from -1 ... acc.ActivationMode = new ActivationMode( activationMode ); @@ -315,7 +327,7 @@ namespace SCJMapper_V2 /// /// /// - public ActionCommandCls AddCommand( String devInput, int index ) + public ActionCommandCls AddCommand( string devInput, int index ) { ActionCommandCls acc = new ActionCommandCls( devInput, index ); acc.ActivationMode = new ActivationMode( ActivationMode.Default ); @@ -353,7 +365,7 @@ namespace SCJMapper_V2 /// Updates an actionCommand with a new input (command) /// /// The input command - public void UpdateCommandFromInput( String devInput, int accIndex ) // ActionCommandCls actionCmd ) + public void UpdateCommandFromInput( string devInput, int accIndex ) // ActionCommandCls actionCmd ) { //log.Debug( "UpdateCommandFromInput - Entry" ); if ( accIndex < 0 ) return; @@ -369,7 +381,7 @@ namespace SCJMapper_V2 /// /// The input /// An actionCommand or null if not found - public ActionCommandCls FindActionInputObject( String devInput ) + public ActionCommandCls FindActionInputObject( string devInput ) { log.Debug( "FindActionInputObject - Entry" ); // Apply the input to the ActionTree @@ -406,21 +418,21 @@ namespace SCJMapper_V2 /// Dump the action as partial XML nicely formatted /// /// the action as XML fragment - public String toXML( ) + public string toXML( ) { - String r = ""; String + string r = ""; string bindCmd = "rebind"; if ( inputList.Count > 0 ) { - if ( !String.IsNullOrEmpty( inputList[0].Input ) ) { - r = String.Format( "\t\n", name ); + 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 + 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 } } - r += String.Format( "\t\t\n" ); + r += string.Format( "\t\t\n" ); } } @@ -432,7 +444,7 @@ namespace SCJMapper_V2 /// /// the XML action fragment /// True if an action was decoded - public Boolean fromXML( String xml ) + public Boolean fromXML( string xml ) { XmlReaderSettings settings = new XmlReaderSettings( ); settings.ConformanceLevel = ConformanceLevel.Fragment; @@ -456,10 +468,10 @@ namespace SCJMapper_V2 if ( reader.Name.ToLowerInvariant( ) == "rebind" ) { if ( reader.HasAttributes ) { device = reader["device"]; - String input = reader["input"]; - if ( String.IsNullOrEmpty( input ) ) return false; // ERROR exit + 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 ) ) { + if ( string.IsNullOrEmpty( device ) ) { // AC2 style - derive the device (Device.DeviceClass) device = DeviceClassFromInput( input ); } @@ -497,10 +509,10 @@ namespace SCJMapper_V2 else if ( reader.Name.ToLowerInvariant( ) == "addbind" ) { if ( reader.HasAttributes ) { device = reader["device"]; - String input = reader["input"]; - if ( String.IsNullOrEmpty( input ) ) return false; // ERROR exit + 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 ) ) { + if ( string.IsNullOrEmpty( device ) ) { // AC2 style - derive the device (Device.DeviceClass) device = DeviceClassFromInput( input ); } @@ -538,6 +550,5 @@ namespace SCJMapper_V2 return true; } - } } diff --git a/actions/ActionCommandCls.cs b/actions/ActionCommandCls.cs index f4f6476..ff7e4ea 100644 --- a/actions/ActionCommandCls.cs +++ b/actions/ActionCommandCls.cs @@ -15,17 +15,17 @@ namespace SCJMapper_V2 /// devID: jsN, mo1, xi1, kb1, thumbl_down and modified ones: ralt+button1 (modifier+deviceinput) /// input: x, mouse1, r, and ~ as internal blend (defined in DeviceCls) /// - public class ActionCommandCls + public class ActionCommandCls : ICloneable { /// /// The Input commands used incl. modifiers (mod+command) /// - public String Input { get; set; } // AC2 style: input command name AC2 e.g. x, mouse1, r, "~" to blend + public string Input { get; set; } // AC2 style: input command name AC2 e.g. x, mouse1, r, "~" to blend /// /// The device ID of the device (jsN, mo1, kb1, xi1) /// - public String DevID { get; set; } // the device ID (jsN, mo1, xi1, kb1) + public string DevID { get; set; } // the device ID (jsN, mo1, xi1, kb1) /// /// The applied ActivationMode for this command @@ -35,14 +35,14 @@ namespace SCJMapper_V2 /// /// Returns true if default ActivationMode is set /// - public Boolean DefaultActivationMode { get { return ActivationMode == ActivationMode.Default; } } + public bool DefaultActivationMode { get { return ActivationMode == ActivationMode.Default; } } /// /// The complete input string (devID_input) /// Assuming internally blended ones only (i.e. no space blends contained) /// Can derive if a device tag is given /// - public String DevInput + public string DevInput { get { @@ -51,7 +51,7 @@ namespace SCJMapper_V2 else if ( string.IsNullOrEmpty( DevID ) ) return Input; // no devID - return input only else - return String.Format( "{0}_{1}", DevID, Input ); // fully qualified only if both exist + return string.Format( "{0}_{1}", DevID, Input ); // fully qualified only if both exist } set { @@ -81,6 +81,41 @@ namespace SCJMapper_V2 public int NodeIndex { get; set; } // index of the vis treenode + /// + /// Clone this object + /// + /// A deep Clone of this object + public object Clone( ) + { + ActionCommandCls ac = (ActionCommandCls)this.MemberwiseClone(); + // more objects to deep copy + ac.ActivationMode = ( ActivationMode )this.ActivationMode.Clone( ); + + return ac; + } + + /// + /// Copy return the action while reassigning the JsN Tag + /// + /// The JsN reassign list + /// The action copy with reassigned input + public ActionCommandCls ReassignJsN( JsReassingList newJsList ) + { + ActionCommandCls newAc = (ActionCommandCls)this.Clone(); + + // reassign the jsX part for Joystick commands + if ( this.DevID.StartsWith( "js" ) ) { + int oldJsN = JoystickCls.JSNum( this.DevID ); + if ( JoystickCls.IsJSValid( oldJsN ) ) { + if ( newJsList.ContainsOldJs( oldJsN ) ) newAc.DevID = JoystickCls.ReassignJSTag( this.DevID, newJsList.newJsFromOldJs( oldJsN ) ); + } + } + + return newAc; + } + + + // ctor public ActionCommandCls( ) { @@ -92,16 +127,7 @@ namespace SCJMapper_V2 } // ctor - public ActionCommandCls( ActionCommandCls other ) - { - Input = other.Input; - DevID = other.DevID; - ActivationMode = new ActivationMode( other.ActivationMode ); - NodeIndex = other.NodeIndex; - } - - // ctor - public ActionCommandCls( String devInp ) + public ActionCommandCls( string devInp ) { DevInput = devInp; ActivationMode = new ActivationMode( ActivationMode.Default ); @@ -109,7 +135,7 @@ namespace SCJMapper_V2 } // ctor - public ActionCommandCls( String devInp, int nodeIx ) + public ActionCommandCls( string devInp, int nodeIx ) { DevInput = devInp; ActivationMode = new ActivationMode( ActivationMode.Default ); @@ -117,7 +143,7 @@ namespace SCJMapper_V2 } // ctor - public ActionCommandCls( String dev, String inp ) + public ActionCommandCls( string dev, string inp ) { Input = inp; DevID = dev; @@ -126,7 +152,7 @@ namespace SCJMapper_V2 } // ctor - public ActionCommandCls( String dev, String inp, int nodeIx ) + public ActionCommandCls( string dev, string inp, int nodeIx ) { Input = inp; DevID = dev; @@ -135,33 +161,11 @@ namespace SCJMapper_V2 } - /// - /// Copy return the action while reassigning the JsN Tag - /// - /// The JsN reassign list - /// The action copy with reassigned input - public ActionCommandCls ReassignJsN( JsReassingList newJsList ) - { - // full copy from 'this' - ActionCommandCls newAc = new ActionCommandCls( this ); - - // reassign the jsX part for Joystick commands - if ( this.DevID.StartsWith( "js" ) ) { - int oldJsN = JoystickCls.JSNum( this.DevID ); - if ( JoystickCls.IsJSValid( oldJsN ) ) { - if ( newJsList.ContainsOldJs( oldJsN ) ) newAc.DevID = JoystickCls.ReassignJSTag( this.DevID, newJsList.newJsFromOldJs( oldJsN ) ); - } - } - - return newAc; - } - - /// /// 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, ActionCls.ActionDevice actionDevice) // ActionCommandCls actionCmd ) { // Apply the input to the ActionTree this.DevInput = ActionCls.BlendInput( devInput, actionDevice ); @@ -177,7 +181,7 @@ namespace SCJMapper_V2 /// /// /// - private String MutitapFudge( ActivationMode actMode ) + private string MutitapFudge( ActivationMode actMode ) { if ( actMode.IsDoubleTap ) { return "multiTap = \"2\""; @@ -191,17 +195,17 @@ namespace SCJMapper_V2 /// Dump the action as partial XML nicely formatted /// /// the action as XML fragment - public String toXML( ) + public string toXML( ) { - String r = ""; - if ( !String.IsNullOrEmpty( Input ) ) { + string r = ""; + if ( !string.IsNullOrEmpty( Input ) ) { // regular - apply XML formatting to internally blended items - r += String.Format( "input=\"{0}_{1}\" {2} ", DevID, DeviceCls.toXML( Input ), DeviceCls.toXMLBlendExtension(Input) ); // add multitap override if needed + r += string.Format( "input=\"{0}_{1}\" {2} ", DevID, DeviceCls.toXML( Input ), DeviceCls.toXMLBlendExtension(Input) ); // add multitap override if needed if ( ! ActivationMode.Equals( ActivationMode.Default ) ) { - r += String.Format( "ActivationMode=\"{0}\" {1} ", ActivationMode.Name, MutitapFudge(ActivationMode) ); + r += string.Format( "ActivationMode=\"{0}\" {1} ", ActivationMode.Name, MutitapFudge(ActivationMode) ); } } - r += String.Format( " />\n" ); + r += string.Format( " />\n" ); return r; } diff --git a/actions/ActionMapCls.cs b/actions/ActionMapCls.cs index 033f30f..f152b2f 100644 --- a/actions/ActionMapCls.cs +++ b/actions/ActionMapCls.cs @@ -5,6 +5,7 @@ using System.Xml; using System.IO; using SCJMapper_V2.Joystick; +using System.Linq; namespace SCJMapper_V2 { @@ -24,7 +25,7 @@ namespace SCJMapper_V2 { 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 @@ -33,18 +34,24 @@ namespace SCJMapper_V2 /// The ActionMap copy with reassigned input public ActionMapCls ReassignJsN( JsReassingList newJsList ) { - ActionMapCls newMap = new ActionMapCls( ); - // full copy from 'this' - newMap.name = this.name; + var newMap = new ActionMapCls(this); foreach ( ActionCls ac in this ) { - newMap.Add( ac.ReassignJsN( newJsList ) ); + newMap.Add( ac.ReassignJsN( newJsList ) ); // creates the deep copy of the tree } return newMap; } + private ActionMapCls( ActionMapCls other ) + { + this.name = other.name; + // no deep copy of refs + } + + public ActionMapCls( ) { } + /// /// Merge the given Map with this Map /// new ones are ignored - we don't learn from XML input for the time beeing @@ -59,8 +66,7 @@ namespace SCJMapper_V2 } ); if ( AC == null ) { ; // this.Add( newAc ); // no, add it - } - else { + } else { AC.Merge( newAc ); // yes, merge it } } @@ -71,17 +77,17 @@ namespace SCJMapper_V2 /// Dump the actionmap as partial XML nicely formatted /// /// the action as XML fragment - public String toXML( ) + public string toXML( ) { - String acs = ""; + string acs = ""; foreach ( ActionCls ac in this ) { - String x = ac.toXML( ); - if ( !String.IsNullOrEmpty( x ) ) acs += String.Format( "\t{0}", x ); + 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 ); + if ( !string.IsNullOrWhiteSpace( acs ) ) { + string r = string.Format( "\t\n", name ); r += acs; - r += String.Format( "\t\n" ); + r += string.Format( "\t\n" ); return r; } // nothing to dump @@ -94,7 +100,7 @@ namespace SCJMapper_V2 /// /// the XML action fragment /// True if an action was decoded - public Boolean fromXML( String xml ) + public Boolean fromXML( string xml ) { XmlReaderSettings settings = new XmlReaderSettings( ); settings.ConformanceLevel = ConformanceLevel.Fragment; @@ -107,16 +113,15 @@ namespace SCJMapper_V2 if ( reader.Name == "actionmap" ) { if ( reader.HasAttributes ) { name = reader["name"]; - } - else { + } else { return false; } } reader.Read( ); // move to next element - String x = reader.ReadOuterXml( ); - while ( !String.IsNullOrEmpty( x ) ) { + string x = reader.ReadOuterXml( ); + while ( !string.IsNullOrEmpty( x ) ) { ActionCls ac = new ActionCls( ); if ( ac.fromXML( x ) ) { this.Add( ac ); // add to list diff --git a/actions/ActionMapsCls.cs b/actions/ActionMapsCls.cs index 8807bf9..aac32a9 100644 --- a/actions/ActionMapsCls.cs +++ b/actions/ActionMapsCls.cs @@ -18,6 +18,7 @@ using SCJMapper_V2.Mouse; using SCJMapper_V2.Gamepad; using SCJMapper_V2.Joystick; using SCJMapper_V2.Options; +using System.Linq; namespace SCJMapper_V2 { @@ -40,7 +41,7 @@ namespace SCJMapper_V2 #region Static Part of ActionMaps // actionmap names to gather (do we need them to be cofigurable ??) - public static String[] ActionMaps = { }; + public static string[] ActionMaps = { }; public static void LoadSupportedActionMaps( SCActionMapList aml ) { @@ -50,26 +51,23 @@ namespace SCJMapper_V2 #endregion Static Part of ActionMaps - private const String ACM_VERSION = "version=\"1\" optionsVersion=\"2\" rebindVersion=\"2\""; //AC2 the FIXED version + private const string ACM_VERSION = "version=\"1\" optionsVersion=\"2\" rebindVersion=\"2\""; //AC2 the FIXED version - private String version { get; set; } + private string version { get; set; } - private JoystickList m_joystickList = null; private UICustHeader m_uiCustHeader = null; - private OptionTree m_optionTree = null; // options are given per deviceClass and instance - it seems - private Deviceoptions m_deviceOptions = null; - private Modifiers m_modifiers = null; - private List m_invertCB = null; // Options owns and handles all Inversions + private Tuningoptions m_tuningOptions = null; + private Deviceoptions m_deviceOptions = null; // own additions for JS mapping - should not harm.. - private String[] m_js; - private String[] m_GUIDs; + private string[] m_js; + private string[] m_GUIDs; /// /// get/set jsN assignment (use 0-based index i.e. js1 -> [0]) /// - public String[] jsN + public string[] jsN { get { return m_js; } } @@ -77,7 +75,7 @@ namespace SCJMapper_V2 /// /// get/set jsN GUID assignment (use 0-based index i.e. js1GUID -> [0]) /// - public String[] jsNGUID + public string[] jsNGUID { get { return m_GUIDs; } } @@ -96,7 +94,8 @@ namespace SCJMapper_V2 /// /// Returns the device tuning items - the OptionTree /// - public OptionTree OptionTree { get { return m_optionTree; } } + public Tuningoptions TuningOptions { get { return m_tuningOptions; } } + // public OptionTree OptionTree { get { return m_optionTree; } } /// @@ -109,20 +108,41 @@ namespace SCJMapper_V2 /// - /// Returns the assigned Modifiers + /// Copy return all ActionMaps while reassigning the JsN Tag /// - public Modifiers Modifiers + /// The JsN reassign list + /// The ActionMaps copy with reassigned input + public ActionMapsCls ReassignJsN( JsReassingList newJsList ) + { + var newMaps = new ActionMapsCls(this); + newMaps.m_uiCustHeader = ( UICustHeader )this.m_uiCustHeader.Clone( ); + newMaps.m_tuningOptions = ( Tuningoptions )this.m_tuningOptions.Clone( ); + newMaps.m_deviceOptions = ( Deviceoptions )this.m_deviceOptions.Clone( ); + + foreach ( ActionMapCls am in this ) { + newMaps.Add( am.ReassignJsN( newJsList ) ); // creates the deep copy of the tree + } + // remap the tuning options + newMaps.m_tuningOptions.ReassignJsN( newJsList ); + + return newMaps; + } + + + private ActionMapsCls( ActionMapsCls other ) { - get { return m_modifiers; } + this.version = other.version; + this.m_js = other.m_js; + this.m_GUIDs = other.m_GUIDs; + // other ref objects are not populated here } /// /// ctor /// - public ActionMapsCls( JoystickList jsList ) + public ActionMapsCls( ) { version = ACM_VERSION; - m_joystickList = jsList; // have to save this for Reassign // create the Joystick assignments Array.Resize( ref m_js, JoystickCls.JSnum_MAX + 1 ); @@ -131,47 +151,20 @@ namespace SCJMapper_V2 m_js[i] = ""; m_GUIDs[i] = ""; } + // create the default mapped optiontree CreateNewOptions( ); //LoadSupportedActionMaps( ); // get them from config @@@@@@@@@ } + private void CreateNewOptions( ) { // create options objs m_uiCustHeader = new UICustHeader( ); - m_optionTree = new OptionTree( ); - m_deviceOptions = new Deviceoptions( m_joystickList ); - m_modifiers = new Modifiers( ); - } - - /// - /// Copy return all ActionMaps while reassigning the JsN Tag - /// - /// The JsN reassign list - /// The ActionMaps copy with reassigned input - public ActionMapsCls ReassignJsN( JsReassingList newJsList ) - { - ActionMapsCls newMaps = new ActionMapsCls( m_joystickList ); - // full copy from 'this' - - newMaps.m_uiCustHeader = this.m_uiCustHeader; - newMaps.m_deviceOptions = this.m_deviceOptions; - newMaps.m_optionTree = this.m_optionTree; - newMaps.m_modifiers = this.m_modifiers; - - for ( int i = 0; i < JoystickCls.JSnum_MAX; i++ ) { - newMaps.jsN[i] = this.jsN[i]; newMaps.jsNGUID[i] = this.jsNGUID[i]; - } - - foreach ( ActionMapCls am in this ) { - newMaps.Add( am.ReassignJsN( newJsList ) ); - } - - //m_options.ReassignJsN( newJsList ); - - return newMaps; + m_tuningOptions = new Tuningoptions( ); + m_deviceOptions = new Deviceoptions( ); } /// @@ -268,7 +261,7 @@ namespace SCJMapper_V2 /// Dump the ActionMaps as partial XML nicely formatted /// /// the action as XML fragment - public String toXML( String fileName ) + public string toXML( string fileName ) { log.Debug( "ActionMapsCls.toXML - Entry" ); @@ -278,17 +271,17 @@ namespace SCJMapper_V2 // handle the versioning of the actionmaps // AC2 do not longer support ignoreversion... enter the new fixed header - String r = "\n" ); + r += string.Format( ">\n" ); // *** CustomisationUIHeader @@ -305,28 +298,27 @@ namespace SCJMapper_V2 // all Joysticks for ( int i = 0; i < JoystickCls.JSnum_MAX; i++ ) { - if ( !String.IsNullOrEmpty( jsN[i] ) ) { + if ( !string.IsNullOrEmpty( jsN[i] ) ) { dr.devType = JoystickCls.DeviceClass; dr.instNo = i + 1; m_uiCustHeader.AddInstances( dr ); } } m_uiCustHeader.Label = fileName.Replace( SCMappings.c_MapStartsWith, "" ); // remove redundant part - r += m_uiCustHeader.toXML( ) + String.Format( "\n" ); + r += m_uiCustHeader.toXML( ) + string.Format( "\n" ); // *** OPTIONS - if ( m_optionTree.Count > 0 ) r += m_optionTree.toXML( ) + String.Format( "\n" ); + foreach ( KeyValuePair kv in m_tuningOptions ) { + if ( kv.Value.Count > 0 ) r += kv.Value.toXML( ) + string.Format( "\n" ); + } // *** DEVICE OPTIONS - if ( m_deviceOptions.Count > 0 ) r += m_deviceOptions.toXML( ) + String.Format( "\n" ); - - // *** MODIFIERS - if ( m_modifiers.Count > 0 ) r += m_modifiers.toXML( ) + String.Format( "\n" ); + if ( m_deviceOptions.Count > 0 ) r += m_deviceOptions.toXML( ) + string.Format( "\n" ); // *** ACTION MAPS foreach ( ActionMapCls amc in this ) { - r += String.Format( "{0}\n", amc.toXML( ) ); + r += string.Format( "{0}\n", amc.toXML( ) ); } - r += String.Format( "\n" ); + r += string.Format( "\n" ); return r; } @@ -336,21 +328,18 @@ namespace SCJMapper_V2 /// /// the XML action fragment /// True if an action was decoded - public Boolean fromXML( String xml ) + public bool fromXML( string xml ) { log.Debug( "ActionMapsCls.fromXML - Entry" ); - CreateNewOptions( ); // Reset those 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( ); - + // read the header element if ( reader.Name == "ActionMaps" ) { if ( reader.HasAttributes ) { version = reader["version"]; @@ -358,38 +347,42 @@ namespace SCJMapper_V2 // 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 )]; + jsN[i] = reader[string.Format( "js{0}", i + 1 )]; + jsNGUID[i] = reader[string.Format( "js{0}G", i + 1 )]; } } 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 read the CIG content of the map reader.Read( ); // move to next element // could be actionmap OR (AC 0.9) deviceoptions OR options - while ( !reader.EOF ) { //!String.IsNullOrEmpty( x ) ) { + while ( !reader.EOF ) { //!string.IsNullOrEmpty( x ) ) { if ( reader.Name.ToLowerInvariant( ) == "actionmap" ) { - String x = reader.ReadOuterXml( ); + string x = reader.ReadOuterXml( ); ActionMapCls acm = new ActionMapCls( ); if ( acm.fromXML( x ) ) { this.Merge( acm ); // merge list } } else if ( reader.Name.ToLowerInvariant( ) == "customisationuiheader" ) { - String x = reader.ReadOuterXml( ); + string x = reader.ReadOuterXml( ); m_uiCustHeader.fromXML( x ); } else if ( reader.Name.ToLowerInvariant( ) == "deviceoptions" ) { - String x = reader.ReadOuterXml( ); + string x = reader.ReadOuterXml( ); m_deviceOptions.fromXML( x ); } else if ( reader.Name.ToLowerInvariant( ) == "options" ) { - String x = reader.ReadOuterXml( ); - m_optionTree.fromXML( x ); - } else if ( reader.Name.ToLowerInvariant( ) == "modifiers" ) { - String x = reader.ReadOuterXml( ); - m_modifiers.fromXML( x ); + string x = reader.ReadOuterXml( ); + m_tuningOptions.fromXML( x ); } else { reader.Read( ); } @@ -398,7 +391,5 @@ namespace SCJMapper_V2 return true; } - - } } diff --git a/actions/ActionTree.cs b/actions/ActionTree.cs index 68aaa1f..3ef5727 100644 --- a/actions/ActionTree.cs +++ b/actions/ActionTree.cs @@ -24,15 +24,17 @@ namespace SCJMapper_V2 { private static readonly log4net.ILog log = log4net.LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod( ).DeclaringType ); + #region Static Parts // static fonts to be used instead of newly allocated ones each time (init when the Ctrl is assigned) static public Font FontActionmap = null; static public Font FontAction = null; static public Font FontActionActivated = null; + #endregion public event EventHandler NodeSelectedEvent; - private void NodeSelected( string action, string ctrl) + private void NodeSelected( string action, string ctrl ) { NodeSelectedEvent?.Invoke( this, new ActionTreeEventArgs( action, ctrl ) ); } @@ -41,22 +43,22 @@ namespace SCJMapper_V2 public ActionMapsCls ActionMaps { get; set; } // the Action Maps and Actions private TreeView m_MasterTree = new TreeView( ); // the master TreeView (mem only) - private TreeView m_ctrl = null; // the TreeView in the GUI - injected from GUI via Ctrl property + private TreeView m_tvCtrlRef = null; // the TreeView in the GUI - injected from GUI via Ctrl property public TreeView Ctrl { - get { return m_ctrl; } + get { return m_tvCtrlRef; } set { - m_ctrl = value; + m_tvCtrlRef = value; // copy props needed - m_MasterTree.Font = m_ctrl.Font; // assign font to master tree as well - m_MasterTree.ImageList = m_ctrl.ImageList; + m_MasterTree.Font = m_tvCtrlRef.Font; // assign font to master tree as well + m_MasterTree.ImageList = m_tvCtrlRef.ImageList; // define some const fonts for further use - FontActionmap = new Font( m_ctrl.Font, FontStyle.Bold ); - FontAction = new Font( m_ctrl.Font, FontStyle.Regular ); - FontActionActivated = new Font( m_ctrl.Font, FontStyle.Underline ); + FontActionmap = new Font( m_tvCtrlRef.Font, FontStyle.Bold ); + FontAction = new Font( m_tvCtrlRef.Font, FontStyle.Regular ); + FontActionActivated = new Font( m_tvCtrlRef.Font, FontStyle.Underline ); - m_ctrl.AfterSelect += M_ctrl_AfterSelect; + m_tvCtrlRef.AfterSelect += M_ctrl_AfterSelect; } } @@ -90,18 +92,14 @@ namespace SCJMapper_V2 /// public string IgnoreMaps { get; set; } - private string m_Filter = ""; // the tree content filter - private JoystickList m_jsList = null; - private GamepadCls m_gamepad = null; + private string m_Filter = ""; // the tree content filter + /// /// ctor /// - public ActionTree( JoystickList jsList, GamepadCls gamepad ) + public ActionTree() { - m_jsList = jsList; - m_gamepad = gamepad; - IgnoreMaps = ""; // nothing to ignore } @@ -113,14 +111,9 @@ namespace SCJMapper_V2 /// The ActionTree Copy with reassigned input public ActionTree ReassignJsN( JsReassingList newJsList ) { - ActionTree nTree = new ActionTree( m_jsList, m_gamepad ); - // full copy from 'this' - nTree.m_MasterTree = this.m_MasterTree; - nTree.m_ctrl = this.m_ctrl; - nTree.IgnoreMaps = this.IgnoreMaps; - nTree.m_Filter = this.m_Filter; - - nTree.ActionMaps = this.ActionMaps.ReassignJsN( newJsList ); + var nTree = (ActionTree)this.MemberwiseClone( ); // shallow copy of the members + // DeepCopy of the tree + nTree.ActionMaps = this.ActionMaps.ReassignJsN( newJsList ); // creates the deep copy of the actionmaps nTree.Dirty = true; return nTree; @@ -199,7 +192,7 @@ namespace SCJMapper_V2 /// /// Add a new Action Child to the selected node to apply an addtional mapping /// - public void AddBinding( ) + public void AddBinding() { if ( Ctrl.SelectedNode == null ) return; if ( Ctrl.SelectedNode.Level != 1 ) return; // can only add to level 1 nodes @@ -223,12 +216,12 @@ namespace SCJMapper_V2 /// /// Delete the selected ActionChild and remove corresponding ActionCommands /// - public void DelBinding( ) + public void DelBinding() { if ( Ctrl.SelectedNode == null ) return; if ( Ctrl.SelectedNode.Level != 2 ) return; // can only delete level 2 nodes - ActionTreeNode matn = FindMasterAction( ( ActionTreeNode )Ctrl.SelectedNode.Parent ); // the parent treenode + ActionTreeNode matn = FindMasterAction( (ActionTreeNode)Ctrl.SelectedNode.Parent ); // the parent treenode ActionCls ac = FindActionObject( matn.Parent.Name, matn.Name ); // the related action // delete items ac.DelCommand( Ctrl.SelectedNode.Index ); @@ -240,12 +233,12 @@ namespace SCJMapper_V2 } - public void BlendBinding( ) + public void BlendBinding() { UpdateSelectedItem( DeviceCls.BlendedInput, ActionCls.ActionDevice.AD_Unknown, false ); } - public void ClearBinding( ) + public void ClearBinding() { UpdateSelectedItem( "", ActionCls.ActionDevice.AD_Unknown, false ); } @@ -260,14 +253,14 @@ namespace SCJMapper_V2 { // must get the jsN information used for Options string nodeText = ""; - nodeText = FindAction( OptionsInvert.MappedActions[( int )item].Map, OptionsInvert.MappedActions[( int )item].Action ); + nodeText = FindAction( OptionsInvert.MappedActions[(int)item].Map, OptionsInvert.MappedActions[(int)item].Action ); if ( !string.IsNullOrWhiteSpace( nodeText ) ) { - DeviceCls dev = m_jsList.Find_jsN( JoystickCls.JSNum( ActionTreeNode.CommandFromNodeText( nodeText ) ) ); + DeviceCls dev = DeviceInst.JoystickListRef.Find_jsN( JoystickCls.JSNum( ActionTreeNode.CommandFromNodeText( nodeText ) ) ); if ( dev != null ) return dev; else { // could be a gamepad then if ( ActionTreeNode.CommandFromNodeText( nodeText ).Contains( "xi_" ) ) { - return m_gamepad; + return DeviceInst.GamepadRef; } else return null; // nope... } } @@ -343,7 +336,7 @@ namespace SCJMapper_V2 /// /// Apply the filter to the GUI TreeView /// - private void ApplyFilter( ) + private void ApplyFilter() { log.Debug( "ApplyFilter - Entry" ); @@ -360,7 +353,7 @@ namespace SCJMapper_V2 // have to search nodes of nodes bool allHidden = true; foreach ( ActionTreeNode stn in tn.Nodes ) { - if ( ( stn.Tag != null ) && ( ( bool )stn.Tag == true ) ) { + if ( ( stn.Tag != null ) && ( (bool)stn.Tag == true ) ) { ; // don't create it i.e hide it - though you cannot hide TreeViewNodes at all... } else { ActionTreeNode tnAction = new ActionTreeNode( stn ); tnMap.Nodes.Add( tnAction ); // copy level 1 nodes @@ -385,7 +378,7 @@ namespace SCJMapper_V2 /// Filters the master tree - only Actions (level 1) and not actionmaps (level 0) /// - Tag gets Bool hidden=true if not to be shown /// - private void FilterTree( ) + private void FilterTree() { bool hidden = !string.IsNullOrEmpty( m_Filter ); // hide only if there is a find string foreach ( ActionTreeNode tn in m_MasterTree.Nodes ) { @@ -434,7 +427,7 @@ namespace SCJMapper_V2 ActionCls ac = null; ActionCommandCls acc = null; - ActionMaps = new ActionMapsCls( m_jsList ); + ActionMaps = new ActionMapsCls( ); m_MasterTree.Nodes.Clear( ); // read the action items into the TreeView @@ -560,7 +553,7 @@ namespace SCJMapper_V2 /// Find the ActivationModes of the selected item /// /// A ActivationModes list - first element is the default, second the selected Mode - public ActivationModes ActivationModeSelectedItem( ) + public ActivationModes ActivationModeSelectedItem() { ActivationModes am = new ActivationModes( ActivationMode.Default, ActivationMode.Default );// policy: get the default first, then the attached one - dummy answer @@ -698,7 +691,7 @@ namespace SCJMapper_V2 //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; } ); + 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 ) { @@ -720,7 +713,7 @@ namespace SCJMapper_V2 //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; } ); + 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 ) { @@ -744,7 +737,7 @@ namespace SCJMapper_V2 //log.Debug( "FindActionObject - Entry" ); // Apply the input to the ActionTree ActionCls ac = null; - ActionMapCls ACM = ActionMaps.Find( delegate( ActionMapCls acm ) { return acm.name == actionMap; } ); + 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" ); @@ -775,18 +768,18 @@ namespace SCJMapper_V2 /// Loads the mappings back into the treeview control /// Note: this takes a while as the list grows... /// - public void ReloadTreeView( ) + public void ReloadTreeView() { log.Debug( "ReloadTreeView - Entry" ); foreach ( ActionMapCls acm in ActionMaps ) { 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 - bool first=true; + ActionTreeNode matn = (ActionTreeNode)mtn.Nodes[ac.key]; // get the action node + bool first = true; // refresh commands foreach ( ActionCommandCls acc in ac.inputList ) { try { @@ -1050,10 +1043,10 @@ namespace SCJMapper_V2 get { if ( Ctrl.SelectedNode == null ) return ""; if ( Ctrl.SelectedNode.Level == 1 ) { - ActionTreeNode matn = FindMasterAction( ( ActionTreeNode )Ctrl.SelectedNode ); + ActionTreeNode matn = FindMasterAction( (ActionTreeNode)Ctrl.SelectedNode ); return ActionTreeNode.ActionFromNodeText( matn.Text ); } else if ( Ctrl.SelectedNode.Level == 2 ) { - ActionTreeNode matn = FindMasterAction( ( ActionTreeNode )Ctrl.SelectedNode.Parent ); // the parent treenode + ActionTreeNode matn = FindMasterAction( (ActionTreeNode)Ctrl.SelectedNode.Parent ); // the parent treenode return ActionTreeNode.ActionFromNodeText( matn.Text ); } else return ""; } @@ -1078,7 +1071,7 @@ namespace SCJMapper_V2 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; } else if ( Ctrl.SelectedNode.Level == 2 ) { @@ -1090,7 +1083,7 @@ namespace SCJMapper_V2 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; } else return ""; @@ -1105,10 +1098,10 @@ namespace SCJMapper_V2 get { if ( Ctrl.SelectedNode == null ) return ""; if ( Ctrl.SelectedNode.Level == 1 ) { - ActionTreeNode matn = FindMasterAction( ( ActionTreeNode )Ctrl.SelectedNode ); + ActionTreeNode matn = FindMasterAction( (ActionTreeNode)Ctrl.SelectedNode ); return ActionTreeNode.CommandFromNodeText( matn.Text ); } else if ( Ctrl.SelectedNode.Level == 2 ) { - ActionTreeNode matn = FindMasterAction( ( ActionTreeNode )Ctrl.SelectedNode.Parent ); // the parent treenode + ActionTreeNode matn = FindMasterAction( (ActionTreeNode)Ctrl.SelectedNode.Parent ); // the parent treenode return ActionTreeNode.CommandFromNodeText( matn.Text ); } else return ""; } @@ -1120,10 +1113,10 @@ namespace SCJMapper_V2 /// returns a null if no changes have been found public ActionTree UpdateFromDataSet( DS_ActionMaps dsa ) { - ActionTree nTree = new ActionTree( this.m_jsList, this.m_gamepad ); // just a copy + ActionTree nTree = new ActionTree( ); // just a copy // full copy from 'this' nTree.m_MasterTree = this.m_MasterTree; - nTree.m_ctrl = this.m_ctrl; + nTree.m_tvCtrlRef = this.m_tvCtrlRef; nTree.IgnoreMaps = this.IgnoreMaps; nTree.m_Filter = this.m_Filter; nTree.ActionMaps = this.ActionMaps.ReassignJsN( new JsReassingList( ) ); // re-use this method with no reassign for full copy of the tree @@ -1132,7 +1125,7 @@ namespace SCJMapper_V2 foreach ( DS_ActionMaps.T_ActionRow ar in dsa.T_Action ) { if ( ar.RowState == System.Data.DataRowState.Modified ) { countChanges++; - ActionCommandCls acc = FindActionInputObject(nTree, DS_ActionMap.ActionMap(ar), DS_ActionMap.ActionKey(ar), DS_ActionMap.ActionCommandIndex(ar)); + 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 ) ); ar.Usr_Binding = acc.DevInput; // feedback the right one @@ -1161,7 +1154,7 @@ namespace SCJMapper_V2 /// Reports a summary list of the mapped items /// /// - public string ReportActions( ) + public string ReportActions() { log.Debug( "FindCtrl - ReportActions" ); @@ -1225,7 +1218,7 @@ namespace SCJMapper_V2 repList += string.Format( "\n" ); repList += "actionmap;action"; // col description line - if (listModifiers ) { + if ( listModifiers ) { repList += ";kbd-tag;kbd-input;kbd-mod-tag;kbd-mod-mode;kbd-mod-multi"; // col description line repList += ";mouse-tag;mouse-input;mouse-mod-tag;mouse-mod-mode;mouse-mod-multi"; repList += ";xpad-tag;xpad-input;xpad-mod-tag;xpad-mod-mode;xpad-mod-multi"; @@ -1263,8 +1256,7 @@ namespace SCJMapper_V2 // 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 - } - else { + } else { kbA = "n.a.;"; // defaults tag;input } moA = kbA; xbA = kbA; @@ -1286,7 +1278,7 @@ namespace SCJMapper_V2 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: - int jsNum = JoystickCls.JSNum(acc.DevInput) - 1; + 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; default: break; @@ -1296,7 +1288,7 @@ namespace SCJMapper_V2 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: - int jsNum = JoystickCls.JSNum(acc.DevInput) - 1; + 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; default: break; diff --git a/actions/MyColors.cs b/actions/MyColors.cs index aadd5d0..03d6df7 100644 --- a/actions/MyColors.cs +++ b/actions/MyColors.cs @@ -10,12 +10,28 @@ namespace SCJMapper_V2 /// class MyColors { - static public Color[] TabColor = { Color.LightGreen, Color.LightBlue, Color.Khaki, Color.LightSalmon, - Color.Beige, Color.Yellow, Color.Plum, Color.MintCream, - Color.LightCyan, Color.MistyRose, Color.Wheat, Color.Pink }; - static public Color GamepadColorDefault = Color.Orchid; // will be changed on init (else we see pink..) - - static public Color[] MapColor = ( System.Drawing.Color[] )TabColor.Clone( ); + static public readonly Color[] InitColor = { Color.LightGreen, Color.LightBlue, Color.Khaki, Color.LightSalmon, + Color.Beige, Color.Yellow, Color.MintCream, Color.LightCyan, + Color.MistyRose, Color.Wheat, Color.Plum, Color.Pink }; + static public readonly Color GamepadColorDefault = Color.SandyBrown; // Must not be one of the Joysticks!! some cruel algo depends on it beeing different... + + static public Color[] TabColor = ( Color[] )InitColor.Clone( ); // the gamepad tab will get reassinged to Gamepad color on Init + + /// + /// Colormap of the Joystick assignment - use (JsN-1) as index + /// + static public Color[] JsMapColor = ( Color[] )TabColor.Clone( ); // maps only Joystick colors + + /// + /// Joystick color of the JsN assigned joystick instance + /// + /// The jsN number of the joystick + /// The (tab) color of this item + static public Color JsColor(int jsN ) { return JsMapColor[jsN - 1]; } + + /// + /// The Gamepad color + /// static public Color GamepadColor = GamepadColorDefault; static public Color KeyboardColor = Color.Lavender; @@ -35,7 +51,7 @@ namespace SCJMapper_V2 static public void Reset( ) { - MapColor = ( System.Drawing.Color[] )TabColor.Clone( ); + JsMapColor = ( Color[] )InitColor.Clone( ); GamepadColor = GamepadColorDefault; } diff --git a/defaultProfile.xml b/defaultProfile.xml index 117466e..48a0811 100644 --- a/defaultProfile.xml +++ b/defaultProfile.xml @@ -333,6 +333,7 @@ + @@ -424,7 +425,7 @@ - + @@ -551,8 +552,8 @@ - - + + @@ -568,14 +569,22 @@ - + + + + + + + + + - + @@ -636,7 +645,7 @@ - + @@ -667,18 +676,187 @@ - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -693,6 +871,13 @@ + + + + + + + @@ -701,11 +886,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - @@ -839,19 +1071,6 @@ - - - - - - - - - - - - - @@ -884,135 +1103,26 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + - - - - - - - - - - - + + + + @@ -1080,61 +1190,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1157,78 +1212,38 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +