mirror of
https://github.com/MaSzyna-EU07/StarterNG.git
synced 2026-07-17 17:09:19 +02:00
Add trainset parser
This commit is contained in:
@@ -9,8 +9,8 @@ namespace StarterNG.Classes;
|
||||
public enum eDriverType
|
||||
{
|
||||
Headdriver,
|
||||
Reardriver,
|
||||
Passanger,
|
||||
Reardriver,
|
||||
Passenger,
|
||||
Nobody
|
||||
}
|
||||
|
||||
@@ -20,57 +20,69 @@ public class Trainset
|
||||
public string Track;
|
||||
public float Offset;
|
||||
public float Velocity;
|
||||
public string Description;
|
||||
public List<Dynamic> Vehicles;
|
||||
public Trainset(string trainsetEntry)
|
||||
{
|
||||
|
||||
Vehicles = new List<Dynamic>();
|
||||
|
||||
Description = "";
|
||||
List<string> tokens = Regex
|
||||
.Matches(trainsetEntry, @"\r\n|\n|[^\s]+")
|
||||
.Matches(trainsetEntry, @"/\*[\s\S]*?\*/|//[^\r\n]*|[^\s\r\n]+")
|
||||
.Select(m => m.Value)
|
||||
.Where(t => !t.StartsWith("//") && !t.StartsWith("/*"))
|
||||
.ToList();
|
||||
|
||||
// handle specific descriptions
|
||||
// //$o
|
||||
var match = Regex.Match(
|
||||
trainsetEntry,
|
||||
@"^\s*//\$o\s*(.*)$",
|
||||
RegexOptions.Multiline
|
||||
);
|
||||
if (match.Success)
|
||||
this.Description = match.Groups[1].Value.Trim();
|
||||
|
||||
// parse trainset
|
||||
|
||||
for (int i = 0; i < tokens.Count; i++)
|
||||
{
|
||||
// handle comments
|
||||
if (tokens[i].StartsWith("//"))
|
||||
{
|
||||
while (tokens[i] != "\n" && tokens.Count < i) i++;
|
||||
}
|
||||
|
||||
|
||||
if (tokens[i] == "endtrainset")
|
||||
break;
|
||||
|
||||
// trainset properties
|
||||
if (tokens[i] == "trainset")
|
||||
{
|
||||
i++;
|
||||
this.Name = tokens[i++];
|
||||
this.Track = tokens[i++];
|
||||
this.Offset = float.Parse(tokens[i++], CultureInfo.InvariantCulture);
|
||||
this.Velocity = float.Parse(tokens[i++], CultureInfo.InvariantCulture);
|
||||
this.Name = tokens[++i];
|
||||
this.Track = tokens[++i];
|
||||
this.Offset = float.Parse(tokens[++i], CultureInfo.InvariantCulture);
|
||||
this.Velocity = float.Parse(tokens[++i], CultureInfo.InvariantCulture);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// skip entire assignments block
|
||||
if (tokens[i] == "assignments")
|
||||
{
|
||||
while (tokens[i] != "endassignment") i++;
|
||||
while (i < tokens.Count && tokens[i] != "endassignment")
|
||||
i++;
|
||||
i++; // jump over endassignment
|
||||
continue;
|
||||
}
|
||||
|
||||
// load vehicles
|
||||
if (tokens[i] == "node")
|
||||
{
|
||||
i++; // node keyword
|
||||
//i++; // node keyword
|
||||
Dynamic nodeDynamic = new Dynamic();
|
||||
nodeDynamic.RangeMax = float.Parse(tokens[i++], CultureInfo.InvariantCulture);
|
||||
nodeDynamic.RangeMin = float.Parse(tokens[i++], CultureInfo.InvariantCulture);
|
||||
nodeDynamic.Name = tokens[i++];
|
||||
nodeDynamic.RangeMax = float.Parse(tokens[++i], CultureInfo.InvariantCulture);
|
||||
nodeDynamic.RangeMin = float.Parse(tokens[++i], CultureInfo.InvariantCulture);
|
||||
nodeDynamic.Name = tokens[++i];
|
||||
i++; // dynamic keyword
|
||||
nodeDynamic.DataFolder = tokens[i++];
|
||||
nodeDynamic.SkinFile = tokens[i++];
|
||||
nodeDynamic.MmdFile = tokens[i++];
|
||||
i++; // skip offset
|
||||
string driverType = tokens[i++];
|
||||
nodeDynamic.DataFolder = tokens[++i];
|
||||
nodeDynamic.SkinFile = tokens[++i];
|
||||
nodeDynamic.MmdFile = tokens[++i];
|
||||
nodeDynamic.Offset = float.Parse(tokens[++i], CultureInfo.InvariantCulture);
|
||||
string driverType = tokens[++i];
|
||||
switch (driverType)
|
||||
{
|
||||
case "headdriver":
|
||||
@@ -79,22 +91,22 @@ public class Trainset
|
||||
case "reardriver":
|
||||
nodeDynamic.DriverType = eDriverType.Reardriver;
|
||||
break;
|
||||
case "passanger":
|
||||
nodeDynamic.DriverType = eDriverType.Passanger;
|
||||
case "passenger":
|
||||
nodeDynamic.DriverType = eDriverType.Passenger;
|
||||
break;
|
||||
default:
|
||||
nodeDynamic.DriverType = eDriverType.Nobody;
|
||||
break;
|
||||
}
|
||||
|
||||
nodeDynamic.couplingData = (byte)int.Parse(tokens[i++].Split('.')[0]);
|
||||
nodeDynamic.couplingData = (byte)int.Parse(tokens[++i].Split('.')[0]);
|
||||
|
||||
nodeDynamic.Tail = "";
|
||||
while (tokens[i] != "enddynamic")
|
||||
while (i + 1 < tokens.Count && tokens[i + 1] != "enddynamic")
|
||||
{
|
||||
nodeDynamic.Tail += " " + tokens[i];
|
||||
i++;
|
||||
nodeDynamic.Tail += " " + tokens[++i];
|
||||
}
|
||||
i++; // jump over enddynamic
|
||||
|
||||
Vehicles.Add(nodeDynamic);
|
||||
}
|
||||
@@ -122,8 +134,8 @@ public class Trainset
|
||||
case eDriverType.Reardriver:
|
||||
driverType = "reardriver";
|
||||
break;
|
||||
case eDriverType.Passanger:
|
||||
driverType = "passanger";
|
||||
case eDriverType.Passenger:
|
||||
driverType = "passenger";
|
||||
break;
|
||||
default:
|
||||
driverType = "nobody";
|
||||
@@ -131,7 +143,10 @@ public class Trainset
|
||||
}
|
||||
|
||||
entry +=
|
||||
$"node {vehicle.RangeMax} {vehicle.RangeMin} {vehicle.Name} dynamic {vehicle.DataFolder} {vehicle.SkinFile} {vehicle.MmdFile} {driverType} {vehicle.couplingData} {vehicle.Tail}\n";
|
||||
$"node {vehicle.RangeMax} {vehicle.RangeMin} {vehicle.Name} dynamic " +
|
||||
$"{vehicle.DataFolder} {vehicle.SkinFile} {vehicle.MmdFile} " +
|
||||
$"{vehicle.Offset.ToString(CultureInfo.InvariantCulture)} " +
|
||||
$"{driverType} {vehicle.couplingData}{vehicle.Tail} enddynamic\n";
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -17,20 +17,17 @@
|
||||
<RowDefinition Height="40" />
|
||||
</Grid.RowDefinitions>
|
||||
<sukiUi:GroupBox Grid.RowSpan="2" Header="Scenerie">
|
||||
<TreeView Name="sceneryList">
|
||||
<TreeView Name="sceneryList" SelectionChanged="SceneryList_OnSelectionChanged">
|
||||
|
||||
</TreeView>
|
||||
</sukiUi:GroupBox>
|
||||
<sukiUi:GroupBox Grid.Column="1" Header="Pojazdy">
|
||||
<ListBox>
|
||||
<ListBoxItem>EP07P-2003</ListBoxItem>
|
||||
<ListBoxItem>EP07-1049</ListBoxItem>
|
||||
<ListBoxItem>EN57AKM-1562</ListBoxItem>
|
||||
<ListBox Name="vehicleList" SelectionChanged="VehicleList_OnSelectionChanged">
|
||||
</ListBox>
|
||||
</sukiUi:GroupBox>
|
||||
<sukiUi:GroupBox Grid.Column="1" Grid.Row="1" Header="Opis scenariusza">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<TextBlock TextWrapping="Wrap">
|
||||
<TextBlock TextWrapping="Wrap" Name="missionDescription">
|
||||
Prowadzimy RegioExpress RPE23119 z Dębicy do Sandomierza. Misję rozpoczynamy w lokomotywowni w Dębicy. Jedziemy zgodnie ze wskazaniami tarcz manewrowych na bocznicę z drugiej strony stacji, gdzie przypinamy wagony do naszego składu, po czym wciągamy je w peron. Następnie jedziemy do Sandomierza, zatrzymując się po drodze tylko w Turowie. Po przyjeździe do Sandomierza odczepiamy lokomotywę i zjeżdżamy na tor postojowy, gdzie kończymy służbę. Czas misji: ok. 80 minut.
|
||||
</TextBlock>
|
||||
</ScrollViewer>
|
||||
@@ -41,8 +38,7 @@
|
||||
<ScrollViewer VerticalAlignment="Bottom"
|
||||
HorizontalScrollBarVisibility="Auto"
|
||||
VerticalScrollBarVisibility="Disabled">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Image Source="avares://StarterNG/Assets/Test/ep07p.bmp" Height="50"></Image>
|
||||
<StackPanel Orientation="Horizontal" Name="consistStack">
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</sukiUi:GroupBox>
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Linq;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Media.Imaging;
|
||||
using StarterNG.Classes;
|
||||
|
||||
namespace StarterNG.Views;
|
||||
@@ -66,8 +67,72 @@ public partial class Scenarios : UserControl
|
||||
Tag = i
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void SceneryList_OnSelectionChanged(object? sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
var item = sceneryList.SelectedItem as TreeViewItem;
|
||||
if (item?.Tag is not int tag)
|
||||
return;
|
||||
Scenery selectedScn = sceneries[tag];
|
||||
vehicleList.Items.Clear();
|
||||
|
||||
// add all trainsets to list
|
||||
for (int i = 0; i < selectedScn.Trainsets.Count; i++)
|
||||
{
|
||||
string trainsetName = string.Join(
|
||||
" + ",
|
||||
selectedScn.Trainsets[i].Vehicles.Select(dyn => dyn.Name)
|
||||
);
|
||||
if (string.IsNullOrWhiteSpace(trainsetName)) continue; // skip empty
|
||||
vehicleList.Items.Add(new ListBoxItem
|
||||
{
|
||||
Content = trainsetName,
|
||||
Tag = i
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void VehicleList_OnSelectionChanged(object? sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
consistStack.Children.Clear();
|
||||
|
||||
// get selected scenery
|
||||
var tItem = sceneryList.SelectedItem as TreeViewItem;
|
||||
if (tItem?.Tag is not int tTag)
|
||||
return;
|
||||
Scenery selectedScn = sceneries[tTag];
|
||||
|
||||
// get selected trainset
|
||||
ListBoxItem vItem = vehicleList.SelectedItem as ListBoxItem;
|
||||
if (vItem?.Tag is not int vTag)
|
||||
return;
|
||||
Trainset selectedTrainset = selectedScn.Trainsets[vTag];
|
||||
foreach (var train in selectedTrainset.Vehicles)
|
||||
{
|
||||
string path = Path.Combine(
|
||||
"textures",
|
||||
"mini",
|
||||
train.SkinFile + ".bmp"
|
||||
);
|
||||
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
// fallback
|
||||
continue;
|
||||
}
|
||||
|
||||
var bitmap = new Bitmap(path);
|
||||
var image = new Image
|
||||
{
|
||||
Source = bitmap,
|
||||
Height = 45,
|
||||
Stretch = Avalonia.Media.Stretch.Uniform,
|
||||
Margin = new Thickness(0)
|
||||
};
|
||||
consistStack.Children.Add(image);
|
||||
}
|
||||
missionDescription.Text = selectedTrainset.Description;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user