railroader-setons-special-s.../src/Modules/Profiler/ProfilerSettingsUI.cs
seton 4853015eff Profiler: new unified overlay module; absorb PhysicsOverlayGUI
Add a standalone Profiler module (S3.profiler.json, disabled by default)
that hosts the in-game frame-time overlay previously owned by Physics
Optimizer.  The overlay now adapts to whichever modules are enabled:

- Always shows: render + physics frame-time graph, timing report.
- Physics Optimizer section (if enabled): LOD fast-path and auto-freeze
  quick-toggles with live stats, debug car count line.
- Mesh LOD section (if enabled): total tracked cars, loco/freight split,
  per-LOD-level counts refreshed once per second.

PhysicsOptimizerModule retains only the Harmony patches and
CarDebugVisualizer; ShowOverlay/OverlayOpacity removed from PhysicsSettings.
MeshLodInjector gains GetLodStats() and GetLodLevel() for the overlay.
BBox material shader search now tries URP/Lit before Standard.
/rpf overlay toggle redirected to ProfilerOverlayGUI.Instance.
2026-06-25 19:06:46 -04:00

76 lines
2.9 KiB
C#

using S3.Modules.MeshLod;
using S3.Modules.PhysicsOptimizer;
using UnityEngine;
namespace S3.Modules.Profiler;
static class ProfilerSettingsUI
{
public static void Draw()
{
ProfilerSettings s = ProfilerModule.Settings;
bool changed = false;
GUILayout.BeginVertical();
GUILayout.Label("<b>Profiler</b> — in-game frame-time overlay with module readouts");
GUILayout.Space(4f);
GUILayout.Label(
" Always shows the render and physics frame-time graph.\n" +
" Physics Optimizer and Mesh LOD sections appear when those modules are enabled.",
GUI.skin.label);
// ── Overlay visibility ────────────────────────────────────────────────
GUILayout.Space(10f);
GUILayout.Label("<b>Display</b>");
GUILayout.Space(4f);
bool newVisible = GUILayout.Toggle(s.visible, " Show overlay in-game");
if (newVisible != s.visible)
{
s.visible = newVisible;
if (ProfilerOverlayGUI.Instance != null)
ProfilerOverlayGUI.Instance.Visible = newVisible;
changed = true;
}
GUILayout.Space(4f);
GUILayout.BeginHorizontal();
GUILayout.Label($"Opacity: {s.opacity * 100f:F0}%", GUILayout.Width(110f));
float newOpacity = GUILayout.HorizontalSlider(s.opacity, 0.1f, 1.0f, GUILayout.Width(200f));
GUILayout.EndHorizontal();
if (Mathf.Abs(newOpacity - s.opacity) > 0.01f)
{
s.opacity = newOpacity;
if (ProfilerOverlayGUI.Instance != null)
ProfilerOverlayGUI.Instance.Opacity = newOpacity;
changed = true;
}
// ── Section visibility ────────────────────────────────────────────────
GUILayout.Space(10f);
GUILayout.Label("<b>Sections</b>");
GUILayout.Space(4f);
bool physAvail = PhysicsOptimizerModule.Settings.enabled;
GUI.enabled = physAvail;
bool newPhys = GUILayout.Toggle(s.showPhysicsSection && physAvail,
" Physics Optimizer" + (physAvail ? "" : " (module not enabled)"));
GUI.enabled = true;
if (newPhys != s.showPhysicsSection && physAvail)
{ s.showPhysicsSection = newPhys; changed = true; }
bool meshAvail = MeshLodModule.Settings.enabled;
GUI.enabled = meshAvail;
bool newMesh = GUILayout.Toggle(s.showMeshLodSection && meshAvail,
" Mesh LOD" + (meshAvail ? "" : " (module not enabled)"));
GUI.enabled = true;
if (newMesh != s.showMeshLodSection && meshAvail)
{ s.showMeshLodSection = newMesh; changed = true; }
GUILayout.EndVertical();
if (changed) ProfilerModule.Persist();
}
}