Files
Nathaniel Cosford 062dfab2cd Patched
2025-05-30 01:04:40 +09:30

212 lines
6.2 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
#if NotEditor
using UniLinq;
#else
using System.Linq;
#endif
using UnityEngine;
using UnityEngine.Jobs;
using Unity.Collections;
using Unity.Jobs;
[AddComponentMenu("")]
public class AnimationDelayRender : MonoBehaviour
{
#if NotEditor
[Serializable]
public class TransformTargets
{
public Transform target;
public bool includeChildren;
}
public struct TransformLocalData
{
public Vector3 localPosition;
public Quaternion localRotation;
public Vector3 localScale;
public TransformLocalData(Vector3 localPosition, Quaternion localRotation, Vector3 localScale)
{
this.localPosition = localPosition;
this.localRotation = localRotation;
this.localScale = localScale;
}
}
private struct TransformRestoreJobs : IJobParallelForTransform
{
public NativeArray<TransformLocalData> data;
public void Execute(int index, TransformAccess transform)
{
if (transform.isValid)
{
transform.SetLocalPositionAndRotation(data[index].localPosition, data[index].localRotation);
transform.localScale = data[index].localScale;
}
}
}
private struct TransformRestoreAndSaveJobs : IJobParallelForTransform
{
public NativeArray<TransformLocalData> data;
public void Execute(int index, TransformAccess transform)
{
if (transform.isValid)
{
TransformLocalData targetData = new TransformLocalData(transform.localPosition, transform.localRotation, transform.localScale);
transform.SetLocalPositionAndRotation(data[index].localPosition, data[index].localRotation);
transform.localScale = data[index].localScale;
data[index] = targetData;
}
}
}
[NonSerialized]
private Transform[] delayTargets;
private TransformLocalData[] posTargets;
private EntityPlayerLocal player;
private NativeArray<TransformLocalData> data;
TransformAccessArray transArr;
private JobHandle restoreJob, restoreAndSaveJob;
private bool dataInitialized = false;
private void Awake()
{
#if NotEditor
player = GameManager.Instance?.World?.GetPrimaryPlayer();
if (player == null)
{
Destroy(this);
return;
}
#endif
}
internal void InitializeTarget()
{
var delayTargetsSet = new HashSet<Transform>();
foreach (Transform child in transform.GetComponentsInChildren<Transform>(true).Skip(1))
{
delayTargetsSet.Add(child);
}
delayTargets = delayTargetsSet.ToArray();
posTargets = new TransformLocalData[delayTargets.Length];
ClearNative();
data = new NativeArray<TransformLocalData>(delayTargets.Length, Allocator.Persistent, NativeArrayOptions.ClearMemory);
transArr = new TransformAccessArray(delayTargets);
}
private void InitializeData()
{
for (int i = 0; i < delayTargets.Length; i++)
{
Transform target = delayTargets[i];
if (target)
{
data[i] = new TransformLocalData(target.localPosition, target.localRotation, target.localScale);
}
}
dataInitialized = true;
}
private void OnEnable()
{
InitializeTarget();
player.playerCamera?.gameObject.GetOrAddComponent<AnimationDelayRenderReference>().targets.Add(this);
//var preAnimatorUpdateJob = new TransformRestoreJobs
//{
// data = data
//};
//restoreJob = preAnimatorUpdateJob.Schedule(transArr);
StartCoroutine(EndOfFrameCo());
Log.Out($"Delay render target count: {delayTargets.Length}");
}
private void OnDisable()
{
ClearNative();
player.playerCamera?.gameObject.GetOrAddComponent<AnimationDelayRenderReference>().targets.Remove(this);
StopAllCoroutines();
dataInitialized = false;
}
private void Update()
{
//for (int i = 0; i < delayTargets.Length; i++)
//{
// Transform target = delayTargets[i];
// if (target)
// {
// target.localPosition = posTargets[i].localPosition;
// target.localRotation = posTargets[i].localRotation;
// target.localScale = posTargets[i].localScale;
// }
// else
// {
// delayTargets[i] = null;
// }
//}
restoreJob.Complete();
}
private void LateUpdate()
{
if (!dataInitialized)
return;
var postAnimationUpdateJob = new TransformRestoreAndSaveJobs
{
data = data
};
restoreAndSaveJob = postAnimationUpdateJob.Schedule(transArr);
//for (int i = 0; i < delayTargets.Length; i++)
//{
// Transform target = delayTargets[i];
// if (target)
// {
// TransformLocalData targetData = new TransformLocalData(target.localPosition, target.localRotation, target.localScale);
// target.localPosition = posTargets[i].localPosition;
// target.localRotation = posTargets[i].localRotation;
// target.localScale = posTargets[i].localScale;
// posTargets[i] = targetData;
// }
// else
// {
// delayTargets[i] = null;
// }
//}
}
internal void PreCullCallback()
{
restoreAndSaveJob.Complete();
}
private IEnumerator EndOfFrameCo()
{
yield return null;
InitializeData();
while (true)
{
yield return new WaitForEndOfFrame();
var eofUpdateJob = new TransformRestoreJobs { data = data };
restoreJob = eofUpdateJob.Schedule(transArr);
}
}
private void ClearNative()
{
if (data.IsCreated)
{
data.Dispose();
}
if (transArr.isCreated)
{
transArr.Dispose();
}
}
#endif
}