first commit
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 57fb05f5d7fd88b41b5eca2077a707f3
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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:
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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:
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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:
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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:
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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:
|
||||
@@ -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>
|
||||
>
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -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:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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:
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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:
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7fee10ab894af4417bc991ed3a2fedcb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 74107573bb9a243fb90014afa5c417d2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 08f245f2f5b21437e9f88d72a8cef6a1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4b4df322b421941b2a0ffa8b0a9847e0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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:
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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:
|
||||
@@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0b922d7bee7fe4a43810ba0b90911a1f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5d7bdd63ca7404ca1bfb21319b7ddf34
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -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:
|
||||
@@ -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>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 063675370bb1d944995e46d040c62f28
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e7adc2784a6054bccaf87e875f5e87af
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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); }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ab8a6a8cfed3ce44cb7f2b5b00713cf7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 80e58e006e9714edbbcbd43e30f6979d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user