LANTERN realignment P3: one look everywhere + scene surgery

- PostFX_Lantern.asset: the ONE shared grade (ACES, bloom 0.6 cool-tinted for the
  HDR gloam, vignette 0.28, faint teal filter) applied to Game, DevSandbox, and
  ArtStaging; PostFX_DarkSciFi / PostFX_Daylight / Sky_DaytimeProcedural deleted.
- Env_SeabedKit.prefab: ArtStaging's environment (seabed, flora, rocks, marine
  snow, caustics, warm pool, gloam fill, key light, StagingAmbiance animator)
  prefab-ized and placed in Game + DevSandbox; ArtStaging connected to it.
- Scene surgery: old DevSandbox.unity deleted; Gym.unity RENAMED DevSandbox.unity
  (GUID preserved -> GymSub wiring + the F1/F2 dev scripts that gate on the
  'DevSandbox' name come back to life). SyntyWorld root deleted from DevSandbox;
  BaseBiome/ExpeditionBiome/Slot1 deleted from Game.
- RenderSettings unified: no skybox, Exp2 teal fog {0.02,0.10,0.12} @ 0.035, flat
  near-black ambient {0.03,0.055,0.08}; camera clearFlags -> solid deep-water.
- ScenePolicy.IsGameplayScene() replaces the six scene.name=="Game" string gates
  (Game + DevSandbox share the dynamic look; menu/ArtStaging untouched).
- WorldAtmosphereSystem rewritten as water-column murk (LANTERN defaults; biome
  variants re-meant to kelp/trench/gloam-bloom; Ground_Arid tint block deleted).

390 green; Play-verified in Game: murk values live, warm-vs-cold reads, no errors.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-15 16:12:00 -07:00
parent 77de740b63
commit c58439d33a
21 changed files with 7628 additions and 95935 deletions
@@ -72,7 +72,7 @@ namespace ProjectM.Client
protected override void OnUpdate()
{
if (UnityEngine.SceneManagement.SceneManager.GetActiveScene().name != "Game") { Hide(); return; }
if (!ScenePolicy.IsGameplayScene()) { Hide(); return; }
if (_cam == null) _cam = Camera.main;
if (_cam == null) return;
if (!AmbientLifeConfig.Enabled) { Hide(); return; }
@@ -69,7 +69,7 @@ namespace ProjectM.Client
protected override void OnUpdate()
{
if (UnityEngine.SceneManagement.SceneManager.GetActiveScene().name != "Game") return;
if (!ScenePolicy.IsGameplayScene()) return;
if (!DecalConfig.Enabled) { if (_tracked.Count > 0) ClearAll(); return; }
EntityManager.CompleteDependencyBeforeRO<BlightClutter>();
@@ -55,7 +55,7 @@ namespace ProjectM.Client
protected override void OnUpdate()
{
if (UnityEngine.SceneManagement.SceneManager.GetActiveScene().name != "Game") return;
if (!ScenePolicy.IsGameplayScene()) return;
var cfg = DynamicLightConfig.Instance;
bool enabled = cfg == null || cfg.Enabled;
if (!enabled)
@@ -50,7 +50,7 @@ namespace ProjectM.Client
protected override void OnUpdate()
{
if (UnityEngine.SceneManagement.SceneManager.GetActiveScene().name != "Game") return;
if (!ScenePolicy.IsGameplayScene()) return;
if (_root == null) return;
var cfg = RoomDressingConfig.Instance;
@@ -0,0 +1,19 @@
using UnityEngine.SceneManagement;
namespace ProjectM.Client
{
/// <summary>
/// The ONE place client presentation systems ask "is this a gameplay-look scene?" — replaces the old
/// scattered <c>scene.name == "Game"</c> string gates (LANTERN realignment: Game and DevSandbox share
/// the same look; MainMenu/ArtStaging stay untouched by the dynamic look systems).
/// </summary>
public static class ScenePolicy
{
/// <summary>True in the scenes that carry the LANTERN gameplay look (Game + DevSandbox).</summary>
public static bool IsGameplayScene()
{
var name = SceneManager.GetActiveScene().name;
return name == "Game" || name == "DevSandbox";
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: f4e4ab296b48b204f866c561e9acd11d
@@ -62,7 +62,7 @@ namespace ProjectM.Client
protected override void OnUpdate()
{
if (UnityEngine.SceneManagement.SceneManager.GetActiveScene().name != "Game") { Pending.Clear(); return; }
if (!ScenePolicy.IsGameplayScene()) { Pending.Clear(); return; }
if (!DecalConfig.Enabled)
{
Pending.Clear();
@@ -4,31 +4,26 @@ using UnityEngine;
namespace ProjectM.Client
{
/// <summary>
/// Client-only ATMOSPHERE cross-fade for the two-region world. A managed presentation system
/// (SystemBase, main thread, NO Burst) in <see cref="PresentationSystemGroup"/> that OBSERVES the
/// follow-camera's world-space X and lerps <see cref="RenderSettings"/> fog + Trilight sky-ambient between
/// the lush cyan meadow base (origin) and the hostile orange arid expedition (+1000 X) — mirroring
/// HudSystem's region split at camera X &gt; 500. The directional light + skybox + post-FX volume stay
/// GLOBAL; only fog colour/density + ambient sky colour shift per region. Pure presentation: never mutates
/// the simulation, no ECS query (camera + RenderSettings only). Knobs live in
/// <see cref="WorldAtmosphereConfig"/> (falls back to baked defaults when absent). Guarded to the gameplay
/// "Game" scene so it never restyles the menu. Fog enable/mode + equator/ground ambient are baked into the
/// scene; this only drives the per-region deltas. Phase 1.5b: also drives a per-room-biome tint on the
/// expedition ground quads (MaterialPropertyBlock — the material asset is never touched).
/// Client-only water-column ATMOSPHERE for the LANTERN seabed (deep-sea murk). A managed presentation
/// system (SystemBase, main thread, NO Burst) in <see cref="PresentationSystemGroup"/> that OBSERVES the
/// follow-camera's world-space X and lerps <see cref="RenderSettings"/> fog + flat ambient between the
/// base-shelf murk (origin) and the deeper out-shelf murk (+1000 X) — mirroring HudSystem's region split
/// at camera X &gt; 500. The skybox stays empty and the post-FX volume GLOBAL; only fog colour/density +
/// ambient shift per region. Pure presentation: never mutates the simulation. Knobs live in
/// <see cref="WorldAtmosphereConfig"/> (falls back to baked LANTERN-murk defaults when absent). Gated by
/// <see cref="ScenePolicy.IsGameplayScene"/> so it never restyles the menu or ArtStaging. Per-room-biome
/// murk variants key on the replicated RunInfo.CurrentBiome (re-meant to depth/water flavors — the old
/// meadow/arid/blight palettes died in the LANTERN realignment).
/// </summary>
[WorldSystemFilter(WorldSystemFilterFlags.ClientSimulation)]
[UpdateInGroup(typeof(PresentationSystemGroup))]
public partial class WorldAtmosphereSystem : SystemBase
{
Camera _cam;
MeshRenderer[] _ground;
MaterialPropertyBlock _mpb;
Color _groundCur;
static readonly int BaseColorId = Shader.PropertyToID("_BaseColor");
protected override void OnUpdate()
{
if (UnityEngine.SceneManagement.SceneManager.GetActiveScene().name != "Game") return;
if (!ScenePolicy.IsGameplayScene()) return;
if (_cam == null) _cam = Camera.main;
if (_cam == null) return;
@@ -36,39 +31,34 @@ namespace ProjectM.Client
float boundary = cfg != null ? cfg.BoundaryX : 500f;
float half = cfg != null ? Mathf.Max(1f, cfg.BlendHalfWidth) : 80f;
Color baseFog = cfg != null ? cfg.BaseFogColor : new Color(0.09f, 0.13f, 0.14f, 1f);
float baseDen = cfg != null ? cfg.BaseFogDensity : 0.010f;
Color baseAmb = cfg != null ? cfg.BaseAmbientSky : new Color(0.32f, 0.38f, 0.48f, 1f);
Color expFog = cfg != null ? cfg.ExpeditionFogColor : new Color(0.24f, 0.13f, 0.06f, 1f);
float expDen = cfg != null ? cfg.ExpeditionFogDensity : 0.016f;
Color expAmb = cfg != null ? cfg.ExpeditionAmbientSky : new Color(0.45f, 0.31f, 0.20f, 1f);
// Step 14 (expedition redesign): the EXPEDITION-side palette keys on the replicated per-room biome
// (RunInfo.CurrentBiome) so every room re-themes — the camera-X blend still owns the base↔run fade.
// Palettes are code consts (cosmetic; per-biome config knobs can layer on later without churn).
// Phase 1.5: all palettes moved to the dark-ambient set (dynamic lights carry readability).
// Ground tints are ABSOLUTE _BaseColor values (the MPB replaces the authored arid sand tint).
Color groundTarget = new Color(0.60f, 0.56f, 0.50f, 1f); // authored arid sand (Mat_Ground_Arid_Dark)
// LANTERN murk defaults (match the ArtStaging source-of-truth hues; density is the play-readability knob).
Color baseFog = cfg != null ? cfg.BaseFogColor : new Color(0.02f, 0.10f, 0.12f, 1f);
float baseDen = cfg != null ? cfg.BaseFogDensity : 0.035f;
Color baseAmb = cfg != null ? cfg.BaseAmbientSky : new Color(0.03f, 0.055f, 0.08f, 1f);
Color expFog = cfg != null ? cfg.ExpeditionFogColor : new Color(0.015f, 0.075f, 0.10f, 1f);
float expDen = cfg != null ? cfg.ExpeditionFogDensity : 0.04f;
Color expAmb = cfg != null ? cfg.ExpeditionAmbientSky : new Color(0.02f, 0.045f, 0.07f, 1f);
// Per-room murk flavors (cosmetic code consts; all stay inside the deep-sea band — hue shifts are
// subtle, value stays dark so dynamic lights keep carrying readability).
bool haveRun = SystemAPI.TryGetSingleton<ProjectM.Simulation.RunInfo>(out var runInfo);
if (haveRun && runInfo.Lifecycle != ProjectM.Simulation.RunLifecycle.Staging)
{
switch (runInfo.CurrentBiome)
{
case ProjectM.Simulation.RoomBiomeId.Meadow:
expFog = new Color(0.10f, 0.16f, 0.10f, 1f); expDen = 0.012f;
expAmb = new Color(0.30f, 0.42f, 0.32f, 1f);
groundTarget = new Color(0.47f, 0.55f, 0.43f, 1f);
case ProjectM.Simulation.RoomBiomeId.Meadow: // kelp shallows: a touch greener
expFog = new Color(0.02f, 0.10f, 0.09f, 1f); expDen = 0.035f;
expAmb = new Color(0.025f, 0.06f, 0.06f, 1f);
break;
case ProjectM.Simulation.RoomBiomeId.Cavern:
expFog = new Color(0.06f, 0.08f, 0.12f, 1f); expDen = 0.020f;
expAmb = new Color(0.24f, 0.28f, 0.38f, 1f);
groundTarget = new Color(0.42f, 0.46f, 0.55f, 1f);
case ProjectM.Simulation.RoomBiomeId.Cavern: // crush-dark trench: colder + denser
expFog = new Color(0.01f, 0.05f, 0.08f, 1f); expDen = 0.05f;
expAmb = new Color(0.015f, 0.035f, 0.06f, 1f);
break;
case ProjectM.Simulation.RoomBiomeId.Blight:
expFog = new Color(0.13f, 0.07f, 0.15f, 1f); expDen = 0.022f;
expAmb = new Color(0.32f, 0.24f, 0.38f, 1f);
groundTarget = new Color(0.52f, 0.42f, 0.58f, 1f);
case ProjectM.Simulation.RoomBiomeId.Blight: // gloam bloom: a sick green-violet cast
expFog = new Color(0.045f, 0.075f, 0.09f, 1f); expDen = 0.045f;
expAmb = new Color(0.045f, 0.05f, 0.075f, 1f);
break;
// Arid keeps the config/default burnt-dusk orange + sand ground above.
// default keeps the config/fallback out-shelf murk above.
}
}
@@ -79,27 +69,6 @@ namespace ProjectM.Client
RenderSettings.fogColor = Color.Lerp(baseFog, expFog, t);
RenderSettings.fogDensity = Mathf.Lerp(baseDen, expDen, t);
RenderSettings.ambientSkyColor = Color.Lerp(baseAmb, expAmb, t);
// Per-room-biome ground tint (expedition quads only; the meadow base keeps its authored material).
if (_ground == null)
{
var found = new System.Collections.Generic.List<MeshRenderer>();
foreach (var mr in Object.FindObjectsByType<MeshRenderer>(FindObjectsSortMode.None))
if (mr.gameObject.name == "Ground_Arid") found.Add(mr);
if (found.Count > 0)
{
_ground = found.ToArray();
_mpb = new MaterialPropertyBlock();
_groundCur = groundTarget; // snap on first sight — no lerp from black
}
}
if (_ground != null)
{
_groundCur = Color.Lerp(_groundCur, groundTarget, 1f - Mathf.Exp(-2.5f * UnityEngine.Time.deltaTime));
_mpb.SetColor(BaseColorId, _groundCur);
for (int i = 0; i < _ground.Length; i++)
if (_ground[i] != null) _ground[i].SetPropertyBlock(_mpb);
}
}
}
}