Skip to content

Commit 27fb483

Browse files
committed
Refactor of PercentToIndex and related code for more robust dynamic brake display
1 parent 50d37b7 commit 27fb483

File tree

2 files changed

+37
-30
lines changed

2 files changed

+37
-30
lines changed

Source/Orts.Formats.Msts/CabViewFile.cs

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1252,13 +1252,14 @@ public CVCDiscrete(STFReader stf, string basepath, DiscreteStates discreteState)
12521252
Positions.Add(0);
12531253
// We will need the FramesCount later!
12541254
// We use Positions only here
1255-
Positions.Add(FramesCount);
1255+
Positions.Add(FramesCount - 1);
12561256

12571257
// Fill empty Values
1258-
for (int i = 0; i < FramesCount; i++)
1258+
for (int i = 0; i < (FramesCount - 1); i++)
12591259
Values.Add(0);
12601260
Values[0] = MinValue;
12611261

1262+
// Add maximum value to the end
12621263
Values.Add(MaxValue);
12631264
}
12641265
else if (Values.Count == 2 && Values[0] == 0 && Values[1] < MaxValue && Positions[0] == 0 && Positions[1] == 1 && Values.Count < FramesCount)
@@ -1271,13 +1272,13 @@ public CVCDiscrete(STFReader stf, string basepath, DiscreteStates discreteState)
12711272
//Orientation ( 0 )
12721273
//DirIncrease ( 0 )
12731274
//ScaleRange ( 0 1 )
1274-
Positions.Add(FramesCount);
1275+
Positions.Add(FramesCount - 1);
12751276
// Fill empty Values
1276-
for (int i = Values.Count; i < FramesCount; i++)
1277+
for (int i = Values.Count; i < (FramesCount - 1); i++)
12771278
Values.Add(Values[1]);
1279+
// Add maximum value to the end
12781280
Values.Add(MaxValue);
12791281
}
1280-
12811282
else
12821283
{
12831284
//This if clause covers among others following cases:
@@ -1303,11 +1304,6 @@ public CVCDiscrete(STFReader stf, string basepath, DiscreteStates discreteState)
13031304
}
13041305
iValues++;
13051306
}
1306-
1307-
// Add the maximums to the end, the Value will be removed
1308-
// We use Positions only here
1309-
if (Values.Count > 0 && Values[0] <= Values[Values.Count - 1]) Values.Add(MaxValue);
1310-
else if (Values.Count > 0 && Values[0] > Values[Values.Count - 1]) Values.Add(MinValue);
13111307
}
13121308

13131309
// OK, we have a valid size of Positions and Values
@@ -1333,9 +1329,6 @@ public CVCDiscrete(STFReader stf, string basepath, DiscreteStates discreteState)
13331329
p = Positions[i];
13341330
}
13351331
}
1336-
1337-
// Don't need the MaxValue added before, remove it
1338-
Values.RemoveAt(Values.Count - 1);
13391332
}
13401333
}
13411334

Source/RunActivity/Viewer3D/RollingStock/MSTSLocomotiveViewer.cs

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2005,6 +2005,7 @@ public class CabViewDiscreteRenderer : CabViewControlRenderer, ICabViewMouseCont
20052005
float Scale = 1;
20062006
int OldFrameIndex = 0;
20072007
public bool ButtonState = false;
2008+
int SplitIndex = -1;
20082009

20092010
/// <summary>
20102011
/// Accumulated mouse movement. Used for controls with no assigned notch controllers, e.g. headlight and reverser.
@@ -2040,6 +2041,8 @@ public CabViewDiscreteRenderer(Viewer viewer, MSTSLocomotive locomotive, CVCWith
20402041
break;
20412042
default: ChangedValue = (value) => value + NormalizedMouseMovement(); break;
20422043
}
2044+
// The cab view control index shown when combined control is at the split position
2045+
SplitIndex = PercentToIndex(Locomotive.CombinedControlSplitPosition);
20432046
}
20442047

20452048
public override void PrepareFrame(RenderFrame frame, ElapsedTime elapsedTime)
@@ -2145,21 +2148,12 @@ public virtual int GetDrawIndex()
21452148
index = PercentToIndex(dynBrakePercent);
21462149
break;
21472150
case CABViewControlTypes.CPH_DISPLAY:
2148-
if (Locomotive.CombinedControlType == MSTSLocomotive.CombinedControl.ThrottleDynamic && Locomotive.DynamicBrakeController?.CurrentValue > 0)
2149-
// TODO <CSComment> This is a sort of hack to allow MSTS-compliant operation of Dynamic brake indications in the standard USA case with 8 steps (e.g. Dash9)
2150-
// This hack returns to code of previous OR versions (e.g. release 1.0).
2151-
// The clean solution for MSTS compliance would be not to increment the percentage of the dynamic brake at first dynamic brake key pression, so that
2152-
// subsequent steps become of 12.5% as in MSTS instead of 11.11% as in OR. This requires changes in the physics logic </CSComment>
2153-
index = (int)((ControlDiscrete.FramesCount) * Locomotive.GetCombinedHandleValue(false));
2154-
else
2155-
index = PercentToIndex(Locomotive.GetCombinedHandleValue(false));
2156-
break;
21572151
case CABViewControlTypes.CP_HANDLE:
2158-
if (Locomotive.CombinedControlType == MSTSLocomotive.CombinedControl.ThrottleDynamic && Locomotive.DynamicBrakeController?.CurrentValue > 0
2159-
|| Locomotive.CombinedControlType == MSTSLocomotive.CombinedControl.ThrottleAir && Locomotive.TrainBrakeController?.CurrentValue > 0)
2160-
index = PercentToIndex(Locomotive.GetCombinedHandleValue(false));
2161-
else
2162-
index = PercentToIndex(Locomotive.GetCombinedHandleValue(false));
2152+
var combinedHandlePosition = Locomotive.GetCombinedHandleValue(false);
2153+
index = PercentToIndex(combinedHandlePosition);
2154+
// Make sure power indications are not shown when locomotive is in braking range
2155+
if (combinedHandlePosition > Locomotive.CombinedControlSplitPosition)
2156+
index = Math.Max(index, SplitIndex + 1);
21632157
break;
21642158
case CABViewControlTypes.ORTS_SELECTED_SPEED_DISPLAY:
21652159
if (Locomotive.CruiseControl == null)
@@ -2816,9 +2810,29 @@ protected int PercentToIndex(float percent)
28162810
{
28172811
try
28182812
{
2819-
var val = ControlDiscrete.Values[0] <= ControlDiscrete.Values[ControlDiscrete.Values.Count - 1] ?
2820-
ControlDiscrete.Values.Where(v => (float)v <= percent + 0.00001).Last() : ControlDiscrete.Values.Where(v => (float)v <= percent + 0.00001).First();
2821-
index = ControlDiscrete.Values.IndexOf(val);
2813+
// 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);
2823+
2824+
if (checkIndex < 0)
2825+
checkIndex = ~checkIndex;
2826+
if (checkIndex > vals.Count - 1)
2827+
checkIndex = vals.Count - 1;
2828+
// Choose lower index if it is closer to percent
2829+
if (checkIndex > 0 && Math.Abs(vals[checkIndex - 1] - percent) < Math.Abs(vals[checkIndex] - percent))
2830+
checkIndex--;
2831+
// Re-reverse the index as needed
2832+
if (reversed)
2833+
checkIndex = (vals.Count - 1) - checkIndex;
2834+
2835+
index = checkIndex;
28222836
}
28232837
catch
28242838
{

0 commit comments

Comments
 (0)