Skip to content

Commit f981ec2

Browse files
committed
refactor: Clean up environment parsing code including a new block list utility
1 parent 6c3df12 commit f981ec2

File tree

3 files changed

+119
-159
lines changed

3 files changed

+119
-159
lines changed
Lines changed: 85 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// COPYRIGHT 2009 - 2023 by the Open Rails project.
1+
// COPYRIGHT 2009 - 2023 by the Open Rails project.
22
//
33
// This file is part of Open Rails.
44
//
@@ -22,124 +22,55 @@ namespace Orts.Formats.Msts
2222
{
2323
public class EnvironmentFile
2424
{
25-
public float WaterWaveHeight;
26-
public float WaterWaveSpeed;
27-
public float WorldSkynLayers;
28-
public List<ENVFileWaterLayer> WaterLayers;
29-
public List<ENVFileSkyLayer> SkyLayers;
30-
public List<ENVFileSkySatellite> SkySatellite;
25+
public List<WaterLayer> WaterLayers;
26+
public List<SkyLayer> SkyLayers;
27+
public List<SkySatellite> SkySatellites;
3128

3229
public EnvironmentFile(string filePath)
3330
{
3431
using (STFReader stf = new STFReader(filePath, false))
3532
{
36-
stf.ParseFile(new STFReader.TokenProcessor[]
33+
stf.ParseFile(new[]
3734
{
38-
new STFReader.TokenProcessor("world", () => stf.ParseWholeBlock(new STFReader.TokenProcessor[]
35+
new STFReader.TokenProcessor("world", () => stf.ParseWholeBlock(new[]
3936
{
40-
new STFReader.TokenProcessor("world_water", () => stf.ParseWholeBlock(new STFReader.TokenProcessor[]
37+
new STFReader.TokenProcessor("world_water", () => stf.ParseWholeBlock(new[]
4138
{
42-
new STFReader.TokenProcessor("world_water_wave_height", () => { WaterWaveHeight = stf.ReadFloatBlock(STFReader.UNITS.Distance, null); }),
43-
new STFReader.TokenProcessor("world_water_wave_speed", () => { WaterWaveSpeed = stf.ReadFloatBlock(STFReader.UNITS.Speed, null); }),
44-
new STFReader.TokenProcessor("world_water_layers", () => { ParseWaterLayers(stf); }),
39+
new STFReader.TokenProcessor("world_water_layers", () => stf.ParseBlockList(ref WaterLayers, "world_water_layer", s => new WaterLayer(s))),
4540
})),
46-
})),
47-
});
48-
}
49-
50-
using (STFReader stf = new STFReader(filePath, false))
51-
{
52-
stf.ParseFile(new STFReader.TokenProcessor[]
53-
{
54-
new STFReader.TokenProcessor("world", () => stf.ParseWholeBlock(new STFReader.TokenProcessor[]
55-
{
56-
new STFReader.TokenProcessor("world_sky", () => stf.ParseWholeBlock(new STFReader.TokenProcessor[]
41+
new STFReader.TokenProcessor("world_sky", () => stf.ParseWholeBlock(new[]
5742
{
58-
new STFReader.TokenProcessor("worldskynlayers_behind_satellites", () => { WorldSkynLayers = stf.ReadFloatBlock(STFReader.UNITS.Any, null); }),
59-
new STFReader.TokenProcessor("world_sky_layers", () => { ParseSkyLayers(stf); }),
60-
new STFReader.TokenProcessor("world_sky_satellites", () => { ParseWorldSkySatellites(stf); }),
43+
new STFReader.TokenProcessor("world_sky_layers", () => stf.ParseBlockList(ref SkyLayers, "world_sky_layer", s => new SkyLayer(s))),
44+
new STFReader.TokenProcessor("world_sky_satellites", () => stf.ParseBlockList(ref SkySatellites, "world_sky_satellite", s => new SkySatellite(s))),
6145
})),
6246
})),
6347
});
6448
}
6549
}
6650

67-
private void ParseWaterLayers(STFReader stf)
68-
{
69-
stf.MustMatch("(");
70-
int texturelayers = stf.ReadInt(null);
71-
WaterLayers = new List<ENVFileWaterLayer>(texturelayers);
72-
stf.ParseBlock(new STFReader.TokenProcessor[]
73-
{
74-
new STFReader.TokenProcessor("world_water_layer", () =>
75-
{
76-
if (texturelayers-- > 0)
77-
{
78-
WaterLayers.Add(new ENVFileWaterLayer(stf));
79-
}
80-
}),
81-
});
82-
}
83-
84-
private void ParseSkyLayers(STFReader stf)
85-
{
86-
stf.MustMatch("(");
87-
int skylayers = stf.ReadInt(null);
88-
SkyLayers = new List<ENVFileSkyLayer>(skylayers);
89-
90-
stf.ParseBlock(new STFReader.TokenProcessor[]
91-
{
92-
new STFReader.TokenProcessor("world_sky_layer", () =>
93-
{
94-
if (skylayers-- > 0)
95-
{
96-
SkyLayers.Add(new ENVFileSkyLayer(stf));
97-
}
98-
}),
99-
});
100-
}
101-
102-
private void ParseWorldSkySatellites(STFReader stf)
103-
{
104-
stf.MustMatch("(");
105-
int skysatellite = stf.ReadInt(null);
106-
SkySatellite = new List<ENVFileSkySatellite>(skysatellite);
107-
108-
stf.ParseBlock(new STFReader.TokenProcessor[]
109-
{
110-
new STFReader.TokenProcessor("world_sky_satellite", () =>
111-
{
112-
if (skysatellite-- > 0)
113-
{
114-
SkySatellite.Add(new ENVFileSkySatellite(stf));
115-
}
116-
}),
117-
});
118-
}
119-
120-
public class ENVFileWaterLayer
51+
public class WaterLayer
12152
{
12253
public float Height;
12354
public string TextureName;
12455

125-
public ENVFileWaterLayer(STFReader stf)
56+
public WaterLayer(STFReader stf)
12657
{
127-
stf.ParseWholeBlock(new STFReader.TokenProcessor[]
58+
stf.ParseWholeBlock(new[]
12859
{
12960
new STFReader.TokenProcessor("world_water_layer_height", () => { Height = stf.ReadFloatBlock(STFReader.UNITS.Distance, null); }),
130-
new STFReader.TokenProcessor("world_anim_shader", () => stf.ParseWholeBlock(new STFReader.TokenProcessor[]
61+
new STFReader.TokenProcessor("world_anim_shader", () => stf.ParseWholeBlock(new[]
13162
{
13263
new STFReader.TokenProcessor("world_shader", () =>
13364
{
13465
stf.MustMatch("(");
13566
stf.ReadString() /*TextureMode*/;
136-
stf.ParseBlock(new STFReader.TokenProcessor[]
67+
stf.ParseBlock(new[]
13768
{
13869
new STFReader.TokenProcessor("terrain_texslots", () =>
13970
{
14071
stf.MustMatch("(");
14172
stf.ReadInt(null) /*Count*/;
142-
stf.ParseBlock(new STFReader.TokenProcessor[]
73+
stf.ParseBlock(new[]
14374
{
14475
new STFReader.TokenProcessor("terrain_texslot", () =>
14576
{
@@ -155,94 +86,54 @@ public ENVFileWaterLayer(STFReader stf)
15586
});
15687
}
15788
}
158-
}
15989

160-
public class ENVFileSkyLayer
161-
{
162-
public string FadeinBeginTime;
163-
public string FadeinEndTime;
164-
public string TextureName;
165-
public string TextureMode;
166-
public float TileX;
167-
public float TileY;
168-
169-
public ENVFileSkyLayer(STFReader stf)
90+
public class SkyLayer
17091
{
171-
stf.ParseWholeBlock(new STFReader.TokenProcessor[]
92+
public string FadeInBeginTime;
93+
public string FadeInEndTime;
94+
public string TextureName;
95+
public string TextureMode;
96+
public float TileX;
97+
public float TileY;
98+
99+
public SkyLayer(STFReader stf)
172100
{
173-
new STFReader.TokenProcessor("world_sky_layer_fadein", () =>
174-
{
175-
stf.MustMatch("(");
176-
FadeinBeginTime = stf.ReadString();
177-
FadeinEndTime = stf.ReadString();
178-
stf.SkipRestOfBlock();
179-
}),
180-
new STFReader.TokenProcessor("world_anim_shader", () => stf.ParseWholeBlock(new STFReader.TokenProcessor[]
101+
stf.ParseWholeBlock(new[]
181102
{
182-
new STFReader.TokenProcessor("world_anim_shader_frames", () => stf.ParseWholeBlock(new STFReader.TokenProcessor[]
103+
new STFReader.TokenProcessor("world_sky_layer_fadein", () =>
183104
{
184-
new STFReader.TokenProcessor("world_anim_shader_frame", () => stf.ParseWholeBlock(new STFReader.TokenProcessor[]
185-
{
186-
new STFReader.TokenProcessor("world_anim_shader_frame_uvtiles", () =>
187-
{
188-
stf.MustMatch("(");
189-
TileX = stf.ReadFloat(STFReader.UNITS.Any, 1.0f);
190-
TileY = stf.ReadFloat(STFReader.UNITS.Any, 1.0f);
191-
stf.ParseBlock(new STFReader.TokenProcessor[]
192-
{
193-
});
194-
}),
195-
})),
196-
})),
197-
})),
198-
new STFReader.TokenProcessor("world_shader", () =>
199-
{
200-
stf.MustMatch("(");
201-
TextureMode = stf.ReadString();
202-
stf.ParseBlock(new STFReader.TokenProcessor[]
105+
stf.MustMatch("(");
106+
FadeInBeginTime = stf.ReadString();
107+
FadeInEndTime = stf.ReadString();
108+
stf.SkipRestOfBlock();
109+
}),
110+
new STFReader.TokenProcessor("world_anim_shader", () => stf.ParseWholeBlock(new[]
203111
{
204-
new STFReader.TokenProcessor("terrain_texslots", () =>
112+
new STFReader.TokenProcessor("world_anim_shader_frames", () => stf.ParseWholeBlock(new[]
205113
{
206-
stf.MustMatch("(");
207-
stf.ReadInt(null) /*Count*/;
208-
stf.ParseBlock(new STFReader.TokenProcessor[]
114+
new STFReader.TokenProcessor("world_anim_shader_frame", () => stf.ParseWholeBlock(new[]
209115
{
210-
new STFReader.TokenProcessor("terrain_texslot", () =>
116+
new STFReader.TokenProcessor("world_anim_shader_frame_uvtiles", () =>
211117
{
212118
stf.MustMatch("(");
213-
TextureName = stf.ReadString();
214-
stf.SkipRestOfBlock();
119+
TileX = stf.ReadFloat(STFReader.UNITS.Any, 1.0f);
120+
TileY = stf.ReadFloat(STFReader.UNITS.Any, 1.0f);
121+
stf.ParseBlock(new STFReader.TokenProcessor[0]);
215122
}),
216-
});
217-
}),
218-
});
219-
}),
220-
});
221-
}
222-
}
223-
224-
public class ENVFileSkySatellite
225-
{
226-
public string TextureName;
227-
public string TextureMode;
228-
229-
public ENVFileSkySatellite(STFReader stf)
230-
{
231-
stf.ParseWholeBlock(new STFReader.TokenProcessor[]
232-
{
233-
new STFReader.TokenProcessor("world_anim_shader", () => stf.ParseWholeBlock(new STFReader.TokenProcessor[]
234-
{
123+
})),
124+
})),
125+
})),
235126
new STFReader.TokenProcessor("world_shader", () =>
236127
{
237128
stf.MustMatch("(");
238129
TextureMode = stf.ReadString();
239-
stf.ParseBlock(new STFReader.TokenProcessor[]
130+
stf.ParseBlock(new[]
240131
{
241132
new STFReader.TokenProcessor("terrain_texslots", () =>
242133
{
243134
stf.MustMatch("(");
244135
stf.ReadInt(null) /*Count*/;
245-
stf.ParseBlock(new STFReader.TokenProcessor[]
136+
stf.ParseBlock(new[]
246137
{
247138
new STFReader.TokenProcessor("terrain_texslot", () =>
248139
{
@@ -254,8 +145,46 @@ public ENVFileSkySatellite(STFReader stf)
254145
}),
255146
});
256147
}),
257-
})),
258-
});
148+
});
149+
}
150+
}
151+
152+
public class SkySatellite
153+
{
154+
public string TextureName;
155+
public string TextureMode;
156+
157+
public SkySatellite(STFReader stf)
158+
{
159+
stf.ParseWholeBlock(new[]
160+
{
161+
new STFReader.TokenProcessor("world_anim_shader", () => stf.ParseWholeBlock(new[]
162+
{
163+
new STFReader.TokenProcessor("world_shader", () =>
164+
{
165+
stf.MustMatch("(");
166+
TextureMode = stf.ReadString();
167+
stf.ParseBlock(new[]
168+
{
169+
new STFReader.TokenProcessor("terrain_texslots", () =>
170+
{
171+
stf.MustMatch("(");
172+
stf.ReadInt(null) /*Count*/;
173+
stf.ParseBlock(new[]
174+
{
175+
new STFReader.TokenProcessor("terrain_texslot", () =>
176+
{
177+
stf.MustMatch("(");
178+
TextureName = stf.ReadString();
179+
stf.SkipRestOfBlock();
180+
}),
181+
});
182+
}),
183+
});
184+
}),
185+
})),
186+
});
187+
}
259188
}
260189
}
261190
}

Source/Orts.Parsers.Msts/STFReader.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1564,6 +1564,37 @@ public void ParseWholeBlock(TokenProcessor[] processors)
15641564
ParseBlock(processors);
15651565
}
15661566

1567+
/// <summary>
1568+
/// Parse an entire STF block containing a count (int) and repeated sub-blocks of name <param name="blockName" />.
1569+
/// </summary>
1570+
/// <param name="list">A list to receive the sub-blocks</param>
1571+
/// <param name="blockName">The name of the repeated sub-blocks</param>
1572+
/// <param name="constructor">A function which constructs an object for the list</param>
1573+
public void ParseBlockList<T>(ref List<T> list, string blockName, Func<STFReader, T> constructor)
1574+
{
1575+
MustMatch("(");
1576+
var count = ReadInt(null);
1577+
var listForLambda = list = new List<T>(count);
1578+
ParseBlock(new[]
1579+
{
1580+
new TokenProcessor(blockName, () =>
1581+
{
1582+
if (count-- > 0)
1583+
{
1584+
listForLambda.Add(constructor(this));
1585+
}
1586+
else
1587+
{
1588+
STFException.TraceWarning(this, $"Skipped extra {blockName}");
1589+
}
1590+
}),
1591+
});
1592+
if (count > 0)
1593+
{
1594+
STFException.TraceWarning(this, $"{count} missing {blockName}");
1595+
}
1596+
}
1597+
15671598
#region *** Delegate and Structure definitions used by the Parse...() methods.
15681599
/// <summary>This delegate definition is used by the ParseFile and ParseBlock methods, and is called when an associated matching token is found.
15691600
/// </summary>

Source/RunActivity/Viewer3D/MSTSSky.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,7 @@ public MSTSSkyMaterial(Viewer viewer)
512512
mstsskytexturey = mstsskytexture[i].TileY;
513513

514514
}
515-
else if(mstsskytexture[i].FadeinBeginTime != null)
515+
else if(mstsskytexture[i].FadeInBeginTime != null)
516516
{
517517
MSTSSkyStarTexture = MSTSSkyTexture[i];
518518
mstsskytexturex = mstsskytexture[i].TileX;
@@ -536,9 +536,9 @@ public MSTSSkyMaterial(Viewer viewer)
536536
MSTSSkyTexture.Add(SharedTextureManager.Get(Viewer.RenderProcess.GraphicsDevice, System.IO.Path.Combine(Viewer.ContentPath, "SkyDome1.png")));
537537
MSTSSkyStarTexture = SharedTextureManager.Get(Viewer.RenderProcess.GraphicsDevice, System.IO.Path.Combine(Viewer.ContentPath, "Starmap_N.png"));
538538
}
539-
if (viewer.ENVFile.SkySatellite != null)
539+
if (viewer.ENVFile.SkySatellites != null)
540540
{
541-
var mstsskysatellitetexture = Viewer.ENVFile.SkySatellite.ToArray();
541+
var mstsskysatellitetexture = Viewer.ENVFile.SkySatellites.ToArray();
542542

543543
string mstsSkySunTexture = Viewer.Simulator.RoutePath + @"\envfiles\textures\" + mstsskysatellitetexture[0].TextureName.ToString();
544544
string mstsSkyMoonTexture = Viewer.Simulator.RoutePath + @"\envfiles\textures\" + mstsskysatellitetexture[1].TextureName.ToString();

0 commit comments

Comments
 (0)