Skip to content

Commit a271215

Browse files
committed
1 parent 57b8254 commit a271215

File tree

2 files changed

+126
-4
lines changed

2 files changed

+126
-4
lines changed

Source/Orts.Formats.Msts/CabViewFile.cs

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ public enum CABViewControlTypes
183183
ORTS_OVERCHARGE,
184184
ORTS_BATTERY,
185185
ORTS_POWERKEY,
186+
ORTS_2DEXTERNALWIPERS,
186187

187188
// TCS Controls
188189
ORTS_TCS1,
@@ -313,7 +314,8 @@ public CabViewControls(STFReader stf, string basepath)
313314
new STFReader.TokenProcessor("combinedcontrol", ()=>{ Add(new CVCDiscrete(stf, basepath)); }),
314315
new STFReader.TokenProcessor("firebox", ()=>{ Add(new CVCFirebox(stf, basepath)); }),
315316
new STFReader.TokenProcessor("dialclock", ()=>{ ProcessDialClock(stf, basepath); }),
316-
new STFReader.TokenProcessor("digitalclock", ()=>{ Add(new CVCDigitalClock(stf, basepath)); })
317+
new STFReader.TokenProcessor("digitalclock", ()=>{ Add(new CVCDigitalClock(stf, basepath)); }),
318+
new STFReader.TokenProcessor("ortsanimateddisplay", ()=>{ Add(new CVCAnimatedDisplay(stf, basepath)); })
317319
});
318320

319321
//TODO Uncomment when parsed all type
@@ -1163,6 +1165,54 @@ protected int ParseNumStyle(STFReader stf)
11631165
return style;
11641166
}
11651167
}
1168+
1169+
public class CVCAnimatedDisplay : CVCWithFrames
1170+
{
1171+
public List<double> MSStyles = new List<double>();
1172+
public float CycleTimeS;
1173+
1174+
public CVCAnimatedDisplay(STFReader stf, string basepath)
1175+
{
1176+
1177+
stf.MustMatch("(");
1178+
stf.ParseBlock(new STFReader.TokenProcessor[] {
1179+
new STFReader.TokenProcessor("type", ()=>{ ParseType(stf); }),
1180+
new STFReader.TokenProcessor("position", ()=>{ ParsePosition(stf); }),
1181+
new STFReader.TokenProcessor("scalerange", ()=>{ ParseScaleRange(stf); }),
1182+
new STFReader.TokenProcessor("graphic", ()=>{ ParseGraphic(stf, basepath); }),
1183+
new STFReader.TokenProcessor("units", ()=>{ ParseUnits(stf); }),
1184+
new STFReader.TokenProcessor("ortscycletime", ()=>{
1185+
CycleTimeS = stf.ReadFloatBlock(STFReader.UNITS.Time, null); }),
1186+
new STFReader.TokenProcessor("states", ()=>{
1187+
stf.MustMatch("(");
1188+
FramesCount = stf.ReadInt(null);
1189+
FramesX = stf.ReadInt(null);
1190+
FramesY = stf.ReadInt(null);
1191+
stf.ParseBlock(new STFReader.TokenProcessor[] {
1192+
new STFReader.TokenProcessor("state", ()=>{
1193+
stf.MustMatch("(");
1194+
stf.ParseBlock( new STFReader.TokenProcessor[] {
1195+
new STFReader.TokenProcessor("style", ()=>{ MSStyles.Add(ParseNumStyle(stf));
1196+
}),
1197+
new STFReader.TokenProcessor("switchval", ()=>{ Values.Add(stf.ReadFloatBlock(STFReader.UNITS.None, null))
1198+
; }),
1199+
});}),
1200+
});
1201+
if (Values.Count > 0) MaxValue = Values.Last();
1202+
for (int i = Values.Count; i < FramesCount; i++)
1203+
Values.Add(-10000);
1204+
}),
1205+
});
1206+
}
1207+
protected int ParseNumStyle(STFReader stf)
1208+
{
1209+
stf.MustMatch("(");
1210+
var style = stf.ReadInt(0);
1211+
stf.SkipRestOfBlock();
1212+
return style;
1213+
}
1214+
}
1215+
11661216
#endregion
11671217

11681218
#region other controls

Source/RunActivity/Viewer3D/RollingStock/MSTSLocomotiveViewer.cs

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1141,6 +1141,16 @@ public CabRenderer(Viewer viewer, MSTSLocomotive car)
11411141
count[(int)cvc.ControlType]++;
11421142
continue;
11431143
}
1144+
CVCAnimatedDisplay anim = cvc as CVCAnimatedDisplay;
1145+
if (anim != null)
1146+
{
1147+
CabViewAnimationsRenderer animr = new CabViewAnimationsRenderer(viewer, car, anim, _Shader);
1148+
animr.SortIndex = controlSortIndex;
1149+
CabViewControlRenderersList[i].Add(animr);
1150+
if (!ControlMap.ContainsKey(key)) ControlMap.Add(key, animr);
1151+
count[(int)cvc.ControlType]++;
1152+
continue;
1153+
}
11441154
CVCMultiStateDisplay multi = cvc as CVCMultiStateDisplay;
11451155
if (multi != null)
11461156
{
@@ -1735,7 +1745,7 @@ public override void Draw(GraphicsDevice graphicsDevice)
17351745
/// </summary>
17361746
public class CabViewDiscreteRenderer : CabViewControlRenderer
17371747
{
1738-
readonly CVCWithFrames ControlDiscrete;
1748+
protected readonly CVCWithFrames ControlDiscrete;
17391749
readonly Rectangle SourceRectangle;
17401750
Rectangle DestinationRectangle = new Rectangle();
17411751
public readonly float CVCFlashTimeOn = 0.75f;
@@ -1823,7 +1833,7 @@ public override void Draw(GraphicsDevice graphicsDevice)
18231833
/// Determines the index of the Texture to be drawn
18241834
/// </summary>
18251835
/// <returns>index of the Texture</returns>
1826-
public int GetDrawIndex()
1836+
public virtual int GetDrawIndex()
18271837
{
18281838
var data = Locomotive.GetDataOf(Control);
18291839

@@ -2226,7 +2236,7 @@ public void HandleUserInput()
22262236
/// </summary>
22272237
/// <param name="percent">Percent to be translated</param>
22282238
/// <returns>The calculated display index by the Control's Values</returns>
2229-
int PercentToIndex(float percent)
2239+
protected int PercentToIndex(float percent)
22302240
{
22312241
var index = 0;
22322242

@@ -2259,6 +2269,68 @@ int PercentToIndex(float percent)
22592269
}
22602270
}
22612271

2272+
/// <summary>
2273+
/// Discrete renderer for animated controls, like external 2D wiper
2274+
/// </summary>
2275+
public class CabViewAnimationsRenderer : CabViewDiscreteRenderer
2276+
{
2277+
float CumulativeTime;
2278+
CVCAnimatedDisplay ControlAnimated;
2279+
float HalfCycleTimeS;
2280+
bool wiperOn = false;
2281+
2282+
public CabViewAnimationsRenderer(Viewer viewer, MSTSLocomotive locomotive, CVCWithFrames control, CabShader shader)
2283+
: base(viewer, locomotive, control, shader)
2284+
{
2285+
ControlAnimated = (CVCAnimatedDisplay)ControlDiscrete;
2286+
HalfCycleTimeS = ControlAnimated.CycleTimeS * 0.5f;
2287+
wiperOn = Locomotive.Wiper;
2288+
}
2289+
2290+
public override void PrepareFrame(RenderFrame frame, ElapsedTime elapsedTime)
2291+
{
2292+
if (Locomotive.Wiper) wiperOn = true;
2293+
if (wiperOn)
2294+
{
2295+
CumulativeTime += elapsedTime.ClockSeconds;
2296+
if (CumulativeTime > ControlAnimated.CycleTimeS && !Locomotive.Wiper)
2297+
wiperOn = false;
2298+
while (CumulativeTime > ControlAnimated.CycleTimeS)
2299+
CumulativeTime -= ControlAnimated.CycleTimeS;
2300+
}
2301+
base.PrepareFrame(frame, elapsedTime);
2302+
}
2303+
2304+
2305+
public override int GetDrawIndex()
2306+
{
2307+
var data = Locomotive.GetDataOf(Control);
2308+
2309+
var index = 0;
2310+
switch (ControlDiscrete.ControlType)
2311+
{
2312+
case CABViewControlTypes.ORTS_2DEXTERNALWIPERS:
2313+
if (wiperOn)
2314+
{
2315+
if (CumulativeTime < HalfCycleTimeS)
2316+
index = PercentToIndex(CumulativeTime / HalfCycleTimeS);
2317+
else
2318+
index = PercentToIndex((ControlAnimated.CycleTimeS - CumulativeTime) / HalfCycleTimeS);
2319+
}
2320+
break;
2321+
}
2322+
// If it is a control with NumPositions and NumValues, the index becomes the reference to the Positions entry, which in turn is the frame index within the .ace file
2323+
if (ControlDiscrete is CVCDiscrete && !(ControlDiscrete is CVCSignal) && (ControlDiscrete as CVCDiscrete).Positions.Count > index &&
2324+
(ControlDiscrete as CVCDiscrete).Positions.Count == ControlDiscrete.Values.Count && index >= 0)
2325+
index = (ControlDiscrete as CVCDiscrete).Positions[index];
2326+
2327+
if (index >= ControlDiscrete.FramesCount) index = ControlDiscrete.FramesCount - 1;
2328+
if (index < 0) index = 0;
2329+
return index;
2330+
}
2331+
}
2332+
2333+
22622334
/// <summary>
22632335
/// Digital Cab Control renderer
22642336
/// Uses fonts instead of graphic

0 commit comments

Comments
 (0)