/// <summary> /// Apply an update from the action to the treenode /// First apply to the GUI tree where the selection happend then copy it over to master tree /// </summary> /// <param name="action">The action that carries the update</param> public void UpdateAction(ActionCommandCls actionCmd) { //log.Debug( "UpdateNodeFromAction - Entry" ); if (actionCmd == null) { return; } // input is either "" or a valid mapping or a blended mapping if (String.IsNullOrEmpty(actionCmd.Input)) { // new unmapped this.Command = ""; this.BackColor = MyColors.UnassignedColor; if (this.Level == 2) { this.Action = "UNDEF"; // apply UNDEF - 20160525 fix addbind not showing UNDEF if assigned } } // blended mapped ones - can only get a Blend Background else if (actionCmd.Input == DeviceCls.BlendedInput) { this.Command = actionCmd.DevInput; this.BackColor = MyColors.BlendedColor; } else { // mapped ( regular ones ) this.Command = actionCmd.DevInput; //if ( this.Level == 2 ) this.Action = ""; // remove UNDEF - 20160525 fix addbind not showing UNDEF if assigned // background is along the input this.BackColor = ActionCls.DeviceColor(actionCmd.DevInput); } this.Modified = !actionCmd.DefaultActivationMode; // apply modifier visual }
/// <summary> /// Merge action is simply copying the new input control /// </summary> /// <param name="newAc"></param> public void Merge(ActionCls newAc) { this.inputList.Clear( ); foreach (ActionCommandCls acc in newAc.inputList) { this.inputList.Add(acc); } }
/// <summary> /// Updates an actionCommand with a new input (command) /// </summary> /// <param name="devInput">The input command</param> public void UpdateCommandFromInput(String devInput, ActionCls.ActionDevice actionDevice) // ActionCommandCls actionCmd ) { // Apply the input to the ActionTree this.DevInput = ActionCls.BlendInput(devInput, actionDevice); if (ActionCls.IsBlendedInput(this.DevInput) || string.IsNullOrEmpty(devInput)) { this.ActivationMode = new ActivationMode(ActivationMode.Default); // reset activation mode if the input is empty } }
/// <summary> /// Reads an action sub element /// </summary> /// <param name="xr">An XML reader @ StartElement</param> private void ReadActionSub(XmlReader xr, String actionName) { //<action name="v_brake" onPress="1" onHold="1" onRelease="1" keyboard="space" xboxpad="xi_shoulderl+xi_shoulderr"> // <joystick input="js2_button7" /> // <joystick input="js2_button8" /> //</action> //or //<action name="v_hud_confirm" onPress="1" onRelease="1" xboxpad="xi_triggerL_btn+xi_a" joystick="js1_button19"> // <keyboard> // <inputdata input="enter"/> // </keyboard> //</action> Boolean done = false; do { xr.Read( ); // get next element Dictionary <String, String> attr = new Dictionary <string, string>( ); String eName = xr.Name; while (xr.MoveToNextAttribute( )) { attr.Add(xr.Name, xr.Value); // save the attributes //Console.Write( " {0}='{1}'", xr.Name, xr.Value ); } xr.MoveToElement( ); // backup Action ac = new Action( ); ac.name = actionName; // the element name is a control if (xr.NodeType == XmlNodeType.EndElement) { done = (xr.Name == "action"); } else if (xr.IsEmptyElement) { // an attribute only element ac.input = ActionCls.DevID(eName); ac.defBinding = attr["input"]; if (!String.IsNullOrEmpty(ac.defBinding)) { m_currentMap.Add(ac); // finally add it to the current map if it was bound } } else { // one with subelements again xr.Read( ); ac.input = ActionCls.DevID(eName); ac.defBinding = xr["input"]; if (!String.IsNullOrEmpty(ac.defBinding)) { m_currentMap.Add(ac); // finally add it to the current map if it was bound } } } while (!done); m_nodeNameStack.Pop( ); // action is finished }
} // regular bind is the 0-element, addbinds are added to the list /// <summary> /// Clone this object /// </summary> /// <returns>A deep Clone of this object</returns> private ActionCls MyClone() { 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); }
/// <summary> /// Copy return the action while reassigning the JsN Tag /// </summary> /// <param name="newJsList">The JsN reassign list</param> /// <returns>The action copy with reassigned input</returns> public ActionCls ReassignJsN(JsReassingList newJsList) { ActionCls newAc = this.MyClone( ); // creates a copy of the list with reassigned jsN devs newAc.inputList.Clear( ); // get rid of cloned list foreach (ActionCommandCls acc in inputList) { newAc.inputList.Add(acc.ReassignJsN(newJsList)); // creates the deep copy of the list } return(newAc); }
/// <summary> /// Copy return the action while reassigning the JsN Tag /// </summary> /// <param name="newJsList">The JsN reassign list</param> /// <returns>The action copy with reassigned input</returns> 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; foreach (ActionCommandCls acc in inputList) { newAc.inputList.Add(acc.ReassignJsN(newJsList)); } return(newAc); }
/// <summary> /// Copy return the action while reassigning the JsN Tag /// </summary> /// <param name="newJsList">The JsN reassign list</param> /// <returns>The action copy with reassigned input</returns> 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; // creates a copy of the list with reassigned jsN devs foreach (ActionCommandCls acc in inputList) { newAc.inputList.Add(acc.ReassignJsN(newJsList)); } return(newAc); }
/// <summary> /// Apply an update from the action to the treenode /// First apply to the GUI tree where the selection happend then copy it over to master tree /// </summary> /// <param name="input">The input command</param> /// <param name="node">The TreeNode to update</param> /// <param name="actionCmd">The actionCommand that carries the update</param> /// <param name="inKind">The input device</param> private void UpdateInputNodeFromAction( ActionTreeInputNode node, ActionCommandCls actionCmd, ActionCls.ActionDevice inKind ) { log.Debug( "UpdateInputNodeFromAction - Entry" ); if ( actionCmd == null ) return; if ( node.Level != 2 ) return; // applies only to ActionTreeInputNode // input is either "" or a valid mapping or a blended mapping if ( String.IsNullOrEmpty( actionCmd.input ) ) { // new unmapped node.Command = ""; node.BackColor = MyColors.UnassignedColor; } // blended mapped ones - can only get a Blend Background else if ( ( inKind == ActionCls.ActionDevice.AD_Joystick ) && ( actionCmd.input == JoystickCls.BlendedInput ) ) { node.Command = actionCmd.input; node.BackColor = MyColors.BlendedColor; } else if ( ( inKind == ActionCls.ActionDevice.AD_Gamepad ) && ( actionCmd.input == GamepadCls.BlendedInput ) ) { node.Command = actionCmd.input; node.BackColor = MyColors.BlendedColor; } else if ( actionCmd.input == DeviceCls.BlendedInput ) { // Manually Blended input node.Command = actionCmd.input; node.BackColor = MyColors.BlendedColor; } else { // mapped ( regular ones ) node.Command = actionCmd.input; // background is along the input if ( inKind == ActionCls.ActionDevice.AD_Joystick ) { int jNum = JoystickCls.JSNum( actionCmd.input ); node.BackColor = JoystickCls.JsNColor( jNum ); } else if ( inKind == ActionCls.ActionDevice.AD_Gamepad ) { node.BackColor = GamepadCls.XiColor( ); } else if ( inKind == ActionCls.ActionDevice.AD_Keyboard ) { node.BackColor = KeyboardCls.KbdColor( ); } else { // ?? what else node.BackColor = MyColors.UnassignedColor; } } UpdateMasterNode( node ); }
/// <summary> /// Updates an actionCommand with a new input (command) /// </summary> /// <param name="input">The input command</param> /// <param name="action">The action to containing the command</param> /// <param name="actionCmd">The actionCommand to update</param> private void UpdateActionCommandFromInput( String input, ActionCommandCls actionCmd, ActionCls.ActionDevice inKind ) { //log.Debug( "UpdateActionCommandFromInput - Entry" ); if ( actionCmd == null ) return; // Apply the input to the ActionTree if ( String.IsNullOrEmpty( input ) ) { // unmapped - handle the blended ones from setting if ( ( inKind == ActionCls.ActionDevice.AD_Joystick ) && BlendUnmappedJS ) actionCmd.input = JoystickCls.BlendedInput; else if ( ( inKind == ActionCls.ActionDevice.AD_Gamepad ) && BlendUnmappedGP ) actionCmd.input = GamepadCls.BlendedInput; else actionCmd.input = ""; } else { // mapped ones actionCmd.input = input; } Dirty = true; }
/// <summary> /// Find an ActionCommand with index in an Action /// </summary> /// <param name="actionMap">The actionmap name</param> /// <param name="action">The action</param> /// <param name="input">The input</param> /// <returns>An actionCommand or null if not found</returns> private ActionCommandCls FindActionInputObject( ActionCls ac, int index ) { log.Debug( "FindActionInputObject - Entry" ); // Apply the input to the ActionTree ActionCommandCls acc = null; if ( ac != null ) acc = ac.inputList.Find( delegate( ActionCommandCls _ACC ) { return _ACC.nodeIndex == index; } ); if ( acc == null ) { log.Error( "FindActionInputObject - Action Input not found in Action" ); return null; // ERROR - Action Input not found in tree } return acc; }
// input is like js1_button3 OR keyboard such as lctrl+x (mouse is keyboard too) /// <summary> /// Apply an update the the treenode /// First apply to the GUI tree where the selection happend then copy it over to master tree /// </summary> /// <param name="input">The new Text property</param> public Boolean UpdateSelectedItem( String input, ActionCls.ActionDevice inKind, Boolean checkKind ) { if ( ( Ctrl.SelectedNode.Level == 0 ) || ( Ctrl.SelectedNode.Level > 2 ) ) return false; // ERROR exit if ( Ctrl.SelectedNode == null ) return false; // ERROR exit if ( Ctrl.SelectedNode.Parent == null ) return false; // ERROR exit // has a parent - must be level 1 or 2 if ( Ctrl.SelectedNode.Level == 1 ) { // this is the main node with Action Cmd ActionCls ac = FindActionObject( Ctrl.SelectedNode.Parent.Name, Ctrl.SelectedNode.Name ); if ( ac == null ) return false; // ERROR exit if ( checkKind && ( ac.actionDevice != inKind ) ) return false; // ERROR exit ActionCommandCls acc = FindActionInputObject( Ctrl.SelectedNode.Parent.Name, Ctrl.SelectedNode.Name, CommandFromNodeText( Ctrl.SelectedNode.Text ) ); if ( acc == null ) return false; // ERROR exit UpdateActionCommandFromInput( input, acc, inKind ); UpdateNodeFromAction( ( ActionTreeNode )Ctrl.SelectedNode, acc, inKind ); } else if ( Ctrl.SelectedNode.Level == 2 ) { // this is a child of an action with further commands ActionTreeNode atn = ( m_ctrl.SelectedNode.Parent as ActionTreeNode ); // the parent treenode ActionCls ac = FindActionObject( atn.Parent.Name, atn.Name ); // the related action if ( ac == null ) return false; // ERROR exit if ( checkKind && ( ac.actionDevice != inKind ) ) return false; // ERROR exit ActionCommandCls acc = FindActionInputObject( ac, m_ctrl.SelectedNode.Index ); if ( acc == null ) return false; // ERROR exit UpdateActionCommandFromInput( input, acc, inKind ); UpdateInputNodeFromAction( ( ActionTreeInputNode )Ctrl.SelectedNode, acc, inKind ); } return true; }
/// <summary> /// Load Mappings into the ActionList and create the Master TreeView /// </summary> /// <param name="defaultProfileName">The name of the profile to load (w/o extension)</param> /// <param name="applyDefaults">True if default mappings should be carried on</param> public void LoadProfileTree( String defaultProfileName, Boolean applyDefaults ) { log.Debug( "LoadProfileTree - Entry" ); ActionTreeNode tn = null; ActionTreeNode[] cnl = { }; ActionTreeNode cn = null; ActionTreeNode topNode = null; ActionMapCls acm = null; ActionCls ac = null; ActionCommandCls acc = null; ActionMaps = new ActionMapsCls( m_jsList ); m_MasterTree.Nodes.Clear( ); // read the action items into the TreeView DProfileReader dpReader = new DProfileReader( ); // we may read a profile TextReader txReader = null; dpReader.fromXML( SCDefaultProfile.DefaultProfile( defaultProfileName + ".xml" ) ); if ( dpReader.ValidContent ) { txReader = new StringReader( dpReader.CSVMap ); } // we assume no addbind items in the profile // so all actions are shown in the ActionTreeNode and no ActionTreeNode childs must be created here // however we create the ActionCommand for each entry that is supported - even if it is not mapped (input= "") using ( TextReader sr = txReader ) { String buf = sr.ReadLine( ); while ( !String.IsNullOrEmpty( buf ) ) { String[] elem = buf.Split( new char[] { ';', ',' } ); if ( elem.Length > 1 ) { if ( !IgnoreMaps.Contains( "," + elem[0] + "," ) ) { // must have 2 elements min Array.Resize( ref cnl, 0 ); acm = new ActionMapCls( ); acm.name = elem[0]; // get actionmap name // process items for ( int ei=1; ei < elem.Length; ei += 2 ) { // step 2 - action;defaultBinding come in pairs if ( !String.IsNullOrEmpty( elem[ei] ) ) { // default assignments String action = elem[ei].Substring( 1 ); String defBinding = elem[ei + 1].Substring( 0 ); String devID = elem[ei].Substring( 0, 1 ); String device = ActionCls.DeviceFromID( devID ); // visual item for the action cn = new ActionTreeNode( "UNDEF" ); cn.Name = elem[ei]; cn.Action = action; cn.BackColor = Color.White; // name with the key it to find it.. cn.ImageKey = devID; cn.BackColor = Color.White; // some stuff does not work properly... Array.Resize( ref cnl, cnl.Length + 1 ); cnl[cnl.Length - 1] = cn; // derive content tree ac = new ActionCls( ); ac.key = cn.Name; ac.name = action; ac.device = device; ac.actionDevice = ActionCls.ADevice( device ); ac.defBinding = defBinding; acm.Add( ac ); // add to our map cn.ActionDevice = ac.actionDevice; // should be known now // create just an unmapped ActionCommand item acc = new ActionCommandCls( ); acc.input = ""; acc.nodeIndex = -1; // profile items are shown in the ActionTreeNode (not in a child) ac.inputList.Add( acc );// add to our Action // modify defaults and blendings if ( applyDefaults ) { // apply the default mappings if ( ac.actionDevice == ActionCls.ActionDevice.AD_Joystick ) { int jNum = JoystickCls.JSNum( ac.defBinding ); if ( JoystickCls.IsJSValid( jNum ) ) { acc.input = ac.defBinding; cn.Command = ac.defBinding; cn.BackColor = JoystickCls.JsNColor( jNum ); } else if ( BlendUnmappedJS ) { // jsx_reserved gets here acc.input = JoystickCls.BlendedInput; cn.Command = JoystickCls.BlendedInput; cn.BackColor = MyColors.BlendedColor; } } else if ( ac.actionDevice == ActionCls.ActionDevice.AD_Gamepad ) { if ( GamepadCls.IsXiValid( ac.defBinding ) ) { acc.input = ac.defBinding; cn.Command = ac.defBinding; cn.BackColor = GamepadCls.XiColor( ); } else if ( BlendUnmappedGP ) { // xi_reserved gets here acc.input = GamepadCls.BlendedInput; cn.Command = GamepadCls.BlendedInput; cn.BackColor = MyColors.BlendedColor; } } else if ( ac.actionDevice == ActionCls.ActionDevice.AD_Keyboard ) { if ( !String.IsNullOrEmpty( ac.defBinding ) ) { acc.input = ac.defBinding; cn.Command = ac.defBinding; cn.BackColor = KeyboardCls.KbdColor( ); } } } // Don't apply defaults - but blend if checked else { if ( ( ac.actionDevice == ActionCls.ActionDevice.AD_Joystick ) && BlendUnmappedJS ) { cn.Command = JoystickCls.BlendedInput; cn.BackColor = MyColors.BlendedColor; acc.input = JoystickCls.BlendedInput; } else if ( ( ac.actionDevice == ActionCls.ActionDevice.AD_Gamepad ) && BlendUnmappedGP ) { cn.Command = GamepadCls.BlendedInput; cn.BackColor = MyColors.BlendedColor; acc.input = GamepadCls.BlendedInput; } } } }//for tn = new ActionTreeNode( acm.name, cnl ); tn.Name = acm.name; // name it to find it.. tn.ImageIndex = 0; tn.NodeFont = new Font( m_MasterTree.Font, FontStyle.Bold ); m_MasterTree.BackColor = Color.White; // fix for defect TreeView (cut off bold text) m_MasterTree.Nodes.Add( tn ); // add to control if ( topNode == null ) topNode = tn; // once to keep the start of list ActionMaps.Add( acm ); // add to our map }//not ignored }// if valid line buf = sr.ReadLine( ); }//while } // fix for defect TreeView (cut off bold text at last element -despite the BackColor fix) add another and delete it tn = new ActionTreeNode( "DUMMY" ); tn.Name = "DUMMY"; tn.ImageIndex = 0; tn.NodeFont = new Font( m_MasterTree.Font, FontStyle.Bold ); m_MasterTree.BackColor = m_MasterTree.BackColor; // fix for defect TreeView (cut off bold text) m_MasterTree.Nodes.Add( tn ); // add to control m_MasterTree.Nodes.RemoveByKey( "DUMMY" ); // fix for defect TreeView (cut off bold text) txReader = null; Dirty = false; // finally apply the filter and make it visible FilterTree( ); }
/// <summary> /// Copy return the action while reassigning the JsN Tag /// </summary> /// <param name="newJsList">The JsN reassign list</param> /// <returns>The action copy with reassigned input</returns> 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; foreach ( ActionCommandCls acc in inputList ) { newAc.inputList.Add( acc.ReassignJsN( newJsList ) ); } return newAc; }
/// <summary> /// Merge action is simply copying the new input control /// </summary> /// <param name="newAc"></param> public void Merge( ActionCls newAc ) { this.inputList.Clear( ); foreach ( ActionCommandCls acc in newAc.inputList ) { this.inputList.Add( acc ); } }