using System.Collections.Generic; using Unity.Collections; namespace UnityEngine.Animations.Rigging { using Experimental.Animations; [Unity.Burst.BurstCompile] public struct TwistChainStep1Job : IWeightedAnimationJob { public ReadWriteTransformHandle rootTarget; public ReadWriteTransformHandle tipTarget; public NativeArray chain; public NativeArray steps; public FloatProperty jobWeight { get; set; } public void ProcessRootMotion(AnimationStream stream) {} public void ProcessAnimation(AnimationStream stream) { // 1. Retrieve root and tip rotation. // ... // 2. Interpolate rotation on chain. // ... // 3. Update position of tip handle for easier visualization. // ... } } [System.Serializable] public struct TwistChainStep1Data : IAnimationJobData { public Transform root; public Transform tip; [SyncSceneToStream] public Transform rootTarget; [SyncSceneToStream] public Transform tipTarget; bool IAnimationJobData.IsValid() => !(root == null || tip == null || !tip.IsChildOf(root) || rootTarget == null || tipTarget == null); void IAnimationJobData.SetDefaultValues() { root = tip = rootTarget = tipTarget = null; } } public class TwistChainStep1JobBinder : AnimationJobBinder { public override TwistChainStep1Job Create(Animator animator, ref TwistChainStep1Data data, Component component) { // Retrieve chain in-between root and tip transforms. Transform[] chain = ConstraintsUtils.ExtractChain(data.root, data.tip); // Extract steps from chain. float[] steps = ConstraintsUtils.ExtractSteps(chain); // Build Job. var job = new TwistChainStep1Job(); job.chain = new NativeArray(chain.Length, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); job.steps = new NativeArray(chain.Length, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); job.rootTarget = ReadWriteTransformHandle.Bind(animator, data.rootTarget); job.tipTarget = ReadWriteTransformHandle.Bind(animator, data.tipTarget); // Set values in NativeArray. for (int i = 0; i < chain.Length; ++i) { job.chain[i] = ReadWriteTransformHandle.Bind(animator, chain[i]); job.steps[i] = steps[i]; } return job; } public override void Destroy(TwistChainStep1Job job) { job.chain.Dispose(); job.steps.Dispose(); } public override void Update(TwistChainStep1Job job, ref TwistChainStep1Data data) { } } [DisallowMultipleComponent, AddComponentMenu("SIGGRAPH 2019/Twist Chain Step 1")] public class TwistChainStep1 : RigConstraint< TwistChainStep1Job, TwistChainStep1Data, TwistChainStep1JobBinder > { } }