2026-06-28 01:18:21 +01:00
|
|
|
using System;
|
|
|
|
|
using GameCult.Aetheria.State.Verse;
|
2026-07-15 20:17:05 +01:00
|
|
|
using GameCult.Eve.PluginFields;
|
2026-06-28 01:18:21 +01:00
|
|
|
using UnityEngine;
|
|
|
|
|
|
|
|
|
|
public sealed class AetheriaUnityRenderSplatViewportSource : MonoBehaviour
|
|
|
|
|
{
|
|
|
|
|
[SerializeField]
|
|
|
|
|
private AetheriaRenderSplatRasterizer rasterizer;
|
|
|
|
|
|
|
|
|
|
[SerializeField]
|
|
|
|
|
private AetheriaRenderSplatLayerRenderer layerRenderer;
|
|
|
|
|
|
|
|
|
|
[SerializeField]
|
|
|
|
|
private string layerKey = AetheriaRuntimeRenderSplatLayerKeys.GravityHeight;
|
|
|
|
|
|
|
|
|
|
[SerializeField]
|
|
|
|
|
private Vector2 position;
|
|
|
|
|
|
|
|
|
|
[SerializeField]
|
|
|
|
|
private Vector2 size = new Vector2(1024, 1024);
|
|
|
|
|
|
|
|
|
|
[SerializeField]
|
|
|
|
|
private float refreshIntervalSeconds = 0.5f;
|
|
|
|
|
|
|
|
|
|
[SerializeField]
|
|
|
|
|
private bool renderInLateUpdate = true;
|
|
|
|
|
|
|
|
|
|
private float _nextRefreshTime;
|
2026-07-05 19:56:18 +01:00
|
|
|
private AetheriaUnityGameViewportDocuments _viewportDocuments;
|
2026-06-30 19:14:49 +01:00
|
|
|
private string _lastWarningMessage = "";
|
2026-06-28 01:18:21 +01:00
|
|
|
|
|
|
|
|
public RenderTexture TargetTexture
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if (layerRenderer != null && layerRenderer.TryGetTexture(layerKey, out var texture))
|
|
|
|
|
return texture;
|
|
|
|
|
|
|
|
|
|
return rasterizer != null ? rasterizer.TargetTexture : null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-15 20:17:05 +01:00
|
|
|
public EveFieldsSplatsDocument CurrentDocument =>
|
2026-07-05 22:23:07 +01:00
|
|
|
_viewportDocuments?.CurrentRenderSplatsViewport;
|
2026-06-30 19:14:49 +01:00
|
|
|
|
|
|
|
|
public bool RenderInLateUpdate
|
|
|
|
|
{
|
|
|
|
|
get => renderInLateUpdate;
|
|
|
|
|
set => renderInLateUpdate = value;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-28 01:18:21 +01:00
|
|
|
private void Reset()
|
|
|
|
|
{
|
|
|
|
|
rasterizer = GetComponent<AetheriaRenderSplatRasterizer>();
|
|
|
|
|
layerRenderer = GetComponent<AetheriaRenderSplatLayerRenderer>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void LateUpdate()
|
|
|
|
|
{
|
|
|
|
|
if (renderInLateUpdate)
|
|
|
|
|
RenderLatest();
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-28 09:36:05 +01:00
|
|
|
private void OnDisable()
|
|
|
|
|
{
|
|
|
|
|
ClearViewportDocument();
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-28 01:18:21 +01:00
|
|
|
public bool RenderLatest()
|
|
|
|
|
{
|
|
|
|
|
ResolveRenderers();
|
|
|
|
|
if (layerRenderer == null && rasterizer == null)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
RefreshDocument(false);
|
2026-07-05 22:23:07 +01:00
|
|
|
var document = _viewportDocuments?.CurrentRenderSplatsViewport;
|
2026-06-28 09:36:05 +01:00
|
|
|
if (document == null)
|
2026-06-28 01:18:21 +01:00
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (layerRenderer != null)
|
|
|
|
|
{
|
2026-06-28 09:36:05 +01:00
|
|
|
layerRenderer.Render(document, Mathf.RoundToInt(size.x), Mathf.RoundToInt(size.y));
|
2026-06-28 01:18:21 +01:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-28 09:36:05 +01:00
|
|
|
rasterizer.Render(document, Mathf.RoundToInt(size.x), Mathf.RoundToInt(size.y));
|
2026-06-28 01:18:21 +01:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ResolveRenderers()
|
|
|
|
|
{
|
|
|
|
|
if (layerRenderer == null)
|
|
|
|
|
layerRenderer = GetComponent<AetheriaRenderSplatLayerRenderer>();
|
|
|
|
|
if (rasterizer == null)
|
|
|
|
|
rasterizer = GetComponent<AetheriaRenderSplatRasterizer>();
|
|
|
|
|
|
|
|
|
|
if (layerRenderer == null && rasterizer == null)
|
|
|
|
|
layerRenderer = gameObject.AddComponent<AetheriaRenderSplatLayerRenderer>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SetLayerKey(string value)
|
|
|
|
|
{
|
|
|
|
|
layerKey = string.IsNullOrWhiteSpace(value)
|
|
|
|
|
? AetheriaRuntimeRenderSplatLayerKeys.GravityHeight
|
|
|
|
|
: value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SetViewport(Vector2 center, Vector2 viewportSize)
|
|
|
|
|
{
|
|
|
|
|
position = center;
|
|
|
|
|
size = viewportSize;
|
|
|
|
|
RefreshDocument(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void RefreshDocument(bool force)
|
|
|
|
|
{
|
2026-06-28 09:36:05 +01:00
|
|
|
var viewport = ResolveViewportBounds();
|
2026-06-29 12:54:07 +01:00
|
|
|
if (!force && _viewportDocuments != null && _viewportDocuments.Matches(viewport))
|
2026-06-28 09:36:05 +01:00
|
|
|
return;
|
|
|
|
|
|
2026-06-28 01:18:21 +01:00
|
|
|
if (!force && Time.unscaledTime < _nextRefreshTime)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
_nextRefreshTime = Time.unscaledTime + Mathf.Max(0.02f, refreshIntervalSeconds);
|
|
|
|
|
try
|
|
|
|
|
{
|
2026-06-29 12:54:07 +01:00
|
|
|
var nextDocuments = AetheriaUnityRuntimeClientProvider
|
|
|
|
|
.RenderSplatViewportDocuments(viewport, "unity-render-splat-viewport");
|
2026-06-28 09:36:05 +01:00
|
|
|
ClearViewportDocument();
|
2026-06-29 12:54:07 +01:00
|
|
|
_viewportDocuments = nextDocuments;
|
2026-06-30 19:14:49 +01:00
|
|
|
_lastWarningMessage = "";
|
2026-06-28 01:18:21 +01:00
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
2026-06-30 19:14:49 +01:00
|
|
|
ClearViewportDocument();
|
2026-07-05 22:23:07 +01:00
|
|
|
WarnOnce($"Failed to read daemon render splats from Verse state: {ex.Message}");
|
2026-06-28 01:18:21 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-30 19:14:49 +01:00
|
|
|
private void WarnOnce(string message)
|
|
|
|
|
{
|
|
|
|
|
if (string.Equals(_lastWarningMessage, message, StringComparison.Ordinal))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
_lastWarningMessage = message;
|
|
|
|
|
Debug.LogWarning(message);
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-05 19:56:18 +01:00
|
|
|
private AetheriaRuntimeViewportBounds ResolveViewportBounds()
|
2026-06-28 01:18:21 +01:00
|
|
|
{
|
|
|
|
|
var halfSize = size * 0.5f;
|
2026-07-05 19:56:18 +01:00
|
|
|
return new AetheriaRuntimeViewportBounds
|
2026-06-28 01:18:21 +01:00
|
|
|
{
|
|
|
|
|
MinX = position.x - halfSize.x,
|
|
|
|
|
MinY = position.y - halfSize.y,
|
|
|
|
|
MaxX = position.x + halfSize.x,
|
|
|
|
|
MaxY = position.y + halfSize.y
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-28 09:36:05 +01:00
|
|
|
private void ClearViewportDocument()
|
|
|
|
|
{
|
2026-06-29 12:54:07 +01:00
|
|
|
_viewportDocuments?.Dispose();
|
|
|
|
|
_viewportDocuments = null;
|
2026-06-28 09:36:05 +01:00
|
|
|
}
|
|
|
|
|
|
2026-06-28 01:18:21 +01:00
|
|
|
}
|