From f33a41afa658fe6013f186fe0136baec8d03faf6 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Sun, 28 Jun 2026 09:36:05 +0100 Subject: [PATCH] Use reactive render splat viewport source --- Aetheria.State.Verify/Program.cs | 24 ++++++++++ .../AetheriaUnityRenderSplatViewportSource.cs | 46 ++++++++++++++++--- 2 files changed, 64 insertions(+), 6 deletions(-) diff --git a/Aetheria.State.Verify/Program.cs b/Aetheria.State.Verify/Program.cs index 9480f5661..b83093637 100644 --- a/Aetheria.State.Verify/Program.cs +++ b/Aetheria.State.Verify/Program.cs @@ -7442,6 +7442,30 @@ static void RequireUnityViewportAndMapReadsUseManagedAccessors(string root) string.Join(", ", offenders)); } + var renderSplatViewportSource = File.ReadAllText(Path.Combine( + root, + "Assets", + "Scripts", + "Gameplay", + "AetheriaUnityRenderSplatViewportSource.cs")); + var requiredRenderSplatViewportSourceSymbols = new[] + { + "CultMeshReactiveDocument _renderSplatsViewport", + ".ReactiveRenderSplats(viewport)", + "_renderSplatsViewport?.Current", + "ClearViewportDocument()" + }; + var missingRenderSplatViewportSourceSymbols = requiredRenderSplatViewportSourceSymbols + .Where(symbol => !renderSplatViewportSource.Contains(symbol, StringComparison.Ordinal)) + .ToArray(); + if (missingRenderSplatViewportSourceSymbols.Length > 0 || + renderSplatViewportSource.Contains(".LatestRenderSplats(", StringComparison.Ordinal)) + { + throw new InvalidOperationException( + "AetheriaUnityRenderSplatViewportSource must keep a managed reactive render-splats viewport document instead of polling latest snapshots: " + + string.Join(", ", missingRenderSplatViewportSourceSymbols)); + } + Console.WriteLine("Viewport and map document accessors: Unity reads map, contact, viewport, and current-entity state through named managed accessors"); } diff --git a/Assets/Scripts/Gameplay/AetheriaUnityRenderSplatViewportSource.cs b/Assets/Scripts/Gameplay/AetheriaUnityRenderSplatViewportSource.cs index c4d211337..29027dd22 100644 --- a/Assets/Scripts/Gameplay/AetheriaUnityRenderSplatViewportSource.cs +++ b/Assets/Scripts/Gameplay/AetheriaUnityRenderSplatViewportSource.cs @@ -1,4 +1,5 @@ using System; +using GameCult.Mesh; using GameCult.Aetheria.State.Verse; using UnityEngine; @@ -26,7 +27,8 @@ public sealed class AetheriaUnityRenderSplatViewportSource : MonoBehaviour private bool renderInLateUpdate = true; private float _nextRefreshTime; - private AetheriaRuntimeRenderSplatsViewportDocument _document; + private AetheriaRuntimeRtsViewportBounds _viewport; + private CultMeshReactiveDocument _renderSplatsViewport; public RenderTexture TargetTexture { @@ -51,6 +53,11 @@ public sealed class AetheriaUnityRenderSplatViewportSource : MonoBehaviour RenderLatest(); } + private void OnDisable() + { + ClearViewportDocument(); + } + public bool RenderLatest() { ResolveRenderers(); @@ -58,16 +65,17 @@ public sealed class AetheriaUnityRenderSplatViewportSource : MonoBehaviour return false; RefreshDocument(false); - if (_document == null) + var document = _renderSplatsViewport?.Current; + if (document == null) return false; if (layerRenderer != null) { - layerRenderer.Render(_document, Mathf.RoundToInt(size.x), Mathf.RoundToInt(size.y)); + layerRenderer.Render(document, Mathf.RoundToInt(size.x), Mathf.RoundToInt(size.y)); return true; } - rasterizer.Render(_document, Mathf.RoundToInt(size.x), Mathf.RoundToInt(size.y)); + rasterizer.Render(document, Mathf.RoundToInt(size.x), Mathf.RoundToInt(size.y)); return true; } @@ -98,16 +106,23 @@ public sealed class AetheriaUnityRenderSplatViewportSource : MonoBehaviour private void RefreshDocument(bool force) { + var viewport = ResolveViewportBounds(); + if (!force && _renderSplatsViewport != null && SameViewport(_viewport, viewport)) + return; + if (!force && Time.unscaledTime < _nextRefreshTime) return; _nextRefreshTime = Time.unscaledTime + Mathf.Max(0.02f, refreshIntervalSeconds); try { - _document = ResolveClient() + var nextRenderSplatsViewport = ResolveClient() .Aetheria() .Viewports - .LatestRenderSplats(ResolveViewportBounds()); + .ReactiveRenderSplats(viewport); + ClearViewportDocument(); + _viewport = viewport; + _renderSplatsViewport = nextRenderSplatsViewport; } catch (Exception ex) { @@ -127,6 +142,25 @@ public sealed class AetheriaUnityRenderSplatViewportSource : MonoBehaviour }; } + private void ClearViewportDocument() + { + _renderSplatsViewport?.Dispose(); + _renderSplatsViewport = null; + } + + private static bool SameViewport( + AetheriaRuntimeRtsViewportBounds left, + AetheriaRuntimeRtsViewportBounds right) + { + if (left == null || right == null) + return false; + + return Mathf.Approximately(left.MinX, right.MinX) && + Mathf.Approximately(left.MinY, right.MinY) && + Mathf.Approximately(left.MaxX, right.MaxX) && + Mathf.Approximately(left.MaxY, right.MaxY); + } + private AetheriaClient ResolveClient() { return AetheriaUnityRuntimeClientProvider.ResolveClient(