New in 0.1.2: - Debug color overlay: tint cars by physics state (yellow=frozen, cyan=fast-path, magenta=full-accuracy), individual toggles per state - Exclude locomotives from Physics Optimizer and Auto Freeze - Debug stats line in overlay showing live counts per state - Resync quality 1/16 option added Defaults tuned for new installs: - Resync quality: 1/4 -> 1/8 - Speed threshold: ~0.7 mph -> 0.2 mph - Overlay opacity: 100% -> 75% Rename: Physics Overhaul -> Physics Optimizer throughout
124 lines
3.9 KiB
C#
124 lines
3.9 KiB
C#
using System.Collections.Generic;
|
|
using Model;
|
|
using UnityEngine;
|
|
|
|
namespace RailroaderPhysicsOverhaul;
|
|
|
|
[UnityEngine.DefaultExecutionOrder(10000)] // run after all game LateUpdates so our MPB is last to write
|
|
public class CarDebugVisualizer : MonoBehaviour
|
|
{
|
|
public static CarDebugVisualizer Instance { get; private set; }
|
|
public int TintedCount => _curr.Count;
|
|
|
|
// A 1x1 white texture fed via MPB overrides _MainTex so the shader renders
|
|
// texture*color = white*color = solid color, regardless of the car's original texture.
|
|
Texture2D _whiteTex;
|
|
readonly MaterialPropertyBlock _mpb = new();
|
|
|
|
readonly Dictionary<Car, Renderer[]> _rendCache = new();
|
|
readonly Dictionary<Car, Color> _curr = new();
|
|
readonly Dictionary<Car, Color> _prev = new();
|
|
|
|
static readonly Color ColFrozen = new(1.00f, 0.90f, 0.00f); // yellow
|
|
static readonly Color ColFastPath = new(0.00f, 1.00f, 1.00f); // cyan
|
|
static readonly Color ColFullPath = new(1.00f, 0.00f, 1.00f); // magenta
|
|
|
|
void Awake()
|
|
{
|
|
Instance = this;
|
|
_whiteTex = new Texture2D(1, 1, TextureFormat.RGBA32, false)
|
|
{ hideFlags = HideFlags.HideAndDontSave };
|
|
_whiteTex.SetPixel(0, 0, Color.white);
|
|
_whiteTex.Apply();
|
|
}
|
|
|
|
void OnDestroy()
|
|
{
|
|
ClearAll();
|
|
if (_whiteTex) Destroy(_whiteTex);
|
|
Instance = null;
|
|
}
|
|
|
|
void LateUpdate()
|
|
{
|
|
_prev.Clear();
|
|
foreach (var kv in _curr) _prev[kv.Key] = kv.Value;
|
|
_curr.Clear();
|
|
|
|
if (Main.Settings.DebugHighlightFrozen)
|
|
Collect(ConsistFreezer.FrozenCars, ColFrozen);
|
|
if (Main.Settings.DebugHighlightFastPath)
|
|
Collect(ConsistLOD.FastPathCars, ColFastPath);
|
|
if (Main.Settings.DebugHighlightFullPath)
|
|
Collect(ConsistLOD.FullPathCars, ColFullPath);
|
|
|
|
foreach (var (car, color) in _curr)
|
|
ApplyTint(car, color);
|
|
|
|
foreach (var car in _prev.Keys)
|
|
if (!_curr.ContainsKey(car))
|
|
ClearTint(car);
|
|
|
|
if (Time.frameCount % 300 == 0)
|
|
PurgeCache();
|
|
}
|
|
|
|
void Collect(HashSet<Car> source, Color color)
|
|
{
|
|
foreach (var car in source)
|
|
if (car != null && !_curr.ContainsKey(car))
|
|
_curr[car] = color;
|
|
}
|
|
|
|
void ApplyTint(Car car, Color color)
|
|
{
|
|
foreach (var r in GetRenderers(car))
|
|
{
|
|
if (r == null) continue;
|
|
_mpb.Clear();
|
|
_mpb.SetColor("_Color", color);
|
|
_mpb.SetColor("_BaseColor", color);
|
|
_mpb.SetTexture("_MainTex", _whiteTex); // built-in RP
|
|
_mpb.SetTexture("_BaseMap", _whiteTex); // URP
|
|
_mpb.SetTexture("_BaseColorMap", _whiteTex); // HDRP
|
|
r.SetPropertyBlock(_mpb);
|
|
}
|
|
}
|
|
|
|
void ClearTint(Car car)
|
|
{
|
|
foreach (var r in GetRenderers(car))
|
|
if (r != null) r.SetPropertyBlock(null);
|
|
}
|
|
|
|
void ClearAll()
|
|
{
|
|
foreach (var car in _curr.Keys) ClearTint(car);
|
|
foreach (var car in _prev.Keys) ClearTint(car);
|
|
_curr.Clear();
|
|
_prev.Clear();
|
|
_rendCache.Clear();
|
|
}
|
|
|
|
Renderer[] GetRenderers(Car car)
|
|
{
|
|
if (!_rendCache.TryGetValue(car, out var renderers) || renderers.Length == 0)
|
|
{
|
|
renderers = car.BodyTransform != null
|
|
? car.BodyTransform.GetComponentsInChildren<Renderer>()
|
|
: System.Array.Empty<Renderer>();
|
|
// Don't cache empty results — retry next frame until the mesh loads
|
|
if (renderers.Length > 0)
|
|
_rendCache[car] = renderers;
|
|
}
|
|
return renderers;
|
|
}
|
|
|
|
void PurgeCache()
|
|
{
|
|
var dead = new List<Car>();
|
|
foreach (var car in _rendCache.Keys)
|
|
if (car == null) dead.Add(car);
|
|
foreach (var car in dead) _rendCache.Remove(car);
|
|
}
|
|
}
|