Icon culling hides car icons when zoomed out past a configurable threshold (default 40%), keeping only locomotive icons visible. Locos scale up automatically when culling is active (configurable boost). An option also hides MU trailing units. All managed by the new MapIconCuller class with smooth fade transitions. EOTD (End-of-Train Device): a blinking red dot at the rear of each consist. Shown by default when car icons are hidden. Dot size and visibility conditions are configurable. Implemented in EotdSystem as a programmatically generated circle texture to avoid asset dependencies. Added an Icons submenu to the gear menu containing all icon and EOTD settings. Controls grey out to reflect dependencies: culling sub-settings (MU hide, loco boost, EOTD) grey out when culling is off; EOTD dot size and hide-when-visible grey out when EOTD is off. Changes round-trip via UICmd events, persist to PopoutSettings, and call MapIconCuller.Refresh(). Native state is seeded from C# on window init via RRPOPOUT_SetIconCullingState. Settings completeness: added Right-click recenters toggle and Map BG opacity slider to the UMM settings panel (were only accessible from the gear menu). Replaced four FindObjectOfType<MapWindow> calls with PanelFinder.GetMapWindow(). Fixed AV false-positive on release zips: ImGui's built-in font blob contained the substring "UPX", matching the heuristic for UPX-packed binaries. Added IMGUI_DISABLE_DEFAULT_FONT to strip the blob; ProggyClean.ttf is now shipped as a separate file alongside the DLL and loaded at runtime instead.
94 lines
4.2 KiB
PowerShell
94 lines
4.2 KiB
PowerShell
# Shared build helpers for S³ (dot-sourced by build-local.ps1 and build-release.ps1).
|
|
# Not run directly.
|
|
|
|
Set-StrictMode -Version Latest
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
$script:RepoRoot = Split-Path $PSScriptRoot -Parent
|
|
$script:ModId = "S3"
|
|
|
|
function Get-ModVersion {
|
|
# Single source of truth: the Version field in Info.json.
|
|
$info = Get-Content (Join-Path $RepoRoot "Info.json") -Raw | ConvertFrom-Json
|
|
return $info.Version
|
|
}
|
|
|
|
function Invoke-ManagedBuild {
|
|
param([string]$Configuration = "Release", [string]$GameDir = "")
|
|
|
|
Write-Host "=== Building managed (S3.dll, $Configuration) ===" -ForegroundColor Cyan
|
|
$csproj = Join-Path $RepoRoot "src\S3.csproj"
|
|
$args = @($csproj, "-c", $Configuration, "--nologo", "-v", "minimal")
|
|
if ($GameDir) { $args += "/p:GameDir=$GameDir" }
|
|
dotnet build @args | Out-Host
|
|
if ($LASTEXITCODE -ne 0) { throw "Managed build failed." }
|
|
|
|
$dll = Join-Path $RepoRoot "src\bin\$Configuration\S3.dll"
|
|
if (-not (Test-Path $dll)) { throw "S3.dll not found at $dll" }
|
|
return $dll
|
|
}
|
|
|
|
function Invoke-NativeBuild {
|
|
param([string]$Configuration = "Release")
|
|
|
|
$cmakeLists = Join-Path $RepoRoot "native\CMakeLists.txt"
|
|
if (-not (Test-Path $cmakeLists)) {
|
|
Write-Host "=== No native/CMakeLists.txt — skipping native build ===" -ForegroundColor DarkYellow
|
|
return $null
|
|
}
|
|
|
|
Write-Host "=== Building native (S3Native.dll, $Configuration) ===" -ForegroundColor Cyan
|
|
$buildDir = Join-Path $RepoRoot "native\build"
|
|
if (-not (Test-Path $buildDir)) { cmake -B $buildDir -A x64 (Join-Path $RepoRoot "native") | Out-Host }
|
|
cmake --build $buildDir --config $Configuration | Out-Host
|
|
if ($LASTEXITCODE -ne 0) { throw "Native build failed." }
|
|
|
|
# MSVC multi-config generators place the DLL in a per-config subfolder.
|
|
$dll = Join-Path $buildDir "bin\$Configuration\S3Native.dll"
|
|
if (-not (Test-Path $dll)) { $dll = Join-Path $buildDir "bin\S3Native.dll" } # single-config fallback
|
|
if (-not (Test-Path $dll)) { throw "S3Native.dll not found under $buildDir\bin" }
|
|
return $dll
|
|
}
|
|
|
|
# Assembles the Mods\S3 layout into $DestModDir (the S3 folder itself).
|
|
#
|
|
# Overwrites in place rather than wiping the folder. A full wipe is dangerous: if
|
|
# the game is running, a loaded DLL is locked, so the wipe deletes Info.json and
|
|
# the managed DLL, then aborts on the locked native DLL — leaving the mod with no
|
|
# manifest, so it silently vanishes from the loader. Overwriting in place keeps
|
|
# the last-good install if a copy fails, and preserves the user's settings files.
|
|
function New-ModLayout {
|
|
param([Parameter(Mandatory)][string]$DestModDir,
|
|
[Parameter(Mandatory)][string]$ManagedDll,
|
|
[string]$NativeDll = $null)
|
|
|
|
New-Item -ItemType Directory -Force -Path $DestModDir | Out-Null
|
|
|
|
# Fail fast with a clear message if a DLL we're about to overwrite is locked
|
|
# (game still running) — before touching anything.
|
|
foreach ($name in @("S3.dll", "S3Native.dll")) {
|
|
$path = Join-Path $DestModDir $name
|
|
if (Test-Path $path) {
|
|
try { [System.IO.File]::Open($path, 'Open', 'ReadWrite', 'None').Close() }
|
|
catch { throw "$name is locked - close Railroader before installing." }
|
|
}
|
|
}
|
|
|
|
# Drop stale artifacts from older builds (the pre-rename native DLL, ngen
|
|
# caches) so they don't linger, but leave Info.json and settings intact.
|
|
$stale = Join-Path $DestModDir "RRPopout.dll"
|
|
if (Test-Path $stale) { Remove-Item $stale -Force }
|
|
Get-ChildItem $DestModDir -Filter "*.cache" -ErrorAction SilentlyContinue | Remove-Item -Force
|
|
|
|
Copy-Item (Join-Path $RepoRoot "Info.json") (Join-Path $DestModDir "Info.json") -Force
|
|
Copy-Item $ManagedDll (Join-Path $DestModDir "S3.dll") -Force
|
|
if ($NativeDll) {
|
|
Copy-Item $NativeDll (Join-Path $DestModDir "S3Native.dll") -Force
|
|
# Ship ProggyClean.ttf alongside the native DLL so IMGUI_DISABLE_DEFAULT_FONT
|
|
# can load it at runtime without the base85 blob in the binary.
|
|
$fontSrc = Join-Path $RepoRoot "native\fonts\ProggyClean.ttf"
|
|
if (Test-Path $fontSrc) {
|
|
Copy-Item $fontSrc (Join-Path $DestModDir "ProggyClean.ttf") -Force
|
|
}
|
|
}
|
|
}
|