Skip to content

Commit

Permalink
Automatic merge of T1.4-84-g4dced6b1d and 10 pull requests
Browse files Browse the repository at this point in the history
- Pull request #525 at b5ac1d2: Add SignalTypeName and DrawStateName to SignalFeatures
- Pull request #527 at 27f05a1: Brake cuts power refactor and new parameters
- Pull request #531 at b2affac: Bug fix for https://bugs.launchpad.net/or/+bug/1950578 Dyn Brake setup state not disappearing in cab
- Pull request #533 at 62a1c27: fix for shapes hidden by animations( 0 )
- Pull request #537 at e753905: C# signal script extensions
- Pull request #538 at c457f11: Delete binary paths if the ascii version or the tdb was modified. Blueprint: https://blueprints.launchpad.net/or/+spec/binary-timetable-paths
- Pull request #542 at 83320ed: adds new webpage, moves Testing out of Download/Programs
- Pull request #543 at 5b0121c: adds Discover > Roadmap webpage
- Pull request #544 at 8117250: Blueprint https://blueprints.launchpad.net/or/+spec/cabview-controls-for-generic-items
- Pull request #545 at 1b818ae: Fix VRAM usage
  • Loading branch information
openrails-bot committed Dec 12, 2021
12 parents 2b2f0d7 + 4dced6b + b5ac1d2 + 27f05a1 + b2affac + 62a1c27 + e753905 + c457f11 + 83320ed + 5b0121c + 8117250 + 1b818ae commit 9c5ca4b
Show file tree
Hide file tree
Showing 3 changed files with 166 additions and 108 deletions.
270 changes: 162 additions & 108 deletions Source/RunActivity/Viewer3D/Signals.cs
Expand Up @@ -30,6 +30,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Event = Orts.Common.Event;
using Events = Orts.Common.Events;

Expand Down Expand Up @@ -175,8 +176,6 @@ internal override void Mark()

class SignalShapeHead
{
static readonly Dictionary<string, SignalTypeData> SignalTypes = new Dictionary<string, SignalTypeData>();

readonly Viewer Viewer;
readonly SignalShape SignalShape;
#if DEBUG_SIGNAL_SHAPES
Expand All @@ -196,7 +195,7 @@ class SignalShapeHead
private readonly SignalLightState[] lightStates;

public SignalShapeHead(Viewer viewer, SignalShape signalShape, int index, SignalHead signalHead,
Orts.Formats.Msts.SignalItem mstsSignalItem, Orts.Formats.Msts.SignalShape.SignalSubObj mstsSignalSubObj)
SignalItem mstsSignalItem, Formats.Msts.SignalShape.SignalSubObj mstsSignalSubObj)
{
Viewer = viewer;
SignalShape = signalShape;
Expand All @@ -217,10 +216,7 @@ class SignalShapeHead

var mstsSignalType = viewer.SIGCFG.SignalTypes[mstsSignalSubObj.SignalSubSignalType];

if (SignalTypes.ContainsKey(mstsSignalType.Name))
SignalTypeData = SignalTypes[mstsSignalType.Name];
else
SignalTypeData = SignalTypes[mstsSignalType.Name] = new SignalTypeData(viewer, mstsSignalType);
SignalTypeData = viewer.SignalTypeDataManager.Get(mstsSignalType);

if (SignalTypeData.Semaphore)
{
Expand Down Expand Up @@ -412,142 +408,200 @@ void renderEffect(Material material)
[CallOnThread("Loader")]
internal void Mark()
{
SignalTypeData.Material.Mark();
SignalTypeData.GlowMaterial?.Mark();
SignalTypeData.Mark();
}
}
}

public class SignalTypeDataManager
{
readonly Viewer Viewer;

Dictionary<string, SignalTypeData> SignalTypes = new Dictionary<string, SignalTypeData>();
Dictionary<string, bool> SignalTypesMarks;

public SignalTypeDataManager(Viewer viewer)
{
Viewer = viewer;
}

public SignalTypeData Get(SignalType mstsSignalType)
{
if (!SignalTypes.ContainsKey(mstsSignalType.Name))
{
SignalTypes[mstsSignalType.Name] = new SignalTypeData(Viewer, mstsSignalType);
}

return SignalTypes[mstsSignalType.Name];
}

public void Mark()
{
SignalTypesMarks = new Dictionary<string, bool>(SignalTypes.Count);
foreach (string signalTypeName in SignalTypes.Keys)
{
SignalTypesMarks.Add(signalTypeName, false);
}
}

public void Mark(SignalTypeData signalType)
{
if (SignalTypes.ContainsValue(signalType))
{
SignalTypesMarks[SignalTypes.First(x => x.Value == signalType).Key] = true;
}
}

class SignalTypeData
public void Sweep()
{
public readonly Material Material;
public readonly Material GlowMaterial;
foreach (var signalTypeName in SignalTypesMarks.Where(x => !x.Value).Select(x => x.Key))
{
SignalTypes.Remove(signalTypeName);
}
}
}

public class SignalTypeData
{
readonly Viewer Viewer;

public readonly Material Material;
public readonly Material GlowMaterial;
#if DEBUG_SIGNAL_SHAPES
public readonly SignalTypeDataType Type;
#endif
public readonly List<SignalLightPrimitive> Lights = new List<SignalLightPrimitive>();
public readonly List<bool> LightsSemaphoreChange = new List<bool>();
public readonly Dictionary<int, SignalAspectData> DrawAspects = new Dictionary<int, SignalAspectData>();
public readonly float FlashTimeOn;
public readonly float FlashTimeTotal;
public readonly float OnOffTimeS;
public readonly bool Semaphore;
public readonly bool DayLight = true;
public readonly float SemaphoreAnimationTime;
public bool AreSemaphoresReindexed;

public SignalTypeData(Viewer viewer, Orts.Formats.Msts.SignalType mstsSignalType)
public readonly List<SignalLightPrimitive> Lights = new List<SignalLightPrimitive>();
public readonly List<bool> LightsSemaphoreChange = new List<bool>();
public readonly Dictionary<int, SignalAspectData> DrawAspects = new Dictionary<int, SignalAspectData>();
public readonly float FlashTimeOn;
public readonly float FlashTimeTotal;
public readonly float OnOffTimeS;
public readonly bool Semaphore;
public readonly bool DayLight = true;
public readonly float SemaphoreAnimationTime;
public bool AreSemaphoresReindexed;

public SignalTypeData(Viewer viewer, SignalType mstsSignalType)
{
Viewer = viewer;

if (!viewer.SIGCFG.LightTextures.ContainsKey(mstsSignalType.LightTextureName))
{
if (!viewer.SIGCFG.LightTextures.ContainsKey(mstsSignalType.LightTextureName))
{
Trace.TraceWarning("Skipped invalid light texture {1} for signal type {0}", mstsSignalType.Name, mstsSignalType.LightTextureName);
Material = viewer.MaterialManager.Load("missing-signal-light");
Trace.TraceWarning("Skipped invalid light texture {1} for signal type {0}", mstsSignalType.Name, mstsSignalType.LightTextureName);
Material = viewer.MaterialManager.Load("missing-signal-light");
#if DEBUG_SIGNAL_SHAPES
Type = SignalTypeDataType.Normal;
#endif
FlashTimeOn = 1;
FlashTimeTotal = 2;
}
else
{
var mstsLightTexture = viewer.SIGCFG.LightTextures[mstsSignalType.LightTextureName];
Material = viewer.MaterialManager.Load("SignalLight", Helpers.GetRouteTextureFile(viewer.Simulator, Helpers.TextureFlags.None, mstsLightTexture.TextureFile));
GlowMaterial = viewer.MaterialManager.Load("SignalLightGlow");
FlashTimeOn = 1;
FlashTimeTotal = 2;
}
else
{
var mstsLightTexture = viewer.SIGCFG.LightTextures[mstsSignalType.LightTextureName];
Material = viewer.MaterialManager.Load("SignalLight", Helpers.GetRouteTextureFile(viewer.Simulator, Helpers.TextureFlags.None, mstsLightTexture.TextureFile));
GlowMaterial = viewer.MaterialManager.Load("SignalLightGlow");
#if DEBUG_SIGNAL_SHAPES
Type = (SignalTypeDataType)mstsSignalType.FnType;
#endif
if (mstsSignalType.Lights != null)
if (mstsSignalType.Lights != null)
{
// Set up some heuristic glow values from the available data:
// Typical electric light is 3.0/5.0
// Semaphore is 0.0/5.0
// Theatre box is 0.0/0.0
var glowDay = 3.0f;
var glowNight = 5.0f;

if (mstsSignalType.Semaphore)
glowDay = 0.0f;
if (mstsSignalType.FnType == MstsSignalFunction.INFO || mstsSignalType.FnType == MstsSignalFunction.SHUNTING) // These are good at identifying theatre boxes.
glowDay = glowNight = 0.0f;

// use values from signal if defined
if (mstsSignalType.DayGlow.HasValue)
{
// Set up some heuristic glow values from the available data:
// Typical electric light is 3.0/5.0
// Semaphore is 0.0/5.0
// Theatre box is 0.0/0.0
var glowDay = 3.0f;
var glowNight = 5.0f;

if (mstsSignalType.Semaphore)
glowDay = 0.0f;
if (mstsSignalType.FnType == MstsSignalFunction.INFO || mstsSignalType.FnType == MstsSignalFunction.SHUNTING) // These are good at identifying theatre boxes.
glowDay = glowNight = 0.0f;

// use values from signal if defined
if (mstsSignalType.DayGlow.HasValue)
{
glowDay = mstsSignalType.DayGlow.Value;
}
if (mstsSignalType.NightGlow.HasValue)
{
glowNight = mstsSignalType.NightGlow.Value;
}
glowDay = mstsSignalType.DayGlow.Value;
}
if (mstsSignalType.NightGlow.HasValue)
{
glowNight = mstsSignalType.NightGlow.Value;
}

foreach (var mstsSignalLight in mstsSignalType.Lights)
foreach (var mstsSignalLight in mstsSignalType.Lights)
{
if (!viewer.SIGCFG.LightsTable.ContainsKey(mstsSignalLight.Name))
{
if (!viewer.SIGCFG.LightsTable.ContainsKey(mstsSignalLight.Name))
{
Trace.TraceWarning("Skipped invalid light {1} for signal type {0}", mstsSignalType.Name, mstsSignalLight.Name);
continue;
}
var mstsLight = viewer.SIGCFG.LightsTable[mstsSignalLight.Name];
Lights.Add(new SignalLightPrimitive(viewer, new Vector3(-mstsSignalLight.X, mstsSignalLight.Y, mstsSignalLight.Z), mstsSignalLight.Radius, new Color(mstsLight.r, mstsLight.g, mstsLight.b, mstsLight.a), glowDay, glowNight, mstsLightTexture.u0, mstsLightTexture.v0, mstsLightTexture.u1, mstsLightTexture.v1));
LightsSemaphoreChange.Add(mstsSignalLight.SemaphoreChange);
Trace.TraceWarning("Skipped invalid light {1} for signal type {0}", mstsSignalType.Name, mstsSignalLight.Name);
continue;
}
var mstsLight = viewer.SIGCFG.LightsTable[mstsSignalLight.Name];
Lights.Add(new SignalLightPrimitive(viewer, new Vector3(-mstsSignalLight.X, mstsSignalLight.Y, mstsSignalLight.Z), mstsSignalLight.Radius, new Color(mstsLight.r, mstsLight.g, mstsLight.b, mstsLight.a), glowDay, glowNight, mstsLightTexture.u0, mstsLightTexture.v0, mstsLightTexture.u1, mstsLightTexture.v1));
LightsSemaphoreChange.Add(mstsSignalLight.SemaphoreChange);
}

foreach (KeyValuePair<string, Orts.Formats.Msts.SignalDrawState> sdrawstate in mstsSignalType.DrawStates)
DrawAspects.Add(sdrawstate.Value.Index, new SignalAspectData(mstsSignalType, sdrawstate.Value));
FlashTimeOn = mstsSignalType.FlashTimeOn;
FlashTimeTotal = mstsSignalType.FlashTimeOn + mstsSignalType.FlashTimeOff;
Semaphore = mstsSignalType.Semaphore;
SemaphoreAnimationTime = mstsSignalType.SemaphoreInfo;
DayLight = mstsSignalType.DayLight;
}

OnOffTimeS = mstsSignalType.OnOffTimeS;
foreach (KeyValuePair<string, SignalDrawState> sdrawstate in mstsSignalType.DrawStates)
DrawAspects.Add(sdrawstate.Value.Index, new SignalAspectData(mstsSignalType, sdrawstate.Value));
FlashTimeOn = mstsSignalType.FlashTimeOn;
FlashTimeTotal = mstsSignalType.FlashTimeOn + mstsSignalType.FlashTimeOff;
Semaphore = mstsSignalType.Semaphore;
SemaphoreAnimationTime = mstsSignalType.SemaphoreInfo;
DayLight = mstsSignalType.DayLight;
}

OnOffTimeS = mstsSignalType.OnOffTimeS;
}

enum SignalTypeDataType
public void Mark()
{
Normal,
Distance,
Repeater,
Shunting,
Info,
Viewer.SignalTypeDataManager.Mark(this);
Material.Mark();
GlowMaterial?.Mark();
}
}

class SignalAspectData
{
public readonly bool[] DrawLights;
public readonly bool[] FlashLights;
public float SemaphorePos;
enum SignalTypeDataType
{
Normal,
Distance,
Repeater,
Shunting,
Info,
}

public SignalAspectData(Orts.Formats.Msts.SignalType mstsSignalType, Orts.Formats.Msts.SignalDrawState drawStateData)
public class SignalAspectData
{
public readonly bool[] DrawLights;
public readonly bool[] FlashLights;
public float SemaphorePos;

public SignalAspectData(SignalType mstsSignalType, SignalDrawState drawStateData)
{
if (mstsSignalType.Lights != null)
{
if (mstsSignalType.Lights != null)
{
DrawLights = new bool[mstsSignalType.Lights.Count];
FlashLights = new bool[mstsSignalType.Lights.Count];
}
else
{
DrawLights = null;
FlashLights = null;
}
DrawLights = new bool[mstsSignalType.Lights.Count];
FlashLights = new bool[mstsSignalType.Lights.Count];
}
else
{
DrawLights = null;
FlashLights = null;
}

if (drawStateData.DrawLights != null)
if (drawStateData.DrawLights != null)
{
foreach (var drawLight in drawStateData.DrawLights)
{
foreach (var drawLight in drawStateData.DrawLights)
if (drawLight.LightIndex < 0 || DrawLights == null || drawLight.LightIndex >= DrawLights.Length)
Trace.TraceWarning("Skipped extra draw light {0}", drawLight.LightIndex);
else
{
if (drawLight.LightIndex < 0 || DrawLights == null || drawLight.LightIndex >= DrawLights.Length)
Trace.TraceWarning("Skipped extra draw light {0}", drawLight.LightIndex);
else
{
DrawLights[drawLight.LightIndex] = true;
FlashLights[drawLight.LightIndex] = drawLight.Flashing;
}
DrawLights[drawLight.LightIndex] = true;
FlashLights[drawLight.LightIndex] = drawLight.Flashing;
}
}
SemaphorePos = drawStateData.SemaphorePos;
}
SemaphorePos = drawStateData.SemaphorePos;
}
}

Expand Down
2 changes: 2 additions & 0 deletions Source/RunActivity/Viewer3D/Viewer.cs
Expand Up @@ -65,6 +65,7 @@ public class Viewer
public SharedTextureManager TextureManager { get; private set; }
public SharedMaterialManager MaterialManager { get; private set; }
public SharedShapeManager ShapeManager { get; private set; }
public SignalTypeDataManager SignalTypeDataManager { get; private set; }
public Point DisplaySize { get { return RenderProcess.DisplaySize; } }
// Components
public Orts.Viewer3D.Processes.Game Game { get; private set; }
Expand Down Expand Up @@ -438,6 +439,7 @@ internal void Initialize()

MaterialManager = new SharedMaterialManager(this);
ShapeManager = new SharedShapeManager(this);
SignalTypeDataManager = new SignalTypeDataManager(this);

WindowManager = new WindowManager(this);
MessagesWindow = new MessagesWindow(WindowManager);
Expand Down
2 changes: 2 additions & 0 deletions Source/RunActivity/Viewer3D/World.cs
Expand Up @@ -99,6 +99,7 @@ public void Load()
Viewer.ShapeManager.Mark();
Viewer.MaterialManager.Mark();
Viewer.TextureManager.Mark();
Viewer.SignalTypeDataManager.Mark();
if (Viewer.Settings.UseMSTSEnv)
MSTSSky.Mark();
else
Expand All @@ -112,6 +113,7 @@ public void Load()
Viewer.ShapeManager.Sweep();
Viewer.MaterialManager.Sweep();
Viewer.TextureManager.Sweep();
Viewer.SignalTypeDataManager.Sweep();
}
}

Expand Down

0 comments on commit 9c5ca4b

Please sign in to comment.