Skip to content

Commit b7485e5

Browse files
committed
Improve handling of cab view controls with values entered in the wrong order
1 parent 27fb483 commit b7485e5

File tree

2 files changed

+60
-36
lines changed

2 files changed

+60
-36
lines changed

Source/Orts.Formats.Msts/CabViewFile.cs

Lines changed: 45 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,6 +1007,7 @@ public abstract class CVCWithFrames : CabViewControl
10071007
public bool MouseControl;
10081008
public int Orientation;
10091009
public int Direction;
1010+
public bool Reversed { get; protected set; } = false;
10101011

10111012
public List<double> Values
10121013
{
@@ -1022,8 +1023,8 @@ public class CVCDiscrete : CVCWithFrames
10221023
public List<int> Positions = new List<int>();
10231024

10241025
private int _ValuesRead;
1025-
private int numPositions;
1026-
private bool canFill = true;
1026+
private int NumPositions;
1027+
private bool CanFill = true;
10271028

10281029
public struct NewScreenData
10291030
{
@@ -1076,7 +1077,7 @@ public CVCDiscrete(STFReader stf, string basepath, DiscreteStates discreteState)
10761077
stf.MustMatch("(");
10771078
// If Positions are not filled before by Values
10781079
bool shouldFill = (Positions.Count == 0);
1079-
numPositions = stf.ReadInt(null); // Number of Positions
1080+
NumPositions = stf.ReadInt(null); // Number of Positions
10801081

10811082
var minPosition = 0;
10821083
var positionsRead = 0;
@@ -1117,20 +1118,20 @@ public CVCDiscrete(STFReader stf, string basepath, DiscreteStates discreteState)
11171118

11181119
// Check if eligible for filling
11191120

1120-
if (Positions.Count > 1 && Positions[0] != 0) canFill = false;
1121+
if (Positions.Count > 1 && Positions[0] != 0) CanFill = false;
11211122
else
11221123
{
11231124
for (var iPos = 1; iPos <= Positions.Count - 1; iPos++)
11241125
{
11251126
if (Positions[iPos] > Positions[iPos-1]) continue;
1126-
canFill = false;
1127+
CanFill = false;
11271128
break;
11281129
}
11291130
}
11301131

11311132
// This is a protection against GP40 locomotives that erroneously have positions pointing beyond frame count limit.
11321133

1133-
if (Positions.Count > 1 && canFill && Positions.Count < FramesCount && Positions[Positions.Count-1] >= FramesCount && Positions[0] == 0)
1134+
if (Positions.Count > 1 && CanFill && Positions.Count < FramesCount && Positions[Positions.Count-1] >= FramesCount && Positions[0] == 0)
11341135
{
11351136
STFException.TraceInformation(stf, "Some NumPositions entries refer to non-exisiting frames, trying to renumber");
11361137
Positions[Positions.Count - 1] = FramesCount - 1;
@@ -1155,7 +1156,7 @@ public CVCDiscrete(STFReader stf, string basepath, DiscreteStates discreteState)
11551156
}
11561157
// Avoid later repositioning, put every value to its Position
11571158
// But before resize Values if needed
1158-
if (numValues != numPositions)
1159+
if (numValues != NumPositions)
11591160
{
11601161
while (Values.Count <= Positions[_ValuesRead])
11611162
{
@@ -1214,7 +1215,7 @@ public CVCDiscrete(STFReader stf, string basepath, DiscreteStates discreteState)
12141215

12151216
// Only shuffle data in following cases
12161217

1217-
if (Values.Count != Positions.Count || (Values.Count < FramesCount & canFill)|| ( Values.Count > 0 && Values[0] == Values[Values.Count - 1] && Values[0] == 0))
1218+
if (Values.Count != Positions.Count || (Values.Count < FramesCount & CanFill)|| ( Values.Count > 0 && Values[0] == Values[Values.Count - 1] && Values[0] == 0))
12181219
{
12191220

12201221
// Fixup Positions and Values collections first
@@ -1257,7 +1258,11 @@ public CVCDiscrete(STFReader stf, string basepath, DiscreteStates discreteState)
12571258
// Fill empty Values
12581259
for (int i = 0; i < (FramesCount - 1); i++)
12591260
Values.Add(0);
1260-
Values[0] = MinValue;
1261+
// Some dummy controls will have only one frame
1262+
if (Values.Count > 0)
1263+
Values[0] = MinValue;
1264+
else
1265+
Values.Add(MinValue);
12611266

12621267
// Add maximum value to the end
12631268
Values.Add(MaxValue);
@@ -1353,13 +1358,21 @@ public CVCDiscrete(STFReader stf, string basepath, DiscreteStates discreteState)
13531358
break;
13541359
}
13551360
}
1356-
// catch (Exception error)
1357-
// {
1358-
// if (error is STFException) // Parsing error, so pass it on
1359-
// throw;
1360-
// else // Unexpected error, so provide a hint
1361-
// throw new STFException(stf, "Problem with NumPositions/NumValues/NumFrames/ScaleRange");
1362-
// } // End of Need check the Values collection for validity
1361+
// catch (Exception error)
1362+
// {
1363+
// if (error is STFException) // Parsing error, so pass it on
1364+
// throw;
1365+
// else // Unexpected error, so provide a hint
1366+
// throw new STFException(stf, "Problem with NumPositions/NumValues/NumFrames/ScaleRange");
1367+
// } // End of Need check the Values collection for validity
1368+
1369+
// Ensure resulting set of values has the correct format (sorted least to greatest) and resort
1370+
// Assume values have been entered in reverse order if final value is less than initial value
1371+
if (Values.Count > 0 && Values[0] > Values[Values.Count - 1])
1372+
Reversed = true;
1373+
// Force sort values from least to greatest
1374+
Values.Sort();
1375+
13631376
} // End of Constructor
13641377

13651378
protected void ParseNewScreen(STFReader stf)
@@ -1407,7 +1420,7 @@ public CVCMultiStateDisplay(STFReader stf, string basepath)
14071420
stf.ParseBlock( new STFReader.TokenProcessor[] {
14081421
new STFReader.TokenProcessor("style", ()=>{ MSStyles.Add(ParseNumStyle(stf));
14091422
}),
1410-
new STFReader.TokenProcessor("switchval", ()=>{ Values.Add(stf.ReadFloatBlock(STFReader.UNITS.None, null))
1423+
new STFReader.TokenProcessor("switchval", ()=>{ Values.Add(stf.ReadDoubleBlock(null))
14111424
; }),
14121425
});}),
14131426
});
@@ -1419,6 +1432,13 @@ public CVCMultiStateDisplay(STFReader stf, string basepath)
14191432
new STFReader.TokenProcessor("ortsscreenpage", () => {ParseScreen(stf); }),
14201433
new STFReader.TokenProcessor("ortscabviewpoint", ()=>{ParseCabViewpoint(stf); }),
14211434
});
1435+
1436+
// Ensure resulting set of values has the correct format (sorted least to greatest) and resort
1437+
// Assume values have been entered in reverse order if final value is less than initial value
1438+
if (Values.Count > 0 && Values[0] > Values[Values.Count - 1])
1439+
Reversed = true;
1440+
// Force sort values from least to greatest
1441+
Values.Sort();
14221442
}
14231443
protected int ParseNumStyle(STFReader stf)
14241444
{
@@ -1457,7 +1477,7 @@ public CVCAnimatedDisplay(STFReader stf, string basepath)
14571477
stf.ParseBlock( new STFReader.TokenProcessor[] {
14581478
new STFReader.TokenProcessor("style", ()=>{ MSStyles.Add(ParseNumStyle(stf));
14591479
}),
1460-
new STFReader.TokenProcessor("switchval", ()=>{ Values.Add(stf.ReadFloatBlock(STFReader.UNITS.None, null))
1480+
new STFReader.TokenProcessor("switchval", ()=>{ Values.Add(stf.ReadDoubleBlock(null))
14611481
; }),
14621482
});}),
14631483
});
@@ -1469,6 +1489,13 @@ public CVCAnimatedDisplay(STFReader stf, string basepath)
14691489
new STFReader.TokenProcessor("ortsscreenpage", () => {ParseScreen(stf); }),
14701490
new STFReader.TokenProcessor("ortscabviewpoint", ()=>{ParseCabViewpoint(stf); }),
14711491
});
1492+
1493+
// Ensure resulting set of values has the correct format (sorted least to greatest) and resort
1494+
// Assume values have been entered in reverse order if final value is less than initial value
1495+
if (Values.Count > 0 && Values[0] > Values[Values.Count - 1])
1496+
Reversed = true;
1497+
// Force sort values from least to greatest
1498+
Values.Sort();
14721499
}
14731500
protected int ParseNumStyle(STFReader stf)
14741501
{

Source/RunActivity/Viewer3D/RollingStock/MSTSLocomotiveViewer.cs

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2153,7 +2153,12 @@ public virtual int GetDrawIndex()
21532153
index = PercentToIndex(combinedHandlePosition);
21542154
// Make sure power indications are not shown when locomotive is in braking range
21552155
if (combinedHandlePosition > Locomotive.CombinedControlSplitPosition)
2156-
index = Math.Max(index, SplitIndex + 1);
2156+
{
2157+
if (ControlDiscrete.Reversed)
2158+
index = Math.Min(index, SplitIndex - 1);
2159+
else
2160+
index = Math.Max(index, SplitIndex + 1);
2161+
}
21572162
break;
21582163
case CABViewControlTypes.ORTS_SELECTED_SPEED_DISPLAY:
21592164
if (Locomotive.CruiseControl == null)
@@ -2811,33 +2816,25 @@ protected int PercentToIndex(float percent)
28112816
try
28122817
{
28132818
// Binary search process to find the control value closest to percent
2814-
List<double> vals = ControlDiscrete.Values;
2815-
// Check if control values were defined in reverse, reverse them back for this calculation
2816-
// This is less efficient, so creators should be encouraged to not do this
2817-
bool reversed = ControlDiscrete.Values[0] > ControlDiscrete.Values[ControlDiscrete.Values.Count - 1];
2818-
if (reversed)
2819-
vals.Reverse();
2820-
2821-
// Returns index of first val larger than percent, or bitwise compliment of this index if percent isn't in the list
2822-
int checkIndex = vals.BinarySearch(percent);
2819+
// Returns index of first val LARGER than percent, or bitwise compliment of this index if percent isn't in the list
2820+
int checkIndex = ControlDiscrete.Values.BinarySearch(percent);
28232821

28242822
if (checkIndex < 0)
28252823
checkIndex = ~checkIndex;
2826-
if (checkIndex > vals.Count - 1)
2827-
checkIndex = vals.Count - 1;
2824+
if (checkIndex > ControlDiscrete.Values.Count - 1)
2825+
checkIndex = ControlDiscrete.Values.Count - 1;
28282826
// Choose lower index if it is closer to percent
2829-
if (checkIndex > 0 && Math.Abs(vals[checkIndex - 1] - percent) < Math.Abs(vals[checkIndex] - percent))
2827+
if (checkIndex > 0 && Math.Abs(ControlDiscrete.Values[checkIndex - 1] - percent) < Math.Abs(ControlDiscrete.Values[checkIndex] - percent))
28302828
checkIndex--;
2831-
// Re-reverse the index as needed
2832-
if (reversed)
2833-
checkIndex = (vals.Count - 1) - checkIndex;
2829+
// If values were originally defined in reverse, correct index to account for the reversing
2830+
if (ControlDiscrete.Reversed)
2831+
checkIndex = (ControlDiscrete.Values.Count - 1) - checkIndex;
28342832

28352833
index = checkIndex;
28362834
}
28372835
catch
28382836
{
2839-
var val = ControlDiscrete.Values.Min();
2840-
index = ControlDiscrete.Values.IndexOf(val);
2837+
index = ControlDiscrete.Reversed ? ControlDiscrete.Values.Count - 1 : 0;
28412838
}
28422839
}
28432840
else if (ControlDiscrete.MaxValue != ControlDiscrete.MinValue)

0 commit comments

Comments
 (0)