Skip to content

Commit 97fed6b

Browse files
committed
1 parent 4dced6b commit 97fed6b

File tree

6 files changed

+426
-60
lines changed

6 files changed

+426
-60
lines changed

Source/Documentation/Manual/cabs.rst

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,60 @@ if e.g. the wiper moves from left to right and back, only the frames related
466466
to the motion from left to right have to be included. For the reverse
467467
motion the same frames are used from last to first. SwitchVal can vary from 0 to 1.
468468

469+
Multiple screen pages on displays
470+
---------------------------------
471+
472+
Modern locomotives have one or more displays in their cabs, and often in such
473+
displays it is possible to switch among more screen pages. Fields and controls
474+
described in this paragraph enable the implementation of .cvf files with such
475+
functionality, for both 2D and 3D cabs.
476+
477+
In the .cvf control blocks following further fields may be optionally present::
478+
479+
ORTSDisplay ( numeric ), indicating the display ID number (from 0 to 7)
480+
to which the control is linked; if such field is missing, display ID number
481+
zero is assumed;
482+
483+
ORTSScreenPage ( alphanumeric-string ) indicating the screen ID string to
484+
which the control is linked; that means that the control is displayed/may be
485+
operated only if its screen is active in that moment; a missing entry
486+
indicates that the control is displayed independently from the selected screen page;
487+
at game start such controls are enabled, plus the ones with line
488+
ORTSScreenPage ( "default" ); more ORTSScreenPage() entries in a single control
489+
are possible.
490+
491+
A new on/off control, called ORTS_SCREEN_SELECT is available, which, in addition to the usual fields and to
492+
the optional fields ORTSDisplay and ORTSScreenPage contains one or more of following fields::
493+
494+
ORTSNewScreenPage ( alphanumeric-string numeric ): when the control is clicked,
495+
the controls with field ORTSScreenPage equal to the string of this field and
496+
with field ORTSDisplay equal to the numeric will be displayed on such display
497+
in place of the ones displayed up to that moment. if the numeric is missing within
498+
ORTSNewScreenPage, the involved display is the one referenced in field ORTSDisplay
499+
of ORTS_SCREEN_SELECT.
500+
501+
A further control is available, named ORTS_STATIC_DISPLAY, which is specially devoted to the loading of the
502+
background of screen pages (their static part).
503+
Here is an example of usage of it::
504+
505+
MultiStateDisplay (
506+
Type ( ORTS_STATIC_DISPLAY MULTI_STATE_DISPLAY )
507+
Position ( 246 151 105 16 )
508+
Graphic ( semproniostatic.ace )
509+
States ( 1 1 1
510+
State (
511+
Style ( 0 )
512+
SwitchVal ( 0 )
513+
)
514+
)
515+
ORTSScreenPage ( "sempronio" )
516+
)
517+
518+
With this block, the static part of the "sempronio" screen page is loaded on display 0 when such screen
519+
becomes the active one.
520+
521+
.cvf files not using fields and controls listed in this paragraph work as usual, with no changes needed.
522+
469523
Further OR cab controls
470524
-----------------------
471525

Source/Orts.Formats.Msts/CabViewFile.cs

Lines changed: 80 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,8 @@ public enum CABViewControlTypes
202202
ORTS_ELECTRIC_TRAIN_SUPPLY_COMMAND_SWITCH,
203203
ORTS_ELECTRIC_TRAIN_SUPPLY_ON,
204204
ORTS_2DEXTERNALWIPERS,
205+
ORTS_SCREEN_SELECT,
206+
ORTS_STATIC_DISPLAY,
205207

206208
// TCS Controls
207209
ORTS_TCS1,
@@ -390,6 +392,10 @@ public class CabViewControl
390392
public double OldValue;
391393
public string ACEFile = "";
392394

395+
public int Display;
396+
public List<string> Screens;
397+
public int CabViewpoint;
398+
393399
public CABViewControlTypes ControlType = CABViewControlTypes.NONE;
394400
public CABViewControlStyles ControlStyle = CABViewControlStyles.NONE;
395401
public CABViewControlUnits Units = CABViewControlUnits.NONE;
@@ -509,6 +515,32 @@ protected virtual float ParseRotation(STFReader stf)
509515
stf.SkipRestOfBlock();
510516
return rotation;
511517
}
518+
519+
protected virtual void ParseDisplay(STFReader stf)
520+
{
521+
stf.MustMatch("(");
522+
Display = stf.ReadInt(0);
523+
stf.SkipRestOfBlock();
524+
}
525+
526+
protected virtual void ParseScreen(STFReader stf)
527+
{
528+
stf.MustMatch("(");
529+
var newScreen = stf.ReadString();
530+
stf.SkipRestOfBlock();
531+
if (Screens == null)
532+
Screens = new List<string>();
533+
Screens.Add(newScreen.ToLower());
534+
}
535+
536+
protected virtual void ParseCabViewpoint(STFReader stf)
537+
{
538+
stf.MustMatch("(");
539+
CabViewpoint = stf.ReadInt(0);
540+
stf.SkipRestOfBlock();
541+
}
542+
543+
512544
}
513545
#endregion
514546

@@ -560,6 +592,9 @@ public CVCDial(STFReader stf, string basepath)
560592
ToDegree = stf.ReadFloat(STFReader.UNITS.None, null);
561593
stf.SkipRestOfBlock();
562594
}),
595+
new STFReader.TokenProcessor("ortsdisplay", ()=>{ParseDisplay(stf); }),
596+
new STFReader.TokenProcessor("ortsscreenpage", () => {ParseScreen(stf); }),
597+
new STFReader.TokenProcessor("ortscabviewpoint", ()=>{ParseCabViewpoint(stf); }),
563598
});
564599
}
565600
}
@@ -645,7 +680,10 @@ public CVCGauge(STFReader stf, string basepath)
645680
new STFReader.TokenProcessor("controlcolour", ()=>{ DecreaseColor = ParseControlColor(stf); }) });
646681
}
647682
}),
648-
new STFReader.TokenProcessor("ortsangle", () =>{ Rotation = ParseRotation(stf); })
683+
new STFReader.TokenProcessor("ortsangle", () =>{ Rotation = ParseRotation(stf); }),
684+
new STFReader.TokenProcessor("ortsdisplay", ()=>{ParseDisplay(stf); }),
685+
new STFReader.TokenProcessor("ortsscreenpage", () => {ParseScreen(stf); }),
686+
new STFReader.TokenProcessor("ortscabviewpoint", ()=>{ParseCabViewpoint(stf); }),
649687
});
650688
}
651689
}
@@ -768,7 +806,10 @@ public CVCDigital(STFReader stf, string basepath)
768806
}
769807
}),
770808
new STFReader.TokenProcessor("ortsfont", ()=>{ParseFont(stf); }),
771-
new STFReader.TokenProcessor("ortsangle", () => {Rotation = ParseRotation(stf); }),
809+
new STFReader.TokenProcessor("ortsangle", () => {Rotation = ParseRotation(stf); }),
810+
new STFReader.TokenProcessor("ortsdisplay", ()=>{ParseDisplay(stf); }),
811+
new STFReader.TokenProcessor("ortsscreenpage", () => {ParseScreen(stf); }),
812+
new STFReader.TokenProcessor("ortscabviewpoint", ()=>{ParseCabViewpoint(stf); }),
772813
});
773814
}
774815

@@ -829,7 +870,10 @@ public CVCDigitalClock(STFReader stf, string basepath)
829870
new STFReader.TokenProcessor("accuracy", ()=>{ ParseAccuracy(stf); }),
830871
new STFReader.TokenProcessor("controlcolour", ()=>{ PositiveColor = ParseControlColor(stf); }),
831872
new STFReader.TokenProcessor("ortsfont", ()=>{ParseFont(stf); }),
832-
new STFReader.TokenProcessor("ortsangle", () => { Rotation = ParseRotation(stf); })
873+
new STFReader.TokenProcessor("ortsangle", () => { Rotation = ParseRotation(stf); }),
874+
new STFReader.TokenProcessor("ortsdisplay", ()=>{ParseDisplay(stf); }),
875+
new STFReader.TokenProcessor("ortsscreenpage", () => {ParseScreen(stf); }),
876+
new STFReader.TokenProcessor("ortscabviewpoint", ()=>{ParseCabViewpoint(stf); }),
833877
});
834878
}
835879

@@ -866,6 +910,14 @@ public class CVCDiscrete : CVCWithFrames
866910
private int numPositions;
867911
private bool canFill = true;
868912

913+
public struct NewScreenData
914+
{
915+
public string NewScreen;
916+
public int NewScreenDisplay;
917+
918+
}
919+
public List<NewScreenData> NewScreens;
920+
869921
public CVCDiscrete(STFReader stf, string basepath, DiscreteStates discreteState)
870922
{
871923
// try
@@ -999,6 +1051,10 @@ public CVCDiscrete(STFReader stf, string basepath, DiscreteStates discreteState)
9991051
_ValuesRead++;
10001052
}
10011053
}),
1054+
new STFReader.TokenProcessor("ortsdisplay", ()=>{ParseDisplay(stf); }),
1055+
new STFReader.TokenProcessor("ortsscreenpage", () => {ParseScreen(stf); }),
1056+
new STFReader.TokenProcessor("ortsnewscreenpage", () => {ParseNewScreen(stf); }),
1057+
new STFReader.TokenProcessor("ortscabviewpoint", ()=>{ParseCabViewpoint(stf); }),
10021058
});
10031059

10041060
// If no ACE, just don't need any fixup
@@ -1188,6 +1244,18 @@ public CVCDiscrete(STFReader stf, string basepath, DiscreteStates discreteState)
11881244
// throw new STFException(stf, "Problem with NumPositions/NumValues/NumFrames/ScaleRange");
11891245
// } // End of Need check the Values collection for validity
11901246
} // End of Constructor
1247+
1248+
protected void ParseNewScreen(STFReader stf)
1249+
{
1250+
stf.MustMatch("(");
1251+
var newScreen = new NewScreenData();
1252+
newScreen.NewScreen = stf.ReadString().ToLower();
1253+
newScreen.NewScreenDisplay = stf.ReadInt(-1);
1254+
stf.SkipRestOfBlock();
1255+
if (NewScreens == null)
1256+
NewScreens = new List<NewScreenData>();
1257+
NewScreens.Add(newScreen); ;
1258+
}
11911259
}
11921260
#endregion
11931261

@@ -1228,6 +1296,9 @@ public CVCMultiStateDisplay(STFReader stf, string basepath)
12281296
for (int i = Values.Count; i < FramesCount; i++)
12291297
Values.Add(-10000);
12301298
}),
1299+
new STFReader.TokenProcessor("ortsdisplay", ()=>{ParseDisplay(stf); }),
1300+
new STFReader.TokenProcessor("ortsscreenpage", () => {ParseScreen(stf); }),
1301+
new STFReader.TokenProcessor("ortscabviewpoint", ()=>{ParseCabViewpoint(stf); }),
12311302
});
12321303
}
12331304
protected int ParseNumStyle(STFReader stf)
@@ -1275,6 +1346,9 @@ public CVCAnimatedDisplay(STFReader stf, string basepath)
12751346
for (int i = Values.Count; i < FramesCount; i++)
12761347
Values.Add(-10000);
12771348
}),
1349+
new STFReader.TokenProcessor("ortsdisplay", ()=>{ParseDisplay(stf); }),
1350+
new STFReader.TokenProcessor("ortsscreenpage", () => {ParseScreen(stf); }),
1351+
new STFReader.TokenProcessor("ortscabviewpoint", ()=>{ParseCabViewpoint(stf); }),
12781352
});
12791353
}
12801354
protected int ParseNumStyle(STFReader stf)
@@ -1307,6 +1381,9 @@ public CVCScreen(STFReader stf, string basepath)
13071381
new STFReader.TokenProcessor("parameters", ()=>{ ParseCustomParameters(stf); }),
13081382
new STFReader.TokenProcessor("disablediflowvoltagepowersupplyoff", ()=>{ ParseDisabledIfLowVoltagePowerSupplyOff(stf); }),
13091383
new STFReader.TokenProcessor("disabledifcabpowersupplyoff", ()=>{ ParseDisabledIfCabPowerSupplyOff(stf); }),
1384+
new STFReader.TokenProcessor("ortsdisplay", ()=>{ParseDisplay(stf); }),
1385+
new STFReader.TokenProcessor("ortsscreenpage", () => {ParseScreen(stf); }),
1386+
new STFReader.TokenProcessor("ortscabviewpoint", ()=>{ParseCabViewpoint(stf); }),
13101387
});
13111388
}
13121389
protected void ParseCustomParameters(STFReader stf)

Source/RunActivity/Viewer3D/Commands.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,32 @@ public override void Redo()
8989
}
9090
}
9191

92+
93+
[Serializable()]
94+
public sealed class SelectScreenCommand : BooleanCommand
95+
{
96+
public static CabRenderer Receiver { get; set; }
97+
98+
public SelectScreenCommand(CommandLog log, bool toState, string screen, int display)
99+
: base(log, toState)
100+
{
101+
Redo(screen, display);
102+
}
103+
104+
public void Redo(string screen, int display)
105+
{
106+
if (ToState)
107+
{
108+
Receiver.ActiveScreen[display] = screen;
109+
}
110+
}
111+
112+
public override string ToString()
113+
{
114+
return base.ToString();
115+
}
116+
}
117+
92118
// Other
93119
[Serializable()]
94120
public sealed class ChangeCabCommand : Command

0 commit comments

Comments
 (0)