Add dynamic lights setting and fix macOS config paths

- Add DynamicLights (0–7) setting mapped to the eu07.ini dynamiclights key,
  exposed as a slider in the Graphics section of Settings.
- Fix config file paths on macOS for eu07.ini, eu07_input-keyboard.ini,
  and userpresets.json to use ~/Library/Application Support/MaSzyna/
  instead of falling through to the Linux XDG path.
This commit is contained in:
Mateusz Włodarczyk
2026-06-30 21:30:52 +02:00
parent 710bfc0d10
commit 211863c921
7 changed files with 46 additions and 6 deletions

View File

@@ -88,6 +88,12 @@ public sealed class KeyboardConfig
if (!string.IsNullOrEmpty(appData))
return Path.Combine(appData, "MaSzyna", "eu07_input-keyboard.ini");
}
else if (OperatingSystem.IsMacOS())
{
string? home = Environment.GetEnvironmentVariable("HOME");
if (!string.IsNullOrEmpty(home))
return Path.Combine(home, "Library", "Application Support", "MaSzyna", "eu07_input-keyboard.ini");
}
else
{
string? home = Environment.GetEnvironmentVariable("HOME");

View File

@@ -27,16 +27,32 @@ public sealed class PresetCollection
/// <summary>
/// The user's vehicle/consist "warehouse": named trainset presets persisted as JSON.
/// Stored under the per-user config directory so it survives reinstalls:
/// Windows: %appdata%\MaSzyna\starter\userpresets.json
/// Unix: ~/.config/MaSzyna/starter/userpresets.json
/// (both resolved via <see cref="Environment.SpecialFolder.ApplicationData"/>).
/// Windows: %APPDATA%\MaSzyna\starter\userpresets.json
/// macOS: ~/Library/Application Support/MaSzyna/starter/userpresets.json
/// Linux: ~/.config/MaSzyna/starter/userpresets.json
/// All operations are best-effort and never throw.
/// </summary>
public static class PresetStore
{
public static string FilePath { get; } = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"MaSzyna", "starter", "userpresets.json");
private static string ResolvePath()
{
if (OperatingSystem.IsWindows())
{
string appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
return Path.Combine(appData, "MaSzyna", "starter", "userpresets.json");
}
if (OperatingSystem.IsMacOS())
{
string home = Environment.GetEnvironmentVariable("HOME") ?? AppContext.BaseDirectory;
return Path.Combine(home, "Library", "Application Support", "MaSzyna", "starter", "userpresets.json");
}
{
string home = Environment.GetEnvironmentVariable("HOME") ?? AppContext.BaseDirectory;
return Path.Combine(home, ".config", "MaSzyna", "starter", "userpresets.json");
}
}
public static string FilePath { get; } = ResolvePath();
// Source-generated metadata keeps (de)serialisation AOT/trim-safe, matching the
// approach used for the vehicle database.

View File

@@ -65,6 +65,7 @@ public sealed class Settings
public int MaxCabTextureSize = 4096; // maxcabtexturesize
public int TextureFiltering = 8; // anisotropicfiltering (1/2/4/8/16)
public int Multisampling = 2; // multisampling (0-3)
public int DynamicLights = 7; // dynamiclights (0-7)
public double DrawRangeFactor = 1.0; // gfx.drawrange.factor.max
public bool VSync = true; // vsync
public bool Smoke = true; // gfx.smoke
@@ -144,6 +145,12 @@ public sealed class Settings
if (!string.IsNullOrEmpty(appData))
return Path.Combine(appData, "MaSzyna", "eu07.ini");
}
else if (OperatingSystem.IsMacOS())
{
string? home = Environment.GetEnvironmentVariable("HOME");
if (!string.IsNullOrEmpty(home))
return Path.Combine(home, "Library", "Application Support", "MaSzyna", "eu07.ini");
}
else
{
string? home = Environment.GetEnvironmentVariable("HOME");
@@ -312,6 +319,7 @@ public sealed class Settings
MaxCabTextureSize = c.GetInt("maxcabtexturesize", 4096);
TextureFiltering = c.GetInt("anisotropicfiltering", 8);
Multisampling = Clamp(c.GetInt("multisampling", 2), 0, 3);
DynamicLights = Clamp(c.GetInt("dynamiclights", 7), 0, 7);
DrawRangeFactor = c.GetDouble("gfx.drawrange.factor.max", 1.0);
VSync = c.GetBool("vsync", true);
Smoke = c.GetBool("gfx.smoke", true);
@@ -403,6 +411,7 @@ public sealed class Settings
c.SetInt("maxcabtexturesize", MaxCabTextureSize);
c.SetInt("anisotropicfiltering", TextureFiltering);
c.SetInt("multisampling", Multisampling);
c.SetInt("dynamiclights", DynamicLights);
c.SetDouble("gfx.drawrange.factor.max", DrawRangeFactor);
c.SetBool("vsync", VSync);
c.SetBool("gfx.smoke", Smoke);

View File

@@ -149,6 +149,11 @@
<Slider x:Name="MultisamplingSlider" Minimum="1" MaxWidth="400" HorizontalAlignment="Left"
MinWidth="250" Maximum="4" TickFrequency="1" IsSnapToTickEnabled="True" Value="3" />
</StackPanel>
<StackPanel Spacing="8" Orientation="Horizontal">
<TextBlock VerticalAlignment="Center" FontSize="14" Text="{Binding [DynamicLights], Source={x:Static starterNg:App.Loc}}" />
<Slider x:Name="DynamicLightsSlider" Minimum="0" MaxWidth="400" HorizontalAlignment="Left"
MinWidth="250" Maximum="7" TickFrequency="1" IsSnapToTickEnabled="True" Value="7" />
</StackPanel>
<StackPanel Spacing="8" Orientation="Horizontal">
<TextBlock VerticalAlignment="Center" FontSize="14" Text="{Binding [RenderRange], Source={x:Static starterNg:App.Loc}}" />
<Slider x:Name="RenderRangeSlider" Minimum="1" MaxWidth="400" HorizontalAlignment="Left"

View File

@@ -84,6 +84,7 @@ public partial class Settings : UserControl
cabTextureResolutionSlider.Value = Log2(s.MaxCabTextureSize, 12);
TexFilteringSlider.Value = AnisotropyToSlider(s.TextureFiltering);
MultisamplingSlider.Value = s.Multisampling + 1;
DynamicLightsSlider.Value = s.DynamicLights;
RenderRangeSlider.Value = (int)Math.Round(s.DrawRangeFactor);
VSyncCb.IsChecked = s.VSync;
SmokeDisplayCb.IsChecked = s.Smoke;
@@ -171,6 +172,7 @@ public partial class Settings : UserControl
s.TextureFiltering = StarterNG.Classes.Settings.AnisotropySteps[
Clamp((int)TexFilteringSlider.Value - 1, 0, StarterNG.Classes.Settings.AnisotropySteps.Length - 1)];
s.Multisampling = Clamp((int)MultisamplingSlider.Value - 1, 0, 3);
s.DynamicLights = (int)DynamicLightsSlider.Value;
s.DrawRangeFactor = RenderRangeSlider.Value;
s.VSync = IsChecked(VSyncCb);
s.Smoke = IsChecked(SmokeDisplayCb);

View File

@@ -243,6 +243,7 @@
<String key="MaxTexCabResolution">Maximum cabin texture resolution:</String>
<String key="TexFilteringQuality">Texture filtering quality:</String>
<String key="Multisampling">Multisampling:</String>
<String key="DynamicLights">Dynamic light sources:</String>
<String key="RenderRange">Rendering range:</String>
<String key="VSync">VSync</String>
<String key="SmokeDisplay">Smoke display</String>

View File

@@ -243,6 +243,7 @@
<String key="MaxTexCabResolution">Maksymalna rozdzielczość tekstur kabiny:</String>
<String key="TexFilteringQuality">Jakość filtrowania tekstur:</String>
<String key="Multisampling">Multisampling:</String>
<String key="DynamicLights">Dynamiczne źródła światła:</String>
<String key="RenderRange">Zasięg renderowania:</String>
<String key="VSync">VSync</String>
<String key="SmokeDisplay">Wyświetlanie dymu</String>