Skip to content

Commit a416124

Browse files
authored
Merge pull request #412 from Sharpe49/tcs-speed-post-features
New TCS function to get speed post information (including warning speed posts) https://trello.com/c/S38d2RoV/482-further-tcs-handles-related-to-signals-and-sound-events
2 parents 920a433 + 26e29ed commit a416124

File tree

8 files changed

+245
-111
lines changed

8 files changed

+245
-111
lines changed

Source/Orts.Simulation/Common/Scripting/TrainControlSystem.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,12 @@ public abstract class TrainControlSystem : AbstractTrainScriptClass
118118
/// </summary>
119119
public Func<string, int, float, SignalFeatures> NextGenericSignalFeatures;
120120
/// <summary>
121+
/// Features of next speed post
122+
/// int: position of speed post in the speed post sequence along the train route, starting from train front; 0 for first speed post;
123+
/// float: max testing distance
124+
/// </summary>
125+
public Func<int, float, SpeedPostFeatures> NextSpeedPostFeatures;
126+
/// <summary>
121127
/// Next normal signal has a repeater head
122128
/// </summary>
123129
public Func<bool> DoesNextNormalSignalHaveRepeaterHead;
@@ -690,6 +696,24 @@ public SignalFeatures(string mainHeadSignalTypeName, Aspect aspect, float distan
690696
}
691697
}
692698

699+
public struct SpeedPostFeatures
700+
{
701+
public readonly string SpeedPostTypeName;
702+
public readonly bool IsWarning;
703+
public readonly float DistanceM;
704+
public readonly float SpeedLimitMpS;
705+
public readonly float AltitudeM;
706+
707+
public SpeedPostFeatures(string speedPostTypeName, bool isWarning, float distanceM, float speedLimitMpS, float altitudeM)
708+
{
709+
SpeedPostTypeName = speedPostTypeName;
710+
IsWarning = isWarning;
711+
DistanceM = distanceM;
712+
SpeedLimitMpS = speedLimitMpS;
713+
AltitudeM = altitudeM;
714+
}
715+
}
716+
693717
public struct TunnelInfo
694718
{
695719
/// <summary>

Source/Orts.Simulation/Orts.Simulation.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@
146146
<Compile Include="Simulation\Signalling\CsSignalScripts.cs" />
147147
<Compile Include="Simulation\Signalling\Signals.cs" />
148148
<Compile Include="Simulation\Signalling\SIGSCRfile.cs" />
149+
<Compile Include="Simulation\Signalling\SpeedPostWorldObject.cs" />
149150
<Compile Include="Simulation\Simulator.cs" />
150151
<Compile Include="Simulation\SuperElevation.cs" />
151152
<Compile Include="Simulation\Timetables\PoolInfo.cs" />

Source/Orts.Simulation/Simulation/AIs/AITrain.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
using System.Collections.Generic;
4242
using System.Diagnostics;
4343
using System.IO;
44+
using System.Linq;
4445
using Event = Orts.Common.Event;
4546

4647
namespace Orts.Simulation.AIs
@@ -1164,7 +1165,7 @@ public void CheckSignalObjects()
11641165
float validSpeed = AllowedMaxSpeedMpS;
11651166
List<ObjectItemInfo> processedList = new List<ObjectItemInfo>();
11661167

1167-
foreach (ObjectItemInfo thisInfo in SignalObjectItems)
1168+
foreach (ObjectItemInfo thisInfo in SignalObjectItems.Where(item => !item.speed_isWarning))
11681169
{
11691170

11701171
// check speedlimit

Source/Orts.Simulation/Simulation/Physics/Train.cs

Lines changed: 102 additions & 83 deletions
Large diffs are not rendered by default.

Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/TrainControlSystem.cs

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// COPYRIGHT 2013, 2014 by the Open Rails project.
1+
// COPYRIGHT 2021 by the Open Rails project.
22
//
33
// This file is part of Open Rails.
44
//
@@ -21,16 +21,15 @@
2121
using Orts.Common;
2222
using Orts.Parsers.Msts;
2323
using Orts.Simulation.Physics;
24-
using Orts.Simulation.Signalling;
2524
using Orts.Simulation.RollingStocks.SubSystems.PowerSupplies;
2625
using ORTS.Common;
2726
using ORTS.Scripting.Api;
27+
using ORTS.Scripting.Api.ETCS;
2828
using System;
2929
using System.Collections.Generic;
30-
using System.IO;
3130
using System.Diagnostics;
31+
using System.IO;
3232
using System.Linq;
33-
using ORTS.Scripting.Api.ETCS;
3433

3534
namespace Orts.Simulation.RollingStocks.SubSystems
3635
{
@@ -288,6 +287,7 @@ public void Initialize()
288287
Script.NextGenericSignalDistanceM = (string type) =>
289288
NextGenericSignalItem<float>(0, ref ItemDistance, GenericItemDistance, Train.TrainObjectItem.TRAINOBJECTTYPE.SIGNAL, type);
290289
Script.NextGenericSignalFeatures = (arg1, arg2, arg3) => NextGenericSignalFeatures(arg1, arg2, arg3, Train.TrainObjectItem.TRAINOBJECTTYPE.SIGNAL);
290+
Script.NextSpeedPostFeatures = (arg1, arg2) => NextSpeedPostFeatures(arg1, arg2);
291291
Script.DoesNextNormalSignalHaveRepeaterHead = () => DoesNextNormalSignalHaveRepeaterHead();
292292
Script.CurrentPostSpeedLimitMpS = () => Locomotive.Train.allowedMaxSpeedLimitMpS;
293293
Script.NextPostSpeedLimitMpS = (value) => NextGenericSignalItem<float>(value, ref ItemSpeedLimit, float.MaxValue, Train.TrainObjectItem.TRAINOBJECTTYPE.SPEEDPOST);
@@ -625,7 +625,7 @@ SignalFeatures NextGenericSignalFeatures(string signalTypeName, int itemSequence
625625
}
626626
else if (type == Train.TrainObjectItem.TRAINOBJECTTYPE.SPEEDPOST)
627627
{
628-
var playerTrainSpeedpostList = Locomotive.Train.PlayerTrainSpeedposts[dir];
628+
var playerTrainSpeedpostList = Locomotive.Train.PlayerTrainSpeedposts[dir].Where(x => !x.IsWarning).ToList();
629629
if (itemSequenceIndex > playerTrainSpeedpostList.Count - 1)
630630
goto Exit; // no n-th speedpost available
631631
var trainSpeedpost = playerTrainSpeedpostList[itemSequenceIndex];
@@ -642,6 +642,43 @@ SignalFeatures NextGenericSignalFeatures(string signalTypeName, int itemSequence
642642
altitudeM: altitudeM, textAspect: textAspect);
643643
}
644644

645+
SpeedPostFeatures NextSpeedPostFeatures(int itemSequenceIndex, float maxDistanceM)
646+
{
647+
var speedPostTypeName = "";
648+
var isWarning = false;
649+
var distanceM = float.MaxValue;
650+
var speedLimitMpS = -1f;
651+
var altitudeM = float.MinValue;
652+
653+
int dir = Locomotive.Train.MUDirection == Direction.Reverse ? 1 : 0;
654+
655+
if (Locomotive.Train.ValidRoute[dir] == null || dir == 1 && Locomotive.Train.PresentPosition[dir].TCSectionIndex < 0)
656+
goto Exit;
657+
658+
int index = dir == 0 ? Locomotive.Train.PresentPosition[dir].RouteListIndex :
659+
Locomotive.Train.ValidRoute[dir].GetRouteIndex(Locomotive.Train.PresentPosition[dir].TCSectionIndex, 0);
660+
if (index < 0)
661+
goto Exit;
662+
663+
var playerTrainSpeedpostList = Locomotive.Train.PlayerTrainSpeedposts[dir];
664+
if (itemSequenceIndex > playerTrainSpeedpostList.Count - 1)
665+
goto Exit; // no n-th speedpost available
666+
var trainSpeedpost = playerTrainSpeedpostList[itemSequenceIndex];
667+
if (trainSpeedpost.DistanceToTrainM > maxDistanceM)
668+
goto Exit; // the requested speedpost is too distant
669+
670+
// All OK, we can retrieve the data for the required speedpost;
671+
speedPostTypeName = Path.GetFileNameWithoutExtension(trainSpeedpost.SignalObject.SpeedPostWorldObject?.SFileName);
672+
isWarning = trainSpeedpost.IsWarning;
673+
distanceM = trainSpeedpost.DistanceToTrainM;
674+
speedLimitMpS = trainSpeedpost.AllowedSpeedMpS;
675+
altitudeM = trainSpeedpost.SignalObject.tdbtraveller.Y;
676+
677+
Exit:
678+
return new SpeedPostFeatures(speedPostTypeName: speedPostTypeName, isWarning: isWarning, distanceM: distanceM, speedLimitMpS: speedLimitMpS,
679+
altitudeM: altitudeM);
680+
}
681+
645682
private bool DoesNextNormalSignalHaveRepeaterHead()
646683
{
647684
var signal = Locomotive.Train.NextSignalObject[Locomotive.Train.MUDirection == Direction.Reverse ? 1 : 0];

Source/Orts.Simulation/Simulation/Signalling/Signals.cs

Lines changed: 57 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ public class Signals
6868
private List<SignalWorldObject> SignalWorldList = new List<SignalWorldObject>();
6969
private Dictionary<uint, SignalRefObject> SignalRefList;
7070
private Dictionary<uint, SignalObject> SignalHeadList;
71+
private List<SpeedPostWorldObject> SpeedPostWorldList = new List<SpeedPostWorldObject>();
72+
private Dictionary<int, int> SpeedPostRefList = new Dictionary<int, int>();
7173
public static SIGSCRfile scrfile;
7274
public static CsSignalScripts CsSignalScripts;
7375
public int ORTSSignalTypeCount { get; private set; }
@@ -467,6 +469,7 @@ private void BuildSignalWorld(Simulator simulator, SignalConfigurationFile sigcf
467469

468470
var Tokens = new List<TokenID>();
469471
Tokens.Add(TokenID.Signal);
472+
Tokens.Add(TokenID.Speedpost);
470473
Tokens.Add(TokenID.Platform);
471474

472475
// loop through files, use only extention .w, skip w+1000000+1000000.w file
@@ -538,7 +541,19 @@ private void BuildSignalWorld(Simulator simulator, SignalConfigurationFile sigcf
538541
}
539542
}
540543
}
541-
else if (worldObject.GetType() == typeof(PlatformObj))
544+
else if (worldObject is SpeedPostObj speedPostObj)
545+
{
546+
SpeedPostWorldList.Add(new SpeedPostWorldObject(speedPostObj));
547+
int thisSpeedPostId = SpeedPostWorldList.Count() - 1;
548+
foreach(TrItemId trItemId in speedPostObj.trItemIDList)
549+
{
550+
if (!SpeedPostRefList.ContainsKey(trItemId.dbID))
551+
{
552+
SpeedPostRefList.Add(trItemId.dbID, thisSpeedPostId);
553+
}
554+
}
555+
}
556+
else if (worldObject.GetType() == typeof(PlatformObj))
542557
{
543558
var thisWorldObj = worldObject as PlatformObj;
544559
if (!PlatformSidesList.ContainsKey(thisWorldObj.trItemIDList[0].dbID)) PlatformSidesList.Add(thisWorldObj.trItemIDList[0].dbID, thisWorldObj.PlatformData);
@@ -633,7 +648,7 @@ private void BuildSignalList(TrItem[] TrItems, TrackNode[] trackNodes, TrackSect
633648
else if (trItem.ItemType == TrItem.trItemType.trSPEEDPOST)
634649
{
635650
SpeedPostItem Speedpost = (SpeedPostItem)trItem;
636-
if (Speedpost.IsLimit)
651+
if (!Speedpost.IsMilePost)
637652
{
638653
noSignals++;
639654
}
@@ -981,15 +996,14 @@ private void ScanSection(TrItem[] TrItems, TrackNode[] trackNodes, int index,
981996
else if (TrItems[TDBRef].ItemType == TrItem.trItemType.trSPEEDPOST)
982997
{
983998
SpeedPostItem speedItem = (SpeedPostItem)TrItems[TDBRef];
984-
if (speedItem.IsLimit)
999+
if (!speedItem.IsMilePost)
9851000
{
9861001
speedItem.SigObj = foundSignals;
9871002

9881003
lastSignal = AddSpeed(index, i, speedItem, TDBRef, tsectiondat, tdbfile, ORTSSignalTypeCount);
9891004
speedItem.SigObj = lastSignal;
990-
9911005
}
992-
else if (speedItem.IsMilePost)
1006+
else
9931007
{
9941008
speedItem.SigObj = foundMileposts;
9951009
lastMilepost = AddMilepost(index, i, speedItem, TDBRef, tsectiondat, tdbfile);
@@ -1231,22 +1245,39 @@ private void AddWorldInfo()
12311245
{
12321246
if (signal != null)
12331247
{
1234-
foreach (SignalHead head in signal.SignalHeads)
1248+
if (signal.isSignal)
12351249
{
1250+
foreach (SignalHead head in signal.SignalHeads)
1251+
{
12361252

1237-
// get reference using TDB index from head
1253+
// get reference using TDB index from head
12381254

1239-
uint TDBRef = Convert.ToUInt32(head.TDBIndex);
1240-
SignalRefObject thisRef;
1255+
uint TDBRef = Convert.ToUInt32(head.TDBIndex);
1256+
SignalRefObject thisRef;
12411257

1242-
if (SignalRefList.TryGetValue(TDBRef, out thisRef))
1258+
if (SignalRefList.TryGetValue(TDBRef, out thisRef))
1259+
{
1260+
uint signalIndex = thisRef.SignalWorldIndex;
1261+
if (signal.WorldObject == null)
1262+
{
1263+
signal.WorldObject = SignalWorldList[(int)signalIndex];
1264+
}
1265+
SignalRefList.Remove(TDBRef);
1266+
}
1267+
}
1268+
}
1269+
else
1270+
{
1271+
SignalHead head = signal.SignalHeads[0];
1272+
int speedPostIndex;
1273+
1274+
if (SpeedPostRefList.TryGetValue(head.TDBIndex, out speedPostIndex))
12431275
{
1244-
uint signalIndex = thisRef.SignalWorldIndex;
1245-
if (signal.WorldObject == null)
1276+
if (signal.SpeedPostWorldObject == null)
12461277
{
1247-
signal.WorldObject = SignalWorldList[(int)signalIndex];
1278+
signal.SpeedPostWorldObject = SpeedPostWorldList[speedPostIndex];
12481279
}
1249-
SignalRefList.Remove(TDBRef);
1280+
SpeedPostRefList.Remove(head.TDBIndex);
12501281
}
12511282
}
12521283
}
@@ -8351,6 +8382,7 @@ public enum HoldState // signal is locked in hold
83518382
public static TrackNode[] trackNodes;
83528383
public static TrItem[] trItems;
83538384
public SignalWorldObject WorldObject; // Signal World Object information
8385+
public SpeedPostWorldObject SpeedPostWorldObject; // Speed Post World Object information
83548386

83558387
public int trackNode; // Track node which contains this signal
83568388
public int trRefIndex; // Index to TrItemRef within Track Node
@@ -9205,7 +9237,7 @@ public MstsSignalAspect this_sig_lr(int fn_type, ref bool sigfound)
92059237
public ObjectSpeedInfo this_sig_speed(MstsSignalFunction fn_type)
92069238
{
92079239
var sigAsp = MstsSignalAspect.STOP;
9208-
var set_speed = new ObjectSpeedInfo(-1, -1, false, false, 0);
9240+
var set_speed = new ObjectSpeedInfo(-1, -1, false, false, 0, false);
92099241

92109242
foreach (SignalHead sigHead in SignalHeads)
92119243
{
@@ -9363,14 +9395,14 @@ public int SpeedPostType()
93639395

93649396
public ObjectSpeedInfo this_lim_speed(MstsSignalFunction fn_type)
93659397
{
9366-
var set_speed = new ObjectSpeedInfo(9E9f, 9E9f, false, false, 0);
9398+
var set_speed = new ObjectSpeedInfo(9E9f, 9E9f, false, false, 0, false);
93679399

93689400
foreach (SignalHead sigHead in SignalHeads)
93699401
{
93709402
if (sigHead.sigFunction == fn_type)
93719403
{
93729404
ObjectSpeedInfo this_speed = sigHead.speed_info[(int)sigHead.state];
9373-
if (this_speed != null)
9405+
if (this_speed != null && !this_speed.speed_isWarning)
93749406
{
93759407
if (this_speed.speed_pass > 0 && this_speed.speed_pass < set_speed.speed_pass)
93769408
{
@@ -12806,7 +12838,7 @@ public SignalHead(SignalObject sigOoject, int trItem, int TDBRef, SpeedPostItem
1280612838

1280712839
float passSpeed = speedItem.IsPassenger ? speedMpS : -1;
1280812840
float freightSpeed = speedItem.IsFreight ? speedMpS : -1;
12809-
ObjectSpeedInfo speedinfo = new ObjectSpeedInfo(passSpeed, freightSpeed, false, false, speedItem is TempSpeedPostItem? (speedMpS == 999f? 2 : 1) : 0);
12841+
ObjectSpeedInfo speedinfo = new ObjectSpeedInfo(passSpeed, freightSpeed, false, false, speedItem is TempSpeedPostItem? (speedMpS == 999f? 2 : 1) : 0, speedItem.IsWarning);
1281012842
speed_info[(int)state] = speedinfo;
1281112843
}
1281212844

@@ -12837,7 +12869,7 @@ public void SetSignalType(TrItem[] TrItems, SignalConfigurationFile sigCFG)
1283712869
foreach (SignalAspect thisAspect in signalType.Aspects)
1283812870
{
1283912871
int arrindex = (int)thisAspect.Aspect;
12840-
speed_info[arrindex] = new ObjectSpeedInfo(thisAspect.SpeedMpS, thisAspect.SpeedMpS, thisAspect.Asap, thisAspect.Reset, thisAspect.NoSpeedReduction? 1 : 0);
12872+
speed_info[arrindex] = new ObjectSpeedInfo(thisAspect.SpeedMpS, thisAspect.SpeedMpS, thisAspect.Asap, thisAspect.Reset, thisAspect.NoSpeedReduction? 1 : 0, false);
1284112873
}
1284212874

1284312875
// set normal subtype
@@ -13558,7 +13590,8 @@ public enum ObjectItemFindState
1355813590
public int speed_flag;
1355913591
public int speed_reset;
1356013592
// for signals: if = 1 no speed reduction; for speedposts: if = 0 standard; = 1 start of temp speedreduction post; = 2 end of temp speed reduction post
13561-
public int speed_noSpeedReductionOrIsTempSpeedReduction;
13593+
public int speed_noSpeedReductionOrIsTempSpeedReduction;
13594+
public bool speed_isWarning;
1356213595
public float actual_speed; // set active by TRAIN
1356313596

1356413597
public bool processed; // for AI trains, set active by TRAIN
@@ -13597,6 +13630,7 @@ public ObjectItemInfo(SignalObject thisObject, float distance)
1359713630
speed_flag = speed_info.speed_flag;
1359813631
speed_reset = speed_info.speed_reset;
1359913632
speed_noSpeedReductionOrIsTempSpeedReduction = speed_info.speed_noSpeedReductionOrIsTempSpeedReduction;
13633+
speed_isWarning = speed_info.speed_isWarning;
1360013634
}
1360113635
}
1360213636

@@ -13622,19 +13656,21 @@ public class ObjectSpeedInfo
1362213656
public int speed_flag;
1362313657
public int speed_reset;
1362413658
public int speed_noSpeedReductionOrIsTempSpeedReduction;
13659+
public bool speed_isWarning;
1362513660

1362613661
//================================================================================================//
1362713662
/// <summary>
1362813663
/// Constructor
1362913664
/// </summary>
1363013665

13631-
public ObjectSpeedInfo(float pass, float freight, bool asap, bool reset, int nospeedreductionOristempspeedreduction)
13666+
public ObjectSpeedInfo(float pass, float freight, bool asap, bool reset, int nospeedreductionOristempspeedreduction, bool isWarning)
1363213667
{
1363313668
speed_pass = pass;
1363413669
speed_freight = freight;
1363513670
speed_flag = asap ? 1 : 0;
1363613671
speed_reset = reset ? 1 : 0;
1363713672
speed_noSpeedReductionOrIsTempSpeedReduction = nospeedreductionOristempspeedreduction;
13673+
speed_isWarning = isWarning;
1363813674
}
1363913675
}
1364013676

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using Orts.Formats.Msts;
2+
using System.IO;
3+
4+
namespace Orts.Simulation.Signalling
5+
{
6+
public class SpeedPostWorldObject
7+
{
8+
public string SFileName { get; }
9+
10+
public SpeedPostWorldObject(SpeedPostObj speedPostItem)
11+
{
12+
// get filename in Uppercase
13+
SFileName = Path.GetFileName(speedPostItem.FileName).ToUpperInvariant();
14+
}
15+
}
16+
}

Source/RunActivity/Viewer3D/Popups/TrackMonitorWindow.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -908,7 +908,7 @@ int drawSpeedpost(SpriteBatch spriteBatch, Point offset, int startObjectArea, in
908908

909909
var labelPoint = new Point(offset.X + speedTextOffset, offset.Y + newLabelPosition + textOffset[forward ? 0 : 1]);
910910
var speedString = FormatStrings.FormatSpeedLimitNoUoM(allowedSpeed, metric);
911-
Font.Draw(spriteBatch, labelPoint, speedString, thisItem.SpeedObjectType == Train.TrainObjectItem.SpeedItemType.Standard ? Color.White :
911+
Font.Draw(spriteBatch, labelPoint, speedString, thisItem.SpeedObjectType == Train.TrainObjectItem.SpeedItemType.Standard ? (thisItem.IsWarning ? Color.Yellow : Color.White) :
912912
(thisItem.SpeedObjectType == Train.TrainObjectItem.SpeedItemType.TempRestrictedStart ? Color.Red : Color.LightGreen));
913913

914914
if (itemOffset < firstLabelPosition && !firstLabelShown)

0 commit comments

Comments
 (0)