SHA256
59 lines
2.5 KiB
C#
59 lines
2.5 KiB
C#
using System.Reflection;
|
|
using Cysharp.Threading.Tasks;
|
|
using HarmonyLib;
|
|
using UnityEngine;
|
|
|
|
namespace ADOFAIRenderer.Core;
|
|
|
|
/// <summary>
|
|
/// Per-frame hook attached to the scrCamera GameObject by RenderManager when the game scene of a render has loaded,
|
|
/// and destroyed again when a render is cancelled or fails.
|
|
/// Execution order int.MaxValue: its LateUpdate runs after every other script's LateUpdate of the frame.
|
|
/// Each frame it calls RenderManager.OnLastUpdate (LateUpdate) and, after the frame has been rendered
|
|
/// (end of frame), RenderManager.OnPostFrame with the texture shown on scrCamera's camera quad, which is the frame
|
|
/// that gets captured.
|
|
/// Reference: https://docs.unity3d.com/ScriptReference/DefaultExecutionOrder.html
|
|
/// </summary>
|
|
[DefaultExecutionOrder(int.MaxValue)]
|
|
internal class PostRenderHook : MonoBehaviour
|
|
{
|
|
/// <summary>Private field scrCamera.camQuadMesh: the MeshRenderer of the quad that displays the camera RenderTexture.</summary>
|
|
private FieldInfo? _camQuadMeshField;
|
|
|
|
/// <summary>Cached value of camQuadMesh for the current scrCamera instance. Looked up again while it is null or destroyed.</summary>
|
|
private MeshRenderer? _camQuadMeshRenderer;
|
|
|
|
private void Awake()
|
|
{
|
|
_camQuadMeshField = AccessTools.Field(typeof(scrCamera), "camQuadMesh");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Main thread, once per frame after all other LateUpdate calls. Runs the last-update work of RenderManager
|
|
/// (OnLastUpdate callbacks of the session) and schedules the end-of-frame capture.
|
|
/// </summary>
|
|
private void LateUpdate()
|
|
{
|
|
if (RenderManager.Instance)
|
|
RenderManager.Instance.OnLastUpdate();
|
|
|
|
PostFrameAsync().Forget();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Waits until the end of the current frame (after the cameras have rendered) and passes the camera quad's main
|
|
/// texture to RenderManager.OnPostFrame. The wait is cancelled when this component is destroyed.
|
|
/// The texture is null when the quad's material has no RenderTexture; OnPostFrame then only updates the audio.
|
|
/// </summary>
|
|
private async UniTaskVoid PostFrameAsync()
|
|
{
|
|
await UniTask.WaitForEndOfFrame(this, destroyCancellationToken);
|
|
|
|
if (!_camQuadMeshRenderer && scrCamera.instance)
|
|
_camQuadMeshRenderer = _camQuadMeshField?.GetValue(scrCamera.instance) as MeshRenderer;
|
|
|
|
if (RenderManager.Instance && _camQuadMeshRenderer)
|
|
RenderManager.Instance.OnPostFrame(_camQuadMeshRenderer.sharedMaterial.mainTexture as RenderTexture);
|
|
}
|
|
}
|