SCJMapper-V2/actions/ActionTree.cs
bm98 d49b0bf934 V 2.25 - BETA Build 59
- fix - an issue in parsing options from imported maps
- add - an option to show the actiontree as CSV list with more/less details (change in Settings)
- improvement - In table view add possibility to Blend All visible unmapped entries
2016-07-01 17:57:58 +02:00

1294 lines
53 KiB
C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Drawing;
using SCJMapper_V2.Properties;
using SCJMapper_V2.SC;
using SCJMapper_V2.Table;
using SCJMapper_V2.Keyboard;
using SCJMapper_V2.Mouse;
using SCJMapper_V2.Gamepad;
using SCJMapper_V2.Joystick;
namespace SCJMapper_V2
{
/// <summary>
/// Maintains the action tree and its GUI representation, the TreeView
/// - the TreeView is managed primary in memory (Master Tree) and copied to the GUI tree via the Filter functions
/// </summary>
class ActionTree
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod( ).DeclaringType );
// 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;
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
public TreeView Ctrl
{
get { return m_ctrl; }
set {
m_ctrl = value;
// copy props needed
m_MasterTree.Font = m_ctrl.Font; // assign font to master tree as well
m_MasterTree.ImageList = m_ctrl.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 );
}
}
private Boolean m_showJoy = true;
private Boolean m_showGameP = true;
private Boolean m_showKbd = true;
private Boolean m_showMouse = true;
private Boolean m_showMappedOnly = false;
/// <summary>
/// maintains the change status (gets reset by reloading the complete tree)
/// </summary>
public Boolean Dirty { get; set; }
/// <summary>
/// a comma separated list of actionmaps to ignore
/// </summary>
public String IgnoreMaps { get; set; }
private String m_Filter = ""; // the tree content filter
private JoystickList m_jsList = null;
private GamepadCls m_gamepad = null;
/// <summary>
/// ctor
/// </summary>
public ActionTree( JoystickList jsList, GamepadCls gamepad )
{
m_jsList = jsList;
m_gamepad = gamepad;
IgnoreMaps = ""; // nothing to ignore
}
/// <summary>
/// Copy return the complete ActionTree while reassigning JsN
/// </summary>
/// <param name="newJsList">The JsN reassign list</param>
/// <returns>The ActionTree Copy with reassigned input</returns>
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 );
nTree.Dirty = true;
return nTree;
}
#region Properties
public Boolean CanAssignBinding
{
get {
if ( Ctrl.SelectedNode == null ) return false;
else return ( Ctrl.SelectedNode.Level == 1 ) || ( Ctrl.SelectedNode.Level == 2 );
}
}
public Boolean CanBlendBinding
{
get {
if ( Ctrl.SelectedNode == null ) return false;
else return ( Ctrl.SelectedNode.Level == 1 );
}
}
public Boolean CanClearBinding
{
get {
if ( Ctrl.SelectedNode == null ) return false;
else return ( Ctrl.SelectedNode.Level == 1 ) && IsMappedAction;
}
}
public Boolean CanAddBinding
{
get {
if ( Ctrl.SelectedNode == null ) return false;
else return ( Ctrl.SelectedNode.Level == 1 ) && IsMappedAction;
}
}
public Boolean CanDelBinding
{
get {
if ( Ctrl.SelectedNode == null ) return false;
else return ( Ctrl.SelectedNode.Level == 2 );
}
}
public Boolean IsMappedAction
{
get {
if ( ( Ctrl.SelectedNode.Level == 0 ) || ( Ctrl.SelectedNode.Level > 2 ) ) return false; // not on node
if ( Ctrl.SelectedNode == null ) return false; // no node selected
if ( Ctrl.SelectedNode.Parent == null ) return false; // ERROR EXIT
return ( Ctrl.SelectedNode as ActionTreeNode ).IsMappedAction;
}
}
public Boolean ShowAction( ActionCls.ActionDevice actDev, string input )
{
if ( ActionCls.IsBlendedInput( input ) && m_showMappedOnly ) return false;
switch ( actDev ) {
case ActionCls.ActionDevice.AD_Gamepad: return m_showGameP;
case ActionCls.ActionDevice.AD_Joystick: return m_showJoy;
case ActionCls.ActionDevice.AD_Keyboard: return m_showKbd;
case ActionCls.ActionDevice.AD_Mouse: return m_showMouse;
default: return false;
}
}
#endregion
/// <summary>
/// Add a new Action Child to the selected node to apply an addtional mapping
/// </summary>
public void AddBinding( )
{
if ( Ctrl.SelectedNode == null ) return;
if ( Ctrl.SelectedNode.Level != 1 ) return; // can only add to level 1 nodes
ActionTreeNode matn = FindMasterAction( (ActionTreeNode)Ctrl.SelectedNode );
ActionCls ac = FindActionObject( matn.Parent.Name, matn.Name ); // the related action
// make new items
ActionTreeInputNode matin = new ActionTreeInputNode( "UNDEF" ); matin.ImageKey = "Add";
matn.Nodes.Add( matin ); // add to master tree
ActionCommandCls acc = ac.AddCommand( "", matin.Index );
// show stuff
FilterTree( );
FindAndSelectCtrlByName( matn.Name );
// jump to the latest
if ( Ctrl.SelectedNode.LastNode != null ) {
Ctrl.SelectedNode = Ctrl.SelectedNode.LastNode;
}
}
/// <summary>
/// Delete the selected ActionChild and remove corresponding ActionCommands
/// </summary>
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
ActionCls ac = FindActionObject( matn.Parent.Name, matn.Name ); // the related action
// delete items
ac.DelCommand( Ctrl.SelectedNode.Index );
matn.Nodes.RemoveAt( Ctrl.SelectedNode.Index );
Dirty = true;
// show stuff
FilterTree( );
FindAndSelectCtrlByName( matn.Name );
}
public void BlendBinding( )
{
UpdateSelectedItem( DeviceCls.BlendedInput, ActionCls.ActionDevice.AD_Unknown, false );
}
public void ClearBinding( )
{
UpdateSelectedItem( "", ActionCls.ActionDevice.AD_Unknown, false );
}
/// <summary>
/// Assign the GUI Invert Checkboxes for further handling
/// </summary>
public List<CheckBox> InvertCheckList
{
set {
if ( ActionMaps != null ) ActionMaps.InvertCheckList = value; // just propagate if possible
else {
log.Error( "ActionTree-InvertCheckList: Program error - ActionMaps not yet created" );
}
}
}
/// <summary>
/// Gets the JS device that is used for one of the Inversion Items supported
/// </summary>
/// <param name="item">The Inversion item</param>
/// <returns>The device used or null</returns>
private DeviceCls GetActionInstance( OptionsInvert.Inversions item )
{
// must get the jsN information used for Options
String nodeText = "";
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 ) ) );
if ( dev != null ) return dev;
else {
// could be a gamepad then
if ( ActionTreeNode.CommandFromNodeText( nodeText ).Contains( "xi_" ) ) {
return m_gamepad;
} else return null; // nope...
}
}
return null;
}
/// <summary>
/// Collects and forwards the device information (instances) to the consuming invert Options
/// </summary>
private void UpdateDeviceInformation( )
{
// must get the jsN information used for Options Inverters
for ( int item = 0; item < ( int )OptionsInvert.Inversions.I_LAST; item++ ) {
ActionMaps.Options.Inverter( ( OptionsInvert.Inversions )item ).GameDevice = GetActionInstance( ( OptionsInvert.Inversions )item );
}
}
/// <summary>
/// Dumps the actions to an XML String
/// </summary>
/// <returns>A string containing the XML</returns>
public String toXML( String fileName )
{
if ( ActionMaps != null ) {
// must update the devices and instances for inversion before dumping the XML
UpdateDeviceInformation( );
return ActionMaps.toXML( fileName ); // just propagate if possible
} else {
log.Error( "ActionTree-toXML: Program error - ActionMaps not yet created" );
return "";
}
}
#region MasterTree Actions
private void UpdateMasterNode( ActionTreeNode node )
{
// copy to master node
TreeNode[] masterNode = m_MasterTree.Nodes.Find( node.Name, true ); // find the same node in master
if ( masterNode.Length == 0 ) throw new IndexOutOfRangeException( "ActionTree ERROR - cannot find synched node in master" ); // OUT OF SYNC
// could return more than one if the action is the same in different actionmaps
foreach ( ActionTreeNode mtn in masterNode ) {
if ( mtn.Parent.Name == node.Parent.Name ) {
mtn.Update( node ); // update from node
}
}
}
private void UpdateMasterNode( ActionTreeInputNode node )
{
// copy to master node
TreeNode[] masterNode = m_MasterTree.Nodes.Find( node.Name, true ); // find the same node in master
if ( masterNode.Length == 0 ) throw new IndexOutOfRangeException( "ActionTree ERROR - cannot find synched node in master" ); // OUT OF SYNC
// could return more than one if the action is the same in different actionmaps
foreach ( ActionTreeInputNode mtn in masterNode ) {
if ( mtn.Parent.Name == node.Parent.Name ) {
mtn.Update( node ); // update from node
}
}
}
/// <summary>
/// Find the master element for the given ActionNode
/// </summary>
/// <param name="atn">The ActionNode to find</param>
/// <returns>The sought node or null</returns>
private ActionTreeNode FindMasterAction( ActionTreeNode atn )
{
if ( atn.Level != 1 ) return null; // sanity
TreeNode[] masterNode = m_MasterTree.Nodes.Find( atn.Name, true ); // find the same node in master
if ( masterNode.Length == 0 ) throw new IndexOutOfRangeException( "ActionTree ERROR - cannot find synched node in master" ); // OUT OF SYNC
// could return more than one if the action is the same in different actionmaps
foreach ( ActionTreeNode mtn in masterNode ) {
if ( mtn.Parent.Name == atn.Parent.Name ) {
return mtn;
}
}
return null;
}
/// <summary>
/// Apply the filter to the GUI TreeView
/// </summary>
private void ApplyFilter( )
{
log.Debug( "ApplyFilter - Entry" );
ActionTreeNode topNode = null; // allow to backup the view - will carry the first node items
Ctrl.BeginUpdate( );
Ctrl.Nodes.Clear( ); // start over
// traverse the master tree and build the GUI tree from it
foreach ( ActionTreeNode tn in m_MasterTree.Nodes ) {
ActionTreeNode tnMap = new ActionTreeNode( tn ); Ctrl.Nodes.Add( tnMap ); // copy level 0 nodes
if ( topNode == null ) topNode = tnMap;
// have to search nodes of nodes
Boolean allHidden = true;
foreach ( ActionTreeNode stn in tn.Nodes ) {
if ( ( stn.Tag != null ) && ( ( Boolean )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
foreach ( ActionTreeInputNode istn in stn.Nodes ) {
ActionTreeInputNode tnActionInput = new ActionTreeInputNode( istn ); tnAction.Nodes.Add( tnActionInput ); // copy level 2 nodes
}
allHidden = false;
}
}
// make it tidier..
if ( allHidden ) tnMap.Collapse( );
else tnMap.ExpandAll( );
}
if ( topNode != null ) Ctrl.TopNode = topNode; // set view to topnode
Ctrl.EndUpdate( ); // enable GUI update
}
/// <summary>
/// Filters the master tree - only Actions (level 1) and not actionmaps (level 0)
/// - Tag gets Bool hidden=true if not to be shown
/// </summary>
private void FilterTree( )
{
Boolean hidden = !String.IsNullOrEmpty( m_Filter ); // hide only if there is a find string
foreach ( ActionTreeNode tn in m_MasterTree.Nodes ) {
// have to search nodes of nodes
foreach ( ActionTreeNode stn in tn.Nodes ) {
stn.Tag = null; // default
if ( ( !m_showJoy ) && stn.IsJoystickAction ) stn.Tag = true;
if ( ( !m_showGameP ) && stn.IsGamepadAction ) stn.Tag = true;
if ( ( !m_showKbd ) && stn.IsKeyboardAction ) stn.Tag = true;
if ( ( !m_showMouse ) && stn.IsMouseAction ) stn.Tag = true;
if ( m_showMappedOnly && ( !stn.IsMappedAction ) ) stn.Tag = true;
if ( !stn.Text.Contains( m_Filter ) ) stn.Tag = hidden;
}
}
ApplyFilter( ); // to the GUI tree
}
/// <summary>
/// Filters entries with given criteria
/// </summary>
/// <param name="filter">The text snip to filter</param>
public void FilterTree( String filter )
{
m_Filter = filter;
FilterTree( );
}
#endregion
/// <summary>
/// Load Mappings into the ActionList and create the Master TreeView
/// </summary>
/// <param name="defaultProfileName">The name of the profile to load (w 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 ) );
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[] { ';', ',' }, StringSplitOptions.None );
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 += 4 ) { // step 2 - action;defaultBinding;defaultActivationMode;defMultiTap come in as quadrupples
if ( !String.IsNullOrEmpty( elem[ei] ) ) {
// default assignments
String action = elem[ei].Substring( 1 );
String defBinding = elem[ei + 1];
string defActivationModeName = elem[ei + 2];
int defMultiTap = int.Parse( elem[ei + 3] );
// need to create a ActivationMode here
ActivationMode defActivationMode = new ActivationMode( defActivationModeName, defMultiTap );
String devID = elem[ei].Substring( 0, 1 );
String device = ActionCls.DeviceClassFromTag( devID );
// visual item for the action
cn = new ActionTreeNode( "UNDEF" ); cn.Name = elem[ei]; cn.Action = action; cn.BackColor = Color.White; // name with the key it to find it..
cn.ImageKey = devID; cn.BackColor = Color.White; // some stuff does not work properly...
if ( ActivationMode.IsDefault( defActivationModeName ) ) {
cn.NodeFont = FontAction;
} else {
cn.NodeFont = FontActionActivated;
}
Array.Resize( ref cnl, cnl.Length + 1 ); cnl[cnl.Length - 1] = cn;
// derive content tree
ac = new ActionCls( ); ac.key = cn.Name; ac.name = action; ac.device = device; ac.actionDevice = ActionCls.ADevice( device );
ac.defBinding = defBinding; ac.defActivationMode = defActivationMode;
acm.Add( ac ); // add to our map
cn.ActionDevice = ac.actionDevice; // should be known now
// create just an unmapped ActionCommand item
acc = ac.AddCommand( "", -1 ); // profile items are shown in the ActionTreeNode (not in a child)
// init and apply the default mappings if requested
if ( ac.actionDevice == ActionCls.ActionDevice.AD_Joystick ) {
acc.DevID = JoystickCls.DeviceID;
int jNum = JoystickCls.JSNum( ac.defBinding );
if ( applyDefaults ) {
if ( JoystickCls.IsJSValid( jNum ) ) {
acc.DevInput = ac.defBinding;
cn.Command = ac.defBinding; cn.BackColor = JoystickCls.JsNColor( jNum );
}
}
} else if ( ac.actionDevice == ActionCls.ActionDevice.AD_Gamepad ) {
acc.DevID = GamepadCls.DeviceID;
if ( applyDefaults ) {
if ( !String.IsNullOrEmpty( ac.defBinding ) ) {
acc.DevInput = ac.defBinding;
cn.Command = ac.defBinding; cn.BackColor = GamepadCls.XiColor( );
}
}
} else if ( ac.actionDevice == ActionCls.ActionDevice.AD_Keyboard ) {
acc.DevID = KeyboardCls.DeviceID;
if ( applyDefaults ) {
if ( !String.IsNullOrEmpty( ac.defBinding ) ) {
acc.DevInput = ac.defBinding;
cn.Command = ac.defBinding; cn.BackColor = KeyboardCls.KbdColor( );
}
}
} else if ( ac.actionDevice == ActionCls.ActionDevice.AD_Mouse ) { // 20151220BM: add mouse device (from AC 2.0 defaultProfile usage)
acc.DevID = MouseCls.DeviceID;
if ( applyDefaults ) {
if ( !String.IsNullOrEmpty( ac.defBinding ) ) {
acc.DevInput = ac.defBinding;
cn.Command = ac.defBinding; cn.BackColor = MouseCls.MouseColor( );
}
}
}
}
}//for
tn = new ActionTreeNode( acm.name, cnl ); tn.Name = acm.name; tn.Action = acm.name; // name it to find it..
tn.ImageIndex = 0; tn.NodeFont = FontActionmap; // new Font( m_MasterTree.Font, FontStyle.Bold );
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 = FontActionmap; // new Font( m_MasterTree.Font, FontStyle.Bold );
m_MasterTree.BackColor = m_MasterTree.BackColor; // fix for defect TreeView (cut off bold text)
m_MasterTree.Nodes.Add( tn ); // add to control
m_MasterTree.Nodes.RemoveByKey( "DUMMY" );
// fix for defect TreeView (cut off bold text)
txReader = null;
Dirty = false;
// finally apply the filter and make it visible
ReloadTreeView( ); // performs the complete job..
}
/// <summary>
/// Find the ActivationModes of the selected item
/// </summary>
/// <returns>A ActivationModes list - first element is the default, second the selected Mode</returns>
public ActivationModes ActivationModeSelectedItem( )
{
ActivationModes am = new ActivationModes( ActivationMode.Default, ActivationMode.Default );// policy: get the default first, then the attached one - dummy answer
if ( Ctrl.SelectedNode == null ) return am; // ERROR exit
if ( ( Ctrl.SelectedNode.Level == 0 ) || ( Ctrl.SelectedNode.Level > 2 ) ) return am;
if ( Ctrl.SelectedNode.Parent == null ) return am; // ERROR exit
// has a parent - must be level 1 or 2
if ( Ctrl.SelectedNode.Level == 1 ) {
// this is the main node with Action Cmd
ActionTreeNode atn = ( Ctrl.SelectedNode as ActionTreeNode ); // the treenode from a level 1
ActionCls ac = FindActionObject( atn.Parent.Name, atn.Name ); if ( ac == null ) return am; // ERROR exit
ActionCommandCls acc = ac.FindActionInputObject( ActionTreeNode.CommandFromNodeText( atn.Text ) ); if ( acc == null ) return am; // ERROR exit
am = new ActivationModes( ac.defActivationMode, acc.ActivationMode ); // policy: get the default first, then the attached one
return am;
} else if ( Ctrl.SelectedNode.Level == 2 ) {
// this is a child of an action with further commands
ActionTreeNode patn = ( Ctrl.SelectedNode.Parent as ActionTreeNode ); // the parent treenode
ActionTreeNode atn = ( Ctrl.SelectedNode as ActionTreeNode ); // the treenode from a level 1
// the related action
ActionCls ac = FindActionObject( patn.Parent.Name, patn.Name ); if ( ac == null ) return am; // ERROR exit
ActionCommandCls acc = ac.FindActionInputObject( atn.Index ); if ( acc == null ) return am; // ERROR exit
am = new ActivationModes( ac.defActivationMode, acc.ActivationMode );// policy: get the default first, then the attached one
return am;
}
return am;
}
/// <summary>
/// Update the ActivationMode of the selected item
/// </summary>
public void UpdateActivationModeSelectedItem( string newActivationModeName )
{
if ( Ctrl.SelectedNode == null ) return; // ERROR exit
if ( ( Ctrl.SelectedNode.Level == 0 ) || ( Ctrl.SelectedNode.Level > 2 ) ) return;
if ( Ctrl.SelectedNode.Parent == null ) return; // ERROR exit
// has a parent - must be level 1 or 2
if ( Ctrl.SelectedNode.Level == 1 ) {
// this is the main node with Action Cmd
ActionTreeNode atn = ( Ctrl.SelectedNode as ActionTreeNode ); // the treenode from a level 1
ActionCls ac = FindActionObject( atn.Parent.Name, atn.Name ); if ( ac == null ) return; // ERROR exit
ActionCommandCls acc = ac.FindActionInputObject( ActionTreeNode.CommandFromNodeText( atn.Text ) ); if ( acc == null ) return; // ERROR exit
// new am is either a named one or the Default from Profile (which is the default from the Action due to multiTaps..)
if ( ActivationMode.IsDefault( newActivationModeName ) ) {
acc.ActivationMode = new ActivationMode( ActivationMode.Default );
} else {
acc.ActivationMode = ActivationModes.Instance.ActivationModeByName( newActivationModeName );
}
atn.UpdateAction( acc ); UpdateMasterNode( atn );
Dirty = true;
} else if ( Ctrl.SelectedNode.Level == 2 ) {
// this is a child of an action with further commands
ActionTreeNode patn = ( Ctrl.SelectedNode.Parent as ActionTreeNode ); // the parent treenode from a level 2
ActionTreeNode atn = ( Ctrl.SelectedNode as ActionTreeNode ); // the treenode from a level 2
// the related action
ActionCls ac = FindActionObject( patn.Parent.Name, patn.Name ); if ( ac == null ) return; // ERROR exit
// find it in the sublist
ActionCommandCls acc = ac.FindActionInputObject( atn.Index ); if ( acc == null ) return; // ERROR exit
// new am is either a named one or the Default from Profile (which is the default from the Action due to multiTaps..)
if ( ActivationMode.IsDefault( newActivationModeName ) ) {
acc.ActivationMode = new ActivationMode( ActivationMode.Default );
} else {
acc.ActivationMode = ActivationModes.Instance.ActivationModeByName( newActivationModeName );
}
atn.UpdateAction( acc ); UpdateMasterNode( atn );
Dirty = true;
}
}
// 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 == null ) return false; // ERROR exit
if ( ( Ctrl.SelectedNode.Level == 0 ) || ( Ctrl.SelectedNode.Level > 2 ) ) 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
ActionTreeNode atn = ( Ctrl.SelectedNode as ActionTreeNode ); // the treenode from a level 1
ActionCls ac = FindActionObject( atn.Parent.Name, atn.Name ); // the related action in an actionmap
if ( ac == null ) return false; // ERROR exit
if ( checkKind && ( ac.actionDevice != inKind ) ) return false; // ERROR exit
ActionCommandCls acc = ac.FindActionInputObject( ActionTreeNode.CommandFromNodeText( atn.Text ) );
if ( acc == null ) return false; // ERROR exit
// have it - continue
ac.UpdateCommandFromInput( ActionCls.DevInput( input, inKind ), acc.NodeIndex + 1 );
atn.UpdateAction( acc ); UpdateMasterNode( atn );
Dirty = true;
} else if ( Ctrl.SelectedNode.Level == 2 ) {
// this is a child of an action with further commands
ActionTreeNode patn = ( Ctrl.SelectedNode.Parent as ActionTreeNode ); // the parent treenode from a level 2
ActionTreeNode atn = ( Ctrl.SelectedNode as ActionTreeNode ); // the treenode from a level 2
if ( string.IsNullOrEmpty( input ) )
atn.Action = "UNDEF"; // apply UNDEF
else
atn.Action = ""; // remove UNDEF
ActionCls ac = FindActionObject( patn.Parent.Name, patn.Name ); // the related action in an actionmap
if ( ac == null ) return false; // ERROR exit
if ( checkKind && ( ac.actionDevice != inKind ) ) return false; // ERROR exit
ActionCommandCls acc = ac.FindActionInputObject( atn.Index );
if ( acc == null ) return false; // ERROR exit
// have it - continue
ac.UpdateCommandFromInput( ActionCls.DevInput( input, inKind ), acc.NodeIndex + 1 );
atn.UpdateAction( acc ); UpdateMasterNode( atn );
Dirty = true;
}
return true;
}
/// <summary>
/// Find an action with name in a actionmap
/// </summary>
/// <param name="actionMap">The actionmap name</param>
/// <param name="actionKey">The action</param>
/// <param name="devInput">The input</param>
/// <returns>An actionCommand or null if not found</returns>
private ActionCommandCls FindActionInputObject( String actionMap, String actionKey, String devInput )
{
//log.Debug( "FindActionInputObject - Entry" );
// Apply the input to the ActionTree
ActionCls ac = null; ActionCommandCls acc = null;
ActionMapCls ACM = ActionMaps.Find( delegate( ActionMapCls _ACM ) { return _ACM.name == actionMap; } );
if ( ACM != null ) ac = ACM.Find( delegate ( ActionCls _AC ) { return _AC.key == actionKey; } );
if ( ac != null ) acc = ac.inputList.Find( delegate ( ActionCommandCls _ACC ) { return _ACC.DevInput == devInput; } );
if ( acc == null ) {
log.Error( "FindActionInputObject - Action Input not found in tree" );
return null; // ERROR - Action Input not found in tree
}
return acc;
}
/// <summary>
/// Find an action with name in a actionmap
/// </summary>
/// <param name="actionMap">The actionmap name</param>
/// <param name="actionKey">The action</param>
/// <param name="input">The input</param>
/// <returns>An actionCommand or null if not found</returns>
private ActionCommandCls FindActionInputObject( ActionTree tree, String actionMap, String actionKey, int index )
{
//log.Debug( "FindActionInputObject - Entry" );
// Apply the input to the ActionTree
ActionCls ac = null; ActionCommandCls acc = null;
ActionMapCls ACM = tree.ActionMaps.Find( delegate( ActionMapCls _ACM ) { return _ACM.name == actionMap; } );
if ( ACM != null ) ac = ACM.Find( delegate ( ActionCls _AC ) { return _AC.key == actionKey; } );
if ( ac != null ) acc = ac.inputList.Find( delegate ( ActionCommandCls _ACC ) { return _ACC.NodeIndex == index; } );
if ( acc == null ) {
log.Error( "FindActionInputObject - Action Input not found in tree" );
return null; // ERROR - Action Input not found in tree
}
return acc;
}
/// <summary>
/// Find an action with name in a actionmap
/// </summary>
/// <param name="actionMap">The actionmap name</param>
/// <param name="action">The action</param>
/// <returns>An action or null if not found</returns>
private ActionCls FindActionObject( String actionMap, String action )
{
//log.Debug( "FindActionObject - Entry" );
// Apply the input to the ActionTree
ActionCls ac = null;
ActionMapCls ACM = ActionMaps.Find( delegate( ActionMapCls acm ) { return acm.name == actionMap; } );
if ( ACM != null ) ac = ACM.Find( delegate ( ActionCls _AC ) { return _AC.key == action; } );
if ( ac == null ) {
log.Error( "FindActionObject - Action Not found in tree" );
return null; // ERROR - Action Not found in tree
}
return ac;
}
/// <summary>
/// Defines what to show in the tree
/// </summary>
/// <param name="showJoystick">True to show Joystick actions</param>
/// <param name="showGamepad">True to show Gamepad actions</param>
/// <param name="showKeyboard">True to show Keyboard actions</param>
/// <param name="showMappedOnly">True to show mapped actions only </param>
public void DefineShowOptions( Boolean showJoystick, Boolean showGamepad, Boolean showKeyboard, Boolean showMouse, Boolean showMappedOnly )
{
m_showJoy = showJoystick;
m_showGameP = showGamepad;
m_showKbd = showKeyboard;
m_showMouse = showMouse;
m_showMappedOnly = showMappedOnly;
}
/// <summary>
/// Loads the mappings back into the treeview control
/// Note: this takes a while as the list grows...
/// </summary>
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
// find the item to reload into the treeview
foreach ( ActionCls ac in acm ) {
ActionTreeNode matn = ( ActionTreeNode )mtn.Nodes[ac.key]; // get the action node
Boolean first=true;
// refresh commands
foreach ( ActionCommandCls acc in ac.inputList ) {
try {
ac.UpdateCommandFromInput( acc.DevInput, acc.NodeIndex + 1 ); // this may apply (un)Blending if needed
// the first one goes into the node, further must be created if not existing
if ( first ) {
matn.UpdateAction( acc ); UpdateMasterNode( matn );
matn.Nodes.Clear( ); // clear add childs - those don't persist from newly loaded actionmaps
first = false;
} else {
// have to recreate the action child nodes
ActionTreeInputNode matin = new ActionTreeInputNode( "UNDEF" ); matin.ImageKey = "Add";
acc.NodeIndex = matin.Index; // assign visual reference
matn.Nodes.Add( matin ); // add to master tree
matin.UpdateAction( acc ); UpdateMasterNode( matin );
}
} catch {
; // key not found
}
Dirty = true;
} // foreach
}
} catch {
; // map key not found ??
}
}
// finally apply the filter and make it visible
FilterTree( );
}
/// <summary>
/// Find a control that contains the string and mark it
/// this method is applied to the GUI TreeView only
/// </summary>
/// <param name="m_MasterTree">The string to find</param>
public void FindAndSelectActionKey( String actionmap, String actionKey, int nodeIndex )
{
log.Debug( "FindAndSelectActionKey - Entry" );
foreach ( ActionTreeNode tn in Ctrl.Nodes ) {
if ( String.IsNullOrEmpty( actionmap ) || ( tn.Text == actionmap ) ) {
// have to search nodes of nodes
foreach ( ActionTreeNode stn in tn.Nodes ) {
if ( stn.Name == actionKey ) {
if ( nodeIndex < 0 ) {
Ctrl.SelectedNode = stn;
Ctrl.SelectedNode.EnsureVisible( );
} else {
// have to search nodes of nodes
int ni = 0;
foreach ( ActionTreeInputNode sstn in stn.Nodes ) {
if ( ni++ == nodeIndex ) {
Ctrl.SelectedNode = sstn;
Ctrl.SelectedNode.EnsureVisible( );
return; // exit all loops
}
}
}
return; // exit all loops
}
}
}
}
}
/// <summary>
/// Find a control that contains the string and mark it
/// this method is applied to the GUI TreeView only
/// </summary>
/// <param name="m_MasterTree">The string to find</param>
public void FindAndSelectCtrl( String ctrl )
{
log.Debug( "FindAndSelectCtrl - Entry" );
foreach ( ActionTreeNode tn in Ctrl.Nodes ) {
// have to search nodes of nodes
foreach ( ActionTreeNode stn in tn.Nodes ) {
if ( stn.Text.Contains( ctrl ) ) {
Ctrl.SelectedNode = stn;
Ctrl.SelectedNode.EnsureVisible( );
return; // exit all loops
}
// have to search nodes of nodes
foreach ( ActionTreeInputNode sstn in stn.Nodes ) {
if ( sstn.Text.Contains( ctrl ) ) {
Ctrl.SelectedNode = sstn;
Ctrl.SelectedNode.EnsureVisible( );
return; // exit all loops
}
}
}
}
}
/// <summary>
/// Find a control that contains the string and mark it
/// this method is applied to the GUI TreeView only
/// </summary>
/// <param name="m_MasterTree">The string to find</param>
public void FindAndSelectCtrlByName( String ctrlName )
{
log.Debug( "FindAndSelectCtrlByName - Entry" );
foreach ( ActionTreeNode tn in Ctrl.Nodes ) {
// have to search nodes of nodes
foreach ( ActionTreeNode stn in tn.Nodes ) {
if ( stn.Name == ctrlName ) {
Ctrl.SelectedNode = stn;
Ctrl.SelectedNode.EnsureVisible( );
return; // exit all loops
}
// have to search nodes of nodes
foreach ( ActionTreeInputNode sstn in stn.Nodes ) {
if ( sstn.Name == ctrlName ) {
Ctrl.SelectedNode = sstn;
Ctrl.SelectedNode.EnsureVisible( );
return; // exit all loops
}
}
}
}
}
/// <summary>
/// Find a control that contains the Action (exact match)
/// </summary>
/// <param name="actionmap">The actionmap to find the string</param>
/// <param name="text">The string to find</param>
public String FindActionKey( String actionmap, String actionKey )
{
log.Debug( "FindActionKey - Entry" );
foreach ( ActionTreeNode tn in Ctrl.Nodes ) {
if ( String.IsNullOrEmpty( actionmap ) || ( tn.Text == actionmap ) ) {
// have to search nodes of nodes
foreach ( ActionTreeNode stn in tn.Nodes ) {
if ( stn.Name == actionKey ) {
return stn.Text;
}
}
}
}
return "";
}
/// <summary>
/// Find a control that contains the Action (exact match)
/// </summary>
/// <param name="actionmap">The actionmap to find the string</param>
/// <param name="text">The string to find</param>
public String FindAction( String actionmap, String action )
{
log.Debug( "FindAction - Entry" );
foreach ( ActionTreeNode tn in Ctrl.Nodes ) {
if ( String.IsNullOrEmpty( actionmap ) || ( tn.Text == actionmap ) ) {
// have to search nodes of nodes
foreach ( ActionTreeNode stn in tn.Nodes ) {
if ( stn.Action == action ) {
return stn.Text;
}
}
}
}
return "";
}
/// <summary>
/// Find a control that contains the Action
/// </summary>
/// <param name="text">The string to find</param>
public String FindAction( String action )
{
return FindAction( "", action );
}
/// <summary>
/// Find a control that contains the Command
/// </summary>
/// <param name="actionmap">The actionmap to find the string</param>
/// <param name="text">The string to find</param>
public String FindCommand( String actionmap, String command )
{
log.Debug( "FindCommand - Entry" );
foreach ( ActionTreeNode tn in Ctrl.Nodes ) {
if ( String.IsNullOrEmpty( actionmap ) || ( tn.Text == actionmap ) ) {
// have to search nodes of nodes
foreach ( ActionTreeNode stn in tn.Nodes ) {
foreach ( ActionTreeInputNode istn in stn.Nodes ) {
if ( istn.Command.Contains( command ) ) {
return stn.Text + " - " + istn.Text;
}
}
}
}
}
return "";
}
/// <summary>
/// Find a control that contains the Command
/// </summary>
/// <param name="text">The string to find</param>
public String FindCommand( String command )
{
return FindCommand( "", command );
}
/// <summary>
/// Find a control the the actionmap that contains the Text
/// </summary>
/// <param name="actionmap">The actionmap to find the string</param>
/// <param name="text">The string to find</param>
public String FindText( String actionmap, String text )
{
log.Debug( "FindText - Entry" );
foreach ( ActionTreeNode tn in Ctrl.Nodes ) {
if ( String.IsNullOrEmpty( actionmap ) || ( tn.Text == actionmap ) ) {
// have to search nodes of nodes
foreach ( ActionTreeNode stn in tn.Nodes ) {
if ( stn.Text.Contains( text ) ) {
return stn.Text;
}
}
}
}
return "";
}
/// <summary>
/// Find a control that contains the Text
/// </summary>
/// <param name="text">The string to find</param>
public String FindText( String text )
{
return FindText( "", text );
}
/// <summary>
/// Returns the Action name of the selected item
/// </summary>
public String SelectedAction
{
get {
if ( Ctrl.SelectedNode == null ) return "";
if ( Ctrl.SelectedNode.Level == 1 ) {
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
return ActionTreeNode.ActionFromNodeText( matn.Text );
} else return "";
}
}
/// <summary>
/// Returns the ActionID (DS_ActionMap) of the selected item
/// </summary>
public String SelectedActionID
{
get {
if ( Ctrl.SelectedNode == null ) return "";
if ( ( Ctrl.SelectedNode.Level == 0 ) || ( Ctrl.SelectedNode.Level > 2 ) ) return ""; // ERROR exit
if ( Ctrl.SelectedNode.Parent == null ) return ""; // ERROR exit
// has a parent - must be level 1 or 2
if ( Ctrl.SelectedNode.Level == 1 ) {
// this is the main node with Action Cmd
ActionTreeNode atn = ( Ctrl.SelectedNode as ActionTreeNode ); // the treenode from a level 1
ActionCls ac = FindActionObject( atn.Parent.Name, atn.Name ); // the related action in an actionmap
if ( ac == null ) return ""; // ERROR exit
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 );
return actionID;
} else if ( Ctrl.SelectedNode.Level == 2 ) {
// this is a child of an action with further commands
ActionTreeNode patn = ( Ctrl.SelectedNode.Parent as ActionTreeNode ); // the parent treenode from a level 2
ActionTreeNode atn = ( Ctrl.SelectedNode as ActionTreeNode ); // the treenode from a level 2
ActionCls ac = FindActionObject( patn.Parent.Name, patn.Name ); // the related action in an actionmap
if ( ac == null ) return ""; // ERROR exit
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 );
return actionID;
} else return "";
}
}
/// <summary>
/// Update from all edits in the dataset DS_ActionMaps
/// </summary>/// <param name="dsa">The dataset to update from</param>
/// <returns>returns a null if no changes have been found</returns>
public ActionTree UpdateFromDataSet( DS_ActionMaps dsa )
{
ActionTree nTree = new ActionTree( this.m_jsList, this.m_gamepad ); // just a copy
// 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( new JsReassingList( ) ); // re-use this method with no reassign for full copy of the tree
int countChanges = 0;
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));
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
} else {
; // DEBUG should not happen...
}
}
}
// finally if there were any changes
if ( countChanges > 0 ) {
dsa.AcceptChanges( );
nTree.Dirty = true;
return nTree;
} else {
return null;
}
}
/// <summary>
/// Reports a summary list of the mapped items
/// </summary>
/// <returns></returns>
public String ReportActions( )
{
log.Debug( "FindCtrl - ReportActions" );
String repList = "";
// JS assignments
for ( int i = 0; i < JoystickCls.JSnum_MAX; i++ ) {
if ( !String.IsNullOrEmpty( ActionMaps.jsN[i] ) ) repList += String.Format( "** js{0} = {1}\n", i + 1, ActionMaps.jsN[i] );
}
// now the mapped actions
const int padAction = 42;
const int padDevice = 4;
const int padInput = 25;
repList += String.Format( "\n" );
repList += String.Format( " {0}+- {1} _ {2}#-[{4}] {3}\n\n", "Action".PadRight( padAction ), "Dev".PadRight( padDevice ), "Binding".PadRight( padInput ), "Activation", "T" ); // col description line
foreach ( ActionMapCls acm in ActionMaps ) {
String rep = String.Format( "*** {0}\n", acm.name );
repList += rep;
foreach ( ActionCls ac in acm ) {
foreach ( ActionCommandCls acc in ac.inputList ) {
if ( ShowAction( ac.actionDevice, acc.Input ) ) {
if ( !String.IsNullOrEmpty( acc.Input ) /* && !( acc.Input == DeviceCls.BlendedInput )*/ ) {
if ( acc.DevInput == ac.defBinding ) {
rep = String.Format( " {0} . {1} _ {2}", ac.name.PadRight( padAction ), acc.DevID.PadRight( padDevice ), acc.Input.PadRight( padInput ) );
} else {
rep = String.Format( " {0} + {1} _ {2}", ac.name.PadRight( padAction ), acc.DevID.PadRight( padDevice ), acc.Input.PadRight( padInput ) ); // my binding
}
if ( acc.ActivationMode == ActivationMode.Default ) {
rep += String.Format( " . [{1}] {0}\n", ac.defActivationMode.Name, ac.defActivationMode.MultiTap );
} else {
rep += String.Format( " # [{1}] {0}\n", acc.ActivationMode.Name, acc.ActivationMode.MultiTap );
}
repList += rep;
}
}
}
}
repList += String.Format( "\n" ); // actionmap spacer
}
return repList;
}
/// <summary>
/// Reports a summary list of the mapped items
/// </summary>
/// <returns></returns>
public String ReportActionsCSV( bool listModifiers )
{
log.Debug( "FindCtrl - ReportActions2" );
String repList = "";
// JS assignments
for ( int i = 0; i < JoystickCls.JSnum_MAX; i++ ) {
if ( !String.IsNullOrEmpty( ActionMaps.jsN[i] ) ) repList += String.Format( "** js{0} = {1}\n", i + 1, ActionMaps.jsN[i] );
}
// now the mapped actions
repList += string.Format( "\n" );
repList += "actionmap;action"; // col description line
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";
repList += ";js1-tag;js1-input;js1-mod-tag;js1-mod-mode;js1-mod-multi";
repList += ";js2-tag;js2-input;js2-mod-tag;js2-mod-mode;js2-mod-multi";
repList += ";js3-tag;js3-input;js3-mod-tag;js3-mod-mode;js3-mod-multi";
repList += ";js4-tag;js4-input;js4-mod-tag;js4-mod-mode;js4-mod-multi";
} else {
repList += ";kbd-tag;kbd-input"; // col description line
repList += ";mouse-tag;mouse-input";
repList += ";xpad-tag;xpad-input";
repList += ";js1-tag;js1-input";
repList += ";js2-tag;js2-input";
repList += ";js3-tag;js3-input";
repList += ";js4-tag;js4-input";
}
repList += string.Format( "\n" );
string action = "";
string rep = ""; string kbA = ""; string moA = ""; string xbA = ""; string[] jsA = new string[] { "", "", "", "" };
foreach ( ActionMapCls acm in ActionMaps ) {
foreach ( ActionCls ac in acm ) {
// we get an action for each device class here - sort it out
if ( ac.name != action ) {
// dump if not empty
if ( !string.IsNullOrEmpty( action ) ) {
// compose one action
rep += string.Format( "{0};{1};{2};{3};{4};{5};{6}\n", kbA, moA, xbA, jsA[0], jsA[1], jsA[2], jsA[3] ); // should be one line now
repList += String.Format( "{0}", rep ); // add to list
}
// action changed - restart collection
action = ac.name;
rep = string.Format( "{0};{1};", acm.name, ac.name ); // actionmap; action
// 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 {
kbA = "n.a.;"; // defaults tag;input
}
moA = kbA; xbA = kbA;
jsA = new string[] { kbA, kbA, kbA, kbA };
}
foreach ( ActionCommandCls acc in ac.inputList ) {
// this is for add binds
if ( ShowAction( ac.actionDevice, acc.Input ) ) {
if ( !String.IsNullOrEmpty( acc.Input ) ) {
// set modified - note: don't add trailing semicolons as the are applied in the output formatting
string aTag = "modified"; //default or modified
string aMode = string.Format( "modified;{0};{1}", ac.defActivationMode.Name, ac.defActivationMode.MultiTap );
// change if they are default mappings
if ( acc.DevInput == ac.defBinding ) aTag = "default";
if ( acc.ActivationMode == ActivationMode.Default ) aMode = string.Format( "default;{0};{1}", ac.defActivationMode.Name, ac.defActivationMode.MultiTap );
if ( listModifiers ) {
switch ( ActionCls.ADeviceFromDevID( acc.DevID ) ) {
case ActionCls.ActionDevice.AD_Keyboard: kbA = string.Format( "{0};{1};{2}", aTag, acc.Input, aMode ); break;
case ActionCls.ActionDevice.AD_Mouse: moA = string.Format( "{0};{1};{2}", aTag, acc.Input, aMode ); break;
case ActionCls.ActionDevice.AD_Joystick:
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;
}//switch
} else {
switch ( ActionCls.ADeviceFromDevID( acc.DevID ) ) {
case ActionCls.ActionDevice.AD_Keyboard: kbA = string.Format( "{0};{1}", aTag, acc.Input ); break;
case ActionCls.ActionDevice.AD_Mouse: moA = string.Format( "{0};{1}", aTag, acc.Input ); break;
case ActionCls.ActionDevice.AD_Joystick:
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;
}//switch
}
}
}// show
}// for aCmd
}// for action
}
// add the last one
// compose one action
rep += string.Format( "{0};{1};{2};{3};{4};{5};{6}\n", kbA, moA, xbA, jsA[0], jsA[1], jsA[2], jsA[3] ); // should be one line now
repList += String.Format( "{0}", rep ); // add to list
return repList;
}
}
}