Skip to content

Commit

Permalink
Merge pull request #717 from cesarBLG/unlimited-tcs-controls
Browse files Browse the repository at this point in the history
Allow unlimited number of TCS cabview controls
  • Loading branch information
cesarBLG committed Jan 19, 2023
2 parents 7047b8c + 98221c0 commit d0b80ed
Show file tree
Hide file tree
Showing 11 changed files with 178 additions and 358 deletions.
16 changes: 8 additions & 8 deletions Source/Documentation/Manual/features-rollingstock.rst
Expand Up @@ -1721,8 +1721,8 @@ interface), which can include a (touch screen) display and buttons.
Being the display fields and icons and the buttons specific of every TCS,
a set of generic cabview controls are available, which can be customized
within the TCS script.
More precisely 48 generic cabview controls, named from ORTS_TCS1 to ORTS_TCS48
are available. All 48 may be used as two state or multistate controls,
Generic cabview controls, named ORTS_TCS1, ORTS_TCS2, and so on
are available. All of them may be used as two state or multistate controls,
like e.g.::

MultiStateDisplay (
Expand Down Expand Up @@ -1766,7 +1766,7 @@ like e.g.::
single: Style
single: MouseControl

Each one of the first 32 can be also used as Two-state commands/displays, like e.g.::
They can be also used as Two-state commands/displays, like e.g.::

TwoState (
Type ( ORTS_TCS7 TWO_STATE )
Expand All @@ -1784,8 +1784,8 @@ The commands are received asynchronously by the script through this method:
public override void HandleEvent(TCSEvent evt, string message)
Where evt may be TCSEvent.GenericTCSButtonPressed or TCSEvent.GenericTCSButtonReleased
and message is a string ranging from "0" to "31", which correspond to controls from
ORTS_TCS1 to ORTS_TCS32.
and message is a string representing the control number with zero-base indexing
(e.g. "5" corresponds to ORTS_TCS6).
The commands may only be triggered by the mouse, except the first two which may also be
triggered by key combinations ``Ctrl,`` (comma) and ``Ctrl.`` (period).
Here's a code excerpt from the script which manages the commands:
Expand Down Expand Up @@ -1846,14 +1846,14 @@ To request a display of a cabview control, method:
public Action<int, float> SetCabDisplayControl;
has to be used, where ``int`` is the index of the cab control (from 0 to 47
corresponding from ORTS_TCS1 to ORTS_TCS48), and ``float`` is the value to be
has to be used, where ``int`` is the index of the cab control (starting from 0
which corresponds to ORTS_TCS1), and ``float`` is the value to be
used to select among frames.

When the player moves the mouse over the cabview controls linked to commands,
the name of such control shortly appears on the display, like e.g. "speedometer",
as a reminder to the player.
In case of these generic commands, strings from "ORTS_TCS1" to "ORTS_TCS32" would
In case of these generic commands, strings like "ORTS_TCS1" or "ORTS_TCS32" would
appear, which aren't mnemonic at all. Therefore following method is available:

.. code-block:: csharp
Expand Down
105 changes: 41 additions & 64 deletions Source/Orts.Formats.Msts/CabViewFile.cs
Expand Up @@ -215,54 +215,7 @@ public enum CABViewControlTypes
ORTS_EOT_EMERGENCY_BRAKE,

// TCS Controls
ORTS_TCS1,
ORTS_TCS2,
ORTS_TCS3,
ORTS_TCS4,
ORTS_TCS5,
ORTS_TCS6,
ORTS_TCS7,
ORTS_TCS8,
ORTS_TCS9,
ORTS_TCS10,
ORTS_TCS11,
ORTS_TCS12,
ORTS_TCS13,
ORTS_TCS14,
ORTS_TCS15,
ORTS_TCS16,
ORTS_TCS17,
ORTS_TCS18,
ORTS_TCS19,
ORTS_TCS20,
ORTS_TCS21,
ORTS_TCS22,
ORTS_TCS23,
ORTS_TCS24,
ORTS_TCS25,
ORTS_TCS26,
ORTS_TCS27,
ORTS_TCS28,
ORTS_TCS29,
ORTS_TCS30,
ORTS_TCS31,
ORTS_TCS32,
ORTS_TCS33,
ORTS_TCS34,
ORTS_TCS35,
ORTS_TCS36,
ORTS_TCS37,
ORTS_TCS38,
ORTS_TCS39,
ORTS_TCS40,
ORTS_TCS41,
ORTS_TCS42,
ORTS_TCS43,
ORTS_TCS44,
ORTS_TCS45,
ORTS_TCS46,
ORTS_TCS47,
ORTS_TCS48,
ORTS_TCS,
ORTS_ETCS,

// Cruise Control
Expand Down Expand Up @@ -386,6 +339,30 @@ public enum DiscreteStates
CAB_SIGNAL_DISPLAY
}

public struct CabViewControlType
{
public CABViewControlTypes Type;
public int Id;
public CabViewControlType(string name)
{
Type = CABViewControlTypes.NONE;
Id = 0;
if (name != null && name.ToUpperInvariant().StartsWith("ORTS_TCS"))
{
if (int.TryParse(name.Substring(8), out Id))
{
Type = CABViewControlTypes.ORTS_TCS;
}
}
else Enum.TryParse(name, true, out Type);
}
public override string ToString()
{
if (Type == CABViewControlTypes.ORTS_TCS) return Type.ToString() + Id;
return Type.ToString();
}
}

public class CabViewControls : List<CabViewControl>
{
public CabViewControls(STFReader stf, string basepath)
Expand Down Expand Up @@ -451,7 +428,7 @@ public class CabViewControl
public List<string> Screens;
public int CabViewpoint;

public CABViewControlTypes ControlType = CABViewControlTypes.NONE;
public CabViewControlType ControlType;
public CABViewControlStyles ControlStyle = CABViewControlStyles.NONE;
public CABViewControlUnits Units = CABViewControlUnits.NONE;

Expand All @@ -463,15 +440,11 @@ public class CabViewControl
protected void ParseType(STFReader stf)
{
stf.MustMatch("(");
try
string name = stf.ReadString();
ControlType = new CabViewControlType(name);
if (ControlType.Type == CABViewControlTypes.NONE)
{
ControlType = (CABViewControlTypes)Enum.Parse(typeof(CABViewControlTypes), stf.ReadString());
}
catch(ArgumentException)
{
stf.StepBackOneItem();
STFException.TraceInformation(stf, "Skipped unknown ControlType " + stf.ReadString());
ControlType = CABViewControlTypes.NONE;
STFException.TraceInformation(stf, "Skipped unknown ControlType " + name);
}
//stf.ReadItem(); // Skip repeated Class Type
stf.SkipRestOfBlock();
Expand Down Expand Up @@ -631,7 +604,11 @@ public CVCDial(CABViewControlTypes dialtype, int maxvalue, STFReader stf, string
new STFReader.TokenProcessor("graphic", ()=>{ ParseGraphic(stf, basepath); }),
new STFReader.TokenProcessor("pivot", ()=>{ Center = stf.ReadFloatBlock(STFReader.UNITS.None, null); }),
});
ControlType = dialtype;
ControlType = new CabViewControlType()
{
Type = dialtype,
Id = 0,
};
ControlStyle = CABViewControlStyles.NEEDLE;
Direction = 0;
MaxValue = maxvalue;
Expand Down Expand Up @@ -1318,15 +1295,15 @@ public CVCDiscrete(STFReader stf, string basepath, DiscreteStates discreteState)
}

// MSTS ignores/overrides various settings by the following exceptional cases:
if (ControlType == CABViewControlTypes.CP_HANDLE)
if (ControlType.Type == CABViewControlTypes.CP_HANDLE)
ControlStyle = CABViewControlStyles.NOT_SPRUNG;
if (ControlType == CABViewControlTypes.PANTOGRAPH || ControlType == CABViewControlTypes.PANTOGRAPH2 ||
ControlType == CABViewControlTypes.ORTS_PANTOGRAPH3 || ControlType == CABViewControlTypes.ORTS_PANTOGRAPH4)
if (ControlType.Type == CABViewControlTypes.PANTOGRAPH || ControlType.Type == CABViewControlTypes.PANTOGRAPH2 ||
ControlType.Type == CABViewControlTypes.ORTS_PANTOGRAPH3 || ControlType.Type == CABViewControlTypes.ORTS_PANTOGRAPH4)
ControlStyle = CABViewControlStyles.ONOFF;
if (ControlType == CABViewControlTypes.HORN || ControlType == CABViewControlTypes.SANDERS || ControlType == CABViewControlTypes.BELL
|| ControlType == CABViewControlTypes.RESET || ControlType == CABViewControlTypes.VACUUM_EXHAUSTER)
if (ControlType.Type == CABViewControlTypes.HORN || ControlType.Type == CABViewControlTypes.SANDERS || ControlType.Type == CABViewControlTypes.BELL
|| ControlType.Type == CABViewControlTypes.RESET || ControlType.Type == CABViewControlTypes.VACUUM_EXHAUSTER)
ControlStyle = CABViewControlStyles.WHILE_PRESSED;
if (ControlType == CABViewControlTypes.DIRECTION && Orientation == 0)
if (ControlType.Type == CABViewControlTypes.DIRECTION && Orientation == 0)
Direction = 1 - Direction;

switch (discreteState)
Expand Down
Expand Up @@ -848,7 +848,7 @@ public override float GetDataOf(CabViewControl cvc)
{
float data = 0;

switch (cvc.ControlType)
switch (cvc.ControlType.Type)
{
case CABViewControlTypes.GEARS:
if (DieselEngines.HasGearBox)
Expand Down Expand Up @@ -1442,7 +1442,7 @@ protected void NormalizeParams()
{
foreach ( var control in cabView.CVFFile.CabViewControls)
{
if (control is CVCDiscrete && control.ControlType == CABViewControlTypes.THROTTLE && (control as CVCDiscrete).Values.Count > 0 && (control as CVCDiscrete).Values[(control as CVCDiscrete).Values.Count - 1] > 1)
if (control is CVCDiscrete && control.ControlType.Type == CABViewControlTypes.THROTTLE && (control as CVCDiscrete).Values.Count > 0 && (control as CVCDiscrete).Values[(control as CVCDiscrete).Values.Count - 1] > 1)
{
var discreteControl = (CVCDiscrete)control;
for (var i = 0; i < discreteControl.Values.Count; i++)
Expand Down
Expand Up @@ -221,7 +221,7 @@ public override float GetDataOf(CabViewControl cvc)
{
float data = 0;

switch (cvc.ControlType)
switch (cvc.ControlType.Type)
{
case CABViewControlTypes.LINE_VOLTAGE:
data = ElectricPowerSupply.PantographVoltageV;
Expand Down
73 changes: 11 additions & 62 deletions Source/Orts.Simulation/Simulation/RollingStocks/MSTSLocomotive.cs
Expand Up @@ -632,16 +632,16 @@ protected MSTSNotchController BuildDPDynamicBrakeController()
{
msDisplay = (CVCMultiStateDisplay) cabView.CVFFile.CabViewControls.Where(
control => control is CVCMultiStateDisplay &&
(((CVCMultiStateDisplay) control).ControlType == CABViewControlTypes.DYNAMIC_BRAKE_DISPLAY ||
((CVCMultiStateDisplay) control).ControlType == CABViewControlTypes.CPH_DISPLAY)).First();
(((CVCMultiStateDisplay) control).ControlType.Type == CABViewControlTypes.DYNAMIC_BRAKE_DISPLAY ||
((CVCMultiStateDisplay) control).ControlType.Type == CABViewControlTypes.CPH_DISPLAY)).First();
}
catch
{

}
if (msDisplay != null)
{
if (msDisplay.ControlType == CABViewControlTypes.DYNAMIC_BRAKE_DISPLAY)
if (msDisplay.ControlType.Type == CABViewControlTypes.DYNAMIC_BRAKE_DISPLAY)
{
foreach (var switchval in msDisplay.Values)
dpDynController.AddNotch((float) switchval);
Expand Down Expand Up @@ -703,11 +703,8 @@ protected void GetPressureUnit()
CabViewControls cvcList = CabViewList[0].CVFFile.CabViewControls;
foreach (CabViewControl cvc in cvcList)
{
if (brakeSystemComponents.ContainsKey(cvc.ControlType) && pressureUnits.ContainsKey(cvc.Units))
if (brakeSystemComponents.TryGetValue(cvc.ControlType.Type, out var component) && pressureUnits.TryGetValue(cvc.Units, out var unit))
{
BrakeSystemComponent component = brakeSystemComponents[cvc.ControlType];
PressureUnit unit = pressureUnits[cvc.Units];

BrakeSystemPressureUnits[component] = unit;
}
}
Expand Down Expand Up @@ -4992,7 +4989,7 @@ public override void SignalEvent(Event evt)
public virtual float GetDataOf(CabViewControl cvc)
{
float data = 0;
switch (cvc.ControlType)
switch (cvc.ControlType.Type)
{
case CABViewControlTypes.SPEEDOMETER:
{
Expand Down Expand Up @@ -5090,7 +5087,7 @@ public virtual float GetDataOf(CabViewControl cvc)
if (DynamicBrakePercent > 0 && MaxDynamicBrakeForceN > 0)
{
float rangeFactor;
if (cvc.ControlType == CABViewControlTypes.AMMETER_ABS)
if (cvc.ControlType.Type == CABViewControlTypes.AMMETER_ABS)
{
if (DynamicBrakeMaxCurrentA == 0)
rangeFactor = direction == 0 ? (float)cvc.MaxValue : (float)cvc.MinValue;
Expand All @@ -5108,11 +5105,11 @@ public virtual float GetDataOf(CabViewControl cvc)
}
if (direction == 1)
data = -data;
if (cvc.ControlType == CABViewControlTypes.AMMETER_ABS) data = Math.Abs(data);
if (cvc.ControlType.Type == CABViewControlTypes.AMMETER_ABS) data = Math.Abs(data);
break;
}
data = this.MotiveForceN / MaxForceN * MaxCurrentA;
if (cvc.ControlType == CABViewControlTypes.AMMETER_ABS) data = Math.Abs(data);
if (cvc.ControlType.Type == CABViewControlTypes.AMMETER_ABS) data = Math.Abs(data);
break;
}
case CABViewControlTypes.LOAD_METER:
Expand Down Expand Up @@ -5780,7 +5777,7 @@ public virtual float GetDataOf(CabViewControl cvc)
case CABViewControlTypes.ORTS_LEFTDOOR:
case CABViewControlTypes.ORTS_RIGHTDOOR:
{
bool right = (cvc.ControlType == CABViewControlTypes.ORTS_RIGHTDOOR) ^ Flipped ^ GetCabFlipped();
bool right = (cvc.ControlType.Type == CABViewControlTypes.ORTS_RIGHTDOOR) ^ Flipped ^ GetCabFlipped();
var state = Train.DoorState(right ? DoorSide.Right : DoorSide.Left);
data = state >= DoorState.Opening ? 1 : 0;
}
Expand Down Expand Up @@ -5820,56 +5817,8 @@ public virtual float GetDataOf(CabViewControl cvc)
break;
}

// Train Control System controls
case CABViewControlTypes.ORTS_TCS1:
case CABViewControlTypes.ORTS_TCS2:
case CABViewControlTypes.ORTS_TCS3:
case CABViewControlTypes.ORTS_TCS4:
case CABViewControlTypes.ORTS_TCS5:
case CABViewControlTypes.ORTS_TCS6:
case CABViewControlTypes.ORTS_TCS7:
case CABViewControlTypes.ORTS_TCS8:
case CABViewControlTypes.ORTS_TCS9:
case CABViewControlTypes.ORTS_TCS10:
case CABViewControlTypes.ORTS_TCS11:
case CABViewControlTypes.ORTS_TCS12:
case CABViewControlTypes.ORTS_TCS13:
case CABViewControlTypes.ORTS_TCS14:
case CABViewControlTypes.ORTS_TCS15:
case CABViewControlTypes.ORTS_TCS16:
case CABViewControlTypes.ORTS_TCS17:
case CABViewControlTypes.ORTS_TCS18:
case CABViewControlTypes.ORTS_TCS19:
case CABViewControlTypes.ORTS_TCS20:
case CABViewControlTypes.ORTS_TCS21:
case CABViewControlTypes.ORTS_TCS22:
case CABViewControlTypes.ORTS_TCS23:
case CABViewControlTypes.ORTS_TCS24:
case CABViewControlTypes.ORTS_TCS25:
case CABViewControlTypes.ORTS_TCS26:
case CABViewControlTypes.ORTS_TCS27:
case CABViewControlTypes.ORTS_TCS28:
case CABViewControlTypes.ORTS_TCS29:
case CABViewControlTypes.ORTS_TCS30:
case CABViewControlTypes.ORTS_TCS31:
case CABViewControlTypes.ORTS_TCS32:
case CABViewControlTypes.ORTS_TCS33:
case CABViewControlTypes.ORTS_TCS34:
case CABViewControlTypes.ORTS_TCS35:
case CABViewControlTypes.ORTS_TCS36:
case CABViewControlTypes.ORTS_TCS37:
case CABViewControlTypes.ORTS_TCS38:
case CABViewControlTypes.ORTS_TCS39:
case CABViewControlTypes.ORTS_TCS40:
case CABViewControlTypes.ORTS_TCS41:
case CABViewControlTypes.ORTS_TCS42:
case CABViewControlTypes.ORTS_TCS43:
case CABViewControlTypes.ORTS_TCS44:
case CABViewControlTypes.ORTS_TCS45:
case CABViewControlTypes.ORTS_TCS46:
case CABViewControlTypes.ORTS_TCS47:
case CABViewControlTypes.ORTS_TCS48:
data = TrainControlSystem.CabDisplayControls[(int)cvc.ControlType - (int)CABViewControlTypes.ORTS_TCS1];
case CABViewControlTypes.ORTS_TCS:
TrainControlSystem.CabDisplayControls.TryGetValue(cvc.ControlType.Id - 1, out data);
break;

case CABViewControlTypes.ORTS_BATTERY_SWITCH_COMMAND_SWITCH:
Expand Down
Expand Up @@ -6177,7 +6177,7 @@ public override float GetDataOf(CabViewControl cvc)
{
float data;

switch (cvc.ControlType)
switch (cvc.ControlType.Type)
{
case CABViewControlTypes.WHISTLE:
data = Horn ? 1 : 0;
Expand Down
Expand Up @@ -1414,7 +1414,7 @@ void SetTrainBrake(ref float brakePercent, float elapsedClockSeconds, float delt
public float GetDataOf(CabViewControl cvc)
{
float data = 0;
switch (cvc.ControlType)
switch (cvc.ControlType.Type)
{
case CABViewControlTypes.ORTS_SELECTED_SPEED:
case CABViewControlTypes.ORTS_SELECTED_SPEED_DISPLAY:
Expand Down
Expand Up @@ -229,7 +229,7 @@ public override void Copy(MSTSWagon copy)
public float GetDataOf(CabViewControl cvc)
{
float data = 0;
switch (cvc.ControlType)
switch (cvc.ControlType.Type)
{
case CABViewControlTypes.ORTS_EOT_ID:
data = ID;
Expand Down

0 comments on commit d0b80ed

Please sign in to comment.