using UnityEngine; using UnityEngine.Animations; using UnityEngine.Animations.Rigging; using Unity.Collections; namespace UnityEditor.Animations.Rigging { /// /// The MultiReferential inverse constraint job. /// [Unity.Burst.BurstCompile] public struct MultiReferentialInverseConstraintJob : IWeightedAnimationJob { /// The list of Transforms that are affected by the specified driver. public NativeArray sources; /// List of AffineTransform to apply to driven source objects. public NativeArray offsetTx; /// 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); sources[0].GetGlobalTR(stream, out Vector3 driverWPos, out Quaternion driverWRot); var driverTx = new AffineTransform(driverWPos, driverWRot); int offset = 0; for (int i = 1; i < sources.Length; ++i) { var tx = driverTx * offsetTx[offset]; var src = sources[i]; src.GetGlobalTR(stream, out Vector3 srcWPos, out Quaternion srcWRot); src.SetGlobalTR(stream, tx.translation, tx.rotation); offset++; sources[i] = src; } } } /// /// The MultiReferential inverse constraint job binder. /// /// The constraint data type public class MultiReferentialInverseConstraintJobBinder : AnimationJobBinder where T : struct, IAnimationJobData, IMultiReferentialConstraintData { /// public override MultiReferentialInverseConstraintJob Create(Animator animator, ref T data, Component component) { var job = new MultiReferentialInverseConstraintJob(); var sources = data.sourceObjects; job.sources = new NativeArray(sources.Length, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); job.offsetTx = new NativeArray(sources.Length - 1, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); var sourceBindTx = new AffineTransform[sources.Length]; for (int i = 0; i < sources.Length; ++i) { job.sources[i] = ReadWriteTransformHandle.Bind(animator, sources[i].transform); sourceBindTx[i] = new AffineTransform(sources[i].position, sources[i].rotation); } int offset = 0; var invDriverTx = sourceBindTx[0].Inverse(); for (int i = 1; i < sourceBindTx.Length; ++i) { job.offsetTx[offset] = invDriverTx * sourceBindTx[i]; offset++; } return job; } /// public override void Destroy(MultiReferentialInverseConstraintJob job) { job.sources.Dispose(); job.offsetTx.Dispose(); } } }