V 2.35 - BETA Build 69 (first save only)

- add - provide CIG asset texts for actions and maps
  (use Settings to choose - for now only French and German are in but have no translations
   for English not all have a proper text - may not be used in the game ??)
- improvement - cache CIG assets into the app/Storage folder, reads from p4k file only if those are updated
- internal cleanup - to many to list
pull/104/head
bm98 6 years ago
parent 66f3d27771
commit 158349474b

@ -10,12 +10,17 @@ namespace SCJMapper_V2
{
sealed class AppSettings : ApplicationSettingsBase, IDisposable
{
FormSettings FS = null;
FormSettings FS = null; // Settings form
public AppSettings( )
// Singleton
private static readonly Lazy<AppSettings> m_lazy = new Lazy<AppSettings>( () => new AppSettings( ) );
public static AppSettings Instance { get => m_lazy.Value; }
private AppSettings( )
{
if ( this.FirstRun ) {
// migrate the settings to the new version if the app runs the rist time
// migrate the settings to the new version if the app runs the first time
try {
this.Upgrade( );
}
@ -23,6 +28,10 @@ namespace SCJMapper_V2
this.FirstRun = false;
this.Save( );
}
if ( string.IsNullOrEmpty( UseLanguage ) ) {
UseLanguage = SC.SCUiText.Languages.profile.ToString( ); // get a default here
this.Save( );
}
}
public void Dispose( bool disposing )
@ -46,7 +55,7 @@ namespace SCJMapper_V2
/// </summary>
public DialogResult ShowSettings( string pasteString )
{
if ( FS == null ) FS = new FormSettings( this );
if ( FS == null ) FS = new FormSettings( );
FS.PasteString = pasteString; // propagate joyinput
FS.ShowDialog( );
return ( FS.Canceled ) ? DialogResult.Cancel : DialogResult.OK;
@ -56,8 +65,8 @@ namespace SCJMapper_V2
#region Setting Properties
// manages Upgrade
[UserScopedSettingAttribute( )]
[DefaultSettingValueAttribute( "True" )]
[UserScopedSetting( )]
[DefaultSettingValue( "True" )]
public bool FirstRun
{
get { return ( bool )this["FirstRun"]; }
@ -66,16 +75,16 @@ namespace SCJMapper_V2
// Control bound settings
[UserScopedSettingAttribute( )]
[DefaultSettingValueAttribute( "1000, 900" )]
[UserScopedSetting( )]
[DefaultSettingValue( "1000, 900" )]
public Size FormSize
{
get { return ( Size )this["FormSize"]; }
set { this["FormSize"] = value; }
}
[UserScopedSettingAttribute( )]
[DefaultSettingValueAttribute( "10, 10" )]
[UserScopedSetting( )]
[DefaultSettingValue( "10, 10" )]
public Point FormLocation
{
get { return ( Point )this["FormLocation"]; }
@ -83,56 +92,56 @@ namespace SCJMapper_V2
}
// User Config Settings
[UserScopedSettingAttribute( )]
[DefaultSettingValueAttribute( "layout_joystick_spacesim" )] // from Game Bundle
[UserScopedSetting( )]
[DefaultSettingValue( "layout_joystick_spacesim" )] // from Game Bundle
public string DefMappingName
{
get { return ( string )this["DefMappingName"]; }
set { this["DefMappingName"] = value; }
}
[UserScopedSettingAttribute( )]
[DefaultSettingValueAttribute( "layout_my_joystick" )] // just a default
[UserScopedSetting( )]
[DefaultSettingValue( "layout_my_joystick" )] // just a default
public string MyMappingName
{
get { return ( string )this["MyMappingName"]; }
set { this["MyMappingName"] = value; }
}
[UserScopedSettingAttribute( )]
[DefaultSettingValueAttribute( "True" )]
[UserScopedSetting( )]
[DefaultSettingValue( "True" )]
public bool ShowJoystick
{
get { return ( bool )this["ShowJoystick"]; }
set { this["ShowJoystick"] = value; }
}
[UserScopedSettingAttribute( )]
[DefaultSettingValueAttribute( "True" )]
[UserScopedSetting( )]
[DefaultSettingValue( "True" )]
public bool ShowGamepad
{
get { return ( bool )this["ShowGamepad"]; }
set { this["ShowGamepad"] = value; }
}
[UserScopedSettingAttribute( )]
[DefaultSettingValueAttribute( "True" )]
[UserScopedSetting( )]
[DefaultSettingValue( "True" )]
public bool ShowKeyboard
{
get { return ( bool )this["ShowKeyboard"]; }
set { this["ShowKeyboard"] = value; }
}
[UserScopedSettingAttribute( )]
[DefaultSettingValueAttribute( "True" )]
[UserScopedSetting( )]
[DefaultSettingValue( "True" )]
public bool ShowMouse // 20151220BM: add mouse device (from AC 2.0 defaultProfile usage)
{
get { return ( bool )this["ShowMouse"]; }
set { this["ShowMouse"] = value; }
}
[UserScopedSettingAttribute( )]
[DefaultSettingValueAttribute( "False" )]
[UserScopedSetting( )]
[DefaultSettingValue( "False" )]
public bool ShowMapped
{
get { return ( bool )this["ShowMapped"]; }
@ -142,120 +151,120 @@ namespace SCJMapper_V2
// Seetings Window
[UserScopedSettingAttribute( )]
[DefaultSettingValueAttribute( "" )]
[UserScopedSetting( )]
[DefaultSettingValue( "" )]
public string IgnoreJS1
{
get { return ( string )this["IgnoreJS1"]; }
set { this["IgnoreJS1"] = value; }
}
[UserScopedSettingAttribute( )]
[DefaultSettingValueAttribute( "" )]
[UserScopedSetting( )]
[DefaultSettingValue( "" )]
public string IgnoreJS2
{
get { return ( string )this["IgnoreJS2"]; }
set { this["IgnoreJS2"] = value; }
}
[UserScopedSettingAttribute( )]
[DefaultSettingValueAttribute( "" )]
[UserScopedSetting( )]
[DefaultSettingValue( "" )]
public string IgnoreJS3
{
get { return ( string )this["IgnoreJS3"]; }
set { this["IgnoreJS3"] = value; }
}
[UserScopedSettingAttribute( )]
[DefaultSettingValueAttribute( "" )]
[UserScopedSetting( )]
[DefaultSettingValue( "" )]
public string IgnoreJS4
{
get { return ( string )this["IgnoreJS4"]; }
set { this["IgnoreJS4"] = value; }
}
[UserScopedSettingAttribute( )]
[DefaultSettingValueAttribute( "" )]
[UserScopedSetting( )]
[DefaultSettingValue( "" )]
public string IgnoreJS5
{
get { return ( string )this["IgnoreJS5"]; }
set { this["IgnoreJS5"] = value; }
}
[UserScopedSettingAttribute( )]
[DefaultSettingValueAttribute( "" )]
[UserScopedSetting( )]
[DefaultSettingValue( "" )]
public string IgnoreJS6
{
get { return ( string )this["IgnoreJS6"]; }
set { this["IgnoreJS6"] = value; }
}
[UserScopedSettingAttribute( )]
[DefaultSettingValueAttribute( "" )]
[UserScopedSetting( )]
[DefaultSettingValue( "" )]
public string IgnoreJS7
{
get { return ( string )this["IgnoreJS7"]; }
set { this["IgnoreJS7"] = value; }
}
[UserScopedSettingAttribute( )]
[DefaultSettingValueAttribute( "" )]
[UserScopedSetting( )]
[DefaultSettingValue( "" )]
public string IgnoreJS8
{
get { return ( string )this["IgnoreJS8"]; }
set { this["IgnoreJS8"] = value; }
}
[UserScopedSettingAttribute( )]
[DefaultSettingValueAttribute( "" )]
[UserScopedSetting( )]
[DefaultSettingValue( "" )]
public string IgnoreJS9
{
get { return ( string )this["IgnoreJS9"]; }
set { this["IgnoreJS9"] = value; }
}
[UserScopedSettingAttribute( )]
[DefaultSettingValueAttribute( "" )]
[UserScopedSetting( )]
[DefaultSettingValue( "" )]
public string IgnoreJS10
{
get { return ( string )this["IgnoreJS10"]; }
set { this["IgnoreJS10"] = value; }
}
[UserScopedSettingAttribute( )]
[DefaultSettingValueAttribute( "" )]
[UserScopedSetting( )]
[DefaultSettingValue( "" )]
public string IgnoreJS11
{
get { return ( string )this["IgnoreJS11"]; }
set { this["IgnoreJS11"] = value; }
}
[UserScopedSettingAttribute( )]
[DefaultSettingValueAttribute( "" )]
[UserScopedSetting( )]
[DefaultSettingValue( "" )]
public string IgnoreJS12
{
get { return ( string )this["IgnoreJS12"]; }
set { this["IgnoreJS12"] = value; }
}
[UserScopedSettingAttribute( )]
[DefaultSettingValueAttribute( "" )]
[UserScopedSetting( )]
[DefaultSettingValue( "" )]
public string UserSCPath
{
get { return ( string )this["UserSCPath"]; }
set { this["UserSCPath"] = value; }
}
[UserScopedSettingAttribute( )]
[DefaultSettingValueAttribute( "False" )]
[UserScopedSetting( )]
[DefaultSettingValue( "False" )]
public bool UserSCPathUsed
{
get { return ( bool )this["UserSCPathUsed"]; }
set { this["UserSCPathUsed"] = value; }
}
[UserScopedSettingAttribute( )]
[DefaultSettingValueAttribute( ",default,multiplayer,singleplayer,player,flycam,vehicle_driver," )] // empty Note: comma separated list, must have a comma at the begining and the end (to find 'player' on its own...)
[UserScopedSetting( )]
[DefaultSettingValue( ",default,multiplayer,singleplayer,player,flycam,vehicle_driver," )] // empty Note: comma separated list, must have a comma at the begining and the end (to find 'player' on its own...)
public string IgnoreActionmaps
{
get { return ( string )this["IgnoreActionmaps"]; }
@ -263,69 +272,77 @@ namespace SCJMapper_V2
}
[UserScopedSettingAttribute( )]
[DefaultSettingValueAttribute( "False" )]
[UserScopedSetting( )]
[DefaultSettingValue( "False" )]
public bool DetectGamepad
{
get { return ( bool )this["DetectGamepad"]; }
set { this["DetectGamepad"] = value; }
}
[UserScopedSettingAttribute( )]
[DefaultSettingValueAttribute( "False" )]
[UserScopedSetting( )]
[DefaultSettingValue( "False" )]
public bool UsePTU
{
get { return false; } // ( bool )this["UsePTU"]; } no longer used
set { this["UsePTU"] = value; }
}
[UserScopedSettingAttribute( )]
[DefaultSettingValueAttribute( "False" )]
[UserScopedSetting( )]
[DefaultSettingValue( "False" )]
public bool UseCSVListing
{
get { return ( bool )this["UseCSVListing"]; }
set { this["UseCSVListing"] = value; }
}
[UserScopedSettingAttribute( )]
[DefaultSettingValueAttribute( "False" )]
[UserScopedSetting( )]
[DefaultSettingValue( "False" )]
public bool ListModifiers
{
get { return ( bool )this["ListModifiers"]; }
set { this["ListModifiers"] = value; }
}
[UserScopedSettingAttribute( )]
[DefaultSettingValueAttribute( "False" )]
[UserScopedSetting( )]
[DefaultSettingValue( "False" )]
public bool AutoTabXML
{
get { return (bool)this["AutoTabXML"]; }
set { this["AutoTabXML"] = value; }
}
[UserScopedSetting( )]
[DefaultSettingValue( "profile" )]
public string UseLanguage
{
get { return (string)this["UseLanguage"]; }
set { this["UseLanguage"] = value; }
}
//**** Form Table
// Control bound settings
[UserScopedSettingAttribute( )]
[DefaultSettingValueAttribute( "1000, 900" )]
[UserScopedSetting( )]
[DefaultSettingValue( "1000, 900" )]
public Size FormTableSize
{
get { return ( Size )this["FormTableSize"]; }
set { this["FormTableSize"] = value; }
}
[UserScopedSettingAttribute( )]
[DefaultSettingValueAttribute( "760, 320" )]
[UserScopedSetting( )]
[DefaultSettingValue( "760, 320" )]
public Point FormTableLocation
{
get { return ( Point )this["FormTableLocation"]; }
set { this["FormTableLocation"] = value; }
}
[UserScopedSettingAttribute( )]
[DefaultSettingValueAttribute( "" )]
[UserScopedSetting( )]
[DefaultSettingValue( "" )]
public string FormTableColumnWidth
{
get { return ( string )this["FormTableColumnWidth"]; }

@ -20,7 +20,6 @@ namespace SCJMapper_V2.Devices.Gamepad
public class GamepadCls : DeviceCls
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod( ).DeclaringType );
private static readonly AppSettings appSettings = new AppSettings( );
#region Static Items
@ -311,7 +310,7 @@ namespace SCJMapper_V2.Devices.Gamepad
private void ApplySettings_low()
{
appSettings.Reload( );
AppSettings.Instance.Reload( );
}

@ -20,7 +20,6 @@ namespace SCJMapper_V2.Devices.Joystick
public class JoystickCls : DeviceCls
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger( MethodBase.GetCurrentMethod( ).DeclaringType );
private static readonly AppSettings appSettings = new AppSettings( );
#region Static Items
@ -520,24 +519,24 @@ namespace SCJMapper_V2.Devices.Joystick
private void ApplySettings_low( )
{
appSettings.Reload( );
AppSettings.Instance.Reload( );
ResetButtons( m_ignoreButtons );
// read ignore buttons
string igs = "";
switch ( m_joystickNumber ) {
case 1: igs = appSettings.IgnoreJS1; break;
case 2: igs = appSettings.IgnoreJS2; break;
case 3: igs = appSettings.IgnoreJS3; break;
case 4: igs = appSettings.IgnoreJS4; break;
case 5: igs = appSettings.IgnoreJS5; break;
case 6: igs = appSettings.IgnoreJS6; break;
case 7: igs = appSettings.IgnoreJS7; break;
case 8: igs = appSettings.IgnoreJS8; break;
case 9: igs = appSettings.IgnoreJS9; break;
case 10: igs = appSettings.IgnoreJS10; break;
case 11: igs = appSettings.IgnoreJS11; break;
case 12: igs = appSettings.IgnoreJS12; break;
case 1: igs = AppSettings.Instance.IgnoreJS1; break;
case 2: igs = AppSettings.Instance.IgnoreJS2; break;
case 3: igs = AppSettings.Instance.IgnoreJS3; break;
case 4: igs = AppSettings.Instance.IgnoreJS4; break;
case 5: igs = AppSettings.Instance.IgnoreJS5; break;
case 6: igs = AppSettings.Instance.IgnoreJS6; break;
case 7: igs = AppSettings.Instance.IgnoreJS7; break;
case 8: igs = AppSettings.Instance.IgnoreJS8; break;
case 9: igs = AppSettings.Instance.IgnoreJS9; break;
case 10: igs = AppSettings.Instance.IgnoreJS10; break;
case 11: igs = AppSettings.Instance.IgnoreJS11; break;
case 12: igs = AppSettings.Instance.IgnoreJS12; break;
default: break;
}
if ( string.IsNullOrWhiteSpace( igs ) ) return; // no setting - all allowed

@ -20,7 +20,6 @@ namespace SCJMapper_V2.Devices.Mouse
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod( ).DeclaringType );
private static readonly AppSettings appSettings = new AppSettings( );
#region Static Items

@ -231,8 +231,8 @@ namespace SCJMapper_V2.Devices.Options
{
// populate from input
// something like "v_pitch - js1_x" OR "v_pitch - xi_thumbl" OR "v_pitch - ximod+xi_thumbl+xi_mod"
string cmd = ActionTreeNode.CommandFromNodeText( NodeText );
m_action = ActionTreeNode.ActionFromNodeText( NodeText );
string cmd = ActionTreeNode.CommandFromActionText( NodeText );
m_action = ActionTreeNode.ActionFromActionText( NodeText );
m_cmdCtrl = "";
if ( !string.IsNullOrWhiteSpace( cmd ) ) {
// decomp gamepad entries - could have modifiers so check for contains...

@ -20,7 +20,6 @@
if ( disposing && ( components != null ) ) components.Dispose( );
if ( disposing && ( m_AT != null ) ) m_AT.Dispose( );
if ( disposing && ( m_AppSettings != null ) ) m_AppSettings.Dispose( );
base.Dispose( disposing );
}

@ -29,7 +29,6 @@ namespace SCJMapper_V2
private const string c_GithubLink = @"https://github.com/SCToolsfactory/SCJMapper-V2/releases";
private AppSettings m_AppSettings = new AppSettings( );
private bool m_appLoading = true; // used to detect if we are loading (or running)
// keyboard modifier handling variables
@ -76,7 +75,8 @@ namespace SCJMapper_V2
// catch if the Tag is not an int...
try {
return ( (int)page.Tag == ID_GAMEPAD_TAB );
} catch {
}
catch {
return false;
}
}
@ -124,7 +124,7 @@ namespace SCJMapper_V2
private void AutoTabXML_Assignment( EATabXML tab )
{
if ( m_AppSettings.AutoTabXML ) {
if ( AppSettings.Instance.AutoTabXML ) {
if ( tcXML.SelectedIndex != (int)tab ) {
tcXML.SelectedTab = tcXML.TabPages[(int)tab];
if ( tab == EATabXML.Tab_Assignment )
@ -133,10 +133,10 @@ namespace SCJMapper_V2
}
}
private void UpdateDDMapping(string mapName )
private void UpdateDDMapping( string mapName )
{
msSelectMapping.Text = mapName;
m_AppSettings.DefMappingName = mapName; m_AppSettings.Save( );
AppSettings.Instance.DefMappingName = mapName; AppSettings.Instance.Save( );
}
@ -151,8 +151,9 @@ namespace SCJMapper_V2
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" ) ) );
} catch {
this.Icon = ( (Icon)( resources.GetObject( "$this.Icon" ) ) );
}
catch {
; // well...
}
@ -211,8 +212,8 @@ namespace SCJMapper_V2
// some applic initialization
// Assign Size property, since databinding to Size doesn't work well.
this.Size = m_AppSettings.FormSize;
this.Location = m_AppSettings.FormLocation;
this.Size = AppSettings.Instance.FormSize;
this.Location = AppSettings.Instance.FormLocation;
string version = Application.ProductVersion; // get the version information
// BETA VERSION; TODO - comment out if not longer
@ -231,16 +232,22 @@ namespace SCJMapper_V2
rtb.DragDrop += new DragEventHandler( rtb_DragDrop );
rtb.AllowDrop = true; // add Drop to rtb
// load languages
SCUiText.Instance.Language = SCUiText.Languages.profile;
if ( Enum.TryParse( AppSettings.Instance.UseLanguage, out SCUiText.Languages lang ) ) {
SCUiText.Instance.Language = lang;
}
// load mappings
log.Debug( "Loading Mappings" );
LoadMappingDD( );
msSelectMapping.Text = m_AppSettings.DefMappingName;
msSelectMapping.Text = AppSettings.Instance.DefMappingName;
SCFileIndication( );
// load other defaults
log.Debug( "Loading Other" );
txMappingName.Text = m_AppSettings.MyMappingName;
txMappingName.Text = AppSettings.Instance.MyMappingName;
SetRebindField( txMappingName.Text );
foreach ( ToolStripDropDownItem d in msSelectMapping.DropDownItems ) {
if ( d.Text == txMappingName.Text ) {
@ -261,7 +268,7 @@ namespace SCJMapper_V2
rtb.LoadFile( SCMappings.MappingFileName( txMappingName.Text ), RichTextBoxStreamType.PlainText );
InitActionTree( false );
Grab( );
m_AppSettings.MyMappingName = txMappingName.Text; m_AppSettings.Save( );// last used - persist
AppSettings.Instance.MyMappingName = txMappingName.Text; AppSettings.Instance.Save( );// last used - persist
txMappingName.BackColor = MyColors.SuccessColor;
}
else {
@ -280,11 +287,11 @@ namespace SCJMapper_V2
// load show checkboxes
cbxShowJoystick.Checked = m_AppSettings.ShowJoystick;
cbxShowGamepad.Checked = m_AppSettings.ShowGamepad;
cbxShowKeyboard.Checked = m_AppSettings.ShowKeyboard;
cbxShowMouse.Checked = m_AppSettings.ShowMouse;
cbxShowMappedOnly.Checked = m_AppSettings.ShowMapped;
cbxShowJoystick.Checked = AppSettings.Instance.ShowJoystick;
cbxShowGamepad.Checked = AppSettings.Instance.ShowGamepad;
cbxShowKeyboard.Checked = AppSettings.Instance.ShowKeyboard;
cbxShowMouse.Checked = AppSettings.Instance.ShowMouse;
cbxShowMappedOnly.Checked = AppSettings.Instance.ShowMapped;
// init current Joystick
int jsIndex = (int)tc1.SelectedTab.Tag; // gets the index into the JS list
@ -292,14 +299,14 @@ namespace SCJMapper_V2
// init PTU folder usage sign
//lblPTU.Visible = false; // m_AppSettings.UsePTU; no longer used
if ( m_AppSettings.UsePTU ) log.Debug( "Using PTU Folders" );
if ( AppSettings.Instance.UsePTU ) log.Debug( "Using PTU Folders" );
// Auto Tab XML
cbxAutoTabXML.Checked = m_AppSettings.AutoTabXML;
cbxAutoTabXML.Checked = AppSettings.Instance.AutoTabXML;
// poll the XInput
log.Debug( "Start XInput polling" );
timer1_Tick( null,null );
timer1_Tick( null, null );
timer1.Start( ); // this one polls the joysticks to show the props
@ -385,7 +392,8 @@ namespace SCJMapper_V2
backBrush.Dispose( );
foreBrush.Dispose( );
}
} catch ( Exception Ex ) {
}
catch ( Exception Ex ) {
log.Error( "Ex DrawItem", Ex );
MessageBox.Show( Ex.Message.ToString( ), "Error Occured", MessageBoxButtons.OK, MessageBoxIcon.Information );
}
@ -410,12 +418,12 @@ namespace SCJMapper_V2
}
m_AT = new ActionTree( );
log.DebugFormat( "InitActionTree - New AT: {0}", m_AT.GetHashCode().ToString() );
log.DebugFormat( "InitActionTree - New AT: {0}", m_AT.GetHashCode( ).ToString( ) );
m_AT.NodeSelectedEvent += M_AT_NodeSelectedEvent; // connect the Event
m_AT.Ctrl = treeView1; // the ActionTree owns the TreeView control
m_AT.IgnoreMaps = m_AppSettings.IgnoreActionmaps;
m_AT.IgnoreMaps = AppSettings.Instance.IgnoreActionmaps;
// provide the display items (init)
m_AT.DefineShowOptions( cbxShowJoystick.Checked, cbxShowGamepad.Checked, cbxShowKeyboard.Checked, cbxShowMouse.Checked, cbxShowMappedOnly.Checked );
// Init with default profile filepath
@ -480,7 +488,8 @@ namespace SCJMapper_V2
log.Debug( "Get Mouse device" );
DeviceInst.MouseInst = new MouseCls( new SharpDX.DirectInput.Mouse( directInput ), this );
} catch ( Exception ex ) {
}
catch ( Exception ex ) {
log.Debug( "InitDirectInput phase 1 failed unexpectedly", ex );
return false;
}
@ -496,7 +505,7 @@ namespace SCJMapper_V2
log.InfoFormat( "GameControl: Type:{0} Device:{1}", instance.Type.ToString( ), instance.ProductName );
// Create the device interface
log.Debug( "Create the device interface" );
if ( m_AppSettings.DetectGamepad && ( instance.Usage == SharpDX.Multimedia.UsageId.GenericGamepad ) ) {
if ( AppSettings.Instance.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++ ) {
dxGamepad = new SharpDX.XInput.Controller( i );
@ -515,7 +524,8 @@ namespace SCJMapper_V2
log.DebugFormat( "Create the device interface for: {0}", myJs.prodName );
}
}
} catch ( Exception ex ) {
}
catch ( Exception ex ) {
log.Debug( "InitDirectInput phase 2 failed unexpectedly", ex );
return false;
}
@ -643,7 +653,8 @@ namespace SCJMapper_V2
// get the text into the view
try {
rtb.ScrollToCaret( );
} catch {
}
catch {
; // just ignore
}
UpdateTable( );
@ -681,19 +692,19 @@ namespace SCJMapper_V2
{
log.Debug( "MainForm_FormClosing - Entry" );
m_AppSettings.FormSize = this.Size;
m_AppSettings.FormLocation = this.Location;
AppSettings.Instance.FormSize = this.Size;
AppSettings.Instance.FormLocation = this.Location;
if ( FTAB != null ) {
m_AppSettings.FormTableLocation = FTAB.LastLocation;
m_AppSettings.FormTableSize = FTAB.LastSize;
m_AppSettings.FormTableColumnWidth = FTAB.LastColSize;
AppSettings.Instance.FormTableLocation = FTAB.LastLocation;
AppSettings.Instance.FormTableSize = FTAB.LastSize;
AppSettings.Instance.FormTableColumnWidth = FTAB.LastColSize;
FTAB.Close( );
FTAB = null;
}
m_AppSettings.Save( );
AppSettings.Instance.Save( );
}
@ -773,9 +784,9 @@ namespace SCJMapper_V2
m_AT.ReloadTreeView( );
if ( m_appLoading ) return; // don't assign while loading defaults
m_AppSettings.ShowJoystick = cbxShowJoystick.Checked; m_AppSettings.ShowGamepad = cbxShowGamepad.Checked;
m_AppSettings.ShowKeyboard = cbxShowKeyboard.Checked; m_AppSettings.ShowMouse = cbxShowMouse.Checked;
m_AppSettings.ShowMapped = cbxShowMappedOnly.Checked;
AppSettings.Instance.ShowJoystick = cbxShowJoystick.Checked; AppSettings.Instance.ShowGamepad = cbxShowGamepad.Checked;
AppSettings.Instance.ShowKeyboard = cbxShowKeyboard.Checked; AppSettings.Instance.ShowMouse = cbxShowMouse.Checked;
AppSettings.Instance.ShowMapped = cbxShowMappedOnly.Checked;
}
@ -784,7 +795,7 @@ namespace SCJMapper_V2
private void btFind_Click( object sender, EventArgs e )
{
m_AT.FindAndSelectCtrl( JoystickCls.MakeThrottle( lblLastJ.Text, cbxThrottle.Checked ) , ""); // find the action for a Control (joystick input)
m_AT.FindAndSelectCtrl( JoystickCls.MakeThrottle( lblLastJ.Text, cbxThrottle.Checked ), "" ); // find the action for a Control (joystick input)
}
private void btAssign_Click( object sender, EventArgs e )
@ -843,7 +854,7 @@ namespace SCJMapper_V2
private void cbxAutoTabXML_CheckedChanged( object sender, EventArgs e )
{
m_AppSettings.AutoTabXML = cbxAutoTabXML.Checked; m_AppSettings.Save( );
AppSettings.Instance.AutoTabXML = cbxAutoTabXML.Checked; AppSettings.Instance.Save( );
}
// Toolstrip Items
@ -872,8 +883,8 @@ namespace SCJMapper_V2
{
AutoTabXML_Assignment( EATabXML.Tab_XML );
if ( m_AppSettings.UseCSVListing )
rtb.Text = string.Format( "-- {0} - SC Joystick Mapping --\n{1}", DateTime.Now, m_AT.ReportActionsCSV( m_AppSettings.ListModifiers ) );
if ( AppSettings.Instance.UseCSVListing )
rtb.Text = string.Format( "-- {0} - SC Joystick Mapping --\n{1}", DateTime.Now, m_AT.ReportActionsCSV( AppSettings.Instance.ListModifiers ) );
else
rtb.Text = string.Format( "-- {0} - SC Joystick Mapping --\n{1}", DateTime.Now, m_AT.ReportActions( ) );
}
@ -909,9 +920,9 @@ namespace SCJMapper_V2
}
if ( FTAB.Visible ) {
m_AppSettings.FormTableSize = FTAB.LastSize;
m_AppSettings.FormTableLocation = FTAB.LastLocation;
m_AppSettings.FormTableColumnWidth = FTAB.LastColSize;
AppSettings.Instance.FormTableSize = FTAB.LastSize;
AppSettings.Instance.FormTableLocation = FTAB.LastLocation;
AppSettings.Instance.FormTableColumnWidth = FTAB.LastColSize;
FTAB.Hide( );
}
@ -919,9 +930,9 @@ namespace SCJMapper_V2
FTAB.Show( );
if ( created ) {
FTAB.Size = m_AppSettings.FormTableSize;
FTAB.Location = m_AppSettings.FormTableLocation;
FTAB.LastColSize = m_AppSettings.FormTableColumnWidth;
FTAB.Size = AppSettings.Instance.FormTableSize;
FTAB.Location = AppSettings.Instance.FormTableLocation;
FTAB.LastColSize = AppSettings.Instance.FormTableColumnWidth;
}
// reload the data to display
UpdateTable( );
@ -939,7 +950,7 @@ namespace SCJMapper_V2
UpdateMoreOptionItems( );
DeviceList devlist = new DeviceList( );
if ( m_AppSettings.DetectGamepad && ( DeviceInst.GamepadRef != null ) ) {
if ( AppSettings.Instance.DetectGamepad && ( DeviceInst.GamepadRef != null ) ) {
devlist.Add( DeviceInst.GamepadRef );
}
devlist.AddRange( DeviceInst.JoystickListRef );
@ -983,16 +994,19 @@ namespace SCJMapper_V2
{
// have to stop polling while the Settings window is open
timer1.Enabled = false;
if ( m_AppSettings.ShowSettings( "" ) != System.Windows.Forms.DialogResult.Cancel ) {
m_AppSettings.Reload( ); // must reload in case of any changes in the form
if ( AppSettings.Instance.ShowSettings( "" ) != DialogResult.Cancel ) {
AppSettings.Instance.Reload( ); // must reload in case of any changes in the form
// then reload the profile and mappings
LoadMappingDD( );
// indicates (in)valid folders
SCFileIndication( );
// change language if needed
if ( Enum.TryParse( AppSettings.Instance.UseLanguage, out SCUiText.Languages lang ) ) {
SCUiText.Instance.Language = lang;
}
// now update the contents according to new settings
foreach ( JoystickCls j in DeviceInst.JoystickListRef ) j.ApplySettings( ); // update Seetings
m_AT.IgnoreMaps = m_AppSettings.IgnoreActionmaps;
m_AT.IgnoreMaps = AppSettings.Instance.IgnoreActionmaps;
// and start over with an empty tree
InitActionTree( false );
UpdateTable( );
@ -1045,10 +1059,10 @@ namespace SCJMapper_V2
{
// start over
InitActionTree( true );
rtb.Text = SCMappings.Mapping( m_AppSettings.DefMappingName );
rtb.Text = SCMappings.Mapping( AppSettings.Instance.DefMappingName );
Grab( );
if ( SCMappings.IsUserMapping( m_AppSettings.DefMappingName ) ) {
txMappingName.Text = m_AppSettings.DefMappingName;
if ( SCMappings.IsUserMapping( AppSettings.Instance.DefMappingName ) ) {
txMappingName.Text = AppSettings.Instance.DefMappingName;
SetRebindField( txMappingName.Text );
}
btDump.BackColor = MyColors.DirtyColor;
@ -1059,9 +1073,9 @@ namespace SCJMapper_V2
{
// start over
InitActionTree( false );
rtb.Text = SCMappings.Mapping( m_AppSettings.DefMappingName );
if ( SCMappings.IsUserMapping( m_AppSettings.DefMappingName ) ) {
txMappingName.Text = m_AppSettings.DefMappingName;
rtb.Text = SCMappings.Mapping( AppSettings.Instance.DefMappingName );
if ( SCMappings.IsUserMapping( AppSettings.Instance.DefMappingName ) ) {
txMappingName.Text = AppSettings.Instance.DefMappingName;
SetRebindField( txMappingName.Text );
}
Grab( );
@ -1070,10 +1084,10 @@ namespace SCJMapper_V2
private void meLoadAndGrab_Click( object sender, EventArgs e )
{
rtb.Text = SCMappings.Mapping( m_AppSettings.DefMappingName );
rtb.Text = SCMappings.Mapping( AppSettings.Instance.DefMappingName );
Grab( );
if ( SCMappings.IsUserMapping( m_AppSettings.DefMappingName ) ) {
txMappingName.Text = m_AppSettings.DefMappingName;
if ( SCMappings.IsUserMapping( AppSettings.Instance.DefMappingName ) ) {
txMappingName.Text = AppSettings.Instance.DefMappingName;
SetRebindField( txMappingName.Text );
}
btDump.BackColor = MyColors.DirtyColor;
@ -1082,9 +1096,9 @@ namespace SCJMapper_V2
private void meLoad_Click( object sender, EventArgs e )
{
rtb.Text = SCMappings.Mapping( m_AppSettings.DefMappingName );
if ( SCMappings.IsUserMapping( m_AppSettings.DefMappingName ) ) {
txMappingName.Text = m_AppSettings.DefMappingName;
rtb.Text = SCMappings.Mapping( AppSettings.Instance.DefMappingName );
if ( SCMappings.IsUserMapping( AppSettings.Instance.DefMappingName ) ) {
txMappingName.Text = AppSettings.Instance.DefMappingName;
SetRebindField( txMappingName.Text );
}
btGrab.BackColor = MyColors.DirtyColor;
@ -1346,7 +1360,7 @@ namespace SCJMapper_V2
// get the new one into the list
LoadMappingDD( );
UpdateDDMapping( txMappingName.Text );
m_AppSettings.MyMappingName = txMappingName.Text; m_AppSettings.Save( );// last used - persist
AppSettings.Instance.MyMappingName = txMappingName.Text; AppSettings.Instance.Save( );// last used - persist
txMappingName.BackColor = MyColors.SuccessColor;
}
}
@ -1407,11 +1421,11 @@ namespace SCJMapper_V2
string find = "";
// find action item for Joysticks
find = ActionTreeNode.ComposeNodeText( action, "js" );
find = ActionTreeNode.ComposeNodeActionText( action, "js" );
nodeText = m_AT.FindText( actionmap, find ); // returns "" or a complete text ("action - command")
if ( !string.IsNullOrWhiteSpace( nodeText ) ) {
if ( !Act.IsDisabledInput( ActionTreeNode.CommandFromNodeText( nodeText ) ) ) {
dev = DeviceInst.JoystickListRef.Find_jsN( JoystickCls.JSNum( ActionTreeNode.CommandFromNodeText( nodeText ) ) );
if ( !Act.IsDisabledInput( ActionTreeNode.CommandFromActionText( nodeText ) ) ) {
dev = DeviceInst.JoystickListRef.Find_jsN( JoystickCls.JSNum( ActionTreeNode.CommandFromActionText( nodeText ) ) );
if ( dev != null ) {
// find the tuning item of the action
string toID = Tuningoptions.TuneOptionIDfromJsN( JoystickCls.DeviceClass, dev.XmlInstance );
@ -1423,10 +1437,10 @@ namespace SCJMapper_V2
if ( dev == null ) {
// nothing found? find action item for GPads
find = ActionTreeNode.ComposeNodeText( action, "xi" );
find = ActionTreeNode.ComposeNodeActionText( action, "xi" );
nodeText = m_AT.FindText( actionmap, find );
if ( !string.IsNullOrWhiteSpace( nodeText ) ) {
if ( !Act.IsDisabledInput( ActionTreeNode.CommandFromNodeText( nodeText ) ) ) {
if ( !Act.IsDisabledInput( ActionTreeNode.CommandFromActionText( nodeText ) ) ) {
dev = DeviceInst.GamepadRef;
if ( dev != null ) {
// find the tuning item of the action
@ -1527,7 +1541,7 @@ namespace SCJMapper_V2
UpdateOptionItem( "turret_aim_pitch", "v_aim_pitch", "spaceship_turret" );
UpdateOptionItem( "turret_aim_yaw", "v_aim_yaw", "spaceship_turret" );
}

@ -64,6 +64,8 @@
this.btCancel = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();
this.groupBox4 = new System.Windows.Forms.GroupBox();
this.label14 = new System.Windows.Forms.Label();
this.comboLanguage = new System.Windows.Forms.ComboBox();
this.cbxAutoTabXML = new System.Windows.Forms.CheckBox();
this.cbxListModifiers = new System.Windows.Forms.CheckBox();
this.cbxCSVListing = new System.Windows.Forms.CheckBox();
@ -425,6 +427,8 @@
//
// groupBox4
//
this.groupBox4.Controls.Add(this.label14);
this.groupBox4.Controls.Add(this.comboLanguage);
this.groupBox4.Controls.Add(this.cbxAutoTabXML);
this.groupBox4.Controls.Add(this.cbxListModifiers);
this.groupBox4.Controls.Add(this.cbxCSVListing);
@ -438,6 +442,24 @@
this.groupBox4.TabStop = false;
this.groupBox4.Text = "Advanced Options ...";
//
// label14
//
this.label14.AutoSize = true;
this.label14.Location = new System.Drawing.Point(200, 22);
this.label14.Name = "label14";
this.label14.Size = new System.Drawing.Size(62, 13);
this.label14.TabIndex = 12;
this.label14.Text = "Language:";
//
// comboLanguage
//
this.comboLanguage.FormattingEnabled = true;
this.comboLanguage.Location = new System.Drawing.Point(271, 19);
this.comboLanguage.Name = "comboLanguage";
this.comboLanguage.Size = new System.Drawing.Size(100, 21);
this.comboLanguage.TabIndex = 11;
this.comboLanguage.SelectedIndexChanged += new System.EventHandler(this.comboLanguage_SelectedIndexChanged);
//
// cbxAutoTabXML
//
this.cbxAutoTabXML.AutoSize = true;
@ -566,5 +588,7 @@
private System.Windows.Forms.CheckBox cbxCSVListing;
private System.Windows.Forms.CheckBox cbxListModifiers;
private System.Windows.Forms.CheckBox cbxAutoTabXML;
private System.Windows.Forms.Label label14;
private System.Windows.Forms.ComboBox comboLanguage;
}
}

@ -13,9 +13,6 @@ namespace SCJMapper_V2
{
partial class FormSettings : Form
{
private readonly AppSettings m_owner = null; // owner class - access to settings
public bool Canceled { get; set; }
public string PasteString { get; set; } // used to copy, paste JS commands
@ -24,10 +21,9 @@ namespace SCJMapper_V2
/// ctor - gets the owning class instance
/// </summary>
/// <param name="owner"></param>
public FormSettings( AppSettings owner )
public FormSettings( )
{
InitializeComponent( );
m_owner = owner;
}
@ -37,6 +33,10 @@ namespace SCJMapper_V2
for ( int i = 0; i < ActionMapsCls.ActionMaps.Length; i++ ) {
chkLbActionMaps.Items.Add( ActionMapsCls.ActionMaps[i] );
}
comboLanguage.Items.Clear( );
comboLanguage.Items.AddRange( SC.SCUiText.Instance.LanguagesS.ToArray() );
LoadSettings( );
}
@ -45,26 +45,26 @@ namespace SCJMapper_V2
private void LoadSettings( )
{
// SC path
txSCPath.Text = m_owner.UserSCPath;
cbxUsePath.Checked = m_owner.UserSCPathUsed;
txSCPath.Text = AppSettings.Instance.UserSCPath;
cbxUsePath.Checked = AppSettings.Instance.UserSCPathUsed;
//Ignore Buttons
txJS1.Text = m_owner.IgnoreJS1;
txJS2.Text = m_owner.IgnoreJS2;
txJS3.Text = m_owner.IgnoreJS3;
txJS4.Text = m_owner.IgnoreJS4;
txJS5.Text = m_owner.IgnoreJS5;
txJS6.Text = m_owner.IgnoreJS6;
txJS7.Text = m_owner.IgnoreJS7;
txJS8.Text = m_owner.IgnoreJS8;
txJS9.Text = m_owner.IgnoreJS9;
txJS10.Text = m_owner.IgnoreJS10;
txJS11.Text = m_owner.IgnoreJS11;
txJS12.Text = m_owner.IgnoreJS12;
txJS1.Text = AppSettings.Instance.IgnoreJS1;
txJS2.Text = AppSettings.Instance.IgnoreJS2;
txJS3.Text = AppSettings.Instance.IgnoreJS3;
txJS4.Text = AppSettings.Instance.IgnoreJS4;
txJS5.Text = AppSettings.Instance.IgnoreJS5;
txJS6.Text = AppSettings.Instance.IgnoreJS6;
txJS7.Text = AppSettings.Instance.IgnoreJS7;
txJS8.Text = AppSettings.Instance.IgnoreJS8;
txJS9.Text = AppSettings.Instance.IgnoreJS9;
txJS10.Text = AppSettings.Instance.IgnoreJS10;
txJS11.Text = AppSettings.Instance.IgnoreJS11;
txJS12.Text = AppSettings.Instance.IgnoreJS12;
// Ignore actionmaps
for ( int i = 0; i < chkLbActionMaps.Items.Count; i++ ) {
if ( m_owner.IgnoreActionmaps.Contains( "," + chkLbActionMaps.Items[i].ToString( ) + "," ) ) {
if ( AppSettings.Instance.IgnoreActionmaps.Contains( "," + chkLbActionMaps.Items[i].ToString( ) + "," ) ) {
chkLbActionMaps.SetItemChecked( i, true );
} else {
chkLbActionMaps.SetItemChecked( i, false ); // 20161223: fix checked items and Canceled
@ -72,19 +72,21 @@ namespace SCJMapper_V2
}
// DetectGamepad
cbxDetectGamepad.Checked = m_owner.DetectGamepad;
cbxDetectGamepad.Checked = AppSettings.Instance.DetectGamepad;
// Use PTU
cbxPTU.Checked = m_owner.UsePTU;
m_owner.UsePTU = false; // no longer used
cbxPTU.Checked = AppSettings.Instance.UsePTU;
AppSettings.Instance.UsePTU = false; // no longer used
// AutoTabXML
cbxAutoTabXML.Checked = m_owner.AutoTabXML;
cbxAutoTabXML.Checked = AppSettings.Instance.AutoTabXML;
// Use CSV Listing
cbxCSVListing.Checked = m_owner.UseCSVListing;
cbxListModifiers.Checked = m_owner.ListModifiers;
cbxCSVListing.Checked = AppSettings.Instance.UseCSVListing;
cbxListModifiers.Checked = AppSettings.Instance.ListModifiers;
// Language
comboLanguage.SelectedItem = AppSettings.Instance.UseLanguage;
}
@ -92,22 +94,22 @@ namespace SCJMapper_V2
private void SaveSettings( )
{
// SC path
m_owner.UserSCPath = txSCPath.Text;
m_owner.UserSCPathUsed = cbxUsePath.Checked;
AppSettings.Instance.UserSCPath = txSCPath.Text;
AppSettings.Instance.UserSCPathUsed = cbxUsePath.Checked;
//Ignore Buttons
m_owner.IgnoreJS1 = txJS1.Text;
m_owner.IgnoreJS2 = txJS2.Text;
m_owner.IgnoreJS3 = txJS3.Text;
m_owner.IgnoreJS4 = txJS4.Text;
m_owner.IgnoreJS5 = txJS5.Text;
m_owner.IgnoreJS6 = txJS6.Text;
m_owner.IgnoreJS7 = txJS7.Text;
m_owner.IgnoreJS8 = txJS8.Text;
m_owner.IgnoreJS9 = txJS9.Text;
m_owner.IgnoreJS10 = txJS10.Text;
m_owner.IgnoreJS11 = txJS11.Text;
m_owner.IgnoreJS12 = txJS12.Text;
AppSettings.Instance.IgnoreJS1 = txJS1.Text;
AppSettings.Instance.IgnoreJS2 = txJS2.Text;
AppSettings.Instance.IgnoreJS3 = txJS3.Text;
AppSettings.Instance.IgnoreJS4 = txJS4.Text;
AppSettings.Instance.IgnoreJS5 = txJS5.Text;
AppSettings.Instance.IgnoreJS6 = txJS6.Text;
AppSettings.Instance.IgnoreJS7 = txJS7.Text;
AppSettings.Instance.IgnoreJS8 = txJS8.Text;
AppSettings.Instance.IgnoreJS9 = txJS9.Text;
AppSettings.Instance.IgnoreJS10 = txJS10.Text;
AppSettings.Instance.IgnoreJS11 = txJS11.Text;
AppSettings.Instance.IgnoreJS12 = txJS12.Text;
// Ignore actionmaps
string ignore = ",";
@ -116,28 +118,31 @@ namespace SCJMapper_V2
ignore += chkLbActionMaps.Items[i].ToString( ) + ",";
}
}
m_owner.IgnoreActionmaps = ignore;
AppSettings.Instance.IgnoreActionmaps = ignore;
// DetectGamepad
if ( m_owner.DetectGamepad != cbxDetectGamepad.Checked ) {
if ( AppSettings.Instance.DetectGamepad != cbxDetectGamepad.Checked ) {
MessageBox.Show( "Changing the Gamepad option needs a restart of the application !!", "Settings Notification", MessageBoxButtons.OK, MessageBoxIcon.Information );
}
m_owner.DetectGamepad = cbxDetectGamepad.Checked;
AppSettings.Instance.DetectGamepad = cbxDetectGamepad.Checked;
//// Use PTU
//if ( m_owner.UsePTU != cbxPTU.Checked ) {
//if ( AppSettings.Instance.UsePTU != cbxPTU.Checked ) {
// MessageBox.Show( "Changing to / from PTU folders needs a restart of the application !!", "Settings Notification", MessageBoxButtons.OK, MessageBoxIcon.Information );
//}
//m_owner.UsePTU = cbxPTU.Checked; // no longer used
//AppSettings.Instance.UsePTU = cbxPTU.Checked; // no longer used
// AutoTabXML
m_owner.AutoTabXML = cbxAutoTabXML.Checked;
AppSettings.Instance.AutoTabXML = cbxAutoTabXML.Checked;
// Use CSV Listing
m_owner.UseCSVListing = cbxCSVListing.Checked;
m_owner.ListModifiers = cbxListModifiers.Checked;
AppSettings.Instance.UseCSVListing = cbxCSVListing.Checked;
AppSettings.Instance.ListModifiers = cbxListModifiers.Checked;
m_owner.Save( );
// Language
AppSettings.Instance.UseLanguage = (string)comboLanguage.SelectedItem;
AppSettings.Instance.Save( );
}
@ -201,6 +206,9 @@ namespace SCJMapper_V2
}
}
private void comboLanguage_SelectedIndexChanged( object sender, EventArgs e )
{
}
}
}

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

@ -1,10 +1,10 @@
SC Joystick Mapper V 2.34 - Build 68 BETA
(c) Cassini, StandardToaster - 26-Dec-2017
SC Joystick Mapper V 2.35 - Build 69 BETA
(c) Cassini, StandardToaster - 05-Jan-2018
Contains 12 files + graphics:
SCJMapper.exe The program (V2.34)
SCJMapper.exe.config Program config (V2.34) - MUST be in the same folder as the Exe file
SCJMapper.exe The program (V2.35)
SCJMapper.exe.config Program config (V2.35) - MUST be in the same folder as the Exe file
SharpDX.DirectInput.dll Managed DirectInput Assembly - MUST be in the same folder as the Exe file
SharpDX.dll Managed DirectX Assembly - MUST be in the same folder as the Exe file
OpenTK.dll Managed OpenGL Assembly - MUST be in the same folder as the Exe file
@ -15,12 +15,12 @@ x86/libzstd.dll Native dll for ZstdNet (v2.33) - MUST be in th
log4net.dll Managed Logging Assembly - MUST be in the same folder as the Exe file
log4net.config.OFF Config file for logging - To use it - rename as log4net.config and run the program
then look for trace.log in the same folder
SCJMapper_QGuide V2.30beta.pdf Quick Guide
SCJMapper_QGuide V2.34beta.pdf Quick Guide (v2.34)
ReadMe.txt This file
graphics folder Skybox Images (V2.32) - graphics folder MUST be in the same folder as the Exe file
NOTE V 2.34:
NOTE V 2.35:
search order for defaultProfile.xml to build the action tree is:
1. directory where SCJMapper Exe is located
2. directory of <SC>\LIVE\USER
@ -40,6 +40,12 @@ Scanned for viruses before packing...
cassini@burri-web.org
Changelog:
V 2.35 - BETA Build 69
- add - provide CIG asset texts for actions and maps
(use Settings to choose - for now only French and German are in but have no translations
for English not all have a proper text - may not be used in the game ??)
- improvement - cache CIG assets into the app/Storage folder, reads from p4k file only if those are updated
- internal cleanup - to many to list
V 2.34 - BETA Build 68
- improvement - complete rework of XML defaultProfile/mapping parsing
- add - provide CIG mappings from game assets

@ -29,6 +29,7 @@ namespace SCJMapper_V2.SC
class ProfileAction
{
public string Name { get; set; } // the action name
public string UILabel { get; set; } // the action name translated
public string DevID { get; set; } // the input method K,J,X,P
private string m_defBinding = ""; // NOTE: this is AC1 style in the Profile - need to conver later when dumping out
public string DefBinding { get { return m_defBinding; } set { m_defBinding = value; } } // DONT! need to clean this one, found spaces...
@ -44,6 +45,7 @@ namespace SCJMapper_V2.SC
class ActionMap : List<ProfileAction> // carries the action list
{
public string Name { get; set; } // the map name
public string UILabel { get; set; } // the map label
static int ContainsLoop( List<ProfileAction> list, string value )
{
@ -95,6 +97,9 @@ namespace SCJMapper_V2.SC
/// <summary>
/// Returns the collected actionmaps as CSV (same format as MappingVars)
/// i.e. one line per actionmap where the first element is the actionmap and following are actions;defaultBinding lead by the input Key in uppercase (JKXP)
///
/// actmap;actmaplabel;action;actionlabel;defBinding;defActMode;defActMultitap;
///
/// </summary>
public string CSVMap
{
@ -103,9 +108,11 @@ namespace SCJMapper_V2.SC
string buf = "";
foreach ( ActionMap am in m_aMap.Values ) {
buf += am.Name + ";";
buf += am.Name + ";"+ am.UILabel + ";";
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.UILabel + ";"
+ a.DefBinding + ";"
+ a.DefActivationMode.Name + ";" + a.DefActivationMode.MultiTap.ToString( ) + ";"; // add default binding + activation mode to the CSV
}
buf += string.Format( "\n" );
}
@ -208,12 +215,15 @@ namespace SCJMapper_V2.SC
bool retVal = true;
string name = (string)action.Attribute( "name" );
string uiLabel = (string)action.Attribute( "UILabel" );
if ( string.IsNullOrEmpty( uiLabel ) )
uiLabel = name; // subst if not found in Action node
// prep all kinds
var jAC = new ProfileAction( ) { Name = name, DevID = Act.DevTag( JoystickCls.DeviceClass ) };
var kAC = new ProfileAction( ) { Name = name, DevID = Act.DevTag( KeyboardCls.DeviceClass ) };
var mAC = new ProfileAction( ) { Name = name, DevID = Act.DevTag( MouseCls.DeviceClass ) };
var xAC = new ProfileAction( ) { Name = name, DevID = Act.DevTag( GamepadCls.DeviceClass ) };
var jAC = new ProfileAction( ) { Name = name, UILabel = uiLabel, DevID = Act.DevTag( JoystickCls.DeviceClass ) };
var kAC = new ProfileAction( ) { Name = name, UILabel = uiLabel, DevID = Act.DevTag( KeyboardCls.DeviceClass ) };
var mAC = new ProfileAction( ) { Name = name, UILabel = uiLabel, DevID = Act.DevTag( MouseCls.DeviceClass ) };
var xAC = new ProfileAction( ) { Name = name, UILabel = uiLabel, DevID = Act.DevTag( GamepadCls.DeviceClass ) };
// process element items
JInput( ref jAC, action, (string)action.Attribute( JoystickCls.DeviceClass ) );
@ -291,11 +301,14 @@ namespace SCJMapper_V2.SC
// check for a valid one
string mapName = (string)actionmap.Attribute( "name" ); // mandatory
string uiLabel = (string)actionmap.Attribute( "UILabel" );
if ( string.IsNullOrEmpty( uiLabel ) )
uiLabel = mapName; // subst if not found in Action node
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_currentMap = new ActionMap { Name = mapName, UILabel = uiLabel };
if ( !m_aMap.ContainsKey( mapName ) ) { //20170325 - fix multiple map names - don't add the second, third etc. (CIG bug..)
m_aMap.Add( mapName, m_currentMap ); // add to our inventory
IEnumerable<XElement> actions = from x in actionmap.Elements( )
@ -421,7 +434,7 @@ namespace SCJMapper_V2.SC
where ( x.Name == "actionmap" )
select x;
foreach ( XElement actionmap in actionmaps ) {
aml.AddActionMap( (string)actionmap.Attribute("name") );
aml.AddActionMap( (string)actionmap.Attribute( "name" ) );
}
}
}

@ -69,10 +69,8 @@ namespace SCJMapper_V2.SC
}
}
// PTU 3.0 those cannot longer work - but let them in for a while
// third try to get the SC defaultProfile from the Data.p4k
retVal = ExtractDefaultBinProfileP4k( DefaultProfileName );
// third try to get the SC defaultProfile from the Data.p4k TODO
retVal = SCFiles.Instance.DefaultProfile;
if ( !string.IsNullOrEmpty( retVal ) ) {
UsedDefProfile = "GamePack defaultProfile";
log.InfoFormat( "- Use {0}", UsedDefProfile );
@ -89,47 +87,6 @@ namespace SCJMapper_V2.SC
}
/// <summary>
/// Zip Extracts the file to a string
/// SC Alpha 2.2: Have to find the new one in E:\G\StarCitizen\StarCitizen\LIVE\Data.p4k (contains the binary XML now)
/// </summary>
static private string ExtractDefaultBinProfileP4k( string defaultProfileName )
{
log.Debug( "ExtractDefaultBinProfileP4k - Entry" );
string retVal = "";
if ( File.Exists( SCPath.SCData_p4k ) ) {
try {
var PD = new p4kFile.p4kDirectory( );
p4kFile.p4kFile p4K = PD.ScanDirectoryFor( SCPath.SCData_p4k, defaultProfileName );
if ( p4K != null ) {
byte[] fContent = PD.GetFile( SCPath.SCData_p4k, p4K );
// use the binary XML reader
CryXmlNodeRef ROOT = null;
CryXmlBinReader.EResult readResult = CryXmlBinReader.EResult.Error;
CryXmlBinReader cbr = new CryXmlBinReader( );
ROOT = cbr.LoadFromBuffer( fContent, out readResult );
if ( readResult == CryXmlBinReader.EResult.Success ) {
XmlTree tree = new XmlTree( );
tree.BuildXML( ROOT );
retVal = tree.XML_string;
}
else {
log.ErrorFormat( " Error in CryXmlBinReader: {0}", cbr.GetErrorDescription( ) );
retVal = ""; // clear any remanents
}
}
}
catch ( Exception ex ) {
log.Error( " Unexpected ", ex );
}
}
return retVal;
}
}

@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SCJMapper_V2.SC
{
/// <summary>
/// One SC asset file
/// </summary>
///
[Serializable()]
class SCFile
{
public enum FileType
{
UnknownFile = -1,
PakFile = 0,
DefProfile = 1,
MapFile=2,
LangFile=3,
}
public FileType Filetype { get; set; }
public string Filename { get; set; }
public string Filepath { get; set; }
public DateTime FileDateTime { get; set; }
public string Filedata { get; set; }
public SCFile()
{
Filetype = FileType.UnknownFile;
Filename = "";
Filepath = "";
FileDateTime = new DateTime( 1970, 1, 1, 0, 0, 0 );
Filedata = "";
}
}
}

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SCJMapper_V2.SC
{
class SCLocale : Dictionary<string,string>
{
public string Language { get; set; } // easier for debuging if knowing the expected language
public SCLocale(string lang )
{
Language = lang;
}
}
}

@ -18,7 +18,7 @@ namespace SCJMapper_V2.SC
private const string c_UserMapStartsWith = c_MapStartsWith + "my_"; // we only allow those mapping names
static private List<string> m_scMappings = new List<string>( );
static private SCGameMaps m_scGameMaps = new SCGameMaps( );
static private SCGameMaps m_scGameMaps = new SCGameMaps( ); // only one instance allowed... else we read it multiple times from the pak file
/// <summary>
/// Returns true if a mapping file exists

@ -13,7 +13,6 @@ namespace SCJMapper_V2.SC
class SCPath
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod( ).DeclaringType );
private static readonly AppSettings appSettings = new AppSettings( );
private static bool hasInformed = false; // prevent msgbox chains..
@ -74,12 +73,12 @@ namespace SCJMapper_V2.SC
{
get {
log.Debug( "SCBasePath - Entry" );
appSettings.Reload( ); // local instance - reload as it might be changed outside
AppSettings.Instance.Reload( ); // local instance - reload as it might be changed outside
string scp = "";
// User setting has Prio
if ( appSettings.UserSCPathUsed ) {
scp = appSettings.UserSCPath;
if ( AppSettings.Instance.UserSCPathUsed ) {
scp = AppSettings.Instance.UserSCPath;
log.InfoFormat( "SCBasePath - user defined folder given: {0}", scp );
#if DEBUG
//***************************************

@ -0,0 +1,115 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SCJMapper_V2.p4kFile;
namespace SCJMapper_V2.SC
{
sealed class SCUiText
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod( ).DeclaringType );
public enum Languages
{
profile = 0, // use profile texts
english, // must be the one used in the game assets.. Data\Localization\<lang>
french,
german
// ADD more if available
}
private SCLocale[] m_locales = { new SCLocale( Languages.profile.ToString( ) ), // creates an empty one and will return the default(profile string) later
new SCLocale( Languages.english.ToString( ) ),
new SCLocale( Languages.french.ToString( ) ),
new SCLocale( Languages.german.ToString( ) ) }; // add supported languages
private Languages m_language = Languages.english;
/// <summary>
/// Set the language to be used
/// </summary>
public Languages Language { get => m_language; set => m_language = value; }
public IList<string> LanguagesS
{
get {
List<string> list = new List<string>( );
foreach ( SCLocale l in m_locales ) {
list.Add( l.Language );
}
return list;
}
}
// Singleton
private static readonly Lazy<SCUiText> m_lazy = new Lazy<SCUiText>( () => new SCUiText( ) );
public static SCUiText Instance { get => m_lazy.Value; }
/// <summary>
/// Load all languages from Assets
/// like: dfm_crusader_port_olisar=Port Olisar
/// </summary>
public SCUiText()
{
foreach ( string fileKey in SCFiles.Instance.LangFiles ) {
string lang = Path.GetFileNameWithoutExtension( fileKey );
// check if it is a valid language
if ( Enum.TryParse( lang, out Languages fileLang ) ) {
string fContent = SCFiles.Instance.LangFile( fileKey );
using ( TextReader sr = new StringReader( fContent ) ) {
string line = sr.ReadLine( );
while ( line != null ) {
int epo = line.IndexOf( '=' );
string tag = "";
string content = "";
if ( epo >= 0 ) {
tag = line.Substring( 0, epo );
if ( line.Length >= ( epo + 1 ) ) {
content = line.Substring( epo + 1 );
}
if ( tag.StartsWith( "ui_C" ) ) {
// seems all strings we may need are ui_Cxyz
m_locales[(int)fileLang].Add( "@" + tag, content ); // cAT is prepending the tags
}
}
line = sr.ReadLine( );
}// while
}
}
}// all files
}
/// <summary>
/// Returns the content from the UILabel in the set Language
/// </summary>
/// <param name="UILabel">The UILabel from defaultProfile</param>
/// <param name="defaultS">A default string to return if the label cannot be found</param>
/// <returns>A text string</returns>
public string Text( string UILabel, string defaultS )
{
try {
string retVal = "";
if ( m_locales[(int)m_language].ContainsKey( UILabel ) ) {
retVal = m_locales[(int)m_language][UILabel];
}
//if ( string.IsNullOrEmpty( retVal ) )
// if ( m_locales[(int)Languages.english].ContainsKey( UILabel ) ) {
// retVal = m_locales[(int)Languages.english][UILabel]; // fallback to english
// }
if ( string.IsNullOrEmpty( retVal ) )
retVal = defaultS; // final fallback to default
return retVal;
}
catch {
log.Error( "SCLocale - Language not valid ??!!" );
}
return defaultS;
}
}
}

@ -0,0 +1,430 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using SCJMapper_V2.CryXMLlib;
using SCJMapper_V2.p4kFile;
using static SCJMapper_V2.SC.SCUiText;
using System.IO.Compression;
namespace SCJMapper_V2.SC
{
/// <summary>
/// Manages all SC files from Pak
/// tracks the filedate to update only if needed
/// </summary>
class SCFiles
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod( ).DeclaringType );
private SCFile m_pakFile; // no content, carries only the filedate
private SCFile m_defProfile;
private Dictionary<string, SCFile> m_mapFiles;
private Dictionary<string, SCFile> m_langFiles;
// Singleton
private static readonly Lazy<SCFiles> m_lazy = new Lazy<SCFiles>( () => new SCFiles( ) );
public static SCFiles Instance { get => m_lazy.Value; }
private SCFiles()
{
UpdatePack( );
}
public string DefaultProfile { get => m_defProfile.Filedata; }
public IList<string> MapFiles
{
get => m_mapFiles.Keys.ToList( );
}
public string MapFile( string filekey )
{
if ( m_mapFiles.ContainsKey( filekey ) ) {
return m_mapFiles[filekey].Filedata;
}
return "";
}
public IList<string> LangFiles
{
get => m_langFiles.Keys.ToList( );
}
public string LangFile( string filekey )
{
if ( m_langFiles.ContainsKey( filekey ) ) {
return m_langFiles[filekey].Filedata;
}
return "";
}
/// <summary>
/// Zip Extracts the file to a string
/// SC Alpha 2.2: Have to find the new one in E:\G\StarCitizen\StarCitizen\LIVE\Data.p4k (contains the binary XML now)
/// </summary>
static private string ExtractDefaultBinProfileP4k( string defaultProfileName )
{
log.Debug( "ExtractDefaultBinProfileP4k - Entry" );
string retVal = "";
if ( File.Exists( SCPath.SCData_p4k ) ) {
try {
var PD = new p4kFile.p4kDirectory( );
p4kFile.p4kFile p4K = PD.ScanDirectoryFor( SCPath.SCData_p4k, defaultProfileName );
if ( p4K != null ) {
byte[] fContent = PD.GetFile( SCPath.SCData_p4k, p4K );
// use the binary XML reader
CryXmlNodeRef ROOT = null;
CryXmlBinReader.EResult readResult = CryXmlBinReader.EResult.Error;
CryXmlBinReader cbr = new CryXmlBinReader( );
ROOT = cbr.LoadFromBuffer( fContent, out readResult );
if ( readResult == CryXmlBinReader.EResult.Success ) {
XmlTree tree = new XmlTree( );
tree.BuildXML( ROOT );
retVal = tree.XML_string;
}
else {
log.ErrorFormat( " Error in CryXmlBinReader: {0}", cbr.GetErrorDescription( ) );
retVal = ""; // clear any remanents
}
}
}
catch ( Exception ex ) {
log.Error( " Unexpected ", ex );
}
}
return retVal;
}
/// <summary>
/// Update from p4k (treats is like never read..)
/// </summary>
private void UpdatePakFile()
{
if ( File.Exists( SCPath.SCData_p4k ) ) {
m_pakFile.Filetype = SCFile.FileType.PakFile;
m_pakFile.Filename = Path.GetFileName( SCPath.SCData_p4k );
m_pakFile.Filepath = Path.GetDirectoryName( SCPath.SCData_p4k );
m_pakFile.FileDateTime = File.GetLastWriteTime( SCPath.SCData_p4k );
m_pakFile.Filedata = "DUMMY CONTENT ONLY"; // not really used
}
}
/// <summary>
/// Update from the pack file (treats is like never read..)
/// </summary>
private void UpdateDefProfileFile()
{
log.Info( "UpdateDefProfileFile - Entry" );
string retVal = "";
if ( File.Exists( SCPath.SCData_p4k ) ) {
try {
var PD = new p4kFile.p4kDirectory( );
p4kFile.p4kFile p4K = PD.ScanDirectoryFor( SCPath.SCData_p4k, SCDefaultProfile.DefaultProfileName );
if ( p4K != null ) {
byte[] fContent = PD.GetFile( SCPath.SCData_p4k, p4K );
// use the binary XML reader
CryXmlNodeRef ROOT = null;
CryXmlBinReader.EResult readResult = CryXmlBinReader.EResult.Error;
CryXmlBinReader cbr = new CryXmlBinReader( );
ROOT = cbr.LoadFromBuffer( fContent, out readResult );
if ( readResult == CryXmlBinReader.EResult.Success ) {
XmlTree tree = new XmlTree( );
tree.BuildXML( ROOT );
retVal = tree.XML_string;
// make our file - only this one gets a new one
m_defProfile.Filetype = SCFile.FileType.DefProfile;
m_defProfile.Filename = Path.GetFileName( p4K.Filename );
m_defProfile.Filepath = Path.GetDirectoryName( p4K.Filename );
m_defProfile.FileDateTime = p4K.FileModifyDate;
m_defProfile.Filedata = retVal;
log.Info( "UpdateDefProfileFile - read from pak file" );
}
else {
log.ErrorFormat( "UpdateDefProfileFile - Error in CryXmlBinReader: {0}", cbr.GetErrorDescription( ) );
retVal = ""; // clear any remanents
}
}
}
catch ( Exception ex ) {
log.Error( "UpdateDefProfileFile - Unexpected ", ex );
}
}
}
/// <summary>
/// Update all map files from the pak file (treats is like never read..)
/// </summary>
private void UpdateMapFiles()
{
log.Info( "UpdateMapFiles - Entry" );
if ( File.Exists( SCPath.SCData_p4k ) ) {
try {
var PD = new p4kDirectory( );
IList<p4kFile.p4kFile> fileList = PD.ScanDirectoryContaining( SCPath.SCData_p4k, @"Data\Libs\Config\Mappings\layout_" );
foreach ( p4kFile.p4kFile file in fileList ) {
byte[] fContent = PD.GetFile( SCPath.SCData_p4k, file );
// use the binary XML reader
CryXmlNodeRef ROOT = null;
CryXmlBinReader.EResult readResult = CryXmlBinReader.EResult.Error;
CryXmlBinReader cbr = new CryXmlBinReader( );
ROOT = cbr.LoadFromBuffer( fContent, out readResult );
if ( readResult == CryXmlBinReader.EResult.Success ) {
XmlTree tree = new XmlTree( );
tree.BuildXML( ROOT );
// make our file - only this one gets a new one
SCFile obj = new SCFile {
Filetype = SCFile.FileType.MapFile,
Filename = Path.GetFileName( file.Filename ),
Filepath = Path.GetDirectoryName( file.Filename ),
FileDateTime = file.FileModifyDate,
Filedata = tree.XML_string
};
// replace
if ( m_mapFiles.ContainsKey( obj.Filename ) )
m_mapFiles.Remove( obj.Filename );
m_mapFiles.Add( obj.Filename, obj );
log.InfoFormat( "UpdateMapFiles - read from pak file {0}", obj.Filename );
}
else {
log.ErrorFormat( "UpdateMapFiles - Error in CryXmlBinReader: {0}", cbr.GetErrorDescription( ) );
}
}
}
catch ( Exception ex ) {
log.Error( "UpdateMapFiles - Unexpected ", ex );
}
}
}
/// <summary>
/// Update all language files from the pak file (treats is like never read..)
/// </summary>
private void UpdateLangFiles()
{
log.Info( "UpdateLangFiles - Entry" );
if ( File.Exists( SCPath.SCData_p4k ) ) {
try {
var PD = new p4kDirectory( );
IList<p4kFile.p4kFile> fileList = PD.ScanDirectoryContaining( SCPath.SCData_p4k, @"\global.ini" );
foreach ( p4kFile.p4kFile file in fileList ) {
string retVal = "";
string lang = Path.GetFileNameWithoutExtension( Path.GetDirectoryName( file.Filename ) );
if ( Enum.TryParse( lang, out Languages fileLang ) ) {
byte[] fContent = PD.GetFile( SCPath.SCData_p4k, file );
using ( TextReader sr = new StringReader( Encoding.UTF8.GetString( fContent ) ) ) {
string line = sr.ReadLine( );
while ( line != null ) {
// try to get only valid lines
int epo = line.IndexOf( '=' );
string tag = "";
string content = "";
if ( epo >= 0 ) {
tag = line.Substring( 0, epo );
if ( line.Length >= ( epo + 1 ) ) {
content = line.Substring( epo + 1 );
}
if ( tag.StartsWith( "ui_C" ) ) {
// seems all strings we may need are ui_Cxyz
retVal += string.Format( "{0}\n", line );
}
}
line = sr.ReadLine( );
}// while
}//using
// make our file - only this one gets a new one
SCFile obj = new SCFile {
Filetype = SCFile.FileType.LangFile,
Filename = Path.GetFileName( lang.ToLowerInvariant( ) ), // all files are named global.ini so we take the directory name (language)
Filepath = Path.GetDirectoryName( file.Filename ),
FileDateTime = file.FileModifyDate,
Filedata = retVal
};
// replace
if ( m_langFiles.ContainsKey( obj.Filename ) )
m_langFiles.Remove( obj.Filename );
m_langFiles.Add( obj.Filename, obj );
log.InfoFormat( "UpdateLangFiles - read from pak file {0}", obj.Filename );
}
}// all files
}
catch ( Exception ex ) {
log.Error( "UpdateLangFiles - Unexpected ", ex );
}
}
}
/// <summary>
/// Load all SC assets from the local stored files
/// avoiding to read through the p4k files at each startup
/// </summary>
private void LoadPack()
{
// make sure we have valid but empty ones
m_pakFile = new SCFile( );
m_defProfile = new SCFile( );
m_mapFiles = new Dictionary<string, SCFile>( );
m_langFiles = new Dictionary<string, SCFile>( );
if ( !Directory.Exists( TheUser.FileStoreDir ) )
return; // EXIT - no files to read from - first time maybe or deleted
// catch any serializing error
try {
IEnumerable<string> filelist = Directory.EnumerateFiles( TheUser.FileStoreDir, "*.scj" );
foreach ( string file in filelist ) {
SCFile obj = new SCFile( );
using ( Stream stream = File.Open( file, FileMode.Open ) ) {
using ( var gZipStream = new GZipStream( stream, CompressionMode.Decompress ) ) {
BinaryFormatter binaryFormatter = new BinaryFormatter( );
obj = (SCFile)binaryFormatter.Deserialize( gZipStream );
}
stream.Close( );
if ( obj.Filetype == SCFile.FileType.PakFile ) {
m_pakFile = obj;
}
else if ( obj.Filetype == SCFile.FileType.DefProfile ) {
m_defProfile = obj;
}
else if ( obj.Filetype == SCFile.FileType.MapFile ) {
m_mapFiles.Add( obj.Filename, obj );
}
else if ( obj.Filetype == SCFile.FileType.LangFile ) {
m_langFiles.Add( obj.Filename, obj );
}
}
}
}
catch ( Exception e ) {
log.Error( "LoadPack - deserialization error:", e );
return; // ERROR EXIT - cannot read
}
}
/// <summary>
/// Save all assets to a local store
/// </summary>
private void SavePack()
{
if ( m_pakFile.Filetype != SCFile.FileType.PakFile ) {
log.Error( "SavePack - no valid data to save?? " );
return; // nothing to save ??
}
// make sure we have a folder to write to
try {
if ( !Directory.Exists( TheUser.FileStoreDir ) )
Directory.CreateDirectory( TheUser.FileStoreDir );
}
catch ( Exception e ) {
log.Error( "SavePack - create dir error:", e );
return; // ERROR EXIT - cannot create a dir to write to
}
// catch any serializing error
try {
// save p4k reference for the filedate
using ( Stream stream = File.Open( Path.Combine( TheUser.FileStoreDir, m_pakFile.Filename + ".scj" ), FileMode.Create ) ) {
using ( var gZipStream = new GZipStream( stream, CompressionMode.Compress ) ) {
BinaryFormatter binaryFormatter = new BinaryFormatter( );
binaryFormatter.Serialize( gZipStream, m_pakFile );
}
stream.Close( );
}
if ( m_defProfile.Filetype == SCFile.FileType.DefProfile ) {
using ( Stream stream = File.Open( Path.Combine( TheUser.FileStoreDir, m_defProfile.Filename + ".scj" ), FileMode.Create ) ) {
using ( var gZipStream = new GZipStream( stream, CompressionMode.Compress ) ) {
BinaryFormatter binaryFormatter = new BinaryFormatter( );
binaryFormatter.Serialize( gZipStream, m_defProfile );
}
stream.Close( );
}
}
foreach ( KeyValuePair<string, SCFile> kv in m_mapFiles ) {
if ( kv.Value.Filetype == SCFile.FileType.MapFile ) {
using ( Stream stream = File.Open( Path.Combine( TheUser.FileStoreDir, kv.Value.Filename + ".scj" ), FileMode.Create ) ) {
using ( var gZipStream = new GZipStream( stream, CompressionMode.Compress ) ) {
BinaryFormatter binaryFormatter = new BinaryFormatter( );
binaryFormatter.Serialize( gZipStream, kv.Value );
}
stream.Close( );
}
}
}
foreach ( KeyValuePair<string, SCFile> kv in m_langFiles ) {
if ( kv.Value.Filetype == SCFile.FileType.LangFile ) {
using ( Stream stream = File.Open( Path.Combine( TheUser.FileStoreDir, kv.Value.Filename + ".scj" ), FileMode.Create ) ) {
using ( var gZipStream = new GZipStream( stream, CompressionMode.Compress ) ) {
BinaryFormatter binaryFormatter = new BinaryFormatter( );
binaryFormatter.Serialize( gZipStream, kv.Value );
}
stream.Close( );
}
}
}
}
catch ( Exception e ) {
log.Error( "SavePack - serialization error:", e );
return; // ERROR EXIT - cannot write
}
}
/// <summary>
/// Checks if the p4k has changed since last read
/// </summary>
/// <returns>True if the p4k file is newer than the saved data</returns>
private bool NeedsUpdate()
{
bool pakUpdated = true; // need to read
// check pak and see if we had read it already
if ( m_pakFile.Filetype == SCFile.FileType.PakFile ) {
// seems we have read and saved some files at least once
if ( File.Exists( SCPath.SCData_p4k ) ) {
DateTime dateTime = File.GetLastWriteTime( SCPath.SCData_p4k );
pakUpdated = ( dateTime > m_pakFile.FileDateTime );
}
}
return pakUpdated;
}
/// <summary>
/// Load the asset files from the local store and reloads from p4k if needed only
/// </summary>
private void UpdatePack()
{
LoadPack( ); // get the lastest ones
// either we have files or not...
if ( NeedsUpdate( ) == false ) return; // EXIT without update
UpdatePakFile( );
UpdateDefProfileFile( );
UpdateMapFiles( );
UpdateLangFiles( );
SavePack( ); // save the latest collection
}
}
}

@ -12,41 +12,15 @@ namespace SCJMapper_V2.SC
/// <summary>
/// Maintains the game mappings contained in the p4k file
/// </summary>
public class SCGameMaps: SortedList<string, string>
public class SCGameMaps : SortedList<string, string>
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod( ).DeclaringType );
public SCGameMaps()
{
if ( File.Exists( SCPath.SCData_p4k ) ) {
try {
var PD = new p4kDirectory( );
IList<p4kFile.p4kFile> fileList = PD.ScanDirectoryContaining( SCPath.SCData_p4k, @"Data\Libs\Config\Mappings\layout_" );
foreach (p4kFile.p4kFile file in fileList ) {
byte[] fContent = PD.GetFile( SCPath.SCData_p4k, file );
// use the binary XML reader
CryXmlNodeRef ROOT = null;
CryXmlBinReader.EResult readResult = CryXmlBinReader.EResult.Error;
CryXmlBinReader cbr = new CryXmlBinReader( );
ROOT = cbr.LoadFromBuffer( fContent, out readResult );
if ( readResult == CryXmlBinReader.EResult.Success ) {
XmlTree tree = new XmlTree( );
tree.BuildXML( ROOT );
this.Add( Path.GetFileNameWithoutExtension(file.Filename), tree.XML_string );
}
else {
log.ErrorFormat( "SCGameMaps - Error in CryXmlBinReader: {0}", cbr.GetErrorDescription( ) );
}
}
}
catch ( Exception ex ) {
log.Error( "SCGameMaps - Unexpected ", ex );
}
foreach ( string fileKey in SCFiles.Instance.MapFiles ) {
this.Add( Path.GetFileNameWithoutExtension( fileKey ), SCFiles.Instance.MapFile( fileKey ) );
}
}

@ -27,8 +27,8 @@
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>68</ApplicationRevision>
<ApplicationVersion>2.34.0.%2a</ApplicationVersion>
<ApplicationRevision>69</ApplicationRevision>
<ApplicationVersion>2.35.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
@ -155,7 +155,11 @@
<Compile Include="SC\p4kFile\p4kZ64EndOfCentralDirLocator.cs" />
<Compile Include="SC\p4kFile\p4kZ64EndOfCentralDirRecord.cs" />
<Compile Include="SC\SCActionMapList.cs" />
<Compile Include="SC\SCFile.cs" />
<Compile Include="SC\SCFiles.cs" />
<Compile Include="SC\SCGameMaps.cs" />
<Compile Include="SC\SCLocale.cs" />
<Compile Include="SC\SCUiText.cs" />
<Compile Include="Table\DS_ActionMap.cs" />
<Compile Include="Table\DS_ActionMaps.cs">
<DependentUpon>DS_ActionMaps.xsd</DependentUpon>

@ -12,7 +12,20 @@ namespace SCJMapper_V2
/// </summary>
class TheUser
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod( ).DeclaringType );
private static readonly log4net.ILog log = log4net.LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod( ).DeclaringType );
private static bool hasWriteAccessToFolder( string folderPath )
{
try {
// Attempt to get a list of security permissions from the folder.
// This will raise an exception if the path is read only or do not have access to view the permissions.
System.Security.AccessControl.DirectorySecurity ds = Directory.GetAccessControl( folderPath );
return true;
}
catch ( UnauthorizedAccessException ) {
return false;
}
}
/// <summary>
/// Returns the name of the Personal Program folder in My Documents
@ -21,15 +34,35 @@ namespace SCJMapper_V2
/// <returns>Path to the Personal Program directory</returns>
static public string UserDir
{
get
{
get {
log.Debug( "UserDir - Entry" );
string docPath = Path.Combine( Environment.GetFolderPath( Environment.SpecialFolder.Personal ), Application.ProductName);
string docPath = Path.Combine( Environment.GetFolderPath( Environment.SpecialFolder.Personal ), Application.ProductName );
if ( !Directory.Exists( docPath ) ) Directory.CreateDirectory( docPath );
return docPath;
}
}
/// <summary>
/// The directory to store the assets
/// </summary>
static public string FileStoreDir
{
get {
log.Debug( "FileStoreDir - Entry" );
string docPath = AppDir;
// fallback
if ( !hasWriteAccessToFolder( docPath ) )
docPath = UserDir;
return Path.Combine( docPath, "Storage");
}
}
/// <summary>
/// The application directory
/// </summary>
static public string AppDir { get => Path.GetDirectoryName( Application.ExecutablePath); }
/// <summary>
/// Returns the mapping file name + path into our user dir

@ -47,7 +47,7 @@ namespace SCJMapper_V2.Actions
private static readonly log4net.ILog log = log4net.LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod( ).DeclaringType );
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 ActionName { get; set; } // the plain action name e.g. v_yaw
public Act.ActionDevice ActionDevice { get; set; } // the enum of the device
public string Device { get; set; } // name of the device (uses DeviceClass)
public string DefBinding { get; set; } // the default binding
@ -96,7 +96,7 @@ namespace SCJMapper_V2.Actions
Key = "";
ActionDevice = Act.ActionDevice.AD_Unknown;
Device = JoystickCls.DeviceClass;
Name = "";
ActionName = "";
DefBinding = "";
DefActivationMode = ActivationMode.Default;
InputList = new List<ActionCommandCls>( ); // empty list
@ -223,7 +223,7 @@ namespace SCJMapper_V2.Actions
bindCmd = "rebind"; // first entry is rebind
if ( InputList.Count > 0 ) {
if ( !string.IsNullOrEmpty( InputList[0].Input ) ) {
r = string.Format( "\t<action name=\"{0}\">\n", Name );
r = string.Format( "\t<action name=\"{0}\">\n", ActionName );
foreach ( ActionCommandCls acc in InputList ) {
if ( !string.IsNullOrEmpty( acc.Input ) ) {
r += string.Format( "\t\t\t<{0} {1}", bindCmd, acc.toXML( ) ); // 20151220BM: format for AC2 style
@ -244,7 +244,7 @@ namespace SCJMapper_V2.Actions
/// <returns>True if an action was decoded</returns>
public bool fromXML( XElement actionNode )
{
Name = (string)actionNode.Attribute( "name" ); // mandadory
ActionName = (string)actionNode.Attribute( "name" ); // mandadory
foreach ( XElement bindingNode in actionNode.Nodes( ) ) {
string binding = bindingNode.Name.ToString( );
string input = "", actModeName = "", multi = "";
@ -273,7 +273,7 @@ namespace SCJMapper_V2.Actions
}
}
if ( binding == "rebind" ) {
Key = Act.DevTag( Device ) + Name; // unique id of the action
Key = Act.DevTag( Device ) + ActionName; // unique id of the action
ActionDevice = Act.ADevice( Device ); // get the enum of the input device
}
AddCommand( input, actMode );

@ -208,7 +208,7 @@ namespace SCJMapper_V2.Actions
ar.ID_Action = DS_ActionMap.ActionID( am.Name, ac.Key, ac.InputList[ilIndex].NodeIndex ); // make a unique key
ar.AddBind = ( ilIndex > 0 ); // all but the first are addbinds
ar.REF_ActionMap = amShown;
ar.ActionName = ac.Name;
ar.ActionName = ac.ActionName;
ar.Device = ac.Device;
ar.Def_Binding = ac.DefBinding;
ar.Def_Modifier = ac.DefActivationMode.Name;
@ -263,7 +263,7 @@ namespace SCJMapper_V2.Actions
{
log.Debug( "ActionMapsCls.toXML - Entry" );
AppSettings appSettings = new AppSettings( );
AppSettings appSettings = AppSettings.Instance; // shortcut only
// *** HEADER

@ -248,6 +248,9 @@ namespace SCJMapper_V2.Actions
ActionTreeInputNode matin = new ActionTreeInputNode( "UNDEF" ) {
ImageKey = "Add"
};
matin.Update( matn );
matin.Command = "";
matn.Nodes.Add( matin ); // add to master tree
ActionCommandCls acc = ac.AddCommand( "", matin.Index );
// show stuff
@ -438,7 +441,8 @@ namespace SCJMapper_V2.Actions
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;
//if ( !stn.Text.Contains( m_Filter ) ) stn.Tag = hidden;
if ( !stn.Contains( m_Filter ) ) stn.Tag = hidden;
}
}
ApplyFilter( ); // to the GUI tree
@ -489,6 +493,9 @@ namespace SCJMapper_V2.Actions
// Input is a CSV formatted defaultprofile
// actmap;actmaplabel;action;actionlabel;defBinding;defActMode;defActMultitap;
const int iMap = 0, iMapLabel = 1, iAction = 2;
// we assume no addbind items in the profile
// so all actions are shown in the ActionTreeNode and no ActionTreeNode childs must be created here
// however we create the ActionCommand for each entry that is supported - even if it is not mapped (input= "")
@ -496,27 +503,28 @@ namespace SCJMapper_V2.Actions
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] + "," ) ) {
if ( elem.Length > iAction ) {
if ( !IgnoreMaps.Contains( "," + elem[iMap] + "," ) ) {
// must have 2 elements min
Array.Resize( ref cnl, 0 );
acm = new ActionMapCls { Name = elem[0] }; // get actionmap name
for ( int ei = 1; ei < elem.Length; ei += 4 ) { // step 2 - action;defaultBinding;defaultActivationMode;defMultiTap come in as quadrupples
if ( !string.IsNullOrEmpty( elem[ei] ) ) {
acm = new ActionMapCls { Name = elem[iMap] }; // get actionmap name
for ( int eIndex = iAction; eIndex < elem.Length; eIndex += 5 ) { // step 2 - action;actionlabel;defaultBinding;defaultActivationMode;defMultiTap come in as 5groups
if ( !string.IsNullOrEmpty( elem[eIndex] ) ) {
// 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] );
string action = elem[eIndex].Substring( 1 ); // has a device Tag as first char
string actionLabel = elem[eIndex + 1];
string defBinding = elem[eIndex + 2];
string defActivationModeName = elem[eIndex + 3];
int defMultiTap = int.Parse( elem[eIndex + 4] );
// need to create a ActivationMode here
ActivationMode defActivationMode = new ActivationMode( defActivationModeName, defMultiTap );
string devID = elem[ei].Substring( 0, 1 );
string devID = elem[eIndex].Substring( 0, 1 );
string device = Act.DeviceClassFromTag( devID );
// visual item for the action
cn = new ActionTreeNode( "UNDEF" ) {
Name = elem[ei], Action = action, BackColor = Color.White, ImageKey = devID // name with the key it to find it..
Name = elem[eIndex], Action = action, ActionLabel = actionLabel, BackColor = Color.White, ImageKey = devID // name with the key it to find it..
};
cn.BackColor = Color.White; // some stuff does not work properly...
if ( ActivationMode.IsDefault( defActivationModeName ) ) {
@ -529,7 +537,7 @@ namespace SCJMapper_V2.Actions
// derive content tree
ac = new ActionCls {
Key = cn.Name, Name = action, Device = device, ActionDevice = Act.ADevice( device ),
Key = cn.Name, ActionName = action, Device = device, ActionDevice = Act.ADevice( device ),
DefBinding = defBinding, DefActivationMode = defActivationMode
};
acm.Add( ac ); // add to our map
@ -577,9 +585,10 @@ namespace SCJMapper_V2.Actions
}
}
}//for
// ActionMap node
tn = new ActionTreeNode( acm.Name, cnl ) {
Name = acm.Name, Action = acm.Name, // name it to find it..
Name = acm.Name, ActionLabel = elem[iMapLabel],
Action = acm.Name, // name it to find it..
ImageIndex = 0, NodeFont = FontActionmap // new Font( m_MasterTree.Font, FontStyle.Bold );
};
m_MasterTree.BackColor = Color.White; // fix for defect TreeView (cut off bold text)
@ -626,7 +635,8 @@ namespace SCJMapper_V2.Actions
// 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
// ActionCommandCls acc = ac.FindActionInputObject( ActionTreeNode.CommandFromNodeText( atn.Text ) ); if ( acc == null ) return am; // ERROR exit
ActionCommandCls acc = ac.FindActionInputObject( atn.Command ); 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;
}
@ -659,7 +669,8 @@ namespace SCJMapper_V2.Actions
// 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
// ActionCommandCls acc = ac.FindActionInputObject( ActionTreeNode.CommandFromNodeText( atn.Text ) ); if ( acc == null ) return; // ERROR exit
ActionCommandCls acc = ac.FindActionInputObject( atn.Command ); 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 );
@ -713,8 +724,8 @@ namespace SCJMapper_V2.Actions
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
// ActionCommandCls acc = ac.FindActionInputObject( ActionTreeNode.CommandFromNodeText( atn.Text ) );
ActionCommandCls acc = ac.FindActionInputObject( atn.Command ); if ( acc == null ) return false; // ERROR exit
// have it - continue
ac.UpdateCommandFromInput( Act.DevInput( input, inKind ), acc.NodeIndex + 1 );
atn.UpdateAction( acc ); UpdateMasterNode( atn );
@ -861,8 +872,9 @@ namespace SCJMapper_V2.Actions
else {
// have to recreate the action child nodes
//ActionTreeInputNode matin = new ActionTreeInputNode( "UNDEF" ); matin.ImageKey = "Add";
ActionTreeInputNode matin = new ActionTreeInputNode( ac.Name ); matin.ImageKey = "Add";
matin.Name = matn.Name + "_" + matin.Index; // unique name needed
ActionTreeInputNode matin = new ActionTreeInputNode( ac.ActionName ) { ImageKey = "Add" };
matin.Update( matn); matin.Command = "";
acc.NodeIndex = matin.Index; // assign visual reference
matn.Nodes.Add( matin ); // add to master tree
matin.UpdateAction( acc ); UpdateMasterNode( matin );
@ -876,7 +888,7 @@ namespace SCJMapper_V2.Actions
}
}
catch ( Exception e ) {
log.DebugFormat( "ReloadTreeView - Exception in loading Treevie\n{0}", e.Message ); // map key not found ??
log.DebugFormat( "ReloadTreeView - Exception in loading Treeview\n{0}", e.Message ); // map key not found ??
}
}
// finally apply the filter and make it visible
@ -894,7 +906,8 @@ namespace SCJMapper_V2.Actions
log.Debug( "FindAndSelectActionKey - Entry" );
foreach ( ActionTreeNode tn in Ctrl.Nodes ) {
if ( string.IsNullOrEmpty( actionmap ) || ( tn.Text == actionmap ) ) {
// if ( string.IsNullOrEmpty( actionmap ) || ( tn.Text == actionmap ) ) {
if ( string.IsNullOrEmpty( actionmap ) || ( tn.Action == actionmap ) ) {
// have to search nodes of nodes
foreach ( ActionTreeNode stn in tn.Nodes ) {
if ( stn.Name == actionKey ) {
@ -935,7 +948,8 @@ namespace SCJMapper_V2.Actions
// have to search nodes of nodes
if ( string.IsNullOrEmpty( actionmap ) || ( tn.Action == actionmap ) ) {
foreach ( ActionTreeNode stn in tn.Nodes ) {
if ( stn.Text.Contains( ctrl ) ) {
//if ( stn.Text.Contains( ctrl ) ) {
if ( stn.Contains( ctrl ) ) {
if ( Ctrl.SelectedNode == stn ) NodeSelected( );
Ctrl.SelectedNode = stn;
Ctrl.SelectedNode.EnsureVisible( );
@ -943,7 +957,8 @@ namespace SCJMapper_V2.Actions
}
// have to search nodes of nodes
foreach ( ActionTreeInputNode sstn in stn.Nodes ) {
if ( sstn.Text.Contains( ctrl ) ) {
//if ( sstn.Text.Contains( ctrl ) ) {
if ( sstn.Contains( ctrl ) ) {
if ( Ctrl.SelectedNode == sstn ) NodeSelected( );
Ctrl.SelectedNode = sstn;
Ctrl.SelectedNode.EnsureVisible( );
@ -1011,7 +1026,7 @@ namespace SCJMapper_V2.Actions
if ( ac.DefBinding == input ) {
ret.Add( "" );
aMode = string.Format( "{0};{1}", ac.DefActivationMode.Name, ac.DefActivationMode.MultiTap );
l = string.Format( "{0} - {1} - {2} - {3}", "profile", ac.Name, acm.Name, aMode );
l = string.Format( "{0} - {1} - {2} - {3}", "profile", ac.ActionName, acm.Name, aMode );
ret.Add( l );
}
foreach ( ActionCommandCls acc in ac.InputList ) {
@ -1019,7 +1034,7 @@ namespace SCJMapper_V2.Actions
aMode = string.Format( "modified;{0};{1}", acc.ActivationMode.Name, acc.ActivationMode.MultiTap );
if ( acc.ActivationMode == ActivationMode.Default )
aMode = string.Format( "default" );
l = string.Format( "{0} - {1} - {2} - {3}", "mapped ", ac.Name, acm.Name, aMode );
l = string.Format( "{0} - {1} - {2} - {3}", "mapped ", ac.ActionName, acm.Name, aMode );
ret.Add( l );
}
}
@ -1060,7 +1075,7 @@ namespace SCJMapper_V2.Actions
if ( acc.ActivationMode == ActivationMode.Default )
aMode = string.Format( "default" );
rtf.RHighlightColor = RTF.RTFformatter.ERColor.ERC_Green;
rtf.Write( "mapped" ); rtf.WriteTab( ac.Name ); rtf.WriteTab( acm.Name ); rtf.WriteTab( aMode.PadRight( 80 ) ); rtf.WriteLn( );
rtf.Write( "mapped" ); rtf.WriteTab( ac.ActionName ); rtf.WriteTab( acm.Name ); rtf.WriteTab( aMode.PadRight( 80 ) ); rtf.WriteLn( );
rtf.RHighlightColor = RTF.RTFformatter.ERColor.ERC_Black;
rtf.WriteLn( );
used = true;
@ -1069,7 +1084,7 @@ namespace SCJMapper_V2.Actions
}
if ( ( !used ) && ac.DefBinding == input ) {
aMode = string.Format( "{0};{1}", ac.DefActivationMode.Name, ac.DefActivationMode.MultiTap );
rtf.Write( "profile" ); rtf.WriteTab( ac.Name ); rtf.WriteTab( acm.Name ); rtf.WriteTab( aMode ); rtf.WriteLn( );
rtf.Write( "profile" ); rtf.WriteTab( ac.ActionName ); rtf.WriteTab( acm.Name ); rtf.WriteTab( aMode ); rtf.WriteLn( );
rtf.WriteLn( );
}
}
@ -1080,18 +1095,20 @@ namespace SCJMapper_V2.Actions
/// <summary>
/// Find a control the the actionmap that contains the Text
/// </summary>
/// <param name="actionmap">The actionmap to find the string</param>
/// <param name="actionmap">The actionmap to find the string, empty string matches all actionmaps</param>
/// <param name="text">The string to find</param>
public string FindText( string actionmap, string text )
{
log.Debug( "FindText - Entry" );
log.DebugFormat ( "FindText - Entry ({0}, {1})", actionmap, text );
foreach ( ActionTreeNode tn in m_MasterTree.Nodes ) {
if ( string.IsNullOrEmpty( actionmap ) || ( tn.Text == actionmap ) ) {
// if ( string.IsNullOrEmpty( actionmap ) || ( tn.Text == actionmap ) ) {
if ( string.IsNullOrEmpty( actionmap ) || ( tn.Action == actionmap ) ) {
// have to search nodes of nodes
foreach ( ActionTreeNode stn in tn.Nodes ) {
if ( stn.Text.Contains( text ) ) {
return stn.Text;
//if ( stn.Text.Contains( text ) ) {
if ( stn.Contains( text ) ) {
return stn.ActionText;
}
}
}
@ -1100,7 +1117,7 @@ namespace SCJMapper_V2.Actions
}
/// <summary>
/// Find a control that contains the Text
/// Find a control that contains the Text (searches all actionmaps)
/// </summary>
/// <param name="text">The string to find</param>
public string FindText( string text )
@ -1121,13 +1138,17 @@ namespace SCJMapper_V2.Actions
if ( Ctrl.SelectedNode.Level == 1 ) {
ActionTreeNode matn = FindMasterAction( (ActionTreeNode)Ctrl.SelectedNode );
action = ActionTreeNode.ActionFromNodeText( matn.Text );
ctrl = ActionTreeNode.CommandFromNodeText( matn.Text );
// action = ActionTreeNode.ActionFromNodeText( matn.Text );
// ctrl = ActionTreeNode.CommandFromNodeText( matn.Text );
action = matn.Action;
ctrl = matn.Command;
}
else if ( Ctrl.SelectedNode.Level == 2 ) {
ActionTreeNode matn = FindMasterAction( (ActionTreeInputNode)Ctrl.SelectedNode ); // the parent treenode
action = ActionTreeNode.ActionFromNodeText( matn.Text );
ctrl = ActionTreeNode.CommandFromNodeText( matn.Text );
// action = ActionTreeNode.ActionFromNodeText( matn.Text );
// ctrl = ActionTreeNode.CommandFromNodeText( matn.Text );
action = matn.Action;
ctrl = matn.Command;
}
}
@ -1140,11 +1161,13 @@ namespace SCJMapper_V2.Actions
if ( Ctrl.SelectedNode == null ) return "";
if ( Ctrl.SelectedNode.Level == 1 ) {
ActionTreeNode matn = FindMasterAction( (ActionTreeNode)Ctrl.SelectedNode );
return ActionTreeNode.CommandFromNodeText( matn.Text );
// return ActionTreeNode.CommandFromNodeText( matn.Text );
return matn.Command;
}
else if ( Ctrl.SelectedNode.Level == 2 ) {
ActionTreeNode matn = FindMasterAction( (ActionTreeInputNode)Ctrl.SelectedNode ); // the parent treenode
return ActionTreeNode.CommandFromNodeText( matn.Text );
// return ActionTreeNode.CommandFromNodeText( matn.Text );
return matn.Command;
}
else return "";
}
@ -1159,11 +1182,13 @@ namespace SCJMapper_V2.Actions
if ( Ctrl.SelectedNode == null ) return "";
if ( Ctrl.SelectedNode.Level == 1 ) {
ActionTreeNode matn = FindMasterAction( (ActionTreeNode)Ctrl.SelectedNode );
return ActionTreeNode.ActionFromNodeText( matn.Text );
// return ActionTreeNode.ActionFromNodeText( matn.Text );
return matn.Action;
}
else if ( Ctrl.SelectedNode.Level == 2 ) {
ActionTreeNode matn = FindMasterAction( (ActionTreeNode)Ctrl.SelectedNode.Parent ); // the parent treenode
return ActionTreeNode.ActionFromNodeText( matn.Text );
// return ActionTreeNode.ActionFromNodeText( matn.Text );
return matn.Action;
}
else return "";
}
@ -1185,8 +1210,8 @@ namespace SCJMapper_V2.Actions
ActionTreeNode atn = ( Ctrl.SelectedNode as ActionTreeNode ); // the treenode from a level 1
ActionCls ac = FindActionObject( atn.Parent.Name, atn.Name ); // the related action in an actionmap
if ( ac == null ) return ""; // ERROR exit
ActionCommandCls acc = ac.FindActionInputObject( ActionTreeNode.CommandFromNodeText( atn.Text ) );
if ( acc == null ) return ""; // ERROR exit
// ActionCommandCls acc = ac.FindActionInputObject( ActionTreeNode.CommandFromNodeText( atn.Text ) ); if ( acc == null ) return ""; // ERROR exit
ActionCommandCls acc = ac.FindActionInputObject( atn.Command ); if ( acc == null ) return ""; // ERROR exit
// have it - continue
string actionID = DS_ActionMap.ActionID( atn.Parent.Name, ac.Key, acc.NodeIndex );
return actionID;
@ -1283,10 +1308,10 @@ namespace SCJMapper_V2.Actions
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 ) );
rep = string.Format( " {0} . {1} _ {2}", ac.ActionName.PadRight( padAction ), acc.DevID.PadRight( padDevice ), acc.Input.PadRight( padInput ) );
}
else {
rep = string.Format( " {0} + {1} _ {2}", ac.Name.PadRight( padAction ), acc.DevID.PadRight( padDevice ), acc.Input.PadRight( padInput ) ); // my binding
rep = string.Format( " {0} + {1} _ {2}", ac.ActionName.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 );
@ -1350,7 +1375,7 @@ namespace SCJMapper_V2.Actions
foreach ( ActionCls ac in acm ) {
// we get an action for each device class here - sort it out
if ( ac.Name != action ) {
if ( ac.ActionName != action ) {
// dump if not empty
if ( !string.IsNullOrEmpty( action ) ) {
// compose one action
@ -1358,9 +1383,9 @@ namespace SCJMapper_V2.Actions
repList += string.Format( "{0}", rep ); // add to list
}
// action changed - restart collection
action = ac.Name;
rep = string.Format( "{0};{1};", acm.Name, ac.Name ); // actionmap; action
// note: don't add trailing semicolons as the are applied in the output formatting
action = ac.ActionName;
rep = string.Format( "{0};{1};", acm.Name, ac.ActionName ); // 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
}

@ -19,108 +19,124 @@ namespace SCJMapper_V2.Actions
// Handle all text label composition and extraction here
/// <summary>
/// Returns a the cmd with standard modifier if modified == true
/// </summary>
/// <param name="cmd">Any string</param>
/// <param name="modified">Bool true if a modifier shall be added</param>
/// <returns>The string with added Modifier if requested</returns>
public static string ComposeNodeText( string cmd, bool modified = false )
{
if ( string.IsNullOrEmpty( cmd ) ) {
return "";
}
else {
if ( modified )
return string.Format( "{0} {1}", cmd, ActionTreeNode.ModDiv ); // js1_button1 #
else
return string.Format( "{0}", cmd ); // js1_button1
}
}
/// <summary>
/// Returns the cmd part of a string like "cmd - anything #"
/// </summary>
/// <param name="nodeText">A nodetext string like "cmd - anything #"</param>
/// <param name="cmd">contains the cmd part if delimiters are present - else returns the input</param>
public static void DecompNodeText( string nodeText, out string cmd )
{
string[] e = nodeText.Split( new char[] { RegDiv, ModDiv }, StringSplitOptions.RemoveEmptyEntries );
if ( e.Length > 0 )
cmd = e[0].TrimEnd( );
else
cmd = nodeText;
}
/// <summary>
/// Returns the command part from a node text
/// i.e. "v_pitch - js1_x" returns v_pitch
/// </summary>
/// <param name="nodeText">The node text in 'action - command' notation</param>
/// <returns>the command part or an empty string</returns>
public new static string CommandFromNodeText( string nodeText )
{
ActionTreeInputNode.DecompNodeText( nodeText, out string cmd );
return cmd;
}
///// <summary>
///// Returns a the cmd with standard modifier if modified == true
///// </summary>
///// <param name="cmd">Any string</param>
///// <param name="modified">Bool true if a modifier shall be added</param>
///// <returns>The string with added Modifier if requested</returns>
//private static string ComposeNodeText( string cmd, bool modified = false )
//{
// if ( string.IsNullOrEmpty( cmd ) ) {
// return "";
// }
// else {
// if ( modified )
// return string.Format( "{0} {1}", cmd, ActionTreeNode.ModDiv ); // js1_button1 #
// else
// return string.Format( "{0}", cmd ); // js1_button1
// }
//}
///// <summary>
///// Returns the cmd part of a string like "cmd - anything #"
///// </summary>
///// <param name="nodeText">A nodetext string like "cmd - anything #"</param>
///// <param name="cmd">contains the cmd part if delimiters are present - else returns the input</param>
//private static void DecompNodeText( string nodeText, out string cmd )
//{
// string[] e = nodeText.Split( new char[] { RegDiv, ModDiv }, StringSplitOptions.RemoveEmptyEntries );
// if ( e.Length > 0 )
// cmd = e[0].TrimEnd( );
// else
// cmd = nodeText;
//}
///// <summary>
///// Returns the command part from a node text
///// i.e. "v_pitch - js1_x" returns v_pitch
///// </summary>
///// <param name="nodeText">The node text in 'action - command' notation</param>
///// <returns>the command part or an empty string</returns>
//private new static string CommandFromNodeText( string nodeText )
//{
// ActionTreeInputNode.DecompNodeText( nodeText, out string cmd );
// return cmd;
//}
#endregion
// Object defs
// ctor
/// <summary>
/// cTor: empty
/// </summary>
public ActionTreeInputNode( )
: base( )
{
}
// ctor
public ActionTreeInputNode( ActionTreeInputNode srcNode )
: base( srcNode )
{
}
// ctor
/// <summary>
/// cTor: just create a node without added functionality
/// NOTE: must fill properties to work
/// </summary>
/// <param name="text">The Text element of the Node</param>
public ActionTreeInputNode( string text )
: base ( text )
{
}
// ctor
/// <summary>
/// cTor: just create a node without added functionality
/// NOTE: must fill properties to work
/// </summary>
/// <param name="text">The Text element of the Node</param>
/// <param name="children">The child list</param>
public ActionTreeInputNode( string text, ActionTreeInputNode[] children )
: base( text, children )
{
}
/// <summary>
/// Property Text of an Input node
/// cTor: Copy src to this new node
/// </summary>
public new string Text
/// <param name="srcNode">Src node to copy from</param>
public ActionTreeInputNode( ActionTreeInputNode srcNode )
: base( srcNode )
{
get { return base.Text; }
set
{
ActionTreeInputNode.DecompNodeText( value, out m_command );
base.Text = ActionTreeInputNode.ComposeNodeText( AddDiv + m_command, m_modified ); // tag for the node processing
}
}
public new string Command
/// <summary>
/// Property Command of an Input node
/// </summary>
{
get { return m_command; }
set
{
m_command = value;
Text = ActionTreeInputNode.ComposeNodeText( m_command, m_modified ); // compose - later it will be decomposed again
}
}
///// <summary>
///// Property Text of an Input node
///// </summary>
//public new string Text
//{
// get { return base.Text; }
// set
// {
// ActionTreeInputNode.DecompNodeText( value, out m_command );
// m_actionText = ActionTreeInputNode.ComposeNodeText( AddDiv + m_command, m_modified ); // tag for the node processing
// base.Text = m_actionText; // TODO
// }
//}
//public new string Command
///// <summary>
///// Property Command of an Input node
///// </summary>
//{
// get { return m_command; }
// set
// {
// m_command = value;
// m_actionText = ActionTreeInputNode.ComposeNodeText( m_command, m_modified ); // compose - later it will be decomposed again
// base.Text = m_actionText; // TODO
// }
//}
}
}

@ -23,7 +23,14 @@ namespace SCJMapper_V2.Actions
// Handle all text label composition and extraction here
public static string ComposeNodeText( string action, string cmd, bool modified = false )
/// <summary>
/// Composes the ActionText from items
/// </summary>
/// <param name="action">The action (profile notation)</param>
/// <param name="cmd">The command applied</param>
/// <param name="modified">True if it represents a modified item</param>
/// <returns>A composed string</returns>
public static string ComposeNodeActionText( string action, string cmd, bool modified = false )
{
if ( string.IsNullOrEmpty( cmd ) ) {
return action; // v_eject
@ -46,13 +53,13 @@ namespace SCJMapper_V2.Actions
/// <param name="nodeText">The node Text</param>
/// <param name="action">The action</param>
/// <param name="cmd">The device command</param>
public static void DecompNodeText( string nodeText, out string action, out string cmd )
protected static void DecompNodeActionText( string nodeText, out string action, out string cmd )
{
action = ""; cmd = "";
string[] e = nodeText.Split( new char[] { RegDiv, ModDiv }, StringSplitOptions.RemoveEmptyEntries );
if ( e.Length > 1 ) {
action = e[0].TrimEnd( );
if ( e[1].Trim() == DeviceCls.DisabledInput ) {
if ( e[1].Trim( ) == DeviceCls.DisabledInput ) {
cmd = e[1];
}
else {
@ -80,9 +87,9 @@ namespace SCJMapper_V2.Actions
/// </summary>
/// <param name="nodeText">The node text in 'action - command' notation</param>
/// <returns>the action part or an empty string</returns>
public static string ActionFromNodeText( string nodeText )
public static string ActionFromActionText( string nodeText )
{
ActionTreeNode.DecompNodeText( nodeText, out string action, out string cmd );
ActionTreeNode.DecompNodeActionText( nodeText, out string action, out string cmd );
return action;
}
@ -92,24 +99,51 @@ namespace SCJMapper_V2.Actions
/// </summary>
/// <param name="nodeText">The node text in 'action - command' notation</param>
/// <returns>the command part or an empty string</returns>
public static string CommandFromNodeText( string nodeText )
public static string CommandFromActionText( string nodeText )
{
ActionTreeNode.DecompNodeText( nodeText, out string action, out string cmd );
ActionTreeNode.DecompNodeActionText( nodeText, out string action, out string cmd );
return cmd;
}
#endregion
// Object defs
// ctor
public ActionTreeNode( )
/// <summary>
/// cTor: empty node
/// </summary>
public ActionTreeNode()
: base( )
{
}
// ctor
/// <summary>
/// cTor: just create a node without added functionality
/// NOTE: must fill properties to work
/// </summary>
/// <param name="text">The Text element of the Node</param>
public ActionTreeNode( string text )
{
this.Text = text;
}
/// <summary>
/// cTor: just create a node without added functionality
/// NOTE: must fill properties to work
/// </summary>
/// <param name="text">The Text element of the Node</param>
/// <param name="children">The child list</param>
public ActionTreeNode( string text, ActionTreeNode[] children )
: base( text, children )
{
}
/// <summary>
/// cTor: Copy src to new node
/// </summary>
/// <param name="srcNode"></param>
public ActionTreeNode( ActionTreeNode srcNode )
: base( )
{
@ -121,30 +155,45 @@ namespace SCJMapper_V2.Actions
this.NodeFont = srcNode.NodeFont;
this.ImageKey = srcNode.ImageKey;
this.Tag = srcNode.Tag;
this.m_actionLabel = srcNode.m_actionLabel;
this.m_action = srcNode.m_action;
this.m_actionDevice = srcNode.m_actionDevice;
this.m_actionText = srcNode.m_actionText;
// these are changing while using it
this.Update( srcNode );
}
// ctor
public ActionTreeNode( string text )
{
this.Text = text;
}
// our own properties
private string m_actionLabel = ""; // the text shown - translated m_action
protected string m_actionText = ""; // contains the former Text property of the TreeNode
private string m_action = ""; // i.e. v_pitch
protected string m_command = ""; // i.e. js2_button3
protected bool m_modified = false; // any modifier applied? (ActivationMode)
private Act.ActionDevice m_actionDevice = Act.ActionDevice.AD_Unknown;
// ctor
public ActionTreeNode( string text, ActionTreeNode[] children )
: base( text, children )
/// <summary>
/// Crates the translated node text for display
/// </summary>
/// <returns>A composed string</returns>
protected string ComposeNodeText( )
{
string tAction = SC.SCUiText.Instance.Text( m_actionLabel, m_action );
if ( string.IsNullOrEmpty( m_command ) ) {
return tAction; // v_eject
}
else if ( string.IsNullOrEmpty( tAction ) ) {
return m_command; // js1_button1
}
else {
if ( m_modified )
return string.Format( "{0} {2} {1} {3}", tAction, m_command, RegDiv, ModDiv ); // v_eject - js1_button1 #
else
return string.Format( "{0} {2} {1}", tAction, m_command, RegDiv ); // v_eject - js1_button1
}
}
// our own properties
private string m_action = "";
protected string m_command ="";
protected bool m_modified = false; // any modifier applied? (ActivationMode)
private Act.ActionDevice m_actionDevice = Act.ActionDevice.AD_Unknown;
/// <summary>
@ -154,10 +203,13 @@ namespace SCJMapper_V2.Actions
/// <param name="other">The node to update from</param>
public void Update( ActionTreeNode other )
{
// TreeNode props
this.BackColor = other.BackColor;
// own props
this.Command = other.Command;
this.Modified = other.Modified;
this.Action = other.Action; //?????????????????
this.ActionLabel = other.ActionLabel;
this.Action = other.Action; //? does this fill all the rest properly?
}
/// <summary>
@ -174,7 +226,10 @@ namespace SCJMapper_V2.Actions
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
if ( this.Level == 2 ) {
this.Action = ( this.Parent as ActionTreeNode ).Action;
this.ActionLabel = (this.Parent as ActionTreeNode).ActionLabel; // apply UNDEF - 20160525 fix addbind not showing UNDEF if assigned
}
}
// blended mapped ones - can only get a Blend Background
else if ( actionCmd.Input == DeviceCls.DisabledInput ) {
@ -190,20 +245,28 @@ namespace SCJMapper_V2.Actions
}
///// <summary>
///// Property Text of an Action node
///// </summary>
//public new string Text
//{
// get { return base.Text; }
// private set {
// ActionTreeNode.DecompNodeActionText( value, out m_action, out m_command );
// m_actionText = ActionTreeNode.ComposeNodeActionText( m_action, m_command, m_modified );
// base.Text = ComposeNodeText(); // TODO for now
// }
//}
/// <summary>
/// Property Text of an Action node
/// Property ActionText (action in profile notation i.e. v_something) of an Action node
/// </summary>
public new string Text
{
get { return base.Text; }
set
{
ActionTreeNode.DecompNodeText( value, out m_action, out m_command );
base.Text = ActionTreeNode.ComposeNodeText( m_action, m_command, m_modified );
}
}
public string ActionText { get => m_actionText; }
/// <summary>
/// Property ActionLabel of an Action node
/// </summary>
public string ActionLabel { get => m_actionLabel; set => m_actionLabel = value; }
/// <summary>
/// Property Action of an Action node
@ -211,10 +274,11 @@ namespace SCJMapper_V2.Actions
public string Action
{
get { return m_action; }
set
{
set {
m_action = value;
base.Text = ActionTreeNode.ComposeNodeText( m_action, m_command, m_modified );
// may need to update too
m_actionText = ActionTreeNode.ComposeNodeActionText( m_action, m_command, m_modified );
base.Text = ComposeNodeText( );
}
}
@ -224,10 +288,25 @@ namespace SCJMapper_V2.Actions
public string Command
{
get { return m_command; }
set
{
set {
m_command = value;
base.Text = ActionTreeNode.ComposeNodeText( m_action, m_command, m_modified );
// may need to update too
m_actionText = ActionTreeNode.ComposeNodeActionText( m_action, m_command, m_modified );
base.Text = ComposeNodeText( );
}
}
/// <summary>
/// Property Modified of an Action node
/// </summary>
public bool Modified
{
get { return m_modified; }
set {
m_modified = value;
// may need to update too
m_actionText = ActionTreeNode.ComposeNodeActionText( m_action, m_command, m_modified );
base.Text = ComposeNodeText( );
}
}
@ -237,26 +316,22 @@ namespace SCJMapper_V2.Actions
public Act.ActionDevice ActionDevice
{
get { return m_actionDevice; }
set
{
set {
m_actionDevice = value;
}
}
/// <summary>
/// Property Modified of an Action node
/// Return true if the content of Action - Command contains the match string
/// </summary>
public bool Modified
/// <param name="match">A string to match</param>
/// <returns>True if the node contains the match</returns>
public bool Contains( string match )
{
get { return m_modified; }
set
{
m_modified = value;
base.Text = ActionTreeNode.ComposeNodeText( m_action, m_command, m_modified );
}
if ( m_actionText.Contains( match ) ) return true;
return false;
}
/// <summary>
/// Property IsJoystickAction of an Action node
/// </summary>

Loading…
Cancel
Save