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.
Map: per-track industry labels rendered via Dear ImGui on both the popout
and in-game overlay. Three zoom stages - per-track labels, merged same-name
clusters, and one-per-industry labels at wider zoom. Settings: font size
(min/max with zoom scaling), leader lines, parallel rotation, collision
spread, utility track filters (repair/diesel/loader/interchange), zoom
thresholds per category. C# runs a world-space AABB solver at rebuild so
offsets are rotation-invariant; native runs a per-frame screen-space
fine-tuning pass and draws leader lines.
Mesh LOD: new module skeleton with 4-level LOD group injected on
HandleModelsLoaded - three progressive renderer cull tiers (sorted by
bounds volume) plus a 12-tri proxy box at max distance. lodBias-corrected
distance-to-screenHeight conversion. Debounced live refresh on settings
change. Disabled by default.
Replace the bare-bones stock map with a full Dear ImGui in-game overlay
(M key). The overlay shares the same toolbar and compass as the OS popout
window: Follow, Pop Out, Gear, rotation compass.
Pop Out button is now in the bottom toolbar where it is actually visible.
Pressing it (or F10) closes the overlay, waits 0.5 s for the camera to
release, then opens the OS popout window. Closing the popout restores the
overlay if it was running when the launch was triggered. Pressing M while
the popout is open closes the popout and reopens the overlay.
Harmony patches intercept MapWindow.Toggle and Show so base-game "Show on
map" links and the map hotkey both route through the S3 overlay. MapBypass
lets internal S3 calls through without triggering the patch recursively.
Camera ownership is enforced in LateUpdate so no base-game script can reset
targetTexture before the camera renders. Object.Destroy replaces Release()
on both RT teardown paths so the D3D address stays live until end-of-frame
and cannot be recycled into a new RT mid-frame.
Consolidates two standalone Railroader mods into one UMM "everything mod"
with an optional-module framework. Modules are disabled by default and
toggled per-module from the S3 settings page.
Core framework:
- IModule contract plus ModuleRegistry, with each module owning a Harmony
instance scoped by its id so only enabled modules patch the game
- Per-module flat JSON settings (SettingsStore). On this Mono runtime
JsonUtility silently drops nested custom-class fields, so settings stay flat
- Foldout-per-module settings panel plus a detector that offers to disable the
old standalone mods if they are still installed
Modules (moved over to parity, verified in-game):
- Physics Optimizer (was RailroaderPhysicsOverhaul): LOD fast-path and
auto-freeze, profiler overlay, debug car tinting, /rpf console commands
- Map Popout (was RRPopout): native map detach window. Pure-UMM install that
drops the winhttp proxy and LoadLibrary's RRPopout.dll from the mod folder.
Native Win32 + D3D11 + Dear ImGui engine included. Fixes a latent break where
the now-private MapBuilder.UpdateForZoom() is reached via Traverse.
Build: dotnet for the managed assembly (netstandard2.1) and CMake for the
native DLL. build-local.ps1 installs into the game, build-release.ps1 packages
the UMM drag-install zip.