using Unity.Collections; using UnityEngine; using UnityEngine.Animations; using UnityEngine.Animations.Rigging; namespace UnityEditor.Animations.Rigging { /// /// The MultiParent inverse constraint job. /// [Unity.Burst.BurstCompile] public struct MultiParentInverseConstraintJob : IWeightedAnimationJob { const float k_Epsilon = 1e-5f; /// The Transform handle for the constrained object Transform. public ReadOnlyTransformHandle driven; /// The Transform handle for the constrained object parent Transform. public ReadOnlyTransformHandle drivenParent; /// List of Transform handles for the source objects. public NativeArray sourceTransforms; /// List of weights for the source objects. public NativeArray sourceWeights; /// List of offsets to apply to source rotations if maintainOffset is enabled. public NativeArray sourceOffsets; /// public FloatProperty jobWeight { get; set; } /// /// Defines what to do when processing the root motion. /// /// The animation stream to work on. public void ProcessRootMotion(AnimationStream stream) { } /// /// Defines what to do when processing the animation. /// /// The animation stream to work on. public void ProcessAnimation(AnimationStream stream) { jobWeight.Set(stream, 1f); driven.GetGlobalTR(stream, out Vector3 currentWPos, out Quaternion currentWRot); var drivenTx = new AffineTransform(currentWPos, currentWRot); for (int i = 0; i < sourceTransforms.Length; ++i) { sourceWeights[i].SetFloat(stream, 1f); var sourceTransform = sourceTransforms[i]; sourceTransform.GetGlobalTR(stream, out var sourcePosition, out var sourceRotation); var result = drivenTx; result *= sourceOffsets[i]; sourceTransform.SetGlobalTR(stream, result.translation, result.rotation); sourceTransforms[i] = sourceTransform; } } } /// /// The MultiParent inverse constraint job binder. /// /// The constraint data type public class MultiParentInverseConstraintJobBinder : AnimationJobBinder where T : struct, IAnimationJobData, IMultiParentConstraintData { /// public override MultiParentInverseConstraintJob Create(Animator animator, ref T data, Component component) { var job = new MultiParentInverseConstraintJob(); job.driven = ReadOnlyTransformHandle.Bind(animator, data.constrainedObject); job.drivenParent = ReadOnlyTransformHandle.Bind(animator, data.constrainedObject.parent); WeightedTransformArray sourceObjects = data.sourceObjects; WeightedTransformArrayBinder.BindReadWriteTransforms(animator, component, sourceObjects, out job.sourceTransforms); WeightedTransformArrayBinder.BindWeights(animator, component, sourceObjects, data.sourceObjectsProperty, out job.sourceWeights); job.sourceOffsets = new NativeArray(sourceObjects.Count, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); var drivenTx = new AffineTransform(data.constrainedObject.position, data.constrainedObject.rotation); for (int i = 0; i < sourceObjects.Count; ++i) { var sourceTransform = sourceObjects[i].transform; var srcTx = new AffineTransform(sourceTransform.position, sourceTransform.rotation); var srcOffset = AffineTransform.identity; var tmp = srcTx.InverseMul(drivenTx); if (data.maintainPositionOffset) srcOffset.translation = tmp.translation; if (data.maintainRotationOffset) srcOffset.rotation = tmp.rotation; srcOffset = srcOffset.Inverse(); job.sourceOffsets[i] = srcOffset; } return job; } /// public override void Destroy(MultiParentInverseConstraintJob job) { job.sourceTransforms.Dispose(); job.sourceWeights.Dispose(); job.sourceOffsets.Dispose(); } } }