Open the scenery editor from the start button's menu

eu07 -edit with the scenery file itself, not the export, so what is saved
lands in the scenery. Not every simulator build has the editor; that is said
before it starts.
This commit is contained in:
maj00r
2026-10-04 14:17:02 +02:00
parent e8cec0867e
commit be34d48033
8 changed files with 74 additions and 5 deletions

View File

@@ -95,6 +95,18 @@ public class StartSimulationTests
Assert.Equal(new[] { "second", "third" }, start.SimulatorLogTail(2));
}
[Fact]
public void The_editor_opens_the_scenery_itself_not_an_export()
{
var (start, launcher, installation) = Rig(files => files.WithExecutable(Build));
var result = start.ExecuteEditor();
Assert.Equal(SimulationStartOutcome.Started, result.Outcome);
Assert.Equal(new[] { "-edit", "td.scn" }, launcher.Arguments);
Assert.False(installation.Files.FileExists(TestInstallation.At("scenery", "$td.scn")));
}
[Fact]
public void A_file_that_cannot_be_run_is_not()
{

View File

@@ -183,6 +183,27 @@ public sealed class StartSimulation
if (saveSettings)
_settings.CaptureAndSave();
string[] arguments = freeFly || string.IsNullOrEmpty(vehicle)
? new[] { "-s", exportName }
: new[] { "-s", exportName, "-v", vehicle };
return Launch(arguments);
}
/// <summary>
/// Opens the selected scenery in the simulator's editor. The scenery file itself,
/// not an export: what the editor saves has to land in the scenery.
/// </summary>
public SimulationStartResult ExecuteEditor()
{
if (_state.CurrentScenery is not { } scenery)
return new SimulationStartResult(SimulationStartOutcome.NothingSelected);
return Launch(new[] { "-edit", Path.GetFileName(scenery.Path) });
}
private SimulationStartResult Launch(IReadOnlyList<string> arguments)
{
string executable = Path.GetFullPath(_settings.ResolveExecutable(out var problem));
// A binary for the other system is let through: on Linux a Windows build
@@ -191,10 +212,6 @@ public sealed class StartSimulation
return new SimulationStartResult(SimulationStartOutcome.ExecutableProblem, ExecutablePath: executable,
Problem: problem);
string[] arguments = freeFly || string.IsNullOrEmpty(vehicle)
? new[] { "-s", exportName }
: new[] { "-s", exportName, "-v", vehicle };
// The installation, not the folder of the binary: a simulator picked from a
// build tree lives beside the data, and the data is what it opens.
var (program, programArguments) = _executables.LaunchCommand(executable, arguments);

View File

@@ -469,6 +469,15 @@ public partial class MainWindow : Window
freeFly.Click += async (_, _) => await LaunchAsync(saveSettings: true, freeFly: true);
menu.Items.Add(freeFly);
menu.Items.Add(new Separator());
var editor = new MenuItem
{
Header = App.Loc["StartEditor"],
IsEnabled = AppServices.Current.State.CurrentScenery is not null
};
editor.Click += async (_, _) => await LaunchEditorAsync();
menu.Items.Add(editor);
menu.Open(startButton);
}
@@ -490,7 +499,28 @@ public partial class MainWindow : Window
LoadingScreen.Prepare(trainset.Logo, Path.GetFileNameWithoutExtension(scenery.Path));
var result = AppServices.Current.StartSimulation.Execute(freeFly, saveSettings);
await FollowStartAsync(AppServices.Current.StartSimulation.Execute(freeFly, saveSettings));
}
/// <summary>
/// The scenery editor, which only some simulator builds have - said up front,
/// since one without it simply does not open it.
/// </summary>
private async Task LaunchEditorAsync()
{
if (AppServices.Current.State.CurrentScenery is not { } scenery)
return;
if (!await MessageBox.Show(this, string.Format(App.Loc["StartEditorWarning"], Path.GetFileName(scenery.Path)),
App.Loc["StartEditor"], MessageBoxButtons.YesNo))
return;
await FollowStartAsync(AppServices.Current.StartSimulation.ExecuteEditor());
}
/// <summary>Reports a start that failed, or steps aside for the simulator that started.</summary>
private async Task FollowStartAsync(SimulationStartResult result)
{
switch (result.Outcome)
{
case SimulationStartOutcome.NothingSelected:

View File

@@ -557,6 +557,8 @@
<String key="WarehouseImportFile">Přidat soupravy ze souboru...</String>
<String key="StartWithoutSaving">Spustit bez uložení nastavení</String>
<String key="StartFreeFly">Spustit bez vozidla</String>
<String key="StartEditor">Spustit editor scenérie</String>
<String key="StartEditorWarning">Editor scenérie (eu07 -edit) mají jen některé verze simulátoru. Pokud ho vybraný simulátor nepodporuje, editor se neotevře. Editor pracuje přímo se souborem {0}, ne s kopií od starteru, takže uložené změny se zapíší do scenérie. Spustit?</String>
<String key="VolumePaused">Hlasitost při pauze</String>
<String key="DebugLogVisible">Zobrazovat průběh simulace</String>
<String key="PyScreenPriority">Frekvence obnovení doplňkových obrazovek</String>

View File

@@ -592,6 +592,8 @@
<String key="WarehouseImportFile">Add consists from file...</String>
<String key="StartWithoutSaving">Start without saving settings</String>
<String key="StartFreeFly">Start with no vehicle</String>
<String key="StartEditor">Open the scenery editor</String>
<String key="StartEditorWarning">Only some simulator builds have the scenery editor (eu07 -edit). If the selected simulator does not, the editor will not open. It works on {0} itself, not on the starter's copy, so what you save goes into the scenery. Start it?</String>
<String key="VolumePaused">Volume while paused</String>
<String key="DebugLogVisible">Show log in console</String>
<String key="PyScreenPriority">Extra screen update delay</String>

View File

@@ -557,6 +557,8 @@
<String key="WarehouseImportFile">Szerelvények hozzáadása fájlból...</String>
<String key="StartWithoutSaving">Indítás a beállítások mentése nélkül</String>
<String key="StartFreeFly">Indítás jármű nélkül</String>
<String key="StartEditor">Pályaszerkesztő indítása</String>
<String key="StartEditorWarning">A pályaszerkesztő (eu07 -edit) csak a szimulátor egyes verzióiban érhető el. Ha a kiválasztott szimulátor nem támogatja, a szerkesztő nem nyílik meg. Közvetlenül a(z) {0} fájlon dolgozik, nem a starter másolatán, így a mentett változások a pályába kerülnek. Elindítod?</String>
<String key="VolumePaused">Hangerő szünet alatt</String>
<String key="DebugLogVisible">Szimuláció menetének megjelenítése</String>
<String key="PyScreenPriority">Kiegészítő képernyők frissítési gyakorisága</String>

View File

@@ -592,6 +592,8 @@
<String key="WarehouseImportFile">Dodaj składy z pliku...</String>
<String key="StartWithoutSaving">Uruchom bez zapisu ustawień</String>
<String key="StartFreeFly">Uruchom bez pojazdu</String>
<String key="StartEditor">Uruchom edytor scenerii</String>
<String key="StartEditorWarning">Edytor scenerii (eu07 -edit) mają tylko niektóre wersje symulatora. Jeśli wybrany plik symulatora go nie obsługuje, edytor się nie otworzy. Edytor pracuje na samym pliku {0}, a nie na kopii przygotowanej przez starter, więc zapisane zmiany trafią do scenerii. Uruchomić?</String>
<String key="VolumePaused">Głośność podczas pauzy</String>
<String key="DebugLogVisible">Wyświetlaj log w konsoli</String>
<String key="PyScreenPriority">Opóźnienie odświeżania ekranów dodatkowych</String>

View File

@@ -557,6 +557,8 @@
<String key="WarehouseImportFile">Добавить составы из файла...</String>
<String key="StartWithoutSaving">Запустить без сохранения настроек</String>
<String key="StartFreeFly">Запустить без транспорта</String>
<String key="StartEditor">Запустить редактор сценария</String>
<String key="StartEditorWarning">Редактор сценария (eu07 -edit) есть только в некоторых версиях симулятора. Если выбранный симулятор его не поддерживает, редактор не откроется. Он работает с самим файлом {0}, а не с копией стартера, поэтому сохранённые изменения попадут в сценарий. Запустить?</String>
<String key="VolumePaused">Громкость на паузе</String>
<String key="DebugLogVisible">Показывать ход симуляции</String>
<String key="PyScreenPriority">Частота обновления дополнительных экранов</String>