using System; using System.Collections.Generic; using UnityEngine; using VRM.FastSpringBones.Blittables; using VRM.FastSpringBones.NativeWrappers; using VRM.FastSpringBones.Registries; namespace VRM.FastSpringBones.Components { /// /// SpringBoneの1本の毛束の処理を担当するクラス /// public sealed class FastSpringRootBone : IDisposable { private readonly TransformRegistry _transformRegistry; private readonly RootBoneRegistry _rootBoneRegistry; private readonly ColliderGroupRegistry _colliderGroupRegistry; private readonly Transform _transform; private float _radius; private NativeTransform _center; private IReadOnlyDictionary _transformIndexMap; private NativeColliderGroups _nativeColliderGroups; private NativePoints _nativePoints; private NativePointer _rootBoneWrapper; private readonly IList _transformWrappers = new List(); private readonly IList> _points = new List>(); public FastSpringRootBone( TransformRegistry transformRegistry, Transform transform, RootBoneRegistry rootBoneRegistry, ColliderGroupRegistry colliderGroupRegistry ) { _transformRegistry = transformRegistry; _transform = transform; _rootBoneRegistry = rootBoneRegistry; _colliderGroupRegistry = colliderGroupRegistry; } public IReadOnlyList ColliderGroups { get => _nativeColliderGroups.ColliderGroups; set => _nativeColliderGroups.ColliderGroups = value; } public unsafe void Initialize( float gravityPower, Vector3 gravityDir, float dragForce, float stiffnessForce, IReadOnlyList colliderGroups, float radius, Transform center) { _radius = radius; if (center != null) { _center = new NativeTransform(_transformRegistry, TransformSynchronizationType.PullOnly, center); } _nativeColliderGroups = new NativeColliderGroups(colliderGroups); NativeTransform parent = null; if (_transform.parent) { parent = new NativeTransform(_transformRegistry, TransformSynchronizationType.PullOnly, _transform.parent); } SetupRecursive(_transform, parent); _nativePoints = new NativePoints(_points); _rootBoneWrapper = new NativePointer(new BlittableRootBone(gravityPower, gravityDir, dragForce, stiffnessForce, _nativePoints.GetUnsafePtr())); _rootBoneRegistry.Register(_rootBoneWrapper); _colliderGroupRegistry.Register(_nativeColliderGroups); } public void Dispose() { _colliderGroupRegistry.Unregister(_nativeColliderGroups); _rootBoneRegistry.Unregister(_rootBoneWrapper); foreach (var transformWrapper in _transformWrappers) { transformWrapper.Dispose(); } foreach (var point in _points) { point.Dispose(); } _center?.Dispose(); _nativeColliderGroups?.Dispose(); _nativePoints.Dispose(); _rootBoneWrapper.Dispose(); } private unsafe void SetupRecursive(Transform trs, NativeTransform parent = null) { var transformWrapper = new NativeTransform(_transformRegistry, TransformSynchronizationType.PushOnly, trs, parent); _transformWrappers.Add(transformWrapper); var point = new NativePointer( new BlittablePoint( trs, _radius, _center != null ? _center.GetUnsafePtr() : null, _nativeColliderGroups.GetUnsafePtr(), transformWrapper.GetUnsafePtr()) ); _points.Add(point); for (var i = 0; i < trs.childCount; ++i) { SetupRecursive(trs.GetChild(i), transformWrapper); } } } }