first commit

This commit is contained in:
lethanhsonvsp
2025-11-17 15:16:36 +07:00
commit a40d0921eb
17012 changed files with 2652386 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 57fb05f5d7fd88b41b5eca2077a707f3
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,92 @@
namespace UnityEngine.Animations.Rigging
{
/// <summary>
/// The Blend constraint data.
/// </summary>
[System.Serializable]
public struct BlendConstraintData : IAnimationJobData, IBlendConstraintData
{
[SerializeField] Transform m_ConstrainedObject;
[SyncSceneToStream, SerializeField] Transform m_SourceA;
[SyncSceneToStream, SerializeField] Transform m_SourceB;
[SyncSceneToStream, SerializeField] bool m_BlendPosition;
[SyncSceneToStream, SerializeField] bool m_BlendRotation;
[SyncSceneToStream, SerializeField, Range(0f, 1f)] float m_PositionWeight;
[SyncSceneToStream, SerializeField, Range(0f, 1f)] float m_RotationWeight;
[NotKeyable, SerializeField] bool m_MaintainPositionOffsets;
[NotKeyable, SerializeField] bool m_MaintainRotationOffsets;
/// <inheritdoc />
public Transform constrainedObject { get => m_ConstrainedObject; set => m_ConstrainedObject = value; }
/// <inheritdoc />
public Transform sourceObjectA { get => m_SourceA; set => m_SourceA = value; }
/// <inheritdoc />
public Transform sourceObjectB { get => m_SourceB; set => m_SourceB = value; }
/// <summary>Toggles whether position is blended in the constraint.</summary>
public bool blendPosition { get => m_BlendPosition; set => m_BlendPosition = value; }
/// <summary>Toggles whether rotation is blended in the constraint.</summary>
public bool blendRotation { get => m_BlendRotation; set => m_BlendRotation = value; }
/// <summary>
/// Specifies the weight with which to blend position.
/// A weight of zero will result in the position of sourceObjectA, while a weight of one will result in the position of sourceObjectB.
/// </summary>
public float positionWeight { get => m_PositionWeight; set => m_PositionWeight = Mathf.Clamp01(value); }
/// <summary>
/// Specifies the weight with which to blend rotation.
/// A weight of zero will result in the rotation of sourceObjectA, while a weight of one will result in the rotation of sourceObjectB.
/// </summary>
public float rotationWeight { get => m_RotationWeight; set => m_RotationWeight = Mathf.Clamp01(value); }
/// <inheritdoc />
public bool maintainPositionOffsets { get => m_MaintainPositionOffsets; set => m_MaintainPositionOffsets = value; }
/// <inheritdoc />
public bool maintainRotationOffsets { get => m_MaintainRotationOffsets; set => m_MaintainRotationOffsets = value; }
/// <inheritdoc />
string IBlendConstraintData.blendPositionBoolProperty => ConstraintsUtils.ConstructConstraintDataPropertyName(nameof(m_BlendPosition));
/// <inheritdoc />
string IBlendConstraintData.blendRotationBoolProperty => ConstraintsUtils.ConstructConstraintDataPropertyName(nameof(m_BlendRotation));
/// <inheritdoc />
string IBlendConstraintData.positionWeightFloatProperty => ConstraintsUtils.ConstructConstraintDataPropertyName(nameof(m_PositionWeight));
/// <inheritdoc />
string IBlendConstraintData.rotationWeightFloatProperty => ConstraintsUtils.ConstructConstraintDataPropertyName(nameof(m_RotationWeight));
/// <inheritdoc />
bool IAnimationJobData.IsValid() => !(m_ConstrainedObject == null || m_SourceA == null || m_SourceB == null);
/// <inheritdoc />
void IAnimationJobData.SetDefaultValues()
{
m_ConstrainedObject = null;
m_SourceA = null;
m_SourceB = null;
m_BlendPosition = true;
m_BlendRotation = true;
m_PositionWeight = 0.5f;
m_RotationWeight = 0.5f;
m_MaintainPositionOffsets = false;
m_MaintainRotationOffsets = false;
}
}
/// <summary>
/// Blend constraint.
/// </summary>
[DisallowMultipleComponent, AddComponentMenu("Animation Rigging/Blend Constraint")]
[HelpURL("https://docs.unity3d.com/Packages/com.unity.animation.rigging@1.3/manual/constraints/BlendConstraint.html")]
public class BlendConstraint : RigConstraint<
BlendConstraintJob,
BlendConstraintData,
BlendConstraintJobBinder<BlendConstraintData>
>
{
/// <inheritdoc />
protected override void OnValidate()
{
base.OnValidate();
m_Data.positionWeight = Mathf.Clamp01(m_Data.positionWeight);
m_Data.rotationWeight = Mathf.Clamp01(m_Data.rotationWeight);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2a2cc48f812a19f40a5c644fbc9b4d9a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: ca41524ec86f0d84ab5675c9622cc1a2, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,107 @@
namespace UnityEngine.Animations.Rigging
{
/// <summary>
/// The ChainIK constraint data.
/// </summary>
[System.Serializable]
public struct ChainIKConstraintData : IAnimationJobData, IChainIKConstraintData
{
internal const int k_MinIterations = 1;
internal const int k_MaxIterations = 50;
internal const float k_MinTolerance = 0f;
internal const float k_MaxTolerance = 0.01f;
[SerializeField] Transform m_Root;
[SerializeField] Transform m_Tip;
[SyncSceneToStream, SerializeField] Transform m_Target;
[SyncSceneToStream, SerializeField, Range(0f, 1f)] float m_ChainRotationWeight;
[SyncSceneToStream, SerializeField, Range(0f, 1f)] float m_TipRotationWeight;
[NotKeyable, SerializeField, Range(k_MinIterations, k_MaxIterations)] int m_MaxIterations;
[NotKeyable, SerializeField, Range(k_MinTolerance, k_MaxTolerance)] float m_Tolerance;
[NotKeyable, SerializeField] bool m_MaintainTargetPositionOffset;
[NotKeyable, SerializeField] bool m_MaintainTargetRotationOffset;
/// <inheritdoc />
public Transform root { get => m_Root; set => m_Root = value; }
/// <inheritdoc />
public Transform tip { get => m_Tip; set => m_Tip = value; }
/// <inheritdoc />
public Transform target { get => m_Target; set => m_Target = value; }
/// <summary>The weight for which ChainIK target has an effect on chain (up to tip Transform). This is a value in between 0 and 1.</summary>
public float chainRotationWeight { get => m_ChainRotationWeight; set => m_ChainRotationWeight = Mathf.Clamp01(value); }
/// <summary>The weight for which ChainIK target has and effect on tip Transform. This is a value in between 0 and 1.</summary>
public float tipRotationWeight { get => m_TipRotationWeight; set => m_TipRotationWeight = Mathf.Clamp01(value); }
/// <inheritdoc />
public int maxIterations { get => m_MaxIterations; set => m_MaxIterations = Mathf.Clamp(value, k_MinIterations, k_MaxIterations); }
/// <inheritdoc />
public float tolerance { get => m_Tolerance; set => m_Tolerance = Mathf.Clamp(value, k_MinTolerance, k_MaxTolerance); }
/// <inheritdoc />
public bool maintainTargetPositionOffset { get => m_MaintainTargetPositionOffset; set => m_MaintainTargetPositionOffset = value; }
/// <inheritdoc />
public bool maintainTargetRotationOffset { get => m_MaintainTargetRotationOffset; set => m_MaintainTargetRotationOffset = value; }
/// <inheritdoc />
string IChainIKConstraintData.chainRotationWeightFloatProperty => ConstraintsUtils.ConstructConstraintDataPropertyName(nameof(m_ChainRotationWeight));
/// <inheritdoc />
string IChainIKConstraintData.tipRotationWeightFloatProperty => ConstraintsUtils.ConstructConstraintDataPropertyName(nameof(m_TipRotationWeight));
/// <inheritdoc />
bool IAnimationJobData.IsValid()
{
if (m_Root == null || m_Tip == null || m_Target == null)
return false;
int count = 1;
Transform tmp = m_Tip;
while (tmp != null && tmp != m_Root)
{
tmp = tmp.parent;
++count;
}
return (tmp == m_Root && count > 2);
}
/// <inheritdoc />
void IAnimationJobData.SetDefaultValues()
{
m_Root = null;
m_Tip = null;
m_Target = null;
m_ChainRotationWeight = 1f;
m_TipRotationWeight = 1f;
m_MaxIterations = 15;
m_Tolerance = 0.0001f;
m_MaintainTargetPositionOffset = false;
m_MaintainTargetRotationOffset = false;
}
}
/// <summary>
/// ChainIK constraint
/// </summary>
[DisallowMultipleComponent, AddComponentMenu("Animation Rigging/Chain IK Constraint")]
[HelpURL("https://docs.unity3d.com/Packages/com.unity.animation.rigging@1.3/manual/constraints/ChainIKConstraint.html")]
public class ChainIKConstraint : RigConstraint<
ChainIKConstraintJob,
ChainIKConstraintData,
ChainIKConstraintJobBinder<ChainIKConstraintData>
>
{
/// <inheritdoc />
protected override void OnValidate()
{
base.OnValidate();
m_Data.chainRotationWeight = Mathf.Clamp01(m_Data.chainRotationWeight);
m_Data.tipRotationWeight = Mathf.Clamp01(m_Data.tipRotationWeight);
m_Data.maxIterations = Mathf.Clamp(
m_Data.maxIterations, ChainIKConstraintData.k_MinIterations, ChainIKConstraintData.k_MaxIterations
);
m_Data.tolerance = Mathf.Clamp(
m_Data.tolerance, ChainIKConstraintData.k_MinTolerance, ChainIKConstraintData.k_MaxTolerance
);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 796b75e345bd64d47a31edd757bd2670
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: ca41524ec86f0d84ab5675c9622cc1a2, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,74 @@
namespace UnityEngine.Animations.Rigging
{
/// <summary>
/// The DampedTransform constraint data.
/// </summary>
[System.Serializable]
public struct DampedTransformData : IAnimationJobData, IDampedTransformData
{
[SerializeField] Transform m_ConstrainedObject;
[SyncSceneToStream, SerializeField] Transform m_Source;
[SyncSceneToStream, SerializeField, Range(0f, 1f)] float m_DampPosition;
[SyncSceneToStream, SerializeField, Range(0f, 1f)] float m_DampRotation;
[NotKeyable, SerializeField] bool m_MaintainAim;
/// <inheritdoc />
public Transform constrainedObject { get => m_ConstrainedObject; set => m_ConstrainedObject = value; }
/// <inheritdoc />
public Transform sourceObject { get => m_Source; set => m_Source = value; }
/// <summary>
/// Damp position weight. Defines how much of constrained object position follows source object position.
/// Constrained position will closely follow source object when set to 0, and will
/// not move when set to 1.
/// </summary>
public float dampPosition { get => m_DampPosition; set => m_DampPosition = Mathf.Clamp01(value); }
/// <summary>
/// Damp rotation weight. Defines how much of constrained object rotation follows source object rotation.
/// Constrained rotation will closely follow source object when set to 0, and will
/// not move when set to 1.
/// </summary>
public float dampRotation { get => m_DampRotation; set => m_DampRotation = Mathf.Clamp01(value); }
/// <inheritdoc />
public bool maintainAim { get => m_MaintainAim; set => m_MaintainAim = value; }
/// <inheritdoc />
string IDampedTransformData.dampPositionFloatProperty => ConstraintsUtils.ConstructConstraintDataPropertyName(nameof(m_DampPosition));
/// <inheritdoc />
string IDampedTransformData.dampRotationFloatProperty => ConstraintsUtils.ConstructConstraintDataPropertyName(nameof(m_DampRotation));
/// <inheritdoc />
bool IAnimationJobData.IsValid() => !(m_ConstrainedObject == null || m_Source == null);
/// <inheritdoc />
void IAnimationJobData.SetDefaultValues()
{
m_ConstrainedObject = null;
m_Source = null;
m_DampPosition = 0.5f;
m_DampRotation = 0.5f;
m_MaintainAim = true;
}
}
/// <summary>
/// DampedTransform constraint.
/// </summary>
[DisallowMultipleComponent, AddComponentMenu("Animation Rigging/Damped Transform")]
[HelpURL("https://docs.unity3d.com/Packages/com.unity.animation.rigging@1.3/manual/constraints/DampedTransform.html")]
public class DampedTransform : RigConstraint<
DampedTransformJob,
DampedTransformData,
DampedTransformJobBinder<DampedTransformData>
>
{
/// <inheritdoc />
protected override void OnValidate()
{
base.OnValidate();
m_Data.dampPosition = Mathf.Clamp01(m_Data.dampPosition);
m_Data.dampRotation = Mathf.Clamp01(m_Data.dampRotation);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1b37cffab30b939469bac076fdd82c59
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: ca41524ec86f0d84ab5675c9622cc1a2, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,214 @@
namespace UnityEngine.Animations.Rigging
{
/// <summary>
/// The MultiAim constraint data.
/// </summary>
[System.Serializable]
public struct MultiAimConstraintData : IAnimationJobData, IMultiAimConstraintData
{
/// <summary>
/// Axis type for MultiAimConstraint.
/// </summary>
public enum Axis
{
/// <summary>Positive X Axis (1, 0, 0)</summary>
X,
/// <summary>Negative X Axis (-1, 0, 0)</summary>
X_NEG,
/// <summary>Positive Y Axis (0, 1, 0)</summary>
Y,
/// <summary>Negative Y Axis (0, -1, 0)</summary>
Y_NEG,
/// <summary>Positive Z Axis (0, 0, 1)</summary>
Z,
/// <summary>Negative Z Axis (0, 0, -1)</summary>
Z_NEG
}
/// <summary>
/// Specifies how the world up vector used by the Multi-Aim constraint is defined.
/// </summary>
public enum WorldUpType
{
/// <summary>Neither defines nor uses a world up vector.</summary>
None,
/// <summary>Uses and defines the world up vector as the Unity Scene up vector (the Y axis).</summary>
SceneUp,
/// <summary>Uses and defines the world up vector as a vector from the constrained object, in the direction of the up object.</summary>
ObjectUp,
/// <summary>Uses and defines the world up vector as relative to the local space of the object.</summary>
ObjectRotationUp,
/// <summary>Uses and defines the world up vector as a vector specified by the user.</summary>
Vector
};
internal const float k_MinAngularLimit = -180f;
internal const float k_MaxAngularLimit = 180f;
[SerializeField] Transform m_ConstrainedObject;
[SyncSceneToStream, SerializeField, WeightRange(0f, 1f)] WeightedTransformArray m_SourceObjects;
[SyncSceneToStream, SerializeField] Vector3 m_Offset;
[SyncSceneToStream, SerializeField, Range(k_MinAngularLimit, k_MaxAngularLimit)] float m_MinLimit;
[SyncSceneToStream, SerializeField, Range(k_MinAngularLimit, k_MaxAngularLimit)] float m_MaxLimit;
[NotKeyable, SerializeField] Axis m_AimAxis;
[NotKeyable, SerializeField] Axis m_UpAxis;
[NotKeyable, SerializeField] WorldUpType m_WorldUpType;
[SyncSceneToStream, SerializeField] Transform m_WorldUpObject;
[NotKeyable, SerializeField] Axis m_WorldUpAxis;
[NotKeyable, SerializeField] bool m_MaintainOffset;
[NotKeyable, SerializeField] Vector3Bool m_ConstrainedAxes;
/// <inheritdoc />
public Transform constrainedObject { get => m_ConstrainedObject; set => m_ConstrainedObject = value; }
/// <inheritdoc />
public WeightedTransformArray sourceObjects
{
get => m_SourceObjects;
set => m_SourceObjects = value;
}
/// <inheritdoc />
public bool maintainOffset { get => m_MaintainOffset; set => m_MaintainOffset = value; }
/// <summary>
/// Post-Rotation offset applied to the constrained Transform.
/// </summary>
public Vector3 offset { get => m_Offset; set => m_Offset = value; }
/// <summary>
/// Minimum and maximum value of the rotation permitted for the constraint. The values are in degrees.
/// </summary>
public Vector2 limits
{
get => new Vector2(m_MinLimit, m_MaxLimit);
set
{
m_MinLimit = Mathf.Clamp(value.x, k_MinAngularLimit, k_MaxAngularLimit);
m_MaxLimit = Mathf.Clamp(value.y, k_MinAngularLimit, k_MaxAngularLimit);
}
}
/// <inheritdoc cref="IMultiAimConstraintData.aimAxis"/>
public Axis aimAxis { get => m_AimAxis; set => m_AimAxis = value; }
/// <inheritdoc cref="IMultiAimConstraintData.upAxis"/>
public Axis upAxis { get => m_UpAxis; set => m_UpAxis = value; }
/// <inheritdoc cref="IMultiAimConstraintData.worldUpType"/>
public WorldUpType worldUpType { get => m_WorldUpType; set => m_WorldUpType = value; }
/// <inheritdoc cref="IMultiAimConstraintData.aimAxis"/>
public Axis worldUpAxis { get => m_WorldUpAxis; set => m_WorldUpAxis = value; }
/// <inheritdoc />
public Transform worldUpObject { get => m_WorldUpObject; set => m_WorldUpObject = value; }
/// <inheritdoc />
public bool constrainedXAxis { get => m_ConstrainedAxes.x; set => m_ConstrainedAxes.x = value; }
/// <inheritdoc />
public bool constrainedYAxis { get => m_ConstrainedAxes.y; set => m_ConstrainedAxes.y = value; }
/// <inheritdoc />
public bool constrainedZAxis { get => m_ConstrainedAxes.z; set => m_ConstrainedAxes.z = value; }
/// <inheritdoc />
Vector3 IMultiAimConstraintData.aimAxis => Convert(m_AimAxis);
/// <inheritdoc />
Vector3 IMultiAimConstraintData.upAxis => Convert(m_UpAxis);
/// <inheritdoc />
int IMultiAimConstraintData.worldUpType => (int) m_WorldUpType;
/// <inheritdoc />
Vector3 IMultiAimConstraintData.worldUpAxis => Convert(m_WorldUpAxis);
/// <inheritdoc />
string IMultiAimConstraintData.offsetVector3Property => ConstraintsUtils.ConstructConstraintDataPropertyName(nameof(m_Offset));
/// <inheritdoc />
string IMultiAimConstraintData.minLimitFloatProperty => ConstraintsUtils.ConstructConstraintDataPropertyName(nameof(m_MinLimit));
/// <inheritdoc />
string IMultiAimConstraintData.maxLimitFloatProperty => ConstraintsUtils.ConstructConstraintDataPropertyName(nameof(m_MaxLimit));
/// <inheritdoc />
string IMultiAimConstraintData.sourceObjectsProperty => ConstraintsUtils.ConstructConstraintDataPropertyName(nameof(m_SourceObjects));
/// <inheritdoc />
bool IAnimationJobData.IsValid()
{
if (m_ConstrainedObject == null || m_SourceObjects.Count == 0)
return false;
foreach (var src in m_SourceObjects)
if (src.transform == null)
return false;
return true;
}
/// <inheritdoc />
void IAnimationJobData.SetDefaultValues()
{
m_ConstrainedObject = null;
m_UpAxis = Axis.Y;
m_AimAxis = Axis.Z;
m_WorldUpType = WorldUpType.None;
m_WorldUpAxis = Axis.Y;
m_WorldUpObject = null;
m_SourceObjects.Clear();
m_MaintainOffset = false;
m_Offset = Vector3.zero;
m_ConstrainedAxes = new Vector3Bool(true);
m_MinLimit = -180f;
m_MaxLimit = 180f;
}
static Vector3 Convert(Axis axis)
{
switch (axis)
{
case Axis.X:
return Vector3.right;
case Axis.X_NEG:
return Vector3.left;
case Axis.Y:
return Vector3.up;
case Axis.Y_NEG:
return Vector3.down;
case Axis.Z:
return Vector3.forward;
case Axis.Z_NEG:
return Vector3.back;
default:
return Vector3.up;
}
}
}
/// <summary>
/// MultiAim constraint.
/// </summary>
[DisallowMultipleComponent, AddComponentMenu("Animation Rigging/Multi-Aim Constraint")]
[HelpURL("https://docs.unity3d.com/Packages/com.unity.animation.rigging@1.3/manual/constraints/MultiAimConstraint.html")]
public class MultiAimConstraint : RigConstraint<
MultiAimConstraintJob,
MultiAimConstraintData,
MultiAimConstraintJobBinder<MultiAimConstraintData>
>
{
/// <inheritdoc />
protected override void OnValidate()
{
base.OnValidate();
var weights = m_Data.sourceObjects;
WeightedTransformArray.OnValidate(ref weights);
m_Data.sourceObjects = weights;
var limits = m_Data.limits;
limits.x = Mathf.Clamp(
limits.x, MultiAimConstraintData.k_MinAngularLimit, MultiAimConstraintData.k_MaxAngularLimit
);
limits.y = Mathf.Clamp(
limits.y, MultiAimConstraintData.k_MinAngularLimit, MultiAimConstraintData.k_MaxAngularLimit
);
m_Data.limits = limits;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e3c430f382484144e925c097c2d33cfe
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: ca41524ec86f0d84ab5675c9622cc1a2, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,94 @@
namespace UnityEngine.Animations.Rigging
{
/// <summary>
/// The MultiParent constraint data.
/// </summary>
[System.Serializable]
public struct MultiParentConstraintData : IAnimationJobData, IMultiParentConstraintData
{
[SerializeField] Transform m_ConstrainedObject;
[SerializeField, SyncSceneToStream, WeightRange(0f, 1f)] WeightedTransformArray m_SourceObjects;
[NotKeyable, SerializeField] Vector3Bool m_ConstrainedPositionAxes;
[NotKeyable, SerializeField] Vector3Bool m_ConstrainedRotationAxes;
[NotKeyable, SerializeField] bool m_MaintainPositionOffset;
[NotKeyable, SerializeField] bool m_MaintainRotationOffset;
/// <inheritdoc />
public Transform constrainedObject { get => m_ConstrainedObject; set => m_ConstrainedObject = value; }
/// <inheritdoc />
public WeightedTransformArray sourceObjects
{
get => m_SourceObjects;
set => m_SourceObjects = value;
}
/// <inheritdoc />
public bool maintainPositionOffset { get => m_MaintainPositionOffset; set => m_MaintainPositionOffset = value; }
/// <inheritdoc />
public bool maintainRotationOffset { get => m_MaintainRotationOffset; set => m_MaintainRotationOffset = value; }
/// <inheritdoc />
public bool constrainedPositionXAxis { get => m_ConstrainedPositionAxes.x; set => m_ConstrainedPositionAxes.x = value; }
/// <inheritdoc />
public bool constrainedPositionYAxis { get => m_ConstrainedPositionAxes.y; set => m_ConstrainedPositionAxes.y = value; }
/// <inheritdoc />
public bool constrainedPositionZAxis { get => m_ConstrainedPositionAxes.z; set => m_ConstrainedPositionAxes.z = value; }
/// <inheritdoc />
public bool constrainedRotationXAxis { get => m_ConstrainedRotationAxes.x; set => m_ConstrainedRotationAxes.x = value; }
/// <inheritdoc />
public bool constrainedRotationYAxis { get => m_ConstrainedRotationAxes.y; set => m_ConstrainedRotationAxes.y = value; }
/// <inheritdoc />
public bool constrainedRotationZAxis { get => m_ConstrainedRotationAxes.z; set => m_ConstrainedRotationAxes.z = value; }
/// <inheritdoc />
string IMultiParentConstraintData.sourceObjectsProperty => ConstraintsUtils.ConstructConstraintDataPropertyName(nameof(m_SourceObjects));
/// <inheritdoc />
bool IAnimationJobData.IsValid()
{
if (m_ConstrainedObject == null || m_SourceObjects.Count == 0)
return false;
foreach (var src in m_SourceObjects)
if (src.transform == null)
return false;
return true;
}
/// <inheritdoc />
void IAnimationJobData.SetDefaultValues()
{
m_ConstrainedObject = null;
m_ConstrainedPositionAxes = new Vector3Bool(true);
m_ConstrainedRotationAxes = new Vector3Bool(true);
m_SourceObjects.Clear();
m_MaintainPositionOffset = false;
m_MaintainRotationOffset = false;
}
}
/// <summary>
/// MultiParent constraint
/// </summary>
[DisallowMultipleComponent, AddComponentMenu("Animation Rigging/Multi-Parent Constraint")]
[HelpURL("https://docs.unity3d.com/Packages/com.unity.animation.rigging@1.3/manual/constraints/MultiParentConstraint.html")]
public class MultiParentConstraint : RigConstraint<
MultiParentConstraintJob,
MultiParentConstraintData,
MultiParentConstraintJobBinder<MultiParentConstraintData>
>
{
/// <inheritdoc />
protected override void OnValidate()
{
base.OnValidate();
var weights = m_Data.sourceObjects;
WeightedTransformArray.OnValidate(ref weights);
m_Data.sourceObjects = weights;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8935e03361a14ec4b8edc872f76bc822
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: ca41524ec86f0d84ab5675c9622cc1a2, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,89 @@
namespace UnityEngine.Animations.Rigging
{
/// <summary>
/// The MultiPosition constraint job.
/// </summary>
[System.Serializable]
public struct MultiPositionConstraintData : IAnimationJobData, IMultiPositionConstraintData
{
[SerializeField] Transform m_ConstrainedObject;
[SyncSceneToStream, SerializeField, WeightRange(0f, 1f)] WeightedTransformArray m_SourceObjects;
[SyncSceneToStream, SerializeField] Vector3 m_Offset;
[NotKeyable, SerializeField] Vector3Bool m_ConstrainedAxes;
[NotKeyable, SerializeField] bool m_MaintainOffset;
/// <inheritdoc />
public Transform constrainedObject { get => m_ConstrainedObject; set => m_ConstrainedObject = value; }
/// <inheritdoc />
public WeightedTransformArray sourceObjects
{
get => m_SourceObjects;
set => m_SourceObjects = value;
}
/// <inheritdoc />
public bool maintainOffset { get => m_MaintainOffset; set => m_MaintainOffset = value; }
/// <summary>Post-Translation offset applied to the constrained Transform.</summary>
public Vector3 offset { get => m_Offset; set => m_Offset = value; }
/// <inheritdoc />
public bool constrainedXAxis { get => m_ConstrainedAxes.x; set => m_ConstrainedAxes.x = value; }
/// <inheritdoc />
public bool constrainedYAxis { get => m_ConstrainedAxes.y; set => m_ConstrainedAxes.y = value; }
/// <inheritdoc />
public bool constrainedZAxis { get => m_ConstrainedAxes.z; set => m_ConstrainedAxes.z = value; }
/// <inheritdoc />
string IMultiPositionConstraintData.offsetVector3Property => ConstraintsUtils.ConstructConstraintDataPropertyName(nameof(m_Offset));
/// <inheritdoc />
string IMultiPositionConstraintData.sourceObjectsProperty => ConstraintsUtils.ConstructConstraintDataPropertyName(nameof(m_SourceObjects));
/// <inheritdoc />
bool IAnimationJobData.IsValid()
{
if (m_ConstrainedObject == null || m_SourceObjects.Count == 0)
return false;
foreach (var src in m_SourceObjects)
if (src.transform == null)
return false;
return true;
}
/// <inheritdoc />
void IAnimationJobData.SetDefaultValues()
{
m_ConstrainedObject = null;
m_ConstrainedAxes = new Vector3Bool(true);
m_SourceObjects.Clear();
m_MaintainOffset = false;
m_Offset = Vector3.zero;
}
}
/// <summary>
/// MultiPosition constraint.
/// </summary>
[DisallowMultipleComponent, AddComponentMenu("Animation Rigging/Multi-Position Constraint")]
[HelpURL("https://docs.unity3d.com/Packages/com.unity.animation.rigging@1.3/manual/constraints/MultiPositionConstraint.html")]
public class MultiPositionConstraint : RigConstraint<
MultiPositionConstraintJob,
MultiPositionConstraintData,
MultiPositionConstraintJobBinder<MultiPositionConstraintData>
>
{
/// <inheritdoc />
protected override void OnValidate()
{
base.OnValidate();
var weights = m_Data.sourceObjects;
WeightedTransformArray.OnValidate(ref weights);
m_Data.sourceObjects = weights;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c10bdb03db33fb148b858a4a3b646cea
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: ca41524ec86f0d84ab5675c9622cc1a2, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,91 @@
using System.Collections.Generic;
namespace UnityEngine.Animations.Rigging
{
/// <summary>
/// The MultiReferential constraint data.
/// </summary>
[System.Serializable]
public struct MultiReferentialConstraintData : IAnimationJobData, IMultiReferentialConstraintData
{
[SyncSceneToStream, SerializeField] int m_Driver;
[SyncSceneToStream, SerializeField] List<Transform> m_SourceObjects;
/// <summary>The driver index. This is a value in between 0 and the number of sourceObjects.</summary>
public int driver
{
get => m_Driver;
set => m_Driver = Mathf.Clamp(value, 0, m_SourceObjects.Count - 1);
}
/// <summary>The list of Transforms that are affected by the specified driver.</summary>
public List<Transform> sourceObjects
{
get
{
if (m_SourceObjects == null)
m_SourceObjects = new List<Transform>();
return m_SourceObjects;
}
set
{
m_SourceObjects = value;
m_Driver = Mathf.Clamp(m_Driver, 0, m_SourceObjects.Count - 1);
}
}
/// <inheritdoc />
Transform[] IMultiReferentialConstraintData.sourceObjects => m_SourceObjects.ToArray();
/// <inheritdoc />
int IMultiReferentialConstraintData.driverValue => m_Driver;
/// <inheritdoc />
string IMultiReferentialConstraintData.driverIntProperty => ConstraintsUtils.ConstructConstraintDataPropertyName(nameof(m_Driver));
/// <inheritdoc />
bool IAnimationJobData.IsValid()
{
if (m_SourceObjects.Count < 2)
return false;
foreach (var src in m_SourceObjects)
if (src == null)
return false;
return true;
}
/// <inheritdoc />
void IAnimationJobData.SetDefaultValues()
{
m_Driver = 0;
m_SourceObjects = new List<Transform>();
}
/// <summary>
/// Updates the driver index to match the number of source objects.
/// </summary>
public void UpdateDriver() =>
m_Driver = Mathf.Clamp(m_Driver, 0, m_SourceObjects != null ? m_SourceObjects.Count - 1 : 0);
}
/// <summary>
/// MultiReferential constraint.
/// </summary>
[DisallowMultipleComponent, AddComponentMenu("Animation Rigging/Multi-Referential Constraint")]
[HelpURL("https://docs.unity3d.com/Packages/com.unity.animation.rigging@1.3/manual/constraints/MultiReferentialConstraint.html")]
public class MultiReferentialConstraint : RigConstraint<
MultiReferentialConstraintJob,
MultiReferentialConstraintData,
MultiReferentialConstraintJobBinder<MultiReferentialConstraintData>
>
{
/// <inheritdoc />
protected override void OnValidate()
{
base.OnValidate();
m_Data.UpdateDriver();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b1577d1bce6e9ec47b4c95dd2d94493a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: ca41524ec86f0d84ab5675c9622cc1a2, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,88 @@
namespace UnityEngine.Animations.Rigging
{
/// <summary>
/// The MultiRotation constraint job.
/// </summary>
[System.Serializable]
public struct MultiRotationConstraintData : IAnimationJobData, IMultiRotationConstraintData
{
[SerializeField] Transform m_ConstrainedObject;
[SyncSceneToStream, SerializeField, WeightRange(0f, 1f)] WeightedTransformArray m_SourceObjects;
[SyncSceneToStream, SerializeField] Vector3 m_Offset;
[NotKeyable, SerializeField] Vector3Bool m_ConstrainedAxes;
[NotKeyable, SerializeField] bool m_MaintainOffset;
/// <inheritdoc />
public Transform constrainedObject { get => m_ConstrainedObject; set => m_ConstrainedObject = value; }
/// <inheritdoc />
public WeightedTransformArray sourceObjects
{
get => m_SourceObjects;
set => m_SourceObjects = value;
}
/// <inheritdoc />
public bool maintainOffset { get => m_MaintainOffset; set => m_MaintainOffset = value; }
/// <summary>Post-Rotation offset applied to the constrained Transform.</summary>
public Vector3 offset { get => m_Offset; set => m_Offset = value; }
/// <inheritdoc />
public bool constrainedXAxis { get => m_ConstrainedAxes.x; set => m_ConstrainedAxes.x = value; }
/// <inheritdoc />
public bool constrainedYAxis { get => m_ConstrainedAxes.y; set => m_ConstrainedAxes.y = value; }
/// <inheritdoc />
public bool constrainedZAxis { get => m_ConstrainedAxes.z; set => m_ConstrainedAxes.z = value; }
/// <inheritdoc />
string IMultiRotationConstraintData.offsetVector3Property => ConstraintsUtils.ConstructConstraintDataPropertyName(nameof(m_Offset));
/// <inheritdoc />
string IMultiRotationConstraintData.sourceObjectsProperty => ConstraintsUtils.ConstructConstraintDataPropertyName(nameof(m_SourceObjects));
/// <inheritdoc />
bool IAnimationJobData.IsValid()
{
if (m_ConstrainedObject == null || m_SourceObjects.Count == 0)
return false;
foreach (var src in m_SourceObjects)
if (src.transform == null)
return false;
return true;
}
/// <inheritdoc />
void IAnimationJobData.SetDefaultValues()
{
m_ConstrainedObject = null;
m_ConstrainedAxes = new Vector3Bool(true);
m_SourceObjects.Clear();
m_MaintainOffset = false;
m_Offset = Vector3.zero;
}
}
/// <summary>
/// MultiRotation constraint.
/// </summary>
[DisallowMultipleComponent, AddComponentMenu("Animation Rigging/Multi-Rotation Constraint")]
[HelpURL("https://docs.unity3d.com/Packages/com.unity.animation.rigging@1.3/manual/constraints/MultiRotationConstraint.html")]
public class MultiRotationConstraint : RigConstraint<
MultiRotationConstraintJob,
MultiRotationConstraintData,
MultiRotationConstraintJobBinder<MultiRotationConstraintData>
>
{
/// <inheritdoc />
protected override void OnValidate()
{
base.OnValidate();
var weights = m_Data.sourceObjects;
WeightedTransformArray.OnValidate(ref weights);
m_Data.sourceObjects = weights;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fdb90b913935e644baaa86c076d788e0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: ca41524ec86f0d84ab5675c9622cc1a2, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,95 @@
namespace UnityEngine.Animations.Rigging
{
/// <summary>
/// The OverrideTransform constraint data.
/// </summary>
[System.Serializable]
public struct OverrideTransformData : IAnimationJobData, IOverrideTransformData
{
/// <summary>
/// The override space controls how the override source Transform
/// is copied unto constrained Transform.
/// </summary>
[System.Serializable]
public enum Space
{
/// <summary>Copy override world TR components into world TR components of the constrained Transform.</summary>
World = OverrideTransformJob.Space.World,
/// <summary>Copy override local TR components into local TR components of the constrained Transform.</summary>
Local = OverrideTransformJob.Space.Local,
/// <summary>Add override local TR components to local TR components of the constrained Transform. </summary>
Pivot = OverrideTransformJob.Space.Pivot
}
[SerializeField] Transform m_ConstrainedObject;
[SyncSceneToStream, SerializeField] Transform m_OverrideSource;
[SyncSceneToStream, SerializeField] Vector3 m_OverridePosition;
[SyncSceneToStream, SerializeField] Vector3 m_OverrideRotation;
[SyncSceneToStream, SerializeField, Range(0f, 1f)] float m_PositionWeight;
[SyncSceneToStream, SerializeField, Range(0f, 1f)] float m_RotationWeight;
[NotKeyable, SerializeField] Space m_Space;
/// <inheritdoc />
public Transform constrainedObject { get => m_ConstrainedObject; set => m_ConstrainedObject = value; }
/// <inheritdoc />
public Transform sourceObject { get => m_OverrideSource; set => m_OverrideSource = value; }
/// <summary>The override space.</summary>
public Space space { get => m_Space; set => m_Space = value; }
/// <summary>The override position. This is taken into account only if sourceObject is null.</summary>
public Vector3 position { get => m_OverridePosition; set => m_OverridePosition = value; }
/// <summary>The override rotation. This is taken into account only if sourceObject is null.</summary>
public Vector3 rotation { get => m_OverrideRotation; set => m_OverrideRotation = value; }
/// <summary>The weight for which override position has an effect on constrained Transform. This is a value in between 0 and 1.</summary>
public float positionWeight { get => m_PositionWeight; set => m_PositionWeight = Mathf.Clamp01(value); }
/// <summary>The weight for which override rotation has an effect on constrained Transform. This is a value in between 0 and 1.</summary>
public float rotationWeight { get => m_RotationWeight; set => m_RotationWeight = Mathf.Clamp01(value); }
/// <inheritdoc />
int IOverrideTransformData.space => (int)m_Space;
/// <inheritdoc />
string IOverrideTransformData.positionWeightFloatProperty => ConstraintsUtils.ConstructConstraintDataPropertyName(nameof(m_PositionWeight));
/// <inheritdoc />
string IOverrideTransformData.rotationWeightFloatProperty => ConstraintsUtils.ConstructConstraintDataPropertyName(nameof(m_RotationWeight));
/// <inheritdoc />
string IOverrideTransformData.positionVector3Property => ConstraintsUtils.ConstructConstraintDataPropertyName(nameof(m_OverridePosition));
/// <inheritdoc />
string IOverrideTransformData.rotationVector3Property => ConstraintsUtils.ConstructConstraintDataPropertyName(nameof(m_OverrideRotation));
/// <inheritdoc />
bool IAnimationJobData.IsValid() => m_ConstrainedObject != null;
/// <inheritdoc />
void IAnimationJobData.SetDefaultValues()
{
m_ConstrainedObject = null;
m_OverrideSource = null;
m_OverridePosition = Vector3.zero;
m_OverrideRotation = Vector3.zero;
m_Space = Space.Pivot;
m_PositionWeight = 1f;
m_RotationWeight = 1f;
}
}
/// <summary>
/// OverrideTransform constraint.
/// </summary>
[DisallowMultipleComponent, AddComponentMenu("Animation Rigging/Override Transform")]
[HelpURL("https://docs.unity3d.com/Packages/com.unity.animation.rigging@1.3/manual/constraints/OverrideTransform.html")]
public class OverrideTransform : RigConstraint<
OverrideTransformJob,
OverrideTransformData,
OverrideTransformJobBinder<OverrideTransformData>
>
{
/// <inheritdoc />
protected override void OnValidate()
{
base.OnValidate();
m_Data.positionWeight = Mathf.Clamp01(m_Data.positionWeight);
m_Data.rotationWeight = Mathf.Clamp01(m_Data.rotationWeight);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cf219326d2292de48a0c671da18d402b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: ca41524ec86f0d84ab5675c9622cc1a2, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,53 @@
namespace UnityEngine.Animations.Rigging
{
/// <summary>
/// The TwistChain constraint data.
/// </summary>
[System.Serializable]
public struct TwistChainConstraintData : IAnimationJobData, ITwistChainConstraintData
{
[SerializeField] private Transform m_Root;
[SerializeField] private Transform m_Tip;
[SyncSceneToStream, SerializeField] private Transform m_RootTarget;
[SyncSceneToStream, SerializeField] private Transform m_TipTarget;
[SerializeField] private AnimationCurve m_Curve;
/// <inheritdoc />
public Transform root { get => m_Root; set => m_Root = value; }
/// <inheritdoc />
public Transform tip { get => m_Tip; set => m_Tip = value; }
/// <inheritdoc />
public Transform rootTarget { get => m_RootTarget; set => m_RootTarget = value; }
/// <inheritdoc />
public Transform tipTarget { get => m_TipTarget; set => m_TipTarget = value; }
/// <inheritdoc />
public AnimationCurve curve { get => m_Curve; set => m_Curve = value; }
/// <inheritdoc />
bool IAnimationJobData.IsValid() => !(root == null || tip == null || !tip.IsChildOf(root) || rootTarget == null || tipTarget == null || curve == null);
/// <inheritdoc />
void IAnimationJobData.SetDefaultValues()
{
root = tip = rootTarget = tipTarget = null;
curve = AnimationCurve.Linear(0f, 0f, 1f, 1f);
}
}
/// <summary>
/// TwistChain constraint
/// </summary>
[DisallowMultipleComponent, AddComponentMenu("Animation Rigging/Twist Chain Constraint")]
[HelpURL("https://docs.unity3d.com/Packages/com.unity.animation.rigging@1.3/manual/constraints/TwistChainConstraint.html")]
public class TwistChainConstraint : RigConstraint<
TwistChainConstraintJob,
TwistChainConstraintData,
TwistChainConstraintJobBinder<TwistChainConstraintData>
>
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: afb1fbe61e5894c96b30693270a4db99
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: ca41524ec86f0d84ab5675c9622cc1a2, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,101 @@
namespace UnityEngine.Animations.Rigging
{
/// <summary>
/// The TwistCorrection constraint data.
/// </summary>
[System.Serializable]
public struct TwistCorrectionData : IAnimationJobData, ITwistCorrectionData
{
/// <summary>
/// Axis type for TwistCorrection.
/// </summary>
public enum Axis
{
/// <summary>X Axis.</summary>
X,
/// <summary>Y Axis.</summary>
Y,
/// <summary>Z Axis.</summary>
Z
}
[SyncSceneToStream, SerializeField] Transform m_Source;
[NotKeyable, SerializeField] Axis m_TwistAxis;
[SyncSceneToStream, SerializeField, WeightRange(-1f, 1f)] WeightedTransformArray m_TwistNodes;
/// <summary>The source Transform that influences the twist nodes.</summary>
public Transform sourceObject { get => m_Source; set => m_Source = value; }
/// <inheritdoc />
public WeightedTransformArray twistNodes
{
get => m_TwistNodes;
set => m_TwistNodes = value;
}
/// <inheritdoc />
public Axis twistAxis { get => m_TwistAxis; set => m_TwistAxis = value; }
/// <inheritdoc />
Transform ITwistCorrectionData.source => m_Source;
/// <inheritdoc />
Vector3 ITwistCorrectionData.twistAxis => Convert(m_TwistAxis);
/// <inheritdoc />
string ITwistCorrectionData.twistNodesProperty => ConstraintsUtils.ConstructConstraintDataPropertyName(nameof(m_TwistNodes));
static Vector3 Convert(Axis axis)
{
if (axis == Axis.X)
return Vector3.right;
if (axis == Axis.Y)
return Vector3.up;
return Vector3.forward;
}
/// <inheritdoc />
bool IAnimationJobData.IsValid()
{
if (m_Source == null)
return false;
for (int i = 0; i < m_TwistNodes.Count; ++i)
if (m_TwistNodes[i].transform == null)
return false;
return true;
}
/// <inheritdoc />
void IAnimationJobData.SetDefaultValues()
{
m_Source = null;
m_TwistAxis = Axis.Z;
m_TwistNodes.Clear();
}
}
/// <summary>
/// TwistCorrection constraint.
/// </summary>
[DisallowMultipleComponent, AddComponentMenu("Animation Rigging/Twist Correction")]
[HelpURL("https://docs.unity3d.com/Packages/com.unity.animation.rigging@1.3/manual/constraints/TwistCorrection.html")]
public class TwistCorrection : RigConstraint<
TwistCorrectionJob,
TwistCorrectionData,
TwistCorrectionJobBinder<TwistCorrectionData>
>
{
/// <inheritdoc />
protected override void OnValidate()
{
base.OnValidate();
var weights = m_Data.twistNodes;
WeightedTransformArray.OnValidate(ref weights, -1f, 1f);
m_Data.twistNodes = weights;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9a4834896bd86034eb2aacc65cb0c593
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: ca41524ec86f0d84ab5675c9622cc1a2, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,91 @@
namespace UnityEngine.Animations.Rigging
{
/// <summary>
/// The TwoBoneIK constraint data.
/// </summary>
[System.Serializable]
public struct TwoBoneIKConstraintData : IAnimationJobData, ITwoBoneIKConstraintData
{
[SerializeField] Transform m_Root;
[SerializeField] Transform m_Mid;
[SerializeField] Transform m_Tip;
[SyncSceneToStream, SerializeField] Transform m_Target;
[SyncSceneToStream, SerializeField] Transform m_Hint;
[SyncSceneToStream, SerializeField, Range(0f, 1f)] float m_TargetPositionWeight;
[SyncSceneToStream, SerializeField, Range(0f, 1f)] float m_TargetRotationWeight;
[SyncSceneToStream, SerializeField, Range(0f, 1f)] float m_HintWeight;
[NotKeyable, SerializeField] bool m_MaintainTargetPositionOffset;
[NotKeyable, SerializeField] bool m_MaintainTargetRotationOffset;
/// <inheritdoc />
public Transform root { get => m_Root; set => m_Root = value; }
/// <inheritdoc />
public Transform mid { get => m_Mid; set => m_Mid = value; }
/// <inheritdoc />
public Transform tip { get => m_Tip; set => m_Tip = value; }
/// <inheritdoc />
public Transform target { get => m_Target; set => m_Target = value; }
/// <inheritdoc />
public Transform hint { get => m_Hint; set => m_Hint = value; }
/// <summary>The weight for which target position has an effect on IK calculations. This is a value in between 0 and 1.</summary>
public float targetPositionWeight { get => m_TargetPositionWeight; set => m_TargetPositionWeight = Mathf.Clamp01(value); }
/// <summary>The weight for which target rotation has an effect on IK calculations. This is a value in between 0 and 1.</summary>
public float targetRotationWeight { get => m_TargetRotationWeight; set => m_TargetRotationWeight = Mathf.Clamp01(value); }
/// <summary>The weight for which hint transform has an effect on IK calculations. This is a value in between 0 and 1.</summary>
public float hintWeight { get => m_HintWeight; set => m_HintWeight = Mathf.Clamp01(value); }
/// <inheritdoc />
public bool maintainTargetPositionOffset { get => m_MaintainTargetPositionOffset; set => m_MaintainTargetPositionOffset = value; }
/// <inheritdoc />
public bool maintainTargetRotationOffset { get => m_MaintainTargetRotationOffset; set => m_MaintainTargetRotationOffset = value; }
/// <inheritdoc />
string ITwoBoneIKConstraintData.targetPositionWeightFloatProperty => ConstraintsUtils.ConstructConstraintDataPropertyName(nameof(m_TargetPositionWeight));
/// <inheritdoc />
string ITwoBoneIKConstraintData.targetRotationWeightFloatProperty => ConstraintsUtils.ConstructConstraintDataPropertyName(nameof(m_TargetRotationWeight));
/// <inheritdoc />
string ITwoBoneIKConstraintData.hintWeightFloatProperty => ConstraintsUtils.ConstructConstraintDataPropertyName(nameof(m_HintWeight));
/// <inheritdoc />
bool IAnimationJobData.IsValid() => (m_Tip != null && m_Mid != null && m_Root != null && m_Target != null && m_Tip.IsChildOf(m_Mid) && m_Mid.IsChildOf(m_Root));
/// <inheritdoc />
void IAnimationJobData.SetDefaultValues()
{
m_Root = null;
m_Mid = null;
m_Tip = null;
m_Target = null;
m_Hint = null;
m_TargetPositionWeight = 1f;
m_TargetRotationWeight = 1f;
m_HintWeight = 1f;
m_MaintainTargetPositionOffset = false;
m_MaintainTargetRotationOffset = false;
}
}
/// <summary>
/// TwoBoneIK constraint
/// </summary>
[DisallowMultipleComponent, AddComponentMenu("Animation Rigging/Two Bone IK Constraint")]
[HelpURL("https://docs.unity3d.com/Packages/com.unity.animation.rigging@1.3/manual/constraints/TwoBoneIKConstraint.html")]
public class TwoBoneIKConstraint : RigConstraint<
TwoBoneIKConstraintJob,
TwoBoneIKConstraintData,
TwoBoneIKConstraintJobBinder<TwoBoneIKConstraintData>
>
{
/// <inheritdoc />
protected override void OnValidate()
{
base.OnValidate();
m_Data.hintWeight = Mathf.Clamp01(m_Data.hintWeight);
m_Data.targetPositionWeight = Mathf.Clamp01(m_Data.targetPositionWeight);
m_Data.targetRotationWeight = Mathf.Clamp01(m_Data.targetRotationWeight);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: aeda7bfbf984f2a4da5ab4b8967b115d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: ca41524ec86f0d84ab5675c9622cc1a2, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,51 @@
namespace UnityEngine.Animations.Rigging
{
/// <summary>
/// This interface is used to represent all constraints classes.
/// </summary>
public interface IRigConstraint
{
/// <summary>
/// Retrieves the constraint valid state.
/// </summary>
/// <returns>Returns true if constraint data can be successfully evaluated. Returns false otherwise.</returns>
bool IsValid();
/// <summary>
/// Creates the animation job for this constraint.
/// </summary>
/// <param name="animator">The animated hierarchy Animator component.</param>
/// <returns>Returns the newly instantiated job.</returns>
IAnimationJob CreateJob(Animator animator);
/// <summary>
/// Updates the specified job data.
/// </summary>
/// <param name="job">The job to update.</param>
void UpdateJob(IAnimationJob job);
/// <summary>
/// Frees the specified job memory.
/// </summary>
/// <param name="job">The job to destroy.</param>
void DestroyJob(IAnimationJob job);
/// <summary>
/// The data container for the constraint.
/// </summary>
IAnimationJobData data { get; }
/// <summary>
/// The job binder for the constraint.
/// </summary>
IAnimationJobBinder binder { get; }
/// <summary>
/// The component for the constraint.
/// </summary>
Component component { get; }
/// <summary>
/// The constraint weight. This is a value in between 0 and 1.
/// </summary>
float weight { get; set; }
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7fee10ab894af4417bc991ed3a2fedcb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,42 @@
namespace UnityEngine.Animations.Rigging
{
/// <summary>
/// Interface for rig layers.
/// </summary>
public interface IRigLayer
{
/// <summary>The Rig associated to the IRigLayer</summary>
Rig rig { get; }
/// <summary>The list of constraints associated with the IRigLayer.</summary>
IRigConstraint[] constraints { get; }
/// <summary>The list of jobs built from constraints associated with the IRigLayer.</summary>
IAnimationJob[] jobs { get; }
/// <summary>The active state. True if the IRigLayer is active, false otherwise.</summary>
bool active { get; }
/// <summary>The IRigLayer name.</summary>
string name { get; }
/// <summary>
/// Initializes the IRigLayer
/// </summary>
/// <param name="animator">The Animator used to animate the IRigLayer constraints.</param>
/// <returns>True if IRigLayer was initialized properly, false otherwise.</returns>
bool Initialize(Animator animator);
/// <summary>
/// Updates the IRigLayer jobs.
/// </summary>
void Update();
/// <summary>
/// Resets the IRigLayer.
/// </summary>
void Reset();
/// <summary>
/// Queries whether the IRigLayer is valid.
/// </summary>
/// <returns>True if IRigLayer is valid, false otherwise.</returns>
bool IsValid();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 74107573bb9a243fb90014afa5c417d2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,96 @@
namespace UnityEngine.Animations.Rigging
{
/// <summary>
/// Use this class to define an override rig constraint on another rig constraint.
/// While the overriden constraint data remains the same, the job is overriden.
/// </summary>
/// <typeparam name="TConstraint">The base constraint to override</typeparam>
/// <typeparam name="TJob">The override job</typeparam>
/// <typeparam name="TData">The constraint data</typeparam>
/// <typeparam name="TBinder">The override constraint job binder</typeparam>
public class OverrideRigConstraint<TConstraint, TJob, TData, TBinder> : IRigConstraint
where TConstraint : MonoBehaviour, IRigConstraint
where TJob : struct, IWeightedAnimationJob
where TData : struct, IAnimationJobData
where TBinder : AnimationJobBinder<TJob, TData>, new()
{
/// <summary>
/// The base constraint.
/// </summary>
[SerializeField]
protected TConstraint m_Constraint;
static readonly TBinder s_Binder = new TBinder();
/// <summary>
/// Constructor
/// </summary>
/// <param name="baseConstraint">The constraint to override.</param>
public OverrideRigConstraint(TConstraint baseConstraint)
{
m_Constraint = baseConstraint;
}
/// <summary>
/// Creates the animation job for this constraint.
/// </summary>
/// <param name="animator">The animated hierarchy Animator component.</param>
/// <returns>Returns the newly instantiated job.</returns>
public IAnimationJob CreateJob(Animator animator)
{
IAnimationJobBinder binder = (IAnimationJobBinder)s_Binder;
TJob job = (TJob)binder.Create(animator, m_Constraint.data, m_Constraint);
// Bind constraint job weight property
job.jobWeight = FloatProperty.BindCustom(
animator,
ConstraintsUtils.ConstructCustomPropertyName(m_Constraint, ConstraintProperties.s_Weight)
);
return job;
}
/// <summary>
/// Frees the specified job memory.
/// </summary>
/// <param name="job"></param>
public void DestroyJob(IAnimationJob job) => s_Binder.Destroy((TJob)job);
/// <summary>
/// Updates the specified job data.
/// </summary>
/// <param name="job"></param>
public void UpdateJob(IAnimationJob job)
{
IAnimationJobBinder binder = (IAnimationJobBinder)s_Binder;
binder.Update(job, m_Constraint.data);
}
/// <summary>
/// Retrieves the constraint valid state.
/// </summary>
/// <returns>Returns true if constraint data can be successfully evaluated. Returns false otherwise.</returns>
public bool IsValid()
{
return m_Constraint.IsValid();
}
/// <summary>
/// The job binder for the constraint.
/// </summary>
IAnimationJobBinder IRigConstraint.binder => s_Binder;
/// <summary>
/// The data container for the constraint.
/// </summary>
IAnimationJobData IRigConstraint.data => m_Constraint.data;
/// <summary>
/// The component for the constraint.
/// </summary>
Component IRigConstraint.component => m_Constraint.component;
/// <summary>
/// The constraint weight. This is a value between 0 and 1.
/// </summary>
public float weight { get => m_Constraint.weight; set => m_Constraint.weight = value; }
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 08f245f2f5b21437e9f88d72a8cef6a1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,115 @@
using System;
using UnityEngine.Serialization;
namespace UnityEngine.Animations.Rigging
{
/// <summary>
/// The OverrideRigLayer is used to override constraints normally evaluated by
/// a specified Rig component.
/// </summary>
[Serializable]
public class OverrideRigLayer : IRigLayer
{
[SerializeField] [FormerlySerializedAs("rig")] private Rig m_Rig;
[SerializeField] [FormerlySerializedAs("active")] private bool m_Active = true;
private IRigConstraint[] m_Constraints;
private IAnimationJob[] m_Jobs;
/// <summary>The Rig associated to the OverrideRigLayer</summary>
public Rig rig { get => m_Rig; private set => m_Rig = value; }
/// <summary>The active state. True if the OverrideRigLayer is active, false otherwise.</summary>
public bool active { get => m_Active; set => m_Active = value; }
/// <summary>The OverrideRigLayer name.</summary>
public string name { get => (rig != null ? rig.gameObject.name : "no-name"); }
/// <summary>The list of constraints associated with the OverrideRigLayer.</summary>
public IRigConstraint[] constraints { get => isInitialized ? m_Constraints : null; }
/// <summary>The list of jobs built from constraints associated with the OverrideRigLayer.</summary>
public IAnimationJob[] jobs { get => isInitialized ? m_Jobs : null; }
/// <summary>Returns true if OverrideRigLayer was initialized or false otherwise.</summary>
/// <seealso cref="RigLayer.Initialize"/>
public bool isInitialized { get; private set; }
/// <summary>
/// Constructor.
/// </summary>
/// <param name="rig">The rig represented by this override rig layer.</param>
/// <param name="constraints">The constraints that override those of the rig.</param>
/// <param name="active">The active state of the override rig layer.</param>
public OverrideRigLayer(Rig rig, IRigConstraint[] constraints, bool active = true)
{
this.rig = rig;
this.active = active;
m_Constraints = constraints;
}
/// <summary>
/// Initializes the OverrideRigLayer. This will create animation jobs using
/// the rig constraints provided to the OverrideRigLayer.
/// </summary>
/// <param name="animator">The Animator used to animate the RigLayer constraints.</param>
/// <returns>True if RigLayer was initialized properly, false otherwise.</returns>
public bool Initialize(Animator animator)
{
if (isInitialized)
return true;
if (rig == null)
return false;
if (m_Constraints == null || m_Constraints.Length == 0)
return false;
m_Jobs = new IAnimationJob[m_Constraints.Length];
for (int i = 0; i < m_Constraints.Length; ++i)
{
m_Jobs[i] = m_Constraints[i].CreateJob(animator);
}
return isInitialized = true;
}
/// <summary>
/// Updates the OverrideRigLayer jobs. This is called during the Update loop before
/// the Animator evaluates the PlayableGraph.
/// </summary>
public void Update()
{
if (!isInitialized)
return;
for (int i = 0; i < m_Constraints.Length; ++i)
{
m_Constraints[i].UpdateJob(m_Jobs[i]);
}
}
/// <summary>
/// Resets the OverrideRigLayer. This will destroy the animation jobs and
/// free up memory.
/// </summary>
public void Reset()
{
if (!isInitialized)
return;
for (int i = 0, count = m_Constraints.Length; i < count; ++i)
{
m_Constraints[i].DestroyJob(m_Jobs[i]);
}
m_Constraints = null;
m_Jobs = null;
isInitialized = false;
}
/// <summary>
/// Queries whether the OverrideRigLayer is valid.
/// </summary>
/// <returns>True if OverrideRigLayer is valid, false otherwise.</returns>
public bool IsValid() => rig != null && isInitialized;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4b4df322b421941b2a0ffa8b0a9847e0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,46 @@
using System.Collections.Generic;
namespace UnityEngine.Animations.Rigging
{
/// <summary>
/// The Rig component is used to group constraints under its GameObject local hierarchy.
/// </summary>
[DisallowMultipleComponent, AddComponentMenu("Animation Rigging/Setup/Rig")]
[HelpURL("https://docs.unity3d.com/Packages/com.unity.animation.rigging@1.3/manual/RiggingWorkflow.html#rig-component")]
public class Rig : MonoBehaviour, IRigEffectorHolder
{
[SerializeField, Range(0f, 1f)]
private float m_Weight = 1f;
/// <summary>The weight given to this rig and its associated constraints. This is a value in between 0 and 1.</summary>
public float weight { get => m_Weight; set => m_Weight = Mathf.Clamp01(value); }
[SerializeField] private List<RigEffectorData> m_Effectors = new List<RigEffectorData>();
#if UNITY_EDITOR
/// <inheritdoc />
public IEnumerable<RigEffectorData> effectors { get => m_Effectors; }
/// <inheritdoc />
public void AddEffector(Transform transform, RigEffectorData.Style style)
{
var effector = new RigEffectorData();
effector.Initialize(transform, style);
m_Effectors.Add(effector);
}
/// <inheritdoc />
public void RemoveEffector(Transform transform)
{
m_Effectors.RemoveAll((RigEffectorData data) => data.transform == transform);
}
/// <inheritdoc />
public bool ContainsEffector(Transform transform)
{
return m_Effectors.Exists((RigEffectorData data) => data.transform == transform);
}
#endif
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 70b342d8ce5c2fd48b8fa3147d48d1d1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: ca41524ec86f0d84ab5675c9622cc1a2, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,349 @@
using System.Collections.Generic;
using UnityEngine.Playables;
namespace UnityEngine.Animations.Rigging
{
/// <summary>
/// RigBuilder is the root component that holds the Rigs that create an Animation Rigging hierarchy.
/// Its purpose is to create the PlayableGraph that will be used in the associated Animator component to animate
/// a character with constraints.
/// </summary>
[RequireComponent(typeof(Animator))]
[DisallowMultipleComponent, ExecuteInEditMode, AddComponentMenu("Animation Rigging/Setup/Rig Builder")]
[HelpURL("https://docs.unity3d.com/Packages/com.unity.animation.rigging@1.3/manual/RiggingWorkflow.html#rig-builder-component")]
public class RigBuilder : MonoBehaviour, IAnimationWindowPreview, IRigEffectorHolder
{
[SerializeField] private List<RigLayer> m_RigLayers;
private IRigLayer[] m_RuntimeRigLayers;
private SyncSceneToStreamLayer m_SyncSceneToStreamLayer;
[SerializeField] private List<RigEffectorData> m_Effectors = new List<RigEffectorData>();
private bool m_IsInPreview;
#if UNITY_EDITOR
/// <inheritdoc />
public IEnumerable<RigEffectorData> effectors { get => m_Effectors; }
#endif
/// <summary>
/// Delegate function that covers a RigBuilder calling OnEnable.
/// </summary>
/// <param name="rigBuilder">The RigBuilder component</param>
public delegate void OnAddRigBuilderCallback(RigBuilder rigBuilder);
/// <summary>
/// Delegate function that covers a RigBuilder calling OnDisable.
/// </summary>
/// <param name="rigBuilder">The RigBuilder component</param>
public delegate void OnRemoveRigBuilderCallback(RigBuilder rigBuilder);
/// <summary>
/// Notification callback that is sent whenever a RigBuilder calls OnEnable.
/// </summary>
public static OnAddRigBuilderCallback onAddRigBuilder;
/// <summary>
/// Notification callback that is sent whenever a RigBuilder calls OnDisable.
/// </summary>
public static OnRemoveRigBuilderCallback onRemoveRigBuilder;
void OnEnable()
{
// Build runtime data.
if (Application.isPlaying)
Build();
onAddRigBuilder?.Invoke(this);
}
void OnDisable()
{
// Clear runtime data.
if (Application.isPlaying)
Clear();
onRemoveRigBuilder?.Invoke(this);
}
void OnDestroy()
{
Clear();
}
/// <summary>
/// Updates the RigBuilder layers and evaluates the PlayableGraph manually.
/// </summary>
/// <param name="deltaTime">The time in seconds by which to advance the RigBuilder PlayableGraph.</param>
/// <example>
/// Manually evaluate the RigBuilder in LateUpdate.
/// <code source="../../DocCodeExamples/CustomRigBuilderEvaluator.cs" language="csharp" region="custom-rig-builder-evaluator"/>
/// </example>
public void Evaluate(float deltaTime)
{
if (!graph.IsValid())
return;
SyncLayers();
graph.Evaluate(deltaTime);
}
void Update()
{
if (!graph.IsValid())
return;
SyncLayers();
}
/// <summary>
/// Synchronizes rigs and constraints with scene values.
/// This must be called before evaluating the PlayableGraph.
/// </summary>
/// <seealso cref="RigBuilder.Build(PlayableGraph)"/>
/// <seealso cref="SyncSceneToStreamAttribute"/>
/// <seealso cref="AnimationJobBinder{TJob,TData}.Update"/>
/// <example>
/// Synchronizing layers before evaluating a PlayableGraph created
/// outside the RigBuilder in LateUpdate.
/// <code source="../../DocCodeExamples/CustomPlayableGraphEvaluator.cs" language="csharp" region="custom-playable-graph-evaluator"/>
/// </example>
public void SyncLayers()
{
if (m_RuntimeRigLayers == null)
return;
syncSceneToStreamLayer.Update(m_RuntimeRigLayers);
for (int i = 0, count = m_RuntimeRigLayers.Length; i < count; ++i)
{
if (m_RuntimeRigLayers[i].IsValid() && m_RuntimeRigLayers[i].active)
m_RuntimeRigLayers[i].Update();
}
}
/// <summary>
/// Builds the RigBuilder PlayableGraph.
/// </summary>
/// <returns>Returns true if the RigBuilder has created a valid PlayableGraph. Returns false otherwise.</returns>
public bool Build()
{
if (m_IsInPreview)
return false;
Clear();
var animator = GetComponent<Animator>();
if (animator == null || layers.Count == 0)
return false;
// Make a copy of the layers list.
m_RuntimeRigLayers = layers.ToArray();
graph = RigBuilderUtils.BuildPlayableGraph(animator, m_RuntimeRigLayers, syncSceneToStreamLayer);
if (!graph.IsValid())
return false;
graph.Play();
return true;
}
/// <summary>
/// Builds the RigBuilder playable nodes in an external PlayableGraph.
/// </summary>
/// <param name="graph">Destination PlayableGraph.</param>
/// <returns>Returns true if the RigBuilder has created Playable nodes. Returns false otherwise.</returns>
public bool Build(PlayableGraph graph)
{
if (m_IsInPreview)
return false;
Clear();
var animator = GetComponent<Animator>();
if (animator == null || layers.Count == 0)
return false;
// Make a copy of the layers list.
m_RuntimeRigLayers = layers.ToArray();
RigBuilderUtils.BuildPlayableGraph(graph, animator, m_RuntimeRigLayers, syncSceneToStreamLayer);
return true;
}
/// <summary>
/// Destroys the RigBuilder PlayableGraph and frees associated RigLayers memory.
/// </summary>
public void Clear()
{
if (m_IsInPreview)
return;
if (graph.IsValid())
graph.Destroy();
if (m_RuntimeRigLayers != null)
{
foreach (var layer in m_RuntimeRigLayers)
layer.Reset();
m_RuntimeRigLayers = null;
}
syncSceneToStreamLayer.Reset();
}
//
// IAnimationWindowPreview methods implementation
//
/// <summary>Notification callback when the animation previewer starts previewing an AnimationClip.</summary>
/// <remarks>This is called by the Animation Window or the Timeline Editor.</remarks>
public void StartPreview()
{
m_IsInPreview = true;
if (!enabled)
return;
// Make a copy of the layer list if it doesn't already exist.
if (m_RuntimeRigLayers == null)
m_RuntimeRigLayers = layers.ToArray();
var animator = GetComponent<Animator>();
if (animator != null)
{
foreach (var layer in m_RuntimeRigLayers)
{
layer.Initialize(animator);
}
}
}
/// <summary>Notification callback when the animation previewer stops previewing an AnimationClip.</summary>
/// <remarks>This is called by the Animation Window or the Timeline Editor.</remarks>
public void StopPreview()
{
m_IsInPreview = false;
if (!enabled)
return;
if (Application.isPlaying)
return;
Clear();
}
/// <summary>Notification callback when the animation previewer updates its PlayableGraph before sampling an AnimationClip.</summary>
/// <remarks>This is called by the Animation Window or the Timeline Editor.</remarks>
/// <param name="graph">The animation previewer PlayableGraph</param>
public void UpdatePreviewGraph(PlayableGraph graph)
{
if (!enabled)
return;
if (!graph.IsValid() || m_RuntimeRigLayers == null)
return;
syncSceneToStreamLayer.Update(m_RuntimeRigLayers);
foreach (var layer in m_RuntimeRigLayers)
{
if (layer.IsValid() && layer.active)
layer.Update();
}
}
/// <summary>
/// Appends custom Playable nodes to the animation previewer PlayableGraph.
/// </summary>
/// <param name="graph">The animation previewer PlayableGraph</param>
/// <param name="inputPlayable">The current root of the PlayableGraph</param>
/// <returns></returns>
public Playable BuildPreviewGraph(PlayableGraph graph, Playable inputPlayable)
{
if (!enabled)
return inputPlayable;
if (m_RuntimeRigLayers == null)
StartPreview();
var animator = GetComponent<Animator>();
if (animator == null || m_RuntimeRigLayers == null || m_RuntimeRigLayers.Length == 0)
return inputPlayable;
var playableChains = RigBuilderUtils.BuildPlayables(animator, graph, m_RuntimeRigLayers, syncSceneToStreamLayer);
foreach(var chain in playableChains)
{
if (chain.playables == null || chain.playables.Length == 0)
continue;
chain.playables[0].AddInput(inputPlayable, 0, 1);
inputPlayable = chain.playables[chain.playables.Length - 1];
}
return inputPlayable;
}
#if UNITY_EDITOR
/// <inheritdoc />
public void AddEffector(Transform transform, RigEffectorData.Style style)
{
var effector = new RigEffectorData();
effector.Initialize(transform, style);
m_Effectors.Add(effector);
}
/// <inheritdoc />
public void RemoveEffector(Transform transform)
{
m_Effectors.RemoveAll((RigEffectorData data) => data.transform == transform);
}
/// <inheritdoc />
public bool ContainsEffector(Transform transform)
{
return m_Effectors.Exists((RigEffectorData data) => data.transform == transform);
}
#endif
/// <summary>
/// Returns a list of RigLayer associated to this RigBuilder.
/// </summary>
public List<RigLayer> layers
{
get
{
if (m_RigLayers == null)
m_RigLayers = new List<RigLayer>();
return m_RigLayers;
}
set => m_RigLayers = value;
}
private SyncSceneToStreamLayer syncSceneToStreamLayer
{
get
{
if (m_SyncSceneToStreamLayer == null)
m_SyncSceneToStreamLayer = new SyncSceneToStreamLayer();
return m_SyncSceneToStreamLayer;
}
set => m_SyncSceneToStreamLayer = value;
}
/// <summary>
/// Retrieves the PlayableGraph created by this RigBuilder.
/// </summary>
public PlayableGraph graph { get; private set; }
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fff0960ef4ea6e04eac66b4a7fd2189d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: ca41524ec86f0d84ab5675c9622cc1a2, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,101 @@
using System;
using System.Collections.Generic;
using UnityEngine.Experimental.Animations;
using UnityEngine.Playables;
namespace UnityEngine.Animations.Rigging
{
internal static class RigBuilderUtils
{
public struct PlayableChain
{
public string name;
public Playable[] playables;
public bool IsValid() => playables != null && playables.Length > 0;
}
private static readonly ushort k_AnimationOutputPriority = 1000;
public static Playable[] BuildRigPlayables(PlayableGraph graph, IRigLayer layer)
{
if (layer == null || layer.jobs == null || layer.jobs.Length == 0)
return null;
var count = layer.jobs.Length;
var playables = new Playable[count];
for (int i = 0; i < count; ++i)
{
var binder = layer.constraints[i].binder;
playables[i] = binder.CreatePlayable(graph, layer.jobs[i]);
}
// Connect rig playables serially
for (int i = 1; i < count; ++i)
playables[i].AddInput(playables[i - 1], 0, 1);
return playables;
}
public static IEnumerable<PlayableChain> BuildPlayables(Animator animator, PlayableGraph graph, IList<IRigLayer> layers, SyncSceneToStreamLayer syncSceneToStreamLayer)
{
var playableChains = new PlayableChain[layers.Count + 1];
// Create all rig layers
int index = 1;
foreach (var layer in layers)
{
var chain = new PlayableChain();
chain.name = layer.name;
if (layer.Initialize(animator))
chain.playables = BuildRigPlayables(graph, layer);
playableChains[index++] = chain;
}
// Create sync to stream job with all rig references
if (syncSceneToStreamLayer.Initialize(animator, layers) && syncSceneToStreamLayer.IsValid())
{
var chain = new PlayableChain();
chain.name = "syncSceneToStream";
chain.playables = new Playable[1] {RigUtils.syncSceneToStreamBinder.CreatePlayable(graph, syncSceneToStreamLayer.job)};
playableChains[0] = chain;
}
return playableChains;
}
public static PlayableGraph BuildPlayableGraph(Animator animator, IList<IRigLayer> layers, SyncSceneToStreamLayer syncSceneToStreamLayer)
{
string graphName = animator.gameObject.transform.name + "_Rigs";
PlayableGraph graph = PlayableGraph.Create(graphName);
graph.SetTimeUpdateMode(DirectorUpdateMode.GameTime);
BuildPlayableGraph(graph, animator, layers, syncSceneToStreamLayer);
return graph;
}
public static void BuildPlayableGraph(PlayableGraph graph, Animator animator, IList<IRigLayer> layers, SyncSceneToStreamLayer syncSceneToStreamLayer)
{
IEnumerable<PlayableChain> playableChains = BuildPlayables(animator, graph, layers, syncSceneToStreamLayer);
foreach(var chain in playableChains)
{
if (!chain.IsValid())
continue;
AnimationPlayableOutput output = AnimationPlayableOutput.Create(graph, String.Format("{0}-Output", chain.name), animator);
output.SetAnimationStreamSource(AnimationStreamSource.PreviousInputs);
output.SetSortingOrder(k_AnimationOutputPriority);
// Connect last rig playable to output
output.SetSourcePlayable(chain.playables[chain.playables.Length - 1]);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0b922d7bee7fe4a43810ba0b90911a1f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,103 @@
namespace UnityEngine.Animations.Rigging
{
/// <summary>
/// This is the base class for rig constraints.
/// Inherit from this class to implement custom constraints.
/// </summary>
/// <typeparam name="TJob">The constraint job</typeparam>
/// <typeparam name="TData">The constraint data</typeparam>
/// <typeparam name="TBinder">The constraint job binder</typeparam>
public class RigConstraint<TJob, TData, TBinder> : MonoBehaviour, IRigConstraint
where TJob : struct, IWeightedAnimationJob
where TData : struct, IAnimationJobData
where TBinder : AnimationJobBinder<TJob, TData>, new()
{
/// <summary>
/// The constraint weight parameter.
/// </summary>
[SerializeField, Range(0f, 1f)]
protected float m_Weight = 1f;
/// <summary>
/// The constraint data.
/// </summary>
[SerializeField, ExpandChildren]
protected TData m_Data;
static readonly TBinder s_Binder = new TBinder();
/// <summary>
/// Resets constraint data to default values.
/// </summary>
public void Reset()
{
m_Weight = 1f;
m_Data.SetDefaultValues();
}
/// <summary>
/// Retrieves the constraint valid state.
/// </summary>
/// <returns>Returns true if constraint data can be successfully evaluated. Returns false otherwise.</returns>
public bool IsValid() => m_Data.IsValid();
/// <summary>
/// This function is called when the script is loaded or a value is changed in the Inspector (Called in the editor only).
/// You can use this to ensure that when you modify data in an editor, that data stays within a certain range.
/// </summary>
protected virtual void OnValidate() => m_Weight = Mathf.Clamp01(m_Weight);
/// <summary>
/// The data container for the constraint.
/// </summary>
public ref TData data => ref m_Data;
/// <summary>
/// The constraint weight. This is a value in between 0 and 1.
/// </summary>
public float weight { get => m_Weight; set => m_Weight = Mathf.Clamp01(value); }
/// <summary>
/// Creates the animation job for this constraint.
/// </summary>
/// <param name="animator">The animated hierarchy Animator component</param>
/// <returns>Returns the newly instantiated job.</returns>
public IAnimationJob CreateJob(Animator animator)
{
TJob job = s_Binder.Create(animator, ref m_Data, this);
// Bind constraint job weight property
job.jobWeight = FloatProperty.BindCustom(
animator,
ConstraintsUtils.ConstructCustomPropertyName(this, ConstraintProperties.s_Weight)
);
return job;
}
/// <summary>
/// Frees the specified job memory.
/// </summary>
/// <param name="job">The job to destroy.</param>
public void DestroyJob(IAnimationJob job) => s_Binder.Destroy((TJob)job);
/// <summary>
/// Updates the specified job data.
/// </summary>
/// <param name="job">The job to update.</param>
public void UpdateJob(IAnimationJob job) => s_Binder.Update((TJob)job, ref m_Data);
/// <summary>
/// The job binder for the constraint.
/// </summary>
IAnimationJobBinder IRigConstraint.binder => s_Binder;
/// <summary>
/// The data container for the constraint.
/// </summary>
IAnimationJobData IRigConstraint.data => m_Data;
/// <summary>
/// The component for the constraint.
/// </summary>
Component IRigConstraint.component => (Component)this;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 96db938db259ddc4ba0c0105e23abf96
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: ca41524ec86f0d84ab5675c9622cc1a2, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,104 @@
using System;
using UnityEngine.Serialization;
namespace UnityEngine.Animations.Rigging
{
/// <summary>
/// The RigLayer is used by the RigBuilder to control in which order rigs will be
/// evaluated and whether they are active or not.
/// </summary>
[Serializable]
public class RigLayer : IRigLayer
{
[SerializeField][FormerlySerializedAs("rig")] private Rig m_Rig;
[SerializeField][FormerlySerializedAs("active")] private bool m_Active = true;
private IRigConstraint[] m_Constraints;
private IAnimationJob[] m_Jobs;
/// <summary>The Rig associated to the RigLayer</summary>
public Rig rig { get => m_Rig; private set => m_Rig = value; }
/// <summary>The active state. True if the RigLayer is active, false otherwise.</summary>
public bool active { get => m_Active; set => m_Active = value; }
/// <summary>The RigLayer name.</summary>
public string name { get => (rig != null ? rig.gameObject.name : "no-name"); }
/// <summary>The list of constraints associated with the RigLayer.</summary>
public IRigConstraint[] constraints { get => isInitialized ? m_Constraints : null; }
/// <summary>The list of jobs built from constraints associated with the RigLayer.</summary>
public IAnimationJob[] jobs { get => isInitialized ? m_Jobs : null; }
/// <summary>Returns true if RigLayer was initialized or false otherwise.</summary>
/// <seealso cref="RigLayer.Initialize"/>
public bool isInitialized { get; private set; }
/// <summary>
/// Constructor.
/// </summary>
/// <param name="rig">The rig represented by this rig layer.</param>
/// <param name="active">The active state of the rig layer.</param>
public RigLayer(Rig rig, bool active = true)
{
this.rig = rig;
this.active = active;
}
/// <summary>
/// Initializes the RigLayer. This will retrieve the constraints associated with the Rig
/// and create the animation jobs required by the PlayableGraph.
/// </summary>
/// <param name="animator">The Animator used to animate the RigLayer constraints.</param>
/// <returns>True if RigLayer was initialized properly, false otherwise.</returns>
public bool Initialize(Animator animator)
{
if (isInitialized)
return true;
if (rig != null)
{
m_Constraints = RigUtils.GetConstraints(rig);
if (m_Constraints == null || m_Constraints.Length == 0)
return false;
m_Jobs = RigUtils.CreateAnimationJobs(animator, m_Constraints);
return (isInitialized = true);
}
return false;
}
/// <summary>
/// Updates the RigLayer jobs. This is called during the Update loop before
/// the Animator evaluates the PlayableGraph.
/// </summary>
public void Update()
{
if (!isInitialized)
return;
for (int i = 0, count = m_Constraints.Length; i < count; ++i)
m_Constraints[i].UpdateJob(m_Jobs[i]);
}
/// <summary>
/// Resets the RigLayer. This will destroy the animation jobs and
/// free up memory.
/// </summary>
public void Reset()
{
if (!isInitialized)
return;
RigUtils.DestroyAnimationJobs(m_Constraints, m_Jobs);
m_Constraints = null;
m_Jobs = null;
isInitialized = false;
}
/// <summary>
/// Queries whether the RigLayer is valid.
/// </summary>
/// <returns>True if RigLayer is valid, false otherwise.</returns>
public bool IsValid() => rig != null && isInitialized;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5d7bdd63ca7404ca1bfb21319b7ddf34
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,11 @@
namespace UnityEngine.Animations.Rigging
{
/// <summary>
///
/// </summary>
[DisallowMultipleComponent, AddComponentMenu("Animation Rigging/Setup/Rig Transform")]
[HelpURL("https://docs.unity3d.com/Packages/com.unity.animation.rigging@1.3/manual/RiggingWorkflow.html#rig-transform")]
public class RigTransform : MonoBehaviour
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 48948dfe9d76b07488dacd46a7955fa1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: ca41524ec86f0d84ab5675c9622cc1a2, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,334 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace UnityEngine.Animations.Rigging
{
static class RigUtils
{
internal static readonly Dictionary<Type, PropertyDescriptor> s_SupportedPropertyTypeToDescriptor = new Dictionary<Type, PropertyDescriptor>
{
{ typeof(float) , new PropertyDescriptor{ size = 1, type = PropertyType.Float } },
{ typeof(int) , new PropertyDescriptor{ size = 1, type = PropertyType.Int } },
{ typeof(bool) , new PropertyDescriptor{ size = 1, type = PropertyType.Bool } },
{ typeof(Vector2) , new PropertyDescriptor{ size = 2, type = PropertyType.Float } },
{ typeof(Vector3) , new PropertyDescriptor{ size = 3, type = PropertyType.Float } },
{ typeof(Vector4) , new PropertyDescriptor{ size = 4, type = PropertyType.Float } },
{ typeof(Quaternion) , new PropertyDescriptor{ size = 4, type = PropertyType.Float } },
{ typeof(Vector3Int) , new PropertyDescriptor{ size = 3, type = PropertyType.Int } },
{ typeof(Vector3Bool), new PropertyDescriptor{ size = 3, type = PropertyType.Bool } }
};
public static IRigConstraint[] GetConstraints(Rig rig)
{
IRigConstraint[] constraints = rig.GetComponentsInChildren<IRigConstraint>();
if (constraints.Length == 0)
return null;
List<IRigConstraint> tmp = new List<IRigConstraint>(constraints.Length);
foreach (var constraint in constraints)
{
if (constraint.IsValid())
tmp.Add(constraint);
}
return tmp.Count == 0 ? null : tmp.ToArray();
}
private static Transform[] GetSyncableRigTransforms(Animator animator)
{
RigTransform[] rigTransforms = animator.GetComponentsInChildren<RigTransform>();
if (rigTransforms.Length == 0)
return null;
Transform[] transforms = new Transform[rigTransforms.Length];
for (int i = 0; i < transforms.Length; ++i)
transforms[i] = rigTransforms[i].transform;
return transforms;
}
private static bool ExtractTransformType(
Animator animator,
FieldInfo field,
object data,
List<Transform> syncableTransforms
)
{
bool handled = true;
Type fieldType = field.FieldType;
if (fieldType == typeof(Transform))
{
var value = (Transform)field.GetValue(data);
if (value != null && value.IsChildOf(animator.avatarRoot))
syncableTransforms.Add(value);
}
else if (fieldType == typeof(Transform[]) || fieldType == typeof(List<Transform>))
{
var list = (IEnumerable<Transform>)field.GetValue(data);
foreach (var element in list)
if (element != null && element.IsChildOf(animator.avatarRoot))
syncableTransforms.Add(element);
}
else
handled = false;
return handled;
}
private static bool ExtractPropertyType(
FieldInfo field,
object data,
List<Property> syncableProperties,
string namePrefix = ""
)
{
if (!s_SupportedPropertyTypeToDescriptor.TryGetValue(field.FieldType, out PropertyDescriptor descriptor))
return false;
syncableProperties.Add(
new Property { name = ConstraintsUtils.ConstructConstraintDataPropertyName(namePrefix + field.Name), descriptor = descriptor }
);
return true;
}
private static bool ExtractWeightedTransforms(
Animator animator,
FieldInfo field,
object data,
List<Transform> syncableTransforms,
List<Property> syncableProperties)
{
bool handled = true;
Type fieldType = field.FieldType;
if (fieldType == typeof(WeightedTransform))
{
var value = ((WeightedTransform)field.GetValue(data)).transform;
if (value != null && value.IsChildOf(animator.avatarRoot))
syncableTransforms.Add(value);
syncableProperties.Add(
new Property { name = ConstraintsUtils.ConstructConstraintDataPropertyName(field.Name + ".weight"), descriptor = s_SupportedPropertyTypeToDescriptor[typeof(float)] }
);
}
else if (fieldType == typeof(WeightedTransformArray))
{
var list = (IEnumerable<WeightedTransform>)field.GetValue(data);
int index = 0;
foreach (var element in list)
{
if (element.transform != null && element.transform.IsChildOf(animator.avatarRoot))
syncableTransforms.Add(element.transform);
syncableProperties.Add(
new Property { name = ConstraintsUtils.ConstructConstraintDataPropertyName(field.Name + ".m_Item" + index + ".weight"), descriptor = s_SupportedPropertyTypeToDescriptor[typeof(float)] }
);
++index;
}
}
else
handled = false;
return handled;
}
private static bool ExtractNestedPropertyType(
Animator animator,
FieldInfo field,
object data,
List<Transform> syncableTransforms,
List<Property> syncableProperties,
string namePrefix = "")
{
Type fieldType = field.FieldType;
var fieldData = field.GetValue(data);
var fieldName = namePrefix + field.Name + ".";
// Only structs
if (!fieldType.IsValueType || fieldType.IsPrimitive)
return false;
var fields = fieldType.GetFields(
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance
).Where(info => info.GetCustomAttribute<SyncSceneToStreamAttribute>() != null);
foreach (var childField in fields)
{
if (ExtractTransformType(animator, childField, fieldData, syncableTransforms))
continue;
if (ExtractPropertyType(childField, fieldData, syncableProperties, fieldName))
continue;
if (ExtractNestedPropertyType(animator, childField, fieldData, syncableTransforms, syncableProperties, fieldName))
continue;
throw new NotSupportedException("Field type [" + field.FieldType + "] is not a supported syncable property type.");
}
return true;
}
private static void ExtractAllSyncableData(Animator animator, IList<IRigLayer> layers, out List<Transform> syncableTransforms, out List<SyncableProperties> syncableProperties)
{
syncableTransforms = new List<Transform>();
syncableProperties = new List<SyncableProperties>(layers.Count);
Dictionary<Type, FieldInfo[]> typeToSyncableFields = new Dictionary<Type, FieldInfo[]>();
foreach (var layer in layers)
{
if (!layer.IsValid())
continue;
var constraints = layer.constraints;
List<ConstraintProperties> allConstraintProperties = new List<ConstraintProperties>(constraints.Length);
foreach (var constraint in constraints)
{
var data = constraint.data;
var dataType = constraint.data.GetType();
if (!typeToSyncableFields.TryGetValue(dataType, out FieldInfo[] syncableFields))
{
FieldInfo[] allFields = dataType.GetFields(
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance
);
List<FieldInfo> filteredFields = new List<FieldInfo>(allFields.Length);
foreach (var field in allFields)
if (field.GetCustomAttribute<SyncSceneToStreamAttribute>() != null)
filteredFields.Add(field);
syncableFields = filteredFields.ToArray();
typeToSyncableFields[dataType] = syncableFields;
}
List<Property> properties = new List<Property>(syncableFields.Length);
foreach (var field in syncableFields)
{
if (ExtractWeightedTransforms(animator, field, data, syncableTransforms, properties))
continue;
if (ExtractTransformType(animator, field, data, syncableTransforms))
continue;
if (ExtractPropertyType(field, data, properties))
continue;
if (ExtractNestedPropertyType(animator, field, data, syncableTransforms, properties))
continue;
throw new NotSupportedException("Field type [" + field.FieldType + "] is not a supported syncable property type.");
}
allConstraintProperties.Add(
new ConstraintProperties {
component = constraint.component,
properties = properties.ToArray()
}
);
}
syncableProperties.Add(
new SyncableProperties {
rig = new RigProperties { component = layer.rig as Component },
constraints = allConstraintProperties.ToArray()
}
);
}
var extraTransforms = GetSyncableRigTransforms(animator);
if (extraTransforms != null)
syncableTransforms.AddRange(extraTransforms);
}
public static IAnimationJob[] CreateAnimationJobs(Animator animator, IRigConstraint[] constraints)
{
if (constraints == null || constraints.Length == 0)
return null;
IAnimationJob[] jobs = new IAnimationJob[constraints.Length];
for (int i = 0; i < constraints.Length; ++i)
jobs[i] = constraints[i].CreateJob(animator);
return jobs;
}
public static void DestroyAnimationJobs(IRigConstraint[] constraints, IAnimationJob[] jobs)
{
if (jobs == null || jobs.Length != constraints.Length)
return;
for (int i = 0; i < constraints.Length; ++i)
constraints[i].DestroyJob(jobs[i]);
}
private struct RigSyncSceneToStreamData : IAnimationJobData, IRigSyncSceneToStreamData
{
public RigSyncSceneToStreamData(Transform[] transforms, SyncableProperties[] properties, int rigCount)
{
if (transforms != null && transforms.Length > 0)
{
var unique = UniqueTransformIndices(transforms);
if (unique.Length != transforms.Length)
{
syncableTransforms = new Transform[unique.Length];
for (int i = 0; i < unique.Length; ++i)
syncableTransforms[i] = transforms[unique[i]];
}
else
syncableTransforms = transforms;
}
else
syncableTransforms = null;
syncableProperties = properties;
rigStates = rigCount > 0 ? new bool[rigCount] : null;
m_IsValid = !(((syncableTransforms == null || syncableTransforms.Length == 0) &&
(syncableProperties == null || syncableProperties.Length == 0) &&
rigStates == null));
}
static int[] UniqueTransformIndices(Transform[] transforms)
{
if (transforms == null || transforms.Length == 0)
return null;
HashSet<int> instanceIDs = new HashSet<int>();
List<int> unique = new List<int>(transforms.Length);
for (int i = 0; i < transforms.Length; ++i)
if (instanceIDs.Add(transforms[i].GetInstanceID()))
unique.Add(i);
return unique.ToArray();
}
public Transform[] syncableTransforms { get; private set; }
public SyncableProperties[] syncableProperties { get; private set; }
public bool[] rigStates { get; set; }
private readonly bool m_IsValid;
bool IAnimationJobData.IsValid() => m_IsValid;
void IAnimationJobData.SetDefaultValues()
{
syncableTransforms = null;
syncableProperties = null;
rigStates = null;
}
}
internal static IAnimationJobData CreateSyncSceneToStreamData(Animator animator, IList<IRigLayer> layers)
{
ExtractAllSyncableData(animator, layers, out List<Transform> syncableTransforms, out List<SyncableProperties> syncableProperties);
return new RigSyncSceneToStreamData(syncableTransforms.ToArray(), syncableProperties.ToArray(), layers.Count);
}
public static IAnimationJobBinder syncSceneToStreamBinder { get; } = new RigSyncSceneToStreamJobBinder<RigSyncSceneToStreamData>();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 063675370bb1d944995e46d040c62f28
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,65 @@
using System.Collections.Generic;
namespace UnityEngine.Animations.Rigging
{
class SyncSceneToStreamLayer
{
public bool Initialize(Animator animator, IList<IRigLayer> layers)
{
if (isInitialized)
return true;
m_RigIndices = new List<int>(layers.Count);
for (int i = 0; i < layers.Count; ++i)
{
if (!layers[i].IsValid())
continue;
m_RigIndices.Add(i);
}
m_Data = RigUtils.CreateSyncSceneToStreamData(animator, layers);
if (!m_Data.IsValid())
return false;
job = RigUtils.syncSceneToStreamBinder.Create(animator, m_Data);
return (isInitialized = true);
}
public void Update(IList<IRigLayer> layers)
{
if (!isInitialized || !m_Data.IsValid())
return;
IRigSyncSceneToStreamData syncData = (IRigSyncSceneToStreamData)m_Data;
for (int i = 0, count = m_RigIndices.Count; i < count; ++i)
syncData.rigStates[i] = layers[m_RigIndices[i]].active;
RigUtils.syncSceneToStreamBinder.Update(job, m_Data);
}
public void Reset()
{
if (!isInitialized)
return;
if (m_Data != null && m_Data.IsValid())
{
RigUtils.syncSceneToStreamBinder.Destroy(job);
m_Data = null;
}
isInitialized = false;
}
public bool IsValid() => job != null && m_Data != null;
public bool isInitialized { get; private set; }
public IAnimationJob job;
private IAnimationJobData m_Data;
private List<int> m_RigIndices;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e7adc2784a6054bccaf87e875f5e87af
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,75 @@
using System;
namespace UnityEngine.Animations.Rigging
{
/// <summary>
/// Provides an accessor to a Transform component reference.
/// </summary>
public interface ITransformProvider
{
/// <summary>
/// Reference to a Transform component.
/// </summary>
Transform transform { get; set; }
}
/// <summary>
/// Provides an access to a weight value.
/// </summary>
public interface IWeightProvider
{
/// <summary>
/// Weight. This is a number in between 0 and 1.
/// </summary>
float weight { get; set; }
}
/// <summary>
/// Tuple of a Reference to a Transform component and a weight number.
/// See also <seealso cref="WeightedTransformArray"/> and <seealso cref="WeightRangeAttribute"/>.
/// </summary>
[Serializable]
public struct WeightedTransform : ITransformProvider, IWeightProvider, IEquatable<WeightedTransform>
{
/// <summary>Reference to a Transform component.</summary>
public Transform transform;
/// <summary>Weight. This is a number be in between 0 and 1.</summary>
public float weight;
/// <summary>
/// Constructor.
/// </summary>
/// <param name="transform">Reference to a Transform component.</param>
/// <param name="weight">Weight. This is a number in between 0 and 1.</param>
public WeightedTransform(Transform transform, float weight)
{
this.transform = transform;
this.weight = Mathf.Clamp01(weight);
}
/// <summary>
/// Returns a WeightedTransform object with an null Transform component reference and the specified weight.
/// </summary>
/// <param name="weight">Weight. This is a number in between 0 and 1.</param>
/// <returns>Returns a new WeightedTransform</returns>
public static WeightedTransform Default(float weight) => new WeightedTransform(null, weight);
/// <summary>
/// Compare two WeightedTransform objects for equality.
/// </summary>
/// <param name="other">A WeightedTransform object</param>
/// <returns>Returns true if both WeightedTransform have the same values. False otherwise.</returns>
public bool Equals(WeightedTransform other)
{
if (transform == other.transform && weight == other.weight)
return true;
return false;
}
/// <inheritdoc />
Transform ITransformProvider.transform { get => transform; set => transform = value; }
/// <inheritdoc />
float IWeightProvider.weight { get => weight; set => weight = Mathf.Clamp01(value); }
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ab8a6a8cfed3ce44cb7f2b5b00713cf7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,454 @@
using System.Collections.Generic;
using System.Collections;
using System;
namespace UnityEngine.Animations.Rigging
{
/// <summary>
/// This struct defines a List of WeightedTransform.
/// WeightedTransformArray can be animated (as opposed to System.List and C# arrays) and is implemented
/// with a hard limit of eight WeightedTransform elements.
/// See also <seealso cref="WeightedTransform"/> and <seealso cref="WeightRangeAttribute"/>.
/// </summary>
[Serializable]
public struct WeightedTransformArray : IList<WeightedTransform>, IList
{
/// <summary>Maximum number of elements in WeightedTransformArray.</summary>
public static readonly int k_MaxLength = 8;
[SerializeField, NotKeyable] private int m_Length;
[SerializeField] private WeightedTransform m_Item0;
[SerializeField] private WeightedTransform m_Item1;
[SerializeField] private WeightedTransform m_Item2;
[SerializeField] private WeightedTransform m_Item3;
[SerializeField] private WeightedTransform m_Item4;
[SerializeField] private WeightedTransform m_Item5;
[SerializeField] private WeightedTransform m_Item6;
[SerializeField] private WeightedTransform m_Item7;
/// <summary>
/// Constructor.
/// </summary>
/// <param name="size">Size of the array. This will clamped to be a number in between 0 and k_MaxLength.</param>
/// <seealso cref="WeightedTransformArray.k_MaxLength"/>
public WeightedTransformArray(int size)
{
m_Length = ClampSize(size);
m_Item0 = new WeightedTransform();
m_Item1 = new WeightedTransform();
m_Item2 = new WeightedTransform();
m_Item3 = new WeightedTransform();
m_Item4 = new WeightedTransform();
m_Item5 = new WeightedTransform();
m_Item6 = new WeightedTransform();
m_Item7 = new WeightedTransform();
}
/// <summary>
/// Returns an enumerator that iterates through a collection.
/// </summary>
/// <returns>An IEnumerator object that can be used to iterate through the collection.</returns>
public IEnumerator<WeightedTransform> GetEnumerator()
{
return new Enumerator(ref this);
}
/// <summary>
/// Returns an enumerator that iterates through a collection.
/// </summary>
/// <returns>An IEnumerator object that can be used to iterate through the collection.</returns>
IEnumerator IEnumerable.GetEnumerator()
{
return new Enumerator(ref this);
}
/// <summary>
/// Adds an item to the WeightedTransformArray.
/// </summary>
/// <param name="value">The object to add to the WeightedTransformArray.</param>
/// <returns>The position into which the new element was inserted, or -1 to indicate that the item was not inserted into the collection.</returns>
int IList.Add(object value)
{
Add((WeightedTransform)value);
return m_Length - 1;
}
/// <summary>
/// Adds an item to the WeightedTransformArray.
/// </summary>
/// <param name="value">The WeightedTransform to add to the WeightedTransformArray.</param>
public void Add(WeightedTransform value)
{
if (m_Length >= k_MaxLength)
throw new ArgumentException($"This array cannot have more than '{k_MaxLength}' items.");
Set(m_Length, value);
++m_Length;
}
/// <summary>
/// Removes all items from the WeightedTransformArray.
/// </summary>
public void Clear()
{
m_Length = 0;
}
/// <summary>
/// Determines the index of a specific item in the WeightedTransformArray.
/// </summary>
/// <param name="value">The object to locate in the WeightedTransformArray.</param>
/// <returns>The index of value if found in the list; otherwise, -1.</returns>
int IList.IndexOf(object value) => IndexOf((WeightedTransform)value);
/// <summary>
/// Determines the index of a specific item in the WeightedTransformArray.
/// </summary>
/// <param name="value">The WeightedTransform to locate in the WeightedTransformArray.</param>
/// <returns>The index of value if found in the list; otherwise, -1.</returns>
public int IndexOf(WeightedTransform value)
{
for (int i = 0; i < m_Length; ++i)
{
if (Get(i).Equals(value))
return i;
}
return -1;
}
/// <summary>
/// Determines whether the WeightedTransformArray contains a specific value.
/// </summary>
/// <param name="value">The object to locate in the WeightedTransformArray.</param>
/// <returns>true if the Object is found in the WeightedTransformArray; otherwise, false.</returns>
bool IList.Contains(object value) => Contains((WeightedTransform)value);
/// <summary>
/// Determines whether the WeightedTransformArray contains a specific value.
/// </summary>
/// <param name="value">The WeightedTransform to locate in the WeightedTransformArray.</param>
/// <returns>true if the Object is found in the WeightedTransformArray; otherwise, false.</returns>
public bool Contains(WeightedTransform value)
{
for (int i = 0; i < m_Length; ++i)
{
if (Get(i).Equals(value))
return true;
}
return false;
}
/// <summary>
/// Copies the elements of the WeightedTransform to an Array, starting at a particular Array index.
/// </summary>
/// <param name="array">The one-dimensional Array that is the destination of the elements copied from WeightedTransform. The Array must have zero-based indexing.</param>
/// <param name="arrayIndex">The zero-based index in array at which copying begins.</param>
void ICollection.CopyTo(Array array, int arrayIndex)
{
if (array == null)
throw new ArgumentNullException("The array cannot be null.");
if (arrayIndex < 0)
throw new ArgumentOutOfRangeException("The starting array index cannot be negative.");
if (Count > array.Length - arrayIndex + 1)
throw new ArgumentException("The destination array has fewer elements than the collection.");
for (int i = 0; i < m_Length; i++)
{
array.SetValue(Get(i), i + arrayIndex);
}
}
/// <summary>
/// Copies the elements of the WeightedTransform to an Array, starting at a particular Array index.
/// </summary>
/// <param name="array">The one-dimensional Array that is the destination of the elements copied from WeightedTransform. The Array must have zero-based indexing.</param>
/// <param name="arrayIndex">The zero-based index in array at which copying begins.</param>
public void CopyTo(WeightedTransform[] array, int arrayIndex)
{
if (array == null)
throw new ArgumentNullException("The array cannot be null.");
if (arrayIndex < 0)
throw new ArgumentOutOfRangeException("The starting array index cannot be negative.");
if (Count > array.Length - arrayIndex + 1)
throw new ArgumentException("The destination array has fewer elements than the collection.");
for (int i = 0; i < m_Length; i++)
{
array[i + arrayIndex] = Get(i);
}
}
/// <summary>
/// Removes the first occurrence of a specific object from the WeightedTransformArray.
/// </summary>
/// <param name="value">The object to remove from the WeightedTransformArray.</param>
void IList.Remove(object value) { Remove((WeightedTransform)value); }
/// <summary>
/// Removes the first occurrence of a specific WeightedTransform from the WeightedTransformArray.
/// </summary>
/// <param name="value">The WeightedTransform to remove from the WeightedTransformArray.</param>
/// <returns>True if value was removed from the array, false otherwise.</returns>
public bool Remove(WeightedTransform value)
{
for (int i = 0; i < m_Length; ++i)
{
if (Get(i).Equals(value))
{
for (; i < m_Length - 1; ++i)
{
Set(i, Get(i + 1));
}
--m_Length;
return true;
}
}
return false;
}
/// <summary>
/// Removes the WeightedTransformArray item at the specified index.
/// </summary>
/// <param name="index">The zero-based index of the item to remove.</param>
public void RemoveAt(int index)
{
CheckOutOfRangeIndex(index);
for (int i = index; i < m_Length - 1; ++i)
{
Set(i, Get(i + 1));
}
--m_Length;
}
/// <summary>
/// Inserts an item to the WeightedTransformArray at the specified index.
/// </summary>
/// <param name="index">The zero-based index at which value should be inserted.</param>
/// <param name="value">The object to insert into the WeightedTransformArray.</param>
void IList.Insert(int index, object value) => Insert(index, (WeightedTransform)value);
/// <summary>
/// Inserts an item to the WeightedTransformArray at the specified index.
/// </summary>
/// <param name="index">The zero-based index at which value should be inserted.</param>
/// <param name="value">The WeightedTransform to insert into the WeightedTransformArray.</param>
public void Insert(int index, WeightedTransform value)
{
if (m_Length >= k_MaxLength)
throw new ArgumentException($"This array cannot have more than '{k_MaxLength}' items.");
CheckOutOfRangeIndex(index);
if (index >= m_Length)
{
Add(value);
return;
}
for (int i = m_Length; i > index; --i)
{
Set(i, Get(i - 1));
}
Set(index, value);
++m_Length;
}
/// <summary>
/// Clamps specified value in between 0 and k_MaxLength.
/// </summary>
/// <param name="size">Size value.</param>
/// <returns>Value in between 0 and k_MaxLength.</returns>
/// <seealso cref="WeightedTransformArray.k_MaxLength"/>
private static int ClampSize(int size)
{
return Mathf.Clamp(size, 0, k_MaxLength);
}
/// <summary>
/// Checks whether specified index value in within bounds.
/// </summary>
/// <param name="index">Index value.</param>
/// <exception cref="IndexOutOfRangeException">Index value is not between 0 and k_MaxLength.</exception>
/// <seealso cref="WeightedTransformArray.k_MaxLength"/>
private void CheckOutOfRangeIndex(int index)
{
if (index < 0 || index >= k_MaxLength)
throw new IndexOutOfRangeException($"Index {index} is out of range of '{m_Length}' Length.");
}
/// <summary>
/// Retrieves a WeightedTransform at specified index.
/// </summary>
/// <param name="index">Index value.</param>
/// <returns>The WeightedTransform value at specified index.</returns>
private WeightedTransform Get(int index)
{
CheckOutOfRangeIndex(index);
switch(index)
{
case 0: return m_Item0;
case 1: return m_Item1;
case 2: return m_Item2;
case 3: return m_Item3;
case 4: return m_Item4;
case 5: return m_Item5;
case 6: return m_Item6;
case 7: return m_Item7;
}
// Shouldn't happen.
return m_Item0;
}
/// <summary>
/// Sets a WeightedTransform at specified index.
/// </summary>
/// <param name="index">Index value.</param>
/// <param name="value">The WeightedTransform value to set.</param>
private void Set(int index, WeightedTransform value)
{
CheckOutOfRangeIndex(index);
switch(index)
{
case 0: m_Item0 = value; break;
case 1: m_Item1 = value; break;
case 2: m_Item2 = value; break;
case 3: m_Item3 = value; break;
case 4: m_Item4 = value; break;
case 5: m_Item5 = value; break;
case 6: m_Item6 = value; break;
case 7: m_Item7 = value; break;
}
}
/// <summary>
/// Sets a weight on a WeightedTransform at specified index.
/// </summary>
/// <param name="index">Index value.</param>
/// <param name="weight">The weight value to set.</param>
public void SetWeight(int index, float weight)
{
var weightedTransform = Get(index);
weightedTransform.weight = weight;
Set(index, weightedTransform);
}
/// <summary>
/// Retrieves a weight on a WeightedTransform at specified index.
/// </summary>
/// <param name="index">Index value.</param>
/// <returns>The weight value at specified index.</returns>
public float GetWeight(int index)
{
return Get(index).weight;
}
/// <summary>
/// Sets the Transform reference on a WeightedTransform at specified index.
/// </summary>
/// <param name="index">Index value.</param>
/// <param name="transform">The Transform reference to set.</param>
public void SetTransform(int index, Transform transform)
{
var weightedTransform = Get(index);
weightedTransform.transform = transform;
Set(index, weightedTransform);
}
/// <summary>
/// Retrieves a Transform reference on a WeightedTransform at specified index.
/// </summary>
/// <param name="index">Index value.</param>
/// <returns>The Transform reference at specified index.</returns>
public Transform GetTransform(int index)
{
return Get(index).transform;
}
/// <summary>
/// Method to call from a provider's OnValidate() callback to ensure all weight values are within the valid range.
/// See also <seealso cref="WeightRangeAttribute"/>.
/// </summary>
/// <param name="array">WeightedTransformArray to adjust.</param>
/// <param name="min">Minimum value to clamp array values with.</param>
/// <param name="max">Maximum value to clamp array values with.</param>
public static void OnValidate(ref WeightedTransformArray array, float min = 0f, float max = 1f)
{
for (var i = 0; i < k_MaxLength; ++i)
array.SetWeight(i, Mathf.Clamp(array.GetWeight(i), min, max));
}
/// <summary>
/// Gets or sets the element at the specified index.
/// </summary>
/// <param name="index">The zero-based index of the element to get or set.</param>
object IList.this[int index] { get => (object)Get(index); set => Set(index, (WeightedTransform)value); }
/// <summary>
/// Gets or sets the WeightedTransform at the specified index.
/// </summary>
/// <param name="index">The zero-based index of the WeightedTransform to get or set.</param>
public WeightedTransform this[int index] { get => Get(index); set => Set(index, value); }
/// <summary>The number of elements contained in the WeightedTransformArray.</summary>
public int Count { get => m_Length; }
/// <summary>
/// Retrieves whether WeightedTransformArray is read-only. Always false.
/// </summary>
public bool IsReadOnly { get => false; }
/// <summary>
/// Retrieves whether WeightedTransformArray has a fixed size. Always false.
/// </summary>
public bool IsFixedSize { get => false; }
bool ICollection.IsSynchronized { get => true; }
object ICollection.SyncRoot { get => null; }
[System.Serializable]
private struct Enumerator : IEnumerator<WeightedTransform>
{
private WeightedTransformArray m_Array;
private int m_Index;
public Enumerator(ref WeightedTransformArray array)
{
m_Array = array;
m_Index = -1;
}
public bool MoveNext()
{
m_Index++;
return (m_Index < m_Array.Count);
}
public void Reset()
{
m_Index = -1;
}
void IDisposable.Dispose() { }
public WeightedTransform Current => m_Array.Get(m_Index);
object IEnumerator.Current => Current;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 80e58e006e9714edbbcbd43e30f6979d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: