@@ -1022,6 +1022,7 @@ public abstract class CVCWithFrames : CabViewControl
10221022 public bool MouseControl ;
10231023 public int Orientation ;
10241024 public int Direction ;
1025+ public bool Reversed { get ; protected set ; } = false ;
10251026
10261027 public List < double > Values
10271028 {
@@ -1037,8 +1038,8 @@ public class CVCDiscrete : CVCWithFrames
10371038 public List < int > Positions = new List < int > ( ) ;
10381039
10391040 private int _ValuesRead ;
1040- private int numPositions ;
1041- private bool canFill = true ;
1041+ private int NumPositions ;
1042+ private bool CanFill = true ;
10421043
10431044 public struct NewScreenData
10441045 {
@@ -1091,7 +1092,7 @@ public CVCDiscrete(STFReader stf, string basepath, DiscreteStates discreteState)
10911092 stf . MustMatch ( "(" ) ;
10921093 // If Positions are not filled before by Values
10931094 bool shouldFill = ( Positions . Count == 0 ) ;
1094- numPositions = stf . ReadInt ( null ) ; // Number of Positions
1095+ NumPositions = stf . ReadInt ( null ) ; // Number of Positions
10951096
10961097 var minPosition = 0 ;
10971098 var positionsRead = 0 ;
@@ -1132,20 +1133,20 @@ public CVCDiscrete(STFReader stf, string basepath, DiscreteStates discreteState)
11321133
11331134 // Check if eligible for filling
11341135
1135- if ( Positions . Count > 1 && Positions [ 0 ] != 0 ) canFill = false ;
1136+ if ( Positions . Count > 1 && Positions [ 0 ] != 0 ) CanFill = false ;
11361137 else
11371138 {
11381139 for ( var iPos = 1 ; iPos <= Positions . Count - 1 ; iPos ++ )
11391140 {
11401141 if ( Positions [ iPos ] > Positions [ iPos - 1 ] ) continue ;
1141- canFill = false ;
1142+ CanFill = false ;
11421143 break ;
11431144 }
11441145 }
11451146
11461147 // This is a protection against GP40 locomotives that erroneously have positions pointing beyond frame count limit.
11471148
1148- if ( Positions . Count > 1 && canFill && Positions . Count < FramesCount && Positions [ Positions . Count - 1 ] >= FramesCount && Positions [ 0 ] == 0 )
1149+ if ( Positions . Count > 1 && CanFill && Positions . Count < FramesCount && Positions [ Positions . Count - 1 ] >= FramesCount && Positions [ 0 ] == 0 )
11491150 {
11501151 STFException . TraceInformation ( stf , "Some NumPositions entries refer to non-exisiting frames, trying to renumber" ) ;
11511152 Positions [ Positions . Count - 1 ] = FramesCount - 1 ;
@@ -1170,7 +1171,7 @@ public CVCDiscrete(STFReader stf, string basepath, DiscreteStates discreteState)
11701171 }
11711172 // Avoid later repositioning, put every value to its Position
11721173 // But before resize Values if needed
1173- if ( numValues != numPositions )
1174+ if ( numValues != NumPositions )
11741175 {
11751176 while ( Values . Count <= Positions [ _ValuesRead ] )
11761177 {
@@ -1232,7 +1233,7 @@ public CVCDiscrete(STFReader stf, string basepath, DiscreteStates discreteState)
12321233
12331234 // Only shuffle data in following cases
12341235
1235- if ( Values . Count != Positions . Count || ( Values . Count < FramesCount & canFill ) || ( Values . Count > 0 && Values [ 0 ] == Values [ Values . Count - 1 ] && Values [ 0 ] == 0 ) )
1236+ if ( Values . Count != Positions . Count || ( Values . Count < FramesCount & CanFill ) || ( Values . Count > 0 && Values [ 0 ] == Values [ Values . Count - 1 ] && Values [ 0 ] == 0 ) )
12361237 {
12371238
12381239 // Fixup Positions and Values collections first
@@ -1275,7 +1276,11 @@ public CVCDiscrete(STFReader stf, string basepath, DiscreteStates discreteState)
12751276 // Fill empty Values
12761277 for ( int i = 0 ; i < ( FramesCount - 1 ) ; i ++ )
12771278 Values . Add ( 0 ) ;
1279+ // Some dummy controls will have only one frame
1280+ if ( Values . Count > 0 )
12781281 Values [ 0 ] = MinValue ;
1282+ else
1283+ Values . Add ( MinValue ) ;
12791284
12801285 // Add maximum value to the end
12811286 Values . Add ( MaxValue ) ;
@@ -1371,13 +1376,21 @@ public CVCDiscrete(STFReader stf, string basepath, DiscreteStates discreteState)
13711376 break ;
13721377 }
13731378 }
1374- // catch (Exception error)
1375- // {
1376- // if (error is STFException) // Parsing error, so pass it on
1377- // throw;
1378- // else // Unexpected error, so provide a hint
1379- // throw new STFException(stf, "Problem with NumPositions/NumValues/NumFrames/ScaleRange");
1380- // } // End of Need check the Values collection for validity
1379+ // catch (Exception error)
1380+ // {
1381+ // if (error is STFException) // Parsing error, so pass it on
1382+ // throw;
1383+ // else // Unexpected error, so provide a hint
1384+ // throw new STFException(stf, "Problem with NumPositions/NumValues/NumFrames/ScaleRange");
1385+ // } // End of Need check the Values collection for validity
1386+
1387+ // Ensure resulting set of values has the correct format (sorted least to greatest) and resort
1388+ // Assume values have been entered in reverse order if final value is less than initial value
1389+ if ( Values . Count > 0 && Values [ 0 ] > Values [ Values . Count - 1 ] )
1390+ Reversed = true ;
1391+ // Force sort values from least to greatest
1392+ Values . Sort ( ) ;
1393+
13811394 } // End of Constructor
13821395
13831396 protected void ParseNewScreen ( STFReader stf )
@@ -1425,7 +1438,7 @@ public CVCMultiStateDisplay(STFReader stf, string basepath)
14251438 stf . ParseBlock ( new STFReader . TokenProcessor [ ] {
14261439 new STFReader . TokenProcessor ( "style" , ( ) => { MSStyles . Add ( ParseNumStyle ( stf ) ) ;
14271440 } ) ,
1428- new STFReader . TokenProcessor ( "switchval" , ( ) => { Values . Add ( stf . ReadFloatBlock ( STFReader . UNITS . None , null ) )
1441+ new STFReader . TokenProcessor ( "switchval" , ( ) => { Values . Add ( stf . ReadDoubleBlock ( null ) )
14291442 ; } ) ,
14301443 } ) ; } ) ,
14311444 } ) ;
@@ -1440,6 +1453,13 @@ public CVCMultiStateDisplay(STFReader stf, string basepath)
14401453 new STFReader . TokenProcessor ( "ortsunitsscalefactor" , ( ) => { UnitsScale = stf . ReadFloatBlock ( STFReader . UNITS . None , null ) ; } ) ,
14411454 new STFReader . TokenProcessor ( "ortsunitsoffset" , ( ) => { UnitsOffset = stf . ReadFloatBlock ( STFReader . UNITS . None , null ) ; } ) ,
14421455 } ) ;
1456+
1457+ // Ensure resulting set of values has the correct format (sorted least to greatest) and resort
1458+ // Assume values have been entered in reverse order if final value is less than initial value
1459+ if ( Values . Count > 0 && Values [ 0 ] > Values [ Values . Count - 1 ] )
1460+ Reversed = true ;
1461+ // Force sort values from least to greatest
1462+ Values . Sort ( ) ;
14431463 }
14441464 protected int ParseNumStyle ( STFReader stf )
14451465 {
@@ -1478,7 +1498,7 @@ public CVCAnimatedDisplay(STFReader stf, string basepath)
14781498 stf . ParseBlock ( new STFReader . TokenProcessor [ ] {
14791499 new STFReader . TokenProcessor ( "style" , ( ) => { MSStyles . Add ( ParseNumStyle ( stf ) ) ;
14801500 } ) ,
1481- new STFReader . TokenProcessor ( "switchval" , ( ) => { Values . Add ( stf . ReadFloatBlock ( STFReader . UNITS . None , null ) )
1501+ new STFReader . TokenProcessor ( "switchval" , ( ) => { Values . Add ( stf . ReadDoubleBlock ( null ) )
14821502 ; } ) ,
14831503 } ) ; } ) ,
14841504 } ) ;
@@ -1493,6 +1513,13 @@ public CVCAnimatedDisplay(STFReader stf, string basepath)
14931513 new STFReader . TokenProcessor ( "ortsunitsscalefactor" , ( ) => { UnitsScale = stf . ReadFloatBlock ( STFReader . UNITS . None , null ) ; } ) ,
14941514 new STFReader . TokenProcessor ( "ortsunitsoffset" , ( ) => { UnitsOffset = stf . ReadFloatBlock ( STFReader . UNITS . None , null ) ; } ) ,
14951515 } ) ;
1516+
1517+ // Ensure resulting set of values has the correct format (sorted least to greatest) and resort
1518+ // Assume values have been entered in reverse order if final value is less than initial value
1519+ if ( Values . Count > 0 && Values [ 0 ] > Values [ Values . Count - 1 ] )
1520+ Reversed = true ;
1521+ // Force sort values from least to greatest
1522+ Values . Sort ( ) ;
14961523 }
14971524 protected int ParseNumStyle ( STFReader stf )
14981525 {
0 commit comments