Skip to content

Commit

Permalink
com.unity.animation.rigging@1.3.0
Browse files Browse the repository at this point in the history
## [1.3.0] - 2023-01-30
- Added the `TransformHandle`'s function `GetLocalToParentMatrix` to get the matrix of an animation stream transform in local space.
- Added the `TransformHandle`'s function `GetLocalToWorldMatrix` to get the matrix of an animation stream transform in world space.
- Fixed handling negative scale in the `MultiAimConstraintJob` (case 1366549).
- Fixed transforms in animator hierarchy, but not children of avatar root not resolving properly (case 1373387).
- Fixed MultiAimConstraint evaluation with a world up axis (UM-1936).
- Fixed crash when calling `RigBuilder.Build` by preventing rebuilding the PlayableGraph when in a preview context (case UUM-8599).
- Fixed an issue where a misplaced `BoneHandles.shader` shader would cause the Scene View's Orientation Overlay to no longer render (case UUM-20874).
  • Loading branch information
Unity Technologies committed Jan 30, 2023
1 parent 2f0c3b5 commit e5c083a
Show file tree
Hide file tree
Showing 28 changed files with 154 additions and 70 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
# Changelog
All notable changes to this package will be documented in this file.

## [1.2.1] - 2023-01-11
## [1.3.0] - 2023-01-30
- Added the `TransformHandle`'s function `GetLocalToParentMatrix` to get the matrix of an animation stream transform in local space.
- Added the `TransformHandle`'s function `GetLocalToWorldMatrix` to get the matrix of an animation stream transform in world space.
- Fixed handling negative scale in the `MultiAimConstraintJob` (case 1366549).
- Fixed transforms in animator hierarchy, but not children of avatar root not resolving properly (case 1373387).
- Fixed MultiAimConstraint evaluation with a world up axis (UM-1936).
- Fixed crash when calling `RigBuilder.Build` by preventing rebuilding the PlayableGraph when in a preview context (case UUM-8599).
- Fixed an issue where a misplaced `BoneHandles.shader` shader would cause the Scene View's Orientation Overlay to no longer render (case UUM-20874).

## [1.2.0] - 2021-12-08
- Updated package icons (case 1361823).
Expand Down
2 changes: 1 addition & 1 deletion Documentation~/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ This documentation describes how to set up a simple Animation Rig for use in a v

This version of Animation Rigging is compatible with the following versions of the Unity Editor:

* 2020.2 and later
* 2023.2 and later

## Document revision history

Expand Down
5 changes: 4 additions & 1 deletion Editor/Effectors/IRigEffectorOverlay.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
using System;

namespace UnityEditor.Animations.Rigging
{
interface IRigEffectorOverlay
interface IRigEffectorOverlay : IDisposable
{
bool IsValid();
void OnSceneGUIOverlay();
}
}
41 changes: 24 additions & 17 deletions Editor/Effectors/RigEffector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -157,34 +157,41 @@ public void OnSceneGUI()
highlight = Handles.selectedColor;
}

Material mat = material;
try
{
Material mat = material;

var shapeHighlight = MeshHasWireframeShapes(style.shape) ? style.color : highlight;
var wireHighlight = new Color(highlight.r, highlight.g, highlight.b, 1f);
var shapeHighlight = MeshHasWireframeShapes(style.shape) ? style.color : highlight;
var wireHighlight = new Color(highlight.r, highlight.g, highlight.b, 1f);

if (style.shape.subMeshCount > 0)
{
// Draw every sub meshes separately to control highlight vs shape colors.
for (int i = 0; i < style.shape.subMeshCount; ++i)
if (style.shape.subMeshCount > 0)
{
// Draw every sub meshes separately to control highlight vs shape colors.
for (int i = 0; i < style.shape.subMeshCount; ++i)
{
MeshTopology topology = style.shape.GetTopology(i);
bool isFilled = (topology == MeshTopology.Triangles || topology == MeshTopology.Quads);

mat.SetColor("_Color", isFilled ? shapeHighlight : wireHighlight);
mat.SetPass(0);

Graphics.DrawMeshNow(style.shape, matrix, i);
}
}
else
{
MeshTopology topology = style.shape.GetTopology(i);
MeshTopology topology = style.shape.GetTopology(0);
bool isFilled = (topology == MeshTopology.Triangles || topology == MeshTopology.Quads);

mat.SetColor("_Color", isFilled ? shapeHighlight : wireHighlight);
mat.SetPass(0);

Graphics.DrawMeshNow(style.shape, matrix, i);
Graphics.DrawMeshNow(style.shape, matrix);
}
}
else
catch (Exception exception)
{
MeshTopology topology = style.shape.GetTopology(0);
bool isFilled = (topology == MeshTopology.Triangles || topology == MeshTopology.Quads);

mat.SetColor("_Color", isFilled ? shapeHighlight : wireHighlight);
mat.SetPass(0);

Graphics.DrawMeshNow(style.shape, matrix);
Debug.LogException(exception);
}
}
break;
Expand Down
19 changes: 15 additions & 4 deletions Editor/Effectors/RigEffectorOverlay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ namespace UnityEditor.Animations.Rigging
[CustomOverlay(typeof(RigEffector))]
class RigEffectorOverlay : IRigEffectorOverlay
{
private Object[] m_TargetObjects;
private SerializedObject m_SerializedObject;

private SerializedProperty m_Visible;
Expand All @@ -30,9 +31,10 @@ class RigEffectorOverlay : IRigEffectorOverlay

private static GUILayoutOption s_FixedWidth = GUILayout.Width(210f);

public void Initialize(SerializedObject serializedObject)
public void Initialize(Object[] effectors)
{
m_SerializedObject = serializedObject;
m_TargetObjects = effectors;
m_SerializedObject = new SerializedObject(effectors);

SerializedProperty data = m_SerializedObject.FindProperty("m_Data");

Expand Down Expand Up @@ -66,16 +68,20 @@ private IRigEffectorHolder FetchRigEffectorHolder(Transform transform)
return null;
}

public bool IsValid() => m_SerializedObject.targetObject != null;

public void OnSceneGUIOverlay()
{
GameObject targetGameObject = null;
if (!IsValid())
return;

m_SerializedObject.Update();

GameObject targetGameObject = null;
if (!m_SerializedObject.isEditingMultipleObjects)
{
RigEffector rigEffector = m_SerializedObject.targetObject as RigEffector;
if (rigEffector.transform != null)
if (rigEffector != null && rigEffector.transform != null)
{
targetGameObject = rigEffector.transform.gameObject;
}
Expand Down Expand Up @@ -175,5 +181,10 @@ public void OnSceneGUIOverlay()
m_SerializedObject.ApplyModifiedProperties();
}
}

public void Dispose()
{
m_SerializedObject?.Dispose();
}
}
}
27 changes: 25 additions & 2 deletions Editor/Effectors/RigEffectorRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,29 @@ static class RigEffectorRenderer
static List<RigEffector> s_ActiveEffectors = null;
static IRigEffectorOverlay s_ActiveOverlay = null;

static bool s_ActiveOverlayDirtied = true;

static RigEffectorRenderer()
{
RigBuilder.onAddRigBuilder += OnAddRigBuilder;
RigBuilder.onRemoveRigBuilder += OnRemoveRigBuilder;

SceneView.duringSceneGui += OnSceneGUI;
Selection.selectionChanged += OnSelectionChange;
ObjectFactory.componentWasAdded += OnComponentAdded;
}

static void OnSelectionChange()
{
s_ActiveOverlayDirtied = true;
}

static void OnComponentAdded(Component component)
{
if (!(component is Rig) && !(component is RigBuilder))
return;

s_ActiveOverlayDirtied = true;
}

static void FetchOrCreateEffectors(IRigEffectorHolder holder)
Expand Down Expand Up @@ -86,8 +103,13 @@ static void FetchOrCreateEffectors()

static IRigEffectorOverlay FetchOrCreateEffectorOverlay()
{
if (!s_ActiveOverlayDirtied && s_ActiveOverlay != null && s_ActiveOverlay.IsValid())
return s_ActiveOverlay;

s_ActiveOverlay?.Dispose();

Transform[] transforms = Selection.GetTransforms(SelectionMode.ExcludePrefab | SelectionMode.Editable);
var inspectedEffectors = new List<ScriptableObject>();
var inspectedEffectors = new List<Object>();

for (int i = 0; i < s_ActiveEffectors.Count; ++i)
{
Expand All @@ -104,7 +126,7 @@ static IRigEffectorOverlay FetchOrCreateEffectorOverlay()
if (inspectedEffectors.Count > 0)
{
var overlay = new RigEffectorOverlay();
overlay.Initialize(new SerializedObject(inspectedEffectors.ToArray()));
overlay.Initialize(inspectedEffectors.ToArray());

s_ActiveOverlay = overlay;
}
Expand Down Expand Up @@ -139,6 +161,7 @@ static IRigEffectorOverlay FetchOrCreateEffectorOverlay()

s_ActiveSelection = transforms;

s_ActiveOverlayDirtied = false;
return s_ActiveOverlay;
}

Expand Down
7 changes: 7 additions & 0 deletions Editor/Effectors/RigEffectorWizard.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ public void Add(IRigEffectorHolder holder, Transform transform)
m_Transforms.Add(new HolderTransformPair() { holder = holder, transform = transform });
}

public bool IsValid() => true;

public void OnSceneGUIOverlay()
{
string labelName = "(no selection)";
Expand Down Expand Up @@ -57,5 +59,10 @@ public void OnSceneGUIOverlay()

GUILayout.EndHorizontal();
}

public void Dispose()
{
// nothing to do.
}
}
}
37 changes: 23 additions & 14 deletions Runtime/AnimationJobs/MultiAimConstraintJob.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using Unity.Collections;

namespace UnityEngine.Animations.Rigging
Expand Down Expand Up @@ -97,33 +98,41 @@ public void ProcessAnimation(AnimationStream stream)
return;
}

var worldUpVector = ComputeWorldUpVector(stream);
var upVector = AnimationRuntimeUtils.Select(Vector3.zero, upAxis, axesMask);
var weightScale = sumWeights > 1f ? 1f / sumWeights : 1f;

float weightScale = sumWeights > 1f ? 1f / sumWeights : 1f;
var drivenParentInvRot = Quaternion.Inverse(drivenParent.GetRotation(stream));
var drivenParentInvWorldMatrix = Matrix4x4.Inverse(drivenParent.GetLocalToWorldMatrix(stream));

Vector2 minMaxAngles = new Vector2(minLimit.Get(stream), maxLimit.Get(stream));
var accumWeights = 0f;
var accumDeltaRot = QuaternionExt.zero;

var drivenWPos = driven.GetPosition(stream);
var drivenLRot = driven.GetLocalRotation(stream);
var drivenParentInvRot = Quaternion.Inverse(drivenParent.GetRotation(stream));
Quaternion accumDeltaRot = QuaternionExt.zero;
float accumWeights = 0f;

var worldUpVector = ComputeWorldUpVector(stream);
var upVector = AnimationRuntimeUtils.Select(Vector3.zero, upAxis, axesMask);

var hasMasks = Vector3.Dot(axesMask, axesMask) < 3f;
var hasUpAxisCorrection = worldUpType != WorldUpType.None && Vector3.Dot(upVector, upVector) > k_Epsilon;

var minMaxAngles = new Vector2(minLimit.Get(stream), maxLimit.Get(stream));

for (int i = 0; i < sourceTransforms.Length; ++i)
{
var normalizedWeight = weightBuffer[i] * weightScale;
if (normalizedWeight < k_Epsilon)
continue;

ReadOnlyTransformHandle sourceTransform = sourceTransforms[i];
var sourceTransform = sourceTransforms[i];

var fromDir = drivenLRot * aimAxis;
var toDir = drivenParentInvRot * (sourceTransform.GetPosition(stream) - drivenWPos);
var toDir = drivenParentInvWorldMatrix.MultiplyVector(sourceTransform.GetPosition(stream) - drivenWPos);

if (toDir.sqrMagnitude < k_Epsilon)
continue;

var crossDir = Vector3.Cross(fromDir, toDir).normalized;
if (Vector3.Dot(axesMask, axesMask) < 3f)
if (hasMasks)
{
crossDir = AnimationRuntimeUtils.Select(Vector3.zero, crossDir, axesMask).normalized;
if (Vector3.Dot(crossDir, crossDir) > k_Epsilon)
Expand All @@ -142,10 +151,10 @@ public void ProcessAnimation(AnimationStream stream)
crossDir
);

if (worldUpType != WorldUpType.None && Vector3.Dot(upVector, upVector) > k_Epsilon)
if (hasUpAxisCorrection)
{
var wupProject = Vector3.Cross(Vector3.Cross(drivenParentInvRot * worldUpVector, toDir).normalized, toDir).normalized;
var rupProject = Vector3.Cross(Vector3.Cross(drivenLRot * rotToSource * upVector, toDir).normalized, toDir).normalized;
var rupProject = Vector3.Cross(Vector3.Cross(rotToSource * drivenLRot * upVector, toDir).normalized, toDir).normalized;

rotToSource = QuaternionExt.FromToRotation(rupProject, wupProject) * rotToSource;
}
Expand All @@ -164,8 +173,8 @@ public void ProcessAnimation(AnimationStream stream)
if (accumWeights < 1f)
accumDeltaRot = Quaternion.Lerp(Quaternion.identity, accumDeltaRot, accumWeights);

Quaternion newRot = accumDeltaRot * drivenLRot;
if (Vector3.Dot(axesMask, axesMask) < 3f)
var newRot = accumDeltaRot * drivenLRot;
if (hasMasks)
newRot = Quaternion.Euler(AnimationRuntimeUtils.Select(drivenLRot.eulerAngles, newRot.eulerAngles, axesMask));

var offset = drivenOffset.Get(stream);
Expand Down
22 changes: 20 additions & 2 deletions Runtime/AnimationJobs/TransformHandle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ public static ReadWriteTransformHandle Bind(Animator animator, Transform transfo
if (transform == null)
throw new ArgumentNullException(nameof(transform));

if (!transform.IsChildOf(animator.transform))
if (!transform.IsChildOf(animator.avatarRoot))
throw new InvalidOperationException($"Transform '{transform.name}' is not a child of the Animator hierarchy, and cannot be written to.");

handle.m_Handle = animator.BindStreamTransform(transform);
Expand Down Expand Up @@ -205,6 +205,15 @@ public void GetLocalTRS(AnimationStream stream, out Vector3 position, out Quater
m_SceneHandle.GetLocalTRS(stream, out position, out rotation, out scale);
}

/// <summary>
/// Gets the matrix of the transform in local space.
/// </summary>
/// <param name="stream">The AnimationStream that holds the animated values.</param>
/// <returns>The matrix of the transform in local space.</returns>
public Matrix4x4 GetLocalToParentMatrix(AnimationStream stream) =>
m_InStream == 1 ? m_StreamHandle.GetLocalToParentMatrix(stream) : m_SceneHandle.GetLocalToParentMatrix(stream);


/// <summary>
/// Gets the position of the transform in world space.
/// </summary>
Expand Down Expand Up @@ -235,6 +244,15 @@ public void GetGlobalTR(AnimationStream stream, out Vector3 position, out Quater
m_SceneHandle.GetGlobalTR(stream, out position, out rotation);
}

/// <summary>
/// Gets the matrix of the transform in world space.
/// </summary>
/// <param name="stream">The AnimationStream that holds the animated values.</param>
/// <returns>The matrix of the transform in world space.</returns>
public Matrix4x4 GetLocalToWorldMatrix(AnimationStream stream) =>
m_InStream == 1 ? m_StreamHandle.GetLocalToWorldMatrix(stream) : m_SceneHandle.GetLocalToWorldMatrix(stream);


/// <summary>
/// Returns whether this handle is resolved.
/// A ReadOnlyTransformHandle is resolved if it is valid, if it has the same bindings version than the one in the stream, and if it is bound to the transform in the stream.
Expand Down Expand Up @@ -282,7 +300,7 @@ public static ReadOnlyTransformHandle Bind(Animator animator, Transform transfor
if (transform == null)
throw new ArgumentNullException(nameof(transform));

handle.m_InStream = (byte)(transform.IsChildOf(animator.transform) ? 1 : 0);
handle.m_InStream = (byte)(transform.IsChildOf(animator.avatarRoot) ? 1 : 0);
if (handle.m_InStream == 1)
handle.m_StreamHandle = animator.BindStreamTransform(transform);
else
Expand Down
2 changes: 1 addition & 1 deletion Runtime/AnimationRig/Constraints/BlendConstraint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ void IAnimationJobData.SetDefaultValues()
/// Blend constraint.
/// </summary>
[DisallowMultipleComponent, AddComponentMenu("Animation Rigging/Blend Constraint")]
[HelpURL("https://docs.unity3d.com/Packages/com.unity.animation.rigging@1.2/manual/constraints/BlendConstraint.html")]
[HelpURL("https://docs.unity3d.com/Packages/com.unity.animation.rigging@1.3/manual/constraints/BlendConstraint.html")]
public class BlendConstraint : RigConstraint<
BlendConstraintJob,
BlendConstraintData,
Expand Down
2 changes: 1 addition & 1 deletion Runtime/AnimationRig/Constraints/ChainIKConstraint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ void IAnimationJobData.SetDefaultValues()
/// ChainIK constraint
/// </summary>
[DisallowMultipleComponent, AddComponentMenu("Animation Rigging/Chain IK Constraint")]
[HelpURL("https://docs.unity3d.com/Packages/com.unity.animation.rigging@1.2/manual/constraints/ChainIKConstraint.html")]
[HelpURL("https://docs.unity3d.com/Packages/com.unity.animation.rigging@1.3/manual/constraints/ChainIKConstraint.html")]
public class ChainIKConstraint : RigConstraint<
ChainIKConstraintJob,
ChainIKConstraintData,
Expand Down
2 changes: 1 addition & 1 deletion Runtime/AnimationRig/Constraints/DampedTransform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ void IAnimationJobData.SetDefaultValues()
/// DampedTransform constraint.
/// </summary>
[DisallowMultipleComponent, AddComponentMenu("Animation Rigging/Damped Transform")]
[HelpURL("https://docs.unity3d.com/Packages/com.unity.animation.rigging@1.2/manual/constraints/DampedTransform.html")]
[HelpURL("https://docs.unity3d.com/Packages/com.unity.animation.rigging@1.3/manual/constraints/DampedTransform.html")]
public class DampedTransform : RigConstraint<
DampedTransformJob,
DampedTransformData,
Expand Down
2 changes: 1 addition & 1 deletion Runtime/AnimationRig/Constraints/MultiAimConstraint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ static Vector3 Convert(Axis axis)
/// MultiAim constraint.
/// </summary>
[DisallowMultipleComponent, AddComponentMenu("Animation Rigging/Multi-Aim Constraint")]
[HelpURL("https://docs.unity3d.com/Packages/com.unity.animation.rigging@1.2/manual/constraints/MultiAimConstraint.html")]
[HelpURL("https://docs.unity3d.com/Packages/com.unity.animation.rigging@1.3/manual/constraints/MultiAimConstraint.html")]
public class MultiAimConstraint : RigConstraint<
MultiAimConstraintJob,
MultiAimConstraintData,
Expand Down
Loading

0 comments on commit e5c083a

Please sign in to comment.