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("Profiler — 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("Display"); 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("Sections"); 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.Space(10f); GUILayout.Label("Benchmark hitch capture"); GUILayout.Space(4f); bool newCapture = GUILayout.Toggle( s.captureHitchProbes, " Attribute base-game work on every benchmark frame"); if (newCapture != s.captureHitchProbes) { s.captureHitchProbes = newCapture; changed = true; } GUILayout.BeginHorizontal(); GUILayout.Label($"Hitch threshold: {s.hitchThresholdMs:F0}ms", GUILayout.Width(160f)); float newThreshold = GUILayout.HorizontalSlider( s.hitchThresholdMs, 33f, 250f, GUILayout.Width(200f)); GUILayout.EndHorizontal(); if (Mathf.Abs(newThreshold - s.hitchThresholdMs) > 0.5f) { s.hitchThresholdMs = newThreshold; changed = true; } bool newBinary = GUILayout.Toggle( s.captureUnityBinaryLog, " Write Unity binary profiler data (high overhead)"); if (newBinary != s.captureUnityBinaryLog) { s.captureUnityBinaryLog = newBinary; changed = true; } GUILayout.EndVertical(); if (changed) ProfilerModule.Persist(); } }