mirror of
https://github.com/MaSzyna-EU07/StarterNG.git
synced 2026-11-12 09:04:09 +01:00
Play back the black box of the simulator: map, cab, timeline, timetable and a summary
The simulator writes a black box of each run to physicslog/*.blackbox (blackbox_doc.md in the maszyna repository). Three new projects read and show it: - Eu07.BlackBox: the reader of the records, the recording as a whole (the user's vehicle and consist at a time, the timetable shown, the progress along it with arrival and departure delays, whether the train stood at the platform), the light patterns Pc 1, Pc 2, Pc 5 and Tb 1 with the ones the run asks for, and a summary of the driving. - Eu07.BlackBox.Views: the player window, with the scenery map (tracks, signals, W4 stop points with their heading and W32, the train, the cameras), the cab, the timeline of speed against the AI's reference, the events, the timetable and the summary. - Eu07.BlackBox.Viewer: the window on its own, with options for the time, following the train and screenshots. The tapes window of the starter lists the black boxes of each session beside the Hasler tapes and opens them in the player.
This commit is contained in:
30
Eu07.BlackBox.Viewer/Eu07.BlackBox.Viewer.csproj
Normal file
30
Eu07.BlackBox.Viewer/Eu07.BlackBox.Viewer.csproj
Normal file
@@ -0,0 +1,30 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<!-- The black box on its own, without the starter: opens the file given on the
|
||||
command line, or one picked. -->
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<PublishAot>true</PublishAot>
|
||||
<PublishTrimmed>true</PublishTrimmed>
|
||||
<IsAotCompatible>true</IsAotCompatible>
|
||||
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
<ApplicationIcon>..\StarterNG\Assets\starter.ico</ApplicationIcon>
|
||||
<AssemblyName>BlackBoxViewer</AssemblyName>
|
||||
<RootNamespace>Eu07.BlackBox.Viewer</RootNamespace>
|
||||
<VersionPrefix>1.0</VersionPrefix>
|
||||
<Company>eu07.pl</Company>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia" Version="12.1.4" />
|
||||
<PackageReference Include="Avalonia.Desktop" Version="12.1.4" />
|
||||
<PackageReference Include="Avalonia.Themes.Fluent" Version="12.1.4" />
|
||||
<PackageReference Include="Avalonia.Fonts.Inter" Version="12.1.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Eu07.BlackBox.Views\Eu07.BlackBox.Views.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
109
Eu07.BlackBox.Viewer/Program.cs
Normal file
109
Eu07.BlackBox.Viewer/Program.cs
Normal file
@@ -0,0 +1,109 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Styling;
|
||||
using Avalonia.Themes.Fluent;
|
||||
using Eu07.BlackBox.Views;
|
||||
|
||||
namespace Eu07.BlackBox.Viewer;
|
||||
|
||||
/// <summary>
|
||||
/// BlackBoxViewer [file.blackbox] [--live] [--time seconds] [--follow] [--timetable | --summary] [--screenshot out.png]
|
||||
/// --live follows a file the simulator still writes; --screenshot saves the window
|
||||
/// at the moment given and quits, for documentation and checks.
|
||||
/// </summary>
|
||||
internal static class Program
|
||||
{
|
||||
[STAThread]
|
||||
public static int Main(string[] args)
|
||||
{
|
||||
return BuildAvaloniaApp().StartWithClassicDesktopLifetime(args);
|
||||
}
|
||||
|
||||
public static AppBuilder BuildAvaloniaApp() =>
|
||||
AppBuilder.Configure<ViewerApp>()
|
||||
.UsePlatformDetect()
|
||||
.WithInterFont();
|
||||
}
|
||||
|
||||
internal sealed class ViewerApp : Application
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
Styles.Add(new FluentTheme());
|
||||
RequestedThemeVariant = ThemeVariant.Dark;
|
||||
}
|
||||
|
||||
public override void OnFrameworkInitializationCompleted()
|
||||
{
|
||||
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||
{
|
||||
var options = ViewerOptions.Parse(desktop.Args ?? Array.Empty<string>());
|
||||
var window = new BlackBoxWindow { WindowStartupLocation = Avalonia.Controls.WindowStartupLocation.CenterScreen };
|
||||
window.Live = options.Live;
|
||||
desktop.MainWindow = window;
|
||||
window.Opened += async (_, _) =>
|
||||
{
|
||||
if (options.File is { } file)
|
||||
await window.OpenAsync(Path.GetFullPath(file));
|
||||
window.ShowTimetable = options.Timetable;
|
||||
if (options.Summary)
|
||||
window.SummaryShown = true;
|
||||
if (options.Screenshot is { } shot)
|
||||
{
|
||||
await Screenshot.SaveAsync(window, shot, options.Time, options.Follow);
|
||||
return;
|
||||
}
|
||||
if (options.Time is { } time)
|
||||
window.SeekTo(time);
|
||||
window.FollowTrain = options.Follow;
|
||||
};
|
||||
}
|
||||
base.OnFrameworkInitializationCompleted();
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed record ViewerOptions(string? File, bool Live, double? Time, string? Screenshot, bool Follow, bool Timetable,
|
||||
bool Summary = false)
|
||||
{
|
||||
public static ViewerOptions Parse(string[] args)
|
||||
{
|
||||
string? file = null, screenshot = null;
|
||||
double? time = null;
|
||||
bool live = false, follow = false, timetable = false, summary = false;
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
{
|
||||
switch (args[i])
|
||||
{
|
||||
case "--live":
|
||||
live = true;
|
||||
break;
|
||||
case "--follow":
|
||||
follow = true;
|
||||
break;
|
||||
case "--timetable":
|
||||
timetable = true;
|
||||
break;
|
||||
case "--summary":
|
||||
summary = true;
|
||||
break;
|
||||
case "--time" when i + 1 < args.Length &&
|
||||
double.TryParse(args[i + 1], System.Globalization.NumberStyles.Float,
|
||||
System.Globalization.CultureInfo.InvariantCulture, out var t):
|
||||
time = t;
|
||||
++i;
|
||||
break;
|
||||
case "--screenshot" when i + 1 < args.Length:
|
||||
screenshot = args[++i];
|
||||
break;
|
||||
default:
|
||||
if (!args[i].StartsWith("--", StringComparison.Ordinal))
|
||||
file ??= args[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return new ViewerOptions(file, live, time, screenshot, follow, timetable, summary);
|
||||
}
|
||||
}
|
||||
28
Eu07.BlackBox.Viewer/Screenshot.cs
Normal file
28
Eu07.BlackBox.Viewer/Screenshot.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Media.Imaging;
|
||||
using Eu07.BlackBox.Views;
|
||||
|
||||
namespace Eu07.BlackBox.Viewer;
|
||||
|
||||
/// <summary>The window as it shows a moment, saved to a PNG; then the viewer closes.</summary>
|
||||
internal static class Screenshot
|
||||
{
|
||||
public static async Task SaveAsync(BlackBoxWindow window, string path, double? time, bool follow)
|
||||
{
|
||||
if (time is { } t)
|
||||
window.SeekTo(t);
|
||||
window.FollowTrain = follow;
|
||||
// A few frames for the layout and the first render.
|
||||
await Task.Delay(1000);
|
||||
if (window.Content is Control content)
|
||||
{
|
||||
var size = new PixelSize((int)content.Bounds.Width, (int)content.Bounds.Height);
|
||||
using var bitmap = new RenderTargetBitmap(size);
|
||||
bitmap.Render(content);
|
||||
bitmap.Save(path, new PngBitmapEncoderOptions());
|
||||
}
|
||||
window.Close();
|
||||
}
|
||||
}
|
||||
18
Eu07.BlackBox.Viewer/app.manifest
Normal file
18
Eu07.BlackBox.Viewer/app.manifest
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<!-- This manifest is used on Windows only.
|
||||
Don't remove it as it might cause problems with window transparency and embedded controls.
|
||||
For more details visit https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests -->
|
||||
<assemblyIdentity version="1.0.0.0" name="Eu07.BlackBoxViewer"/>
|
||||
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
<application>
|
||||
<!-- A list of the Windows versions that this application has been tested on
|
||||
and is designed to work with. Uncomment the appropriate elements
|
||||
and Windows will automatically select the most compatible environment. -->
|
||||
|
||||
<!-- Windows 10 -->
|
||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
||||
</application>
|
||||
</compatibility>
|
||||
</assembly>
|
||||
Reference in New Issue
Block a user