Skip to content

Commit 57fc520

Browse files
committed
Merge remote-tracking branch 'upstream/master'
2 parents 892cbe7 + 55f3ff8 commit 57fc520

File tree

16 files changed

+616
-73
lines changed

16 files changed

+616
-73
lines changed

Source/Documentation/Manual/cabs.rst

Lines changed: 84 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

@@ -480,6 +534,36 @@ and the mirrors.
480534
The control blocks are like the one shown for the cab light. The Type strings
481535
are ORTS_LEFTDOOR, ORTS_RIGHTDOOR and ORTS_MIRRORS.
482536

537+
.. _cabs-generic-items:
538+
539+
Cab controls for generic items
540+
------------------------------
541+
542+
OR supports the cabview controls for two generic two-state items.
543+
The cabview controls aree called ``<ORTS_GENERIC_ITEM1>`` and
544+
``<ORTS_GENERIC_ITEM2>``. Their state can be toggled also by respectively
545+
clicking keys ``<Shift+.>`` and ``<Shift+,>``.
546+
547+
Sound events are associated, that is::
548+
549+
240: GenericItem1On
550+
241: GenericItem1Off
551+
242: GenericItem2On
552+
243: GenericItem2Off
553+
554+
Animations within the .s file of the locomotive, either stopped/moving or
555+
two-state can be associated to the item state. Linked stopped/moving (wiper type)
556+
animations are named ``<ORTSITEM1CONTINUOUS>`` and ``<ORTSITEM2CONTINUOUS>``.
557+
Linked two-state animations (doors type) are named ``<ORTSITEM1TWOSTATE>`` and
558+
``<ORTSITEM2TWOSTATE>``.
559+
The default animation speed for stopped/moving type animations is 8 FPS.
560+
It may be modified with following parameter in the .sd file::
561+
562+
ESD_CustomAnimationSpeed ( 8 )
563+
564+
Examples of use are fan control, open/close of aerodynamic coverages of couplers
565+
in high speed trains, menu pages switching.
566+
483567

484568
High-resolution Cab Backgrounds and Controls
485569
--------------------------------------------

Source/Documentation/Manual/sound.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,18 @@ Trigger Function
391391
235 AirConditioningOff
392392
========= =====================================
393393

394+
Triggers from 240 to 243 associated to the two generic items
395+
(see :ref:`here <cabs-generic-items>`) :
396+
397+
========= =====================================
398+
Trigger Function
399+
========= =====================================
400+
240 GenericItem1On
401+
241 GenericItem1Off
402+
242 GenericItem2On
403+
243 GenericItem2Off
404+
========= =====================================
405+
394406
Variable Triggers
395407
-----------------
396408

Source/ORTS.Common/Input/UserCommand.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,8 +205,10 @@ public enum UserCommand
205205
[GetString("Control ImmediateRefill")] ControlImmediateRefill,
206206
[GetString("Control Turntable Clockwise")] ControlTurntableClockwise,
207207
[GetString("Control Turntable Counterclockwise")] ControlTurntableCounterclockwise,
208-
[GetString("Control Generic 1")] ControlGeneric1,
209-
[GetString("Control Generic 2")] ControlGeneric2,
208+
[GetString("Control Generic Item 1")] ControlGenericItem1,
209+
[GetString("Control Generic Item 2")] ControlGenericItem2,
210+
[GetString("Control TCS Generic 1")] ControlTCSGeneric1,
211+
[GetString("Control TCS Generic 2")] ControlTCSGeneric2,
210212
[GetString("Control Cab Radio")] ControlCabRadio,
211213
[GetString("Control AI Fire On")] ControlAIFireOn,
212214
[GetString("Control AI Fire Off")] ControlAIFireOff,

Source/ORTS.Settings/InputSettings.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -388,8 +388,10 @@ static void InitializeCommands(UserCommandInput[] Commands)
388388
Commands[(int)UserCommand.ControlForwards] = new UserCommandKeyInput(0x11);
389389
Commands[(int)UserCommand.ControlGearDown] = new UserCommandKeyInput(0x12, KeyModifiers.Shift);
390390
Commands[(int)UserCommand.ControlGearUp] = new UserCommandKeyInput(0x12);
391-
Commands[(int)UserCommand.ControlGeneric1] = new UserCommandKeyInput(0x33, KeyModifiers.Control);
392-
Commands[(int)UserCommand.ControlGeneric2] = new UserCommandKeyInput(0x34, KeyModifiers.Control);
391+
Commands[(int)UserCommand.ControlGenericItem1] = new UserCommandKeyInput(0x33, KeyModifiers.Shift);
392+
Commands[(int)UserCommand.ControlGenericItem2] = new UserCommandKeyInput(0x34, KeyModifiers.Shift);
393+
Commands[(int)UserCommand.ControlTCSGeneric1] = new UserCommandKeyInput(0x33, KeyModifiers.Control);
394+
Commands[(int)UserCommand.ControlTCSGeneric2] = new UserCommandKeyInput(0x34, KeyModifiers.Control);
393395
Commands[(int)UserCommand.ControlHandbrakeFull] = new UserCommandKeyInput(0x28, KeyModifiers.Shift);
394396
Commands[(int)UserCommand.ControlHandbrakeNone] = new UserCommandKeyInput(0x27, KeyModifiers.Shift);
395397
Commands[(int)UserCommand.ControlHeadlightDecrease] = new UserCommandKeyInput(0x23, KeyModifiers.Shift);

Source/Orts.Formats.Msts/CabViewFile.cs

Lines changed: 82 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,10 @@ public enum CABViewControlTypes
202202
ORTS_ELECTRIC_TRAIN_SUPPLY_COMMAND_SWITCH,
203203
ORTS_ELECTRIC_TRAIN_SUPPLY_ON,
204204
ORTS_2DEXTERNALWIPERS,
205+
ORTS_GENERIC_ITEM1,
206+
ORTS_GENERIC_ITEM2,
207+
ORTS_SCREEN_SELECT,
208+
ORTS_STATIC_DISPLAY,
205209

206210
// TCS Controls
207211
ORTS_TCS1,
@@ -390,6 +394,10 @@ public class CabViewControl
390394
public double OldValue;
391395
public string ACEFile = "";
392396

397+
public int Display;
398+
public List<string> Screens;
399+
public int CabViewpoint;
400+
393401
public CABViewControlTypes ControlType = CABViewControlTypes.NONE;
394402
public CABViewControlStyles ControlStyle = CABViewControlStyles.NONE;
395403
public CABViewControlUnits Units = CABViewControlUnits.NONE;
@@ -509,6 +517,32 @@ protected virtual float ParseRotation(STFReader stf)
509517
stf.SkipRestOfBlock();
510518
return rotation;
511519
}
520+
521+
protected virtual void ParseDisplay(STFReader stf)
522+
{
523+
stf.MustMatch("(");
524+
Display = stf.ReadInt(0);
525+
stf.SkipRestOfBlock();
526+
}
527+
528+
protected virtual void ParseScreen(STFReader stf)
529+
{
530+
stf.MustMatch("(");
531+
var newScreen = stf.ReadString();
532+
stf.SkipRestOfBlock();
533+
if (Screens == null)
534+
Screens = new List<string>();
535+
Screens.Add(newScreen.ToLower());
536+
}
537+
538+
protected virtual void ParseCabViewpoint(STFReader stf)
539+
{
540+
stf.MustMatch("(");
541+
CabViewpoint = stf.ReadInt(0);
542+
stf.SkipRestOfBlock();
543+
}
544+
545+
512546
}
513547
#endregion
514548

@@ -560,6 +594,9 @@ public CVCDial(STFReader stf, string basepath)
560594
ToDegree = stf.ReadFloat(STFReader.UNITS.None, null);
561595
stf.SkipRestOfBlock();
562596
}),
597+
new STFReader.TokenProcessor("ortsdisplay", ()=>{ParseDisplay(stf); }),
598+
new STFReader.TokenProcessor("ortsscreenpage", () => {ParseScreen(stf); }),
599+
new STFReader.TokenProcessor("ortscabviewpoint", ()=>{ParseCabViewpoint(stf); }),
563600
});
564601
}
565602
}
@@ -645,7 +682,10 @@ public CVCGauge(STFReader stf, string basepath)
645682
new STFReader.TokenProcessor("controlcolour", ()=>{ DecreaseColor = ParseControlColor(stf); }) });
646683
}
647684
}),
648-
new STFReader.TokenProcessor("ortsangle", () =>{ Rotation = ParseRotation(stf); })
685+
new STFReader.TokenProcessor("ortsangle", () =>{ Rotation = ParseRotation(stf); }),
686+
new STFReader.TokenProcessor("ortsdisplay", ()=>{ParseDisplay(stf); }),
687+
new STFReader.TokenProcessor("ortsscreenpage", () => {ParseScreen(stf); }),
688+
new STFReader.TokenProcessor("ortscabviewpoint", ()=>{ParseCabViewpoint(stf); }),
649689
});
650690
}
651691
}
@@ -768,7 +808,10 @@ public CVCDigital(STFReader stf, string basepath)
768808
}
769809
}),
770810
new STFReader.TokenProcessor("ortsfont", ()=>{ParseFont(stf); }),
771-
new STFReader.TokenProcessor("ortsangle", () => {Rotation = ParseRotation(stf); }),
811+
new STFReader.TokenProcessor("ortsangle", () => {Rotation = ParseRotation(stf); }),
812+
new STFReader.TokenProcessor("ortsdisplay", ()=>{ParseDisplay(stf); }),
813+
new STFReader.TokenProcessor("ortsscreenpage", () => {ParseScreen(stf); }),
814+
new STFReader.TokenProcessor("ortscabviewpoint", ()=>{ParseCabViewpoint(stf); }),
772815
});
773816
}
774817

@@ -829,7 +872,10 @@ public CVCDigitalClock(STFReader stf, string basepath)
829872
new STFReader.TokenProcessor("accuracy", ()=>{ ParseAccuracy(stf); }),
830873
new STFReader.TokenProcessor("controlcolour", ()=>{ PositiveColor = ParseControlColor(stf); }),
831874
new STFReader.TokenProcessor("ortsfont", ()=>{ParseFont(stf); }),
832-
new STFReader.TokenProcessor("ortsangle", () => { Rotation = ParseRotation(stf); })
875+
new STFReader.TokenProcessor("ortsangle", () => { Rotation = ParseRotation(stf); }),
876+
new STFReader.TokenProcessor("ortsdisplay", ()=>{ParseDisplay(stf); }),
877+
new STFReader.TokenProcessor("ortsscreenpage", () => {ParseScreen(stf); }),
878+
new STFReader.TokenProcessor("ortscabviewpoint", ()=>{ParseCabViewpoint(stf); }),
833879
});
834880
}
835881

@@ -866,6 +912,14 @@ public class CVCDiscrete : CVCWithFrames
866912
private int numPositions;
867913
private bool canFill = true;
868914

915+
public struct NewScreenData
916+
{
917+
public string NewScreen;
918+
public int NewScreenDisplay;
919+
920+
}
921+
public List<NewScreenData> NewScreens;
922+
869923
public CVCDiscrete(STFReader stf, string basepath, DiscreteStates discreteState)
870924
{
871925
// try
@@ -999,6 +1053,10 @@ public CVCDiscrete(STFReader stf, string basepath, DiscreteStates discreteState)
9991053
_ValuesRead++;
10001054
}
10011055
}),
1056+
new STFReader.TokenProcessor("ortsdisplay", ()=>{ParseDisplay(stf); }),
1057+
new STFReader.TokenProcessor("ortsscreenpage", () => {ParseScreen(stf); }),
1058+
new STFReader.TokenProcessor("ortsnewscreenpage", () => {ParseNewScreen(stf); }),
1059+
new STFReader.TokenProcessor("ortscabviewpoint", ()=>{ParseCabViewpoint(stf); }),
10021060
});
10031061

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

@@ -1228,6 +1298,9 @@ public CVCMultiStateDisplay(STFReader stf, string basepath)
12281298
for (int i = Values.Count; i < FramesCount; i++)
12291299
Values.Add(-10000);
12301300
}),
1301+
new STFReader.TokenProcessor("ortsdisplay", ()=>{ParseDisplay(stf); }),
1302+
new STFReader.TokenProcessor("ortsscreenpage", () => {ParseScreen(stf); }),
1303+
new STFReader.TokenProcessor("ortscabviewpoint", ()=>{ParseCabViewpoint(stf); }),
12311304
});
12321305
}
12331306
protected int ParseNumStyle(STFReader stf)
@@ -1275,6 +1348,9 @@ public CVCAnimatedDisplay(STFReader stf, string basepath)
12751348
for (int i = Values.Count; i < FramesCount; i++)
12761349
Values.Add(-10000);
12771350
}),
1351+
new STFReader.TokenProcessor("ortsdisplay", ()=>{ParseDisplay(stf); }),
1352+
new STFReader.TokenProcessor("ortsscreenpage", () => {ParseScreen(stf); }),
1353+
new STFReader.TokenProcessor("ortscabviewpoint", ()=>{ParseCabViewpoint(stf); }),
12781354
});
12791355
}
12801356
protected int ParseNumStyle(STFReader stf)
@@ -1307,6 +1383,9 @@ public CVCScreen(STFReader stf, string basepath)
13071383
new STFReader.TokenProcessor("parameters", ()=>{ ParseCustomParameters(stf); }),
13081384
new STFReader.TokenProcessor("disablediflowvoltagepowersupplyoff", ()=>{ ParseDisabledIfLowVoltagePowerSupplyOff(stf); }),
13091385
new STFReader.TokenProcessor("disabledifcabpowersupplyoff", ()=>{ ParseDisabledIfCabPowerSupplyOff(stf); }),
1386+
new STFReader.TokenProcessor("ortsdisplay", ()=>{ParseDisplay(stf); }),
1387+
new STFReader.TokenProcessor("ortsscreenpage", () => {ParseScreen(stf); }),
1388+
new STFReader.TokenProcessor("ortscabviewpoint", ()=>{ParseCabViewpoint(stf); }),
13101389
});
13111390
}
13121391
protected void ParseCustomParameters(STFReader stf)

Source/Orts.Formats.Msts/ShapeDescriptorFile.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ public SDShape(STFReader stf)
6464
ESD_Bounding_Box = null;
6565
}),
6666
new STFReader.TokenProcessor("esd_ortssoundfilename", ()=>{ ESD_SoundFileName = stf.ReadStringBlock(null); }),
67-
new STFReader.TokenProcessor("esd_ortsbellanimationfps", ()=>{ ESD_BellAnimationFPS = stf.ReadFloatBlock(STFReader.UNITS.Frequency, null); }),
67+
new STFReader.TokenProcessor("esd_ortsbellanimationfps", ()=>{ ESD_CustomAnimationFPS = stf.ReadFloatBlock(STFReader.UNITS.Frequency, null); }),
68+
new STFReader.TokenProcessor("esd_ortscustomanimationfps", ()=>{ ESD_CustomAnimationFPS = stf.ReadFloatBlock(STFReader.UNITS.Frequency, null); }),
6869
});
6970
// TODO - some objects have no bounding box - ie JP2BillboardTree1.sd
7071
//if (ESD_Bounding_Box == null) throw new STFException(stf, "Missing ESD_Bound_Box statement");
@@ -76,7 +77,7 @@ public SDShape(STFReader stf)
7677
public bool ESD_Snapable;
7778
public bool ESD_SubObj;
7879
public string ESD_SoundFileName = "";
79-
public float ESD_BellAnimationFPS = 8;
80+
public float ESD_CustomAnimationFPS = 8;
8081
}
8182

8283
public class ESD_Bounding_Box

Source/Orts.Simulation/Common/Commands.cs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1999,4 +1999,47 @@ public override string ToString()
19991999
}
20002000
}
20012001

2002+
[Serializable()]
2003+
public sealed class ToggleGenericItem1Command : Command
2004+
{
2005+
public static MSTSLocomotive Receiver { get; set; }
2006+
2007+
public ToggleGenericItem1Command(CommandLog log)
2008+
: base(log)
2009+
{
2010+
Redo();
2011+
}
2012+
2013+
public override void Redo()
2014+
{
2015+
Receiver.GenericItem1Toggle();
2016+
}
2017+
2018+
public override string ToString()
2019+
{
2020+
return base.ToString();
2021+
}
2022+
}
2023+
2024+
[Serializable()]
2025+
public sealed class ToggleGenericItem2Command : Command
2026+
{
2027+
public static MSTSLocomotive Receiver { get; set; }
2028+
2029+
public ToggleGenericItem2Command(CommandLog log)
2030+
: base(log)
2031+
{
2032+
Redo();
2033+
}
2034+
2035+
public override void Redo()
2036+
{
2037+
Receiver.GenericItem2Toggle();
2038+
}
2039+
2040+
public override string ToString()
2041+
{
2042+
return base.ToString();
2043+
}
2044+
}
20022045
}

0 commit comments

Comments
 (0)