using System; using Unity.Collections; using Unity.Collections.LowLevel.Unsafe; using UnityEngine; using UnityEngine.Profiling; using UniVRM10.FastSpringBones.Blittables; namespace UniVRM10.FastSpringBones.System { /// /// ひとつのVRMに紐づくFastSpringBoneに関連したバッファを保持するクラス /// public class FastSpringBoneBuffer : IDisposable { // NOTE: これらはFastSpringBoneBufferCombinerによってバッチングされる public NativeArray Springs { get; } public NativeArray Joints { get; } public NativeArray Colliders { get; } public NativeArray Logics { get; } public NativeArray BlittableTransforms { get; } public Transform[] Transforms { get; } public bool IsDisposed { get; private set; } // NOTE: これは更新頻度が高くバッチングが難しいため、ランダムアクセスを許容してメモリへ直接アクセスする // 生のヒープ領域は扱いにくいので長さ1のNativeArrayで代用 private NativeArray _externalData; public Vector3 ExternalForce { get => _externalData[0].ExternalForce; set { _externalData[0] = new BlittableExternalData { ExternalForce = value, IsSpringBoneEnabled = _externalData[0].IsSpringBoneEnabled, }; } } public bool IsSpringBoneEnabled { get => _externalData[0].IsSpringBoneEnabled; set { _externalData[0] = new BlittableExternalData { ExternalForce = _externalData[0].ExternalForce, IsSpringBoneEnabled = value, }; } } public unsafe FastSpringBoneBuffer(FastSpringBoneBufferBuilder b) { Profiler.BeginSample("FastSpringBone.ConstructBuffers.ConstructNativeArrays"); _externalData = new NativeArray(1, Allocator.Persistent); _externalData[0] = new BlittableExternalData { ExternalForce = Vector3.zero, IsSpringBoneEnabled = true, }; b.SetExternalDataPtr((BlittableExternalData*)_externalData.GetUnsafePtr()); Springs = new NativeArray(b.BlittableSprings.ToArray(), Allocator.Persistent); Joints = new NativeArray(b.BlittableJoints.ToArray(), Allocator.Persistent); Colliders = new NativeArray(b.BlittableColliders.ToArray(), Allocator.Persistent); Logics = new NativeArray(b.BlittableLogics.ToArray(), Allocator.Persistent); BlittableTransforms = new NativeArray(b.Transforms.Length, Allocator.Persistent); Transforms = b.Transforms; Profiler.EndSample(); } public void Dispose() { if (IsDisposed) return; IsDisposed = true; Springs.Dispose(); Joints.Dispose(); BlittableTransforms.Dispose(); Colliders.Dispose(); Logics.Dispose(); _externalData.Dispose(); } } }