consist editor improvements

This commit is contained in:
2026-06-13 00:54:37 +02:00
parent 6dc9b77a24
commit 0e82841a56
16 changed files with 1081 additions and 250 deletions

View File

@@ -4,6 +4,7 @@
xmlns:sukiUi="clr-namespace:SukiUI.Controls;assembly=SukiUI"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:starterNg="clr-namespace:StarterNG"
xmlns:views="clr-namespace:StarterNG.Views"
mc:Ignorable="d" d:DesignWidth="1000" d:DesignHeight="700"
x:Class="StarterNG.Views.Depot">
<Grid Margin="16" ColumnSpacing="16" RowSpacing="16">
@@ -30,6 +31,8 @@
<TextBox Name="searchBox" DockPanel.Dock="Top" Margin="0,0,0,8"
Watermark="{Binding [Search], Source={x:Static starterNg:App.Loc}}"
TextChanged="SearchBox_OnTextChanged" />
<!-- Folded groups (built in code-behind); collapsed groups hold no
controls, so the list stays light and scrolls smoothly. -->
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
<StackPanel Name="browserStack" Spacing="2" />
</ScrollViewer>
@@ -47,6 +50,7 @@
<ComboBox Name="sceneryConsistCombo" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"
HorizontalAlignment="Stretch" MaxDropDownHeight="420"
PlaceholderText="{Binding [LoadFromScenery], Source={x:Static starterNg:App.Loc}}"
DropDownOpened="SceneryConsistCombo_OnDropDownOpened"
SelectionChanged="SceneryConsistCombo_OnSelectionChanged" />
</Grid>
</sukiUi:GroupBox>

File diff suppressed because it is too large Load Diff

View File

@@ -45,8 +45,9 @@
<Button Grid.Column="0" Height="36" Classes="Flat"
VerticalAlignment="Bottom" Grid.Row="3" Grid.ColumnSpan="2"
Click="StartButton_OnClick"
Content="{Binding [Start], Source={x:Static starterNg:App.Loc}}">
</Button>
</Grid>
</UserControl>

View File

@@ -1,8 +1,11 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.Media.Imaging;
using StarterNG.Classes;
@@ -16,20 +19,10 @@ public partial class Scenarios : UserControl
public Scenarios()
{
InitializeComponent();
sceneries = new List<Scenery>();
// load sceneries
List<string> scnFiles = Directory.GetFiles("scenery/", "*.scn").ToList();
foreach (string scnFile in scnFiles)
{
// skip temp sceneries
if (Path.GetFileName(scnFile).StartsWith("$"))
continue;
// Parse all files
sceneries.Add(new Scenery(scnFile));
}
// Sceneries are parsed once at startup (behind the splash).
sceneries = GameData.Instance.Sceneries;
var groupNodes = new Dictionary<string, TreeViewItem>();
for (int i = 0; i < sceneries.Count; i++)
@@ -109,20 +102,23 @@ public partial class Scenarios : UserControl
if (vItem?.Tag is not int vTag)
return;
Trainset selectedTrainset = selectedScn.Trainsets[vTag];
// share the selection so the depot edits this consist in place
AppState.Instance.CurrentScenery = selectedScn;
AppState.Instance.CurrentTrainset = selectedTrainset;
var db = GameData.Instance.Vehicles;
foreach (var train in selectedTrainset.Vehicles)
{
string path = Path.Combine(
"textures",
"mini",
train.SkinFile + ".bmp"
);
if (!File.Exists(path))
// thumbnail name comes from the matching texture's texture_mini
string miniName = db.MiniForSkin(train.SkinFile) ?? train.SkinFile;
string? path = VehicleDatabase.MiniPath(miniName);
if (path is null)
{
// fallback
continue;
}
}
var bitmap = new Bitmap(path);
var image = new Image
{
@@ -135,4 +131,46 @@ public partial class Scenarios : UserControl
}
missionDescription.Text = selectedTrainset.Description;
}
// Exports the (possibly depot-modified) scenery to a $-prefixed copy and
// launches the game on it with the selected consist's driven vehicle.
private void StartButton_OnClick(object? sender, RoutedEventArgs e)
{
var scenery = AppState.Instance.CurrentScenery;
if (scenery is null)
return;
var trainset = AppState.Instance.CurrentTrainset;
// write scenery/$<name>.scn with the replaced trainsets
string dir = System.IO.Path.GetDirectoryName(scenery.Path) ?? "scenery";
string exportName = "$" + System.IO.Path.GetFileName(scenery.Path);
string exportPath = System.IO.Path.Combine(dir, exportName);
try
{
File.WriteAllText(exportPath, scenery.BuildExportContent(), Encoding.GetEncoding(1250));
}
catch
{
return; // couldn't write the scenery file
}
// the player's vehicle is the node name of the driven car in the consist
string? vehicle = trainset?.Vehicles
.FirstOrDefault(v => v.DriverType is eDriverType.Headdriver or eDriverType.Reardriver)?.Name
?? trainset?.Vehicles.FirstOrDefault()?.Name;
// launch the game: -s $<name>.scn -v <vehicle>
try
{
Process.Start(new ProcessStartInfo(StarterNG.Classes.Settings.Instance.ExecutablePath)
{
Arguments = $"-s {exportName} -v {vehicle}",
UseShellExecute = true
});
}
catch
{
// executable not found / not configured yet
}
}
}