| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 | using System;using Unity.Collections;using Unity.Collections.LowLevel.Unsafe;using Unity.Jobs;using UnityEngine;namespace LitMotion{    internal interface IUpdateRunner    {        public void Update(double time, double unscaledTime, double realtime);        public void Reset();    }    internal sealed class UpdateRunner<TValue, TOptions, TAdapter> : IUpdateRunner        where TValue : unmanaged        where TOptions : unmanaged, IMotionOptions        where TAdapter : unmanaged, IMotionAdapter<TValue, TOptions>    {        public UpdateRunner(MotionStorage<TValue, TOptions, TAdapter> storage, double time, double unscaledTime, double realtime)        {            this.storage = storage;            prevTime = time;            prevUnscaledTime = unscaledTime;            prevRealtime = realtime;        }        readonly MotionStorage<TValue, TOptions, TAdapter> storage;        double prevTime;        double prevUnscaledTime;        double prevRealtime;        public unsafe void Update(double time, double unscaledTime, double realtime)        {            var count = storage.Count;            using var output = new NativeArray<TValue>(count, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);            using var completedIndexList = new NativeList<int>(count, Allocator.TempJob);            var deltaTime = time - prevTime;            var unscaledDeltaTime = unscaledTime - prevUnscaledTime;            var realDeltaTime = realtime - prevRealtime;            prevTime = time;            prevUnscaledTime = unscaledTime;            prevRealtime = realtime;            fixed (MotionData<TValue, TOptions>* dataPtr = storage.dataArray)            {                // update data                var job = new MotionUpdateJob<TValue, TOptions, TAdapter>()                {                    DataPtr = dataPtr,                    DeltaTime = deltaTime,                    UnscaledDeltaTime = unscaledDeltaTime,                    RealDeltaTime = realDeltaTime,                    Output = output,                    CompletedIndexList = completedIndexList.AsParallelWriter()                };                job.Schedule(count, 16).Complete();                // invoke delegates                var callbackSpan = storage.GetCallbacksSpan();                var outputPtr = (TValue*)output.GetUnsafePtr();                for (int i = 0; i < callbackSpan.Length; i++)                {                    var status = (dataPtr + i)->Core.Status;                    ref var callbackData = ref callbackSpan[i];                    if (status == MotionStatus.Playing || (status == MotionStatus.Delayed && !callbackData.SkipValuesDuringDelay))                    {                        try                        {                            callbackData.InvokeUnsafe(outputPtr[i]);                        }                        catch (Exception ex)                        {                            MotionDispatcher.GetUnhandledExceptionHandler()?.Invoke(ex);                            if (callbackData.CancelOnError)                            {                                (dataPtr + i)->Core.Status = MotionStatus.Canceled;                                callbackData.OnCancelAction?.Invoke();                            }                        }                    }                    else if (status == MotionStatus.Completed)                    {                        try                        {                            callbackData.InvokeUnsafe(outputPtr[i]);                        }                        catch (Exception ex)                        {                            MotionDispatcher.GetUnhandledExceptionHandler()?.Invoke(ex);                            if (callbackData.CancelOnError)                            {                                (dataPtr + i)->Core.Status = MotionStatus.Canceled;                                callbackData.OnCancelAction?.Invoke();                                continue;                            }                        }                        try                        {                            callbackData.OnCompleteAction?.Invoke();                        }                        catch (Exception ex)                        {                            MotionDispatcher.GetUnhandledExceptionHandler()?.Invoke(ex);                        }                    }                }            }            storage.RemoveAll(completedIndexList);        }        public void Reset()        {            storage.Reset();        }    }}
 |