diff --git a/Packages/com.unity.animation.rigging/.signature b/Packages/com.unity.animation.rigging/.signature
new file mode 100644
index 00000000..5b3dacec
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/.signature
@@ -0,0 +1,5 @@
+{
+ "timestamp": 1675097346,
+ "signature": "sLaf7UbDWeIQ1rbAZUqsDzJE5/0srDNWDpraziCbDW4CB1xkeWHyWhc+dfHkeB/vaJfm8lU2RHER8PwViFYDfsJoP6KzEpL2dlfFew2kyc5SldgxNylVg6dzfUy28niNlErhEd8nVizxROaTfUTDE8Qe3A66zdGWqUqz0j9R1TWAiuOLHVQOI4VzbkyjF3CL+b67Y2tRI9IBc9KcY5Mc7UCTji1QI1OQNAkVMbMOmdEBPkoiujnA5Vn3YLYYY24trSvNG0NGsFOOWWyus9QDJDWOjeMImiYl8Vc9k4s/pz11LLtVqKslsbRDc4V5AeD1mWV+p/QI2WlkDvdlKOLjt6/ITPp07LDNIJy5+A8E6VXAXCepcJ9z9Vm5HozelqU4WoPnScA1o2tVxeGVMXZjEesK/0WaMXTlqjOWNKEKtJtqoRcpdvGvqKnV7JTVTq/oWZDjcjdcNmE8ee6C2x6rijc/oYEsHbBVonco5OnOX1jynHW9gYquOcOkiPlojGeQ",
+ "publicKey": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQm9qQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FZOEFNSUlCaWdLQ0FZRUFzdUhXYUhsZ0I1cVF4ZEJjTlJKSAordHR4SmoxcVY1NTdvMlZaRE1XaXhYRVBkRTBEMVFkT1JIRXNSS1RscmplUXlERU83ZlNQS0ZwZ1A3MU5TTnJCCkFHM2NFSU45aHNQVDhOVmllZmdWem5QTkVMenFkVmdEbFhpb2VpUnV6OERKWFgvblpmU1JWKytwbk9ySTRibG4KS0twelJlNW14OTc1SjhxZ1FvRktKT0NNRlpHdkJMR2MxSzZZaEIzOHJFODZCZzgzbUovWjBEYkVmQjBxZm13cgo2ZDVFUXFsd0E5Y3JZT1YyV1VpWXprSnBLNmJZNzRZNmM1TmpBcEFKeGNiaTFOaDlRVEhUcU44N0ZtMDF0R1ZwCjVNd1pXSWZuYVRUemEvTGZLelR5U0pka0tldEZMVGdkYXpMYlpzUEE2aHBSK0FJRTJhc0tLTi84UUk1N3UzU2cKL2xyMnZKS1IvU2l5eEN1Q20vQWJkYnJMbXk0WjlSdm1jMGdpclA4T0lLQWxBRWZ2TzV5Z2hSKy8vd1RpTFlzUQp1SllDM0V2UE16ZGdKUzdGR2FscnFLZzlPTCsxVzROY05yNWdveVdSUUJ0cktKaWlTZEJVWmVxb0RvSUY5NHpCCndGbzJJT1JFdXFqcU51M3diMWZIM3p1dGdtalFra3IxVjJhd3hmcExLWlROQWdNQkFBRT0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg"
+}
\ No newline at end of file
diff --git a/Packages/com.unity.animation.rigging/CHANGELOG.md b/Packages/com.unity.animation.rigging/CHANGELOG.md
new file mode 100644
index 00000000..064221d5
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/CHANGELOG.md
@@ -0,0 +1,208 @@
+# Changelog
+All notable changes to this package will be documented in this file.
+
+## [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).
+- Fixed BoneRenderer to refresh bones rendered in viewport on a mouse drag and drop event (case 1361819).
+- Fixed potential performance issue with rig effectors when used in a deep hierarchy.
+- Fixed NullReferenceException when previewing animation and layers were not initialized in `RigBuilder.StartPreview` (case 1367857).
+- Added the function RigBuilder.SyncLayers to manually update rigs and constraints prior to PlayableGraph evaluation.
+- Added the function RigBuilder.Evaluate(float) to manually update and evaluate the RigBuilder.
+- Added the function RigBuilder.Build(PlayableGraph) to build the RigBuilder Playable nodes in an external PlayableGraph.
+- Added effector visuals for auto setup of Two-Bone IK.
+- Correctly positioned effectors for auto setup of Two-Bone IK.
+
+## [1.1.1] - 2021-08-23
+### Patch Update of *Animation Rigging*.
+- Added missing tooltips to components (case 1265274).
+- Labels on components now support localization in supported regions.
+- Upgraded Animation Rigging overlay toolbox to use new Unity overlays.
+
+## [1.1.0] - 2021-04-09
+### Patch Update of *Animation Rigging*.
+- Fixed Auto Setup on TwoBoneIK throwing an ArgumentNullException instead of a warning message.
+- Fixed MultiReferential constraint not writing driver transform to stream.
+- Added exceptions in ReadWriteTransformHandle and ReadOnlyTransformHandle to cover invalid Transform references (case 1275002).
+- Added functions ConstructConstraintDataPropertyName and ConstructCustomPropertyName to ConstraintsUtils public API.
+- Fixed Gizmo icons reimporting when switching platforms.
+- Added missing icon to TwistChainConstraint.
+- Built-in RigConstraint components now support multi-object editing in the Inspector.
+- Fixed bug causing multi-target constraints to add a new target simply by viewing them in the Inspector.
+- Fixed collapsing Source Objects and Settings foldouts in the Inspector going on the undo stack.
+ - Appearance of foldout groups now matches other Unity components.
+- Appearance of WeightedTransformArray in the Inspector now matches default array control.
+ - Header now supports dragging and dropping Transforms.
+- Validate constraint weights and source object weights are within supported range when deserializing built-in constraints in the Editor.
+- Improvements to help when creating custom constraints:
+ - RigConstraint m_Data field no longer displays nested under a foldout in the Inspector by default.
+ - RigConstraint.OnValidate() is now overridable in sub-classes.
+ - Added WeightedTransformArray.OnValidate().
+ - Added default PropertyDrawer for WeightedTransformArray that supports multi-select.
+ - Added optional WeightRangeAttribute. It should now be used in conjunction with WeightedTransformArray fields instead of RangeAttribute to specify the control should use a slider.
+- Updated samples to standard Samples/PackageName/Version/SampleName structure (case 1276329).
+- Fixed BoneRenderer and RigEffectors not respecting layer visibility flags (case 1238204).
+- Added support for nested struct properties tagged with the SyncSceneToStream attribute.
+- Fixed MultiParent and MultiPosition constraints evaluating with an offset when root game object scale is not one (case 1246893).
+- Fixed unnormalized rotation in TwoBoneIK constraint when hint weight is lower than one (case 1311769).
+- Removed editor only conditional compilation on serialized data (case 1324071).
+- Updated Burst to version 1.4.1.
+
+## [1.0.3] - 2020-08-21
+### Patch Update of *Animation Rigging*.
+- Updated Burst to version 1.3.4.
+
+## [1.0.2] - 2020-07-02
+### Patch Update of *Animation Rigging*.
+- Updated minimum unity release to 2020.2.0a16.
+
+## [1.0.1] - 2020-06-26
+### Verified release of *Animation Rigging*.
+- Added world up vector options for MultiAim.
+- Removed use of `latest` keyword in links to documentation (case 1233972).
+- Removed error log in CustomOverlayAttribute (case 1253862).
+- Disabled alt-picking on BoneRenderer in Scene View. [AAA-102]
+- Fixed unecessary GC Alloc in RigBuilder.Update(). [AAA-103]
+- Fixed TwoBoneIK inverse constraint not taking dynamic bone lengths into account.
+- Fixed ChainIK not applying chain rotation weight properly.
+
+## [0.3.3] - 2020-03-06
+### Patch Update of *Animation Rigging*.
+- Improved RigEffector picking when using custom shapes.
+- Improved RigEffector hover feedback when shape does not have line geometry.
+- Adjusted MultiAim calculations to prevent rolling effects (case 1215736).
+- Removed cached 'LimbLengths' in TwoBoneIKConstraintJob which lets users modify bone lengths dynamically. [AAA-97]
+- Fixed erroneous link to TwistChain constraint documentation in the ConstraintSamples readme. [AAA-95]
+- Fixed add and remove operations in ReorderableList when constraint is nested in prefab. [AAA-98]
+- Fixed undo operations in ReorderableList. [AAA-98]
+- Removed uses of Resources.Load in Runtime and Editor assemblies.
+
+## [0.3.2] - 2020-01-23
+### Patch Update of *Animation Rigging*.
+- Updated documentation.
+
+## [0.3.1] - 2020-01-14
+### Patch Update of *Animation Rigging*.
+- Removed unecessary files BakeUtils.cs.orig and BakeUtils.cs.orig.meta.
+- Updated Burst to version 1.2.0-preview.12.
+
+## [0.3.0] - 2019-10-18
+### Patch Update of *Animation Rigging*.
+- Added support for bidirectional-baking to existing constraints.
+
+## [0.2.5] - 2019-11-20
+### Patch Update of *Animation Rigging*.
+- Adjusted calculations on MultiAim constrained axes. [AAA-86]
+
+## [0.2.4] - 2019-11-06
+### Patch Update of *Animation Rigging*.
+- Added support for scene visibility and picking flags on BoneRenderer component and Rig effectors. [AAA-65]
+- Fixed preview of disabled RigBuilder component in Animation Window and Timeline. [AAA-37]
+- Fixed constrained axes in MultiAim not properly constraining local rotation. [AAA-86]
+- Updated Animation Rigging samples and added a Readme file.
+
+## [0.2.3] - 2019-07-24
+### Patch Update of *Animation Rigging*.
+- Increased the priority index of AnimationPlayableOutput in order for Animation Rigging to always evaluate after State Machine and Timeline.
+- Fixed NullReferenceException in RigEffectorRenderer.
+- Fixed TwoBoneIK evaluation when used on straight limbs by using hint target to define a valid IK plane.
+- Fixed Multi-Parent, Multi-Rotation and Multi-Aim constraints to perform order independent rotation blending. [AAA-17]
+- Fixed RigTransform component to work on all objects of an animator hierarchy not only specific to sub rig hierarchies. [AAA-18]
+- Fixed crash in RigSyncSceneToStreamJob when rebuilding jobs after having deleted all valid rigs (case 1167624).
+- Fixed undo/redo issues with Rig Effectors set on Prefab instances (case 1162002).
+- Fixed missing links to package documentation for MonoBehaviour scripts. [AAA-16]
+- Added Vector3IntProperty and Vector3BoolProperty helper structs.
+- Updated Burst to version 1.1.1.
+
+## [0.2.2] - 2019-04-29
+### Patch Update of *Animation Rigging*.
+- Added Rig Effector visualization toolkit for Animation Rigging.
+- Fixed Animation Rigging align operations not using the same selection order in Scene View and Hierarchy.
+- Updated Burst to version 1.0.4.
+
+## [0.2.1] - 2019-02-28
+### Patch Update of *Animation Rigging*.
+- Added Burst support to existing constraints. The Animation Rigging package now depends on com.unity.burst.
+- Upgraded weighted transform arrays in order for weights to be animatable. The following constraints were modified and will require a manual update:
+ - MultiAimConstraint
+ - MultiParentConstraint
+ - MultiPositionConstraint
+ - MultiReferentialConstraint
+ - TwistCorrection
+
+## [0.2.0] - 2019-02-12
+
+### Keyframing support for *Animation Rigging*.
+- Changed RigBuilder to build and update the PlayableGraph for Animation Window.
+- Added attribute [NotKeyable] to properties that shouldn't be animated.
+- Removed 'sync' property flag on transform fields for constraints. Syncing scene data to the animation stream is now performed by marking a constraint field with [SyncSceneToStream].
+- Fixed issue where constraint parameters were evaluated one frame late when animated.
+- Added attribute [DisallowMultipleComponent] to constraints to avoid use of multiple constraints per Game Object.
+- Updated constraints to use new AnimationStream API to reduce engine to script conversion.
+- Added IAnimatableProperty helpers for Bool/Int/Float/Vector2/Vector3/Vector4 properties.
+- Added ReadOnlyTransformHandle and ReadWriteTransformHandle.
+
+## [0.1.4] - 2018-12-21
+
+### Patch Update of *Animation Rigging*.
+- Fixed onSceneGUIDelegate deprecation warning in BoneRenderUtils
+
+## [0.1.3] - 2018-12-21
+
+### Patch Update of *Animation Rigging*.
+- Fixed stale bone rendering in prefab isolation view.
+- Updated constraints to have a transform sync scene to stream toggle only on inputs.
+- Fixed Twist Correction component to have twist nodes with weight varying between [-1, 1]
+- Added Maintain Offset dropdown to TwoBoneIK, ChainIK, Blend and Multi-Parent constraints
+- Added Rig Transform component in order to tag extra objects not specified by constraints to have an influence in the animation stream
+- Updated documentation and samples to reflect component changes
+
+## [0.1.2] - 2018-11-29
+
+### Patch Update of *Animation Rigging*.
+- Added constraint examples to Sample folder (Samples/ConstraintExamples/AnimationRiggingExamples.unitypackage)
+- Fixed links in documentation
+- Updated package description
+
+## [0.1.1] - 2018-11-26
+
+### Patch Update of *Animation Rigging*.
+- Improved blend constraint UI layout
+- Fixed jittering of DampedTransform when constraint weight was in between 0 and 1
+- Made generic interface of Get/Set AnimationJobCache functions
+- Added separate size parameters for bones and tripods in BoneRenderer.
+- Fixed NullReferenceException when deleting skeleton hierarchy while it's still being drawn by BoneRenderer.
+- Fixed Reset and Undo operations on BoneRenderer not updating skeleton rendering.
+- Reworked multi rig playable graph setup to have one initial scene to stream sync layer followed by subsequent rigs
+- Prune duplicate rig references prior to creating sync to stream job
+- Added passthrough conditions in animation jobs for proper stream values to be passed downstream when job weights are zero. Fixes a few major issues when character did not have a controller.
+- Fixed bug in ChainIK causing chain to not align to full extent when target is out of reach
+- Fixed TwoBoneIK bend normal strategy when limbs are collinear
+- Reworked AnimationJobData classes to be declared as structs in order for their serialized members to be keyable within the Animation Window.
+- Renamed component section and menu item "Runtime Rigging" to "Animation Rigging"
+- Added check in SyncToStreamJob to make sure StreamHandle is still valid prior to reading it's values.
+- Adding first draft of package documentation.
+
+## [0.1.0] - 2018-11-01
+
+### This is the first release of *Animation Rigging*.
+### Added
+- RigBuilder component.
+- Rig component.
+- The following RuntimeRigConstraint components:
+ - BlendConstraint
+ - ChainIKConstraint
+ - MultiAimConstraint
+ - MultiParentConstraint
+ - MultiPositionConstraint
+ - MultiReferentialConstraint
+ - OverrideTransform
+ - TwistCorrection
diff --git a/Packages/com.unity.animation.rigging/CHANGELOG.md.meta b/Packages/com.unity.animation.rigging/CHANGELOG.md.meta
new file mode 100644
index 00000000..b8d0e8f9
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/CHANGELOG.md.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 39c18d859abc65e41b8e5bf2267e013d
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.animation.rigging/DocCodeExamples.meta b/Packages/com.unity.animation.rigging/DocCodeExamples.meta
new file mode 100644
index 00000000..95fc13fd
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/DocCodeExamples.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: be78dea739b9e4fa68fe04d39c94b597
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.animation.rigging/DocCodeExamples/CustomPlayableGraphEvaluator.cs b/Packages/com.unity.animation.rigging/DocCodeExamples/CustomPlayableGraphEvaluator.cs
new file mode 100644
index 00000000..9c495e6f
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/DocCodeExamples/CustomPlayableGraphEvaluator.cs
@@ -0,0 +1,40 @@
+using UnityEngine;
+using UnityEngine.Animations.Rigging;
+using UnityEngine.Playables;
+
+namespace DocCodeExamples
+{
+ ///
+ /// Custom evaluator that manually evaluates the PlayableGraph in LateUpdate.
+ ///
+ #region custom-playable-graph-evaluator
+ [RequireComponent(typeof(RigBuilder))]
+ public class CustomPlayableGraphEvaluator : MonoBehaviour
+ {
+ private RigBuilder m_RigBuilder;
+ private PlayableGraph m_PlayableGraph;
+
+ void OnEnable()
+ {
+ m_RigBuilder = GetComponent();
+ m_PlayableGraph = PlayableGraph.Create();
+ m_PlayableGraph.SetTimeUpdateMode(DirectorUpdateMode.Manual);
+
+ m_RigBuilder.Build(m_PlayableGraph);
+ }
+
+ void OnDisable()
+ {
+ if (m_PlayableGraph.IsValid())
+ m_PlayableGraph.Destroy();
+ }
+
+ void LateUpdate()
+ {
+ m_RigBuilder.UpdateLayers();
+ m_PlayableGraph.Evaluate(Time.deltaTime);
+ m_RigBuilder.LateUpdateLayers();
+ }
+ }
+ #endregion
+}
diff --git a/Packages/com.unity.render-pipelines.core/Tests/Editor/Volumes/VolumeComponentCopyPasteTests.cs.meta b/Packages/com.unity.animation.rigging/DocCodeExamples/CustomPlayableGraphEvaluator.cs.meta
similarity index 83%
rename from Packages/com.unity.render-pipelines.core/Tests/Editor/Volumes/VolumeComponentCopyPasteTests.cs.meta
rename to Packages/com.unity.animation.rigging/DocCodeExamples/CustomPlayableGraphEvaluator.cs.meta
index 364037c2..6b52d127 100644
--- a/Packages/com.unity.render-pipelines.core/Tests/Editor/Volumes/VolumeComponentCopyPasteTests.cs.meta
+++ b/Packages/com.unity.animation.rigging/DocCodeExamples/CustomPlayableGraphEvaluator.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: ff5ab0e3d6cd4a5bab92dab9c63e8962
+guid: a2411ac2c7bbd4f58aaae3e6cefda2aa
MonoImporter:
externalObjects: {}
serializedVersion: 2
diff --git a/Packages/com.unity.animation.rigging/DocCodeExamples/CustomRigBuilderEvaluator.cs b/Packages/com.unity.animation.rigging/DocCodeExamples/CustomRigBuilderEvaluator.cs
new file mode 100644
index 00000000..5ba62153
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/DocCodeExamples/CustomRigBuilderEvaluator.cs
@@ -0,0 +1,35 @@
+using UnityEngine;
+using UnityEngine.Animations.Rigging;
+using UnityEngine.Playables;
+
+namespace DocCodeExamples
+{
+ ///
+ /// Custom Evaluator that manually evaluates the RigBuilder in LateUpdate.
+ ///
+ #region custom-rig-builder-evaluator
+ [RequireComponent(typeof(RigBuilder))]
+ public class CustomRigBuilderEvaluator : MonoBehaviour
+ {
+ private RigBuilder m_RigBuilder;
+
+ void OnEnable()
+ {
+ m_RigBuilder = GetComponent();
+
+ // Disable the RigBuilder and set its PlayableGraph to manual update mode
+ // to let the script evaluate it instead.
+ m_RigBuilder.enabled = false;
+ if (m_RigBuilder.Build())
+ {
+ m_RigBuilder.graph.SetTimeUpdateMode(DirectorUpdateMode.Manual);
+ }
+ }
+
+ void LateUpdate()
+ {
+ m_RigBuilder.Evaluate(Time.deltaTime);
+ }
+ }
+ #endregion
+}
diff --git a/Packages/com.unity.animation.rigging/DocCodeExamples/CustomRigBuilderEvaluator.cs.meta b/Packages/com.unity.animation.rigging/DocCodeExamples/CustomRigBuilderEvaluator.cs.meta
new file mode 100644
index 00000000..effbe104
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/DocCodeExamples/CustomRigBuilderEvaluator.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: dc9f69976d6143e489b841bec6ac5cfd
+timeCreated: 1636580728
\ No newline at end of file
diff --git a/Packages/com.unity.animation.rigging/DocCodeExamples/Unity.Animation.Rigging.DocCodeExamples.asmdef b/Packages/com.unity.animation.rigging/DocCodeExamples/Unity.Animation.Rigging.DocCodeExamples.asmdef
new file mode 100644
index 00000000..26c72887
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/DocCodeExamples/Unity.Animation.Rigging.DocCodeExamples.asmdef
@@ -0,0 +1,16 @@
+{
+ "name": "Unity.Animation.Rigging.DocCodeExamples",
+ "rootNamespace": "",
+ "references": [
+ "Unity.Animation.Rigging"
+ ],
+ "includePlatforms": [],
+ "excludePlatforms": [],
+ "allowUnsafeCode": false,
+ "overrideReferences": true,
+ "precompiledReferences": [],
+ "autoReferenced": false,
+ "defineConstraints": [],
+ "versionDefines": [],
+ "noEngineReferences": false
+}
diff --git a/Packages/com.unity.animation.rigging/DocCodeExamples/Unity.Animation.Rigging.DocCodeExamples.asmdef.meta b/Packages/com.unity.animation.rigging/DocCodeExamples/Unity.Animation.Rigging.DocCodeExamples.asmdef.meta
new file mode 100644
index 00000000..51aa406c
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/DocCodeExamples/Unity.Animation.Rigging.DocCodeExamples.asmdef.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: c2a5362f5f25b455f8f4eeea25441772
+AssemblyDefinitionImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.animation.rigging/Editor.meta b/Packages/com.unity.animation.rigging/Editor.meta
new file mode 100644
index 00000000..e3b2dc19
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 25a1bcc63261564418263e1b1fa0a713
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.animation.rigging/Editor/AnimationRig.meta b/Packages/com.unity.animation.rigging/Editor/AnimationRig.meta
new file mode 100644
index 00000000..bd149142
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: eade225a3b4a03d49af6485534a9dc23
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints.meta b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints.meta
new file mode 100644
index 00000000..1d22186c
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 754562bd98582a44e875ea6d688127ac
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/BlendConstraintEditor.cs b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/BlendConstraintEditor.cs
new file mode 100644
index 00000000..cfef227f
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/BlendConstraintEditor.cs
@@ -0,0 +1,163 @@
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Animations.Rigging;
+
+namespace UnityEditor.Animations.Rigging
+{
+ [CustomEditor(typeof(BlendConstraint))]
+ [CanEditMultipleObjects]
+ class BlendConstraintEditor : Editor
+ {
+ static class Content
+ {
+ public static readonly GUIContent sourceObjects = new GUIContent(CommonContent.sourceObjects.text);
+ public static readonly GUIContent sourceA = EditorGUIUtility.TrTextContent(
+ "Source A",
+ "The first source GameObject that influences the position and rotation of the Constrained Object."
+ );
+ public static readonly GUIContent sourceB = EditorGUIUtility.TrTextContent(
+ "Source B",
+ "The second source GameObject that influences the position and rotation of the Constrained Object."
+ );
+ public static readonly GUIContent settings = CommonContent.settings;
+ public static readonly GUIContent maintainOffset = CommonContent.maintainOffset;
+ public static readonly GUIContent blendPosition = EditorGUIUtility.TrTextContent(
+ "Blend A | B Position",
+ "If enabled, the constrained GameObject's position blends between those of Source A and Source B by the specified amount."
+ );
+ public static readonly GUIContent blendRotation = EditorGUIUtility.TrTextContent(
+ "Blend A | B Rotation",
+ "If enabled, the constrained GameObject's rotation blends between those of Source A and Source B by the specified amount."
+ );
+ }
+
+ SerializedProperty m_Weight;
+ SerializedProperty m_ConstrainedObject;
+ SerializedProperty m_SourceA;
+ SerializedProperty m_SourceB;
+ SerializedProperty m_BlendPosition;
+ SerializedProperty m_BlendRotation;
+ SerializedProperty m_PositionWeight;
+ SerializedProperty m_RotationWeight;
+ SerializedProperty m_MaintainPositionOffsets;
+ SerializedProperty m_MaintainRotationOffsets;
+
+ readonly FoldoutState m_SourceObjectsToggle = FoldoutState.ForSourceObjects();
+ readonly FoldoutState m_SettingsToggle = FoldoutState.ForSettings();
+
+ void OnEnable()
+ {
+ m_Weight = serializedObject.FindProperty("m_Weight");
+
+ var data = serializedObject.FindProperty("m_Data");
+ m_ConstrainedObject = data.FindPropertyRelative("m_ConstrainedObject");
+ m_SourceA = data.FindPropertyRelative("m_SourceA");
+ m_SourceB = data.FindPropertyRelative("m_SourceB");
+ m_BlendPosition = data.FindPropertyRelative("m_BlendPosition");
+ m_BlendRotation = data.FindPropertyRelative("m_BlendRotation");
+ m_PositionWeight = data.FindPropertyRelative("m_PositionWeight");
+ m_RotationWeight = data.FindPropertyRelative("m_RotationWeight");
+ m_MaintainPositionOffsets = data.FindPropertyRelative("m_MaintainPositionOffsets");
+ m_MaintainRotationOffsets = data.FindPropertyRelative("m_MaintainRotationOffsets");
+ }
+
+ public override void OnInspectorGUI()
+ {
+ serializedObject.Update();
+
+ EditorGUILayout.PropertyField(m_Weight, CommonContent.weight);
+ EditorGUILayout.PropertyField(m_ConstrainedObject, CommonContent.constrainedObject);
+
+ m_SourceObjectsToggle.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_SourceObjectsToggle.value, Content.sourceObjects);
+ if (m_SourceObjectsToggle.value)
+ {
+ EditorGUI.indentLevel++;
+ EditorGUILayout.PropertyField(m_SourceA, Content.sourceA);
+ EditorGUILayout.PropertyField(m_SourceB, Content.sourceB);
+ EditorGUI.indentLevel--;
+ }
+ EditorGUILayout.EndFoldoutHeaderGroup();
+
+ m_SettingsToggle.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_SettingsToggle.value, Content.settings);
+ if (m_SettingsToggle.value)
+ {
+ EditorGUI.indentLevel++;
+
+ MaintainOffsetHelper.DoDropdown(Content.maintainOffset, m_MaintainPositionOffsets, m_MaintainRotationOffsets);
+
+ EditorGUILayout.BeginHorizontal();
+ EditorGUILayout.PropertyField(m_BlendPosition, Content.blendPosition);
+ using (new EditorGUI.DisabledScope(!m_BlendPosition.boolValue))
+ EditorGUILayout.PropertyField(m_PositionWeight, GUIContent.none);
+ EditorGUILayout.EndHorizontal();
+
+ EditorGUILayout.BeginHorizontal();
+ EditorGUILayout.PropertyField(m_BlendRotation, Content.blendRotation);
+ using (new EditorGUI.DisabledScope(!m_BlendRotation.boolValue))
+ EditorGUILayout.PropertyField(m_RotationWeight, GUIContent.none);
+ EditorGUILayout.EndHorizontal();
+
+ EditorGUI.indentLevel--;
+ }
+ EditorGUILayout.EndFoldoutHeaderGroup();
+
+ serializedObject.ApplyModifiedProperties();
+ }
+
+ [MenuItem("CONTEXT/BlendConstraint/Transfer motion to skeleton", false, 612)]
+ public static void TransferMotionToSkeleton(MenuCommand command)
+ {
+ var constraint = command.context as BlendConstraint;
+ BakeUtils.TransferMotionToSkeleton(constraint);
+ }
+
+ [MenuItem("CONTEXT/BlendConstraint/Transfer motion to skeleton", true)]
+ public static bool TransferMotionValidate(MenuCommand command)
+ {
+ var constraint = command.context as BlendConstraint;
+ return BakeUtils.TransferMotionValidate(constraint);
+ }
+ }
+
+ [BakeParameters(typeof(BlendConstraint))]
+ class BlendConstraintBakeParameters : BakeParameters
+ {
+ public override bool canBakeToSkeleton => true;
+ public override bool canBakeToConstraint => false;
+
+ public override IEnumerable GetSourceCurveBindings(RigBuilder rigBuilder, BlendConstraint constraint)
+ {
+ var bindings = new List();
+ var sourceA = constraint.data.sourceObjectA;
+ var sourceB = constraint.data.sourceObjectB;
+
+ if (constraint.data.blendPosition)
+ {
+ EditorCurveBindingUtils.CollectPositionBindings(rigBuilder.transform, sourceA, bindings);
+ EditorCurveBindingUtils.CollectPositionBindings(rigBuilder.transform, sourceB, bindings);
+ }
+
+ if (constraint.data.blendRotation)
+ {
+ EditorCurveBindingUtils.CollectRotationBindings(rigBuilder.transform, sourceA, bindings);
+ EditorCurveBindingUtils.CollectRotationBindings(rigBuilder.transform, sourceB, bindings);
+ }
+
+ return bindings;
+ }
+
+ public override IEnumerable GetConstrainedCurveBindings(RigBuilder rigBuilder, BlendConstraint constraint)
+ {
+ var bindings = new List();
+ var constrained = constraint.data.constrainedObject;
+
+ if (constraint.data.blendPosition)
+ EditorCurveBindingUtils.CollectPositionBindings(rigBuilder.transform, constrained, bindings);
+
+ if(constraint.data.blendRotation)
+ EditorCurveBindingUtils.CollectRotationBindings(rigBuilder.transform, constrained, bindings);
+
+ return bindings;
+ }
+ }
+}
diff --git a/Packages/com.unity.render-pipelines.core/Tests/Editor/Volumes/VolumeComponentEditorSupportedOnTests.cs.meta b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/BlendConstraintEditor.cs.meta
similarity index 83%
rename from Packages/com.unity.render-pipelines.core/Tests/Editor/Volumes/VolumeComponentEditorSupportedOnTests.cs.meta
rename to Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/BlendConstraintEditor.cs.meta
index 30e83ce7..3a37288b 100644
--- a/Packages/com.unity.render-pipelines.core/Tests/Editor/Volumes/VolumeComponentEditorSupportedOnTests.cs.meta
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/BlendConstraintEditor.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: 172ced047a38440389ff238ad1d347ce
+guid: a8670d948642f1546a4835c189aea303
MonoImporter:
externalObjects: {}
serializedVersion: 2
diff --git a/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/ChainIKConstraintEditor.cs b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/ChainIKConstraintEditor.cs
new file mode 100644
index 00000000..8ccde887
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/ChainIKConstraintEditor.cs
@@ -0,0 +1,156 @@
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Animations.Rigging;
+
+namespace UnityEditor.Animations.Rigging
+{
+ [CustomEditor(typeof(ChainIKConstraint))]
+ [CanEditMultipleObjects]
+ class ChainIKConstraintEditor : Editor
+ {
+ static class Content
+ {
+ public static readonly GUIContent root = EditorGUIUtility.TrTextContent(
+ "Root",
+ "The root GameObject of the chain hierarchy."
+ );
+ public static readonly GUIContent tip = EditorGUIUtility.TrTextContent(
+ "Tip",
+ "The final GameObject of the chain hierarchy. It must be a descendant of the Root GameObject."
+ );
+ public static readonly GUIContent target = EditorGUIUtility.TrTextContent(
+ "Target",
+ "The GameObject that specifies the desired target transform for the chain's Tip."
+ );
+ public static readonly GUIContent sourceObjects = new GUIContent(CommonContent.sourceObjects.text);
+ public static readonly GUIContent chainRotationWeight = EditorGUIUtility.TrTextContent(
+ "Chain Rotation Weight",
+ "The weight of rotations applied throughout the chain."
+ );
+ public static readonly GUIContent tipRotationWeight = EditorGUIUtility.TrTextContent(
+ "Tip Rotation Weight",
+ "The weight of the rotation applied to the Tip."
+ );
+ public static readonly GUIContent maxIterations = EditorGUIUtility.TrTextContent(
+ "Max Iterations",
+ "The maximum number of solver iterations to perform to try to make the Tip reach the Target within the specified Tolerance threshold."
+ );
+ public static readonly GUIContent tolerance = EditorGUIUtility.TrTextContent(
+ "Tolerance",
+ "Distance tolerance between the Target and Tip GameObjects. " +
+ "The solver will finish its computation if the distance is less than this value at any point, even if Max Iterations has not been reached."
+ );
+ }
+
+ SerializedProperty m_Weight;
+ SerializedProperty m_Root;
+ SerializedProperty m_Tip;
+ SerializedProperty m_Target;
+ SerializedProperty m_ChainRotationWeight;
+ SerializedProperty m_TipRotationWeight;
+ SerializedProperty m_MaxIterations;
+ SerializedProperty m_Tolerance;
+ SerializedProperty m_MaintainTargetPositionOffset;
+ SerializedProperty m_MaintainTargetRotationOffset;
+
+ readonly FoldoutState m_SourceObjectsToggle = FoldoutState.ForSourceObjects();
+ readonly FoldoutState m_SettingsToggle = FoldoutState.ForSettings();
+
+ void OnEnable()
+ {
+ m_Weight = serializedObject.FindProperty("m_Weight");
+
+ var data = serializedObject.FindProperty("m_Data");
+ m_Root = data.FindPropertyRelative("m_Root");
+ m_Tip = data.FindPropertyRelative("m_Tip");
+ m_Target = data.FindPropertyRelative("m_Target");
+ m_ChainRotationWeight = data.FindPropertyRelative("m_ChainRotationWeight");
+ m_TipRotationWeight = data.FindPropertyRelative("m_TipRotationWeight");
+ m_MaxIterations = data.FindPropertyRelative("m_MaxIterations");
+ m_Tolerance = data.FindPropertyRelative("m_Tolerance");
+ m_MaintainTargetPositionOffset = data.FindPropertyRelative("m_MaintainTargetPositionOffset");
+ m_MaintainTargetRotationOffset = data.FindPropertyRelative("m_MaintainTargetRotationOffset");
+ }
+
+ public override void OnInspectorGUI()
+ {
+ serializedObject.Update();
+
+ EditorGUILayout.PropertyField(m_Weight, CommonContent.weight);
+ EditorGUILayout.PropertyField(m_Root, Content.root);
+ EditorGUILayout.PropertyField(m_Tip, Content.tip);
+
+ m_SourceObjectsToggle.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_SourceObjectsToggle.value, Content.sourceObjects);
+ if (m_SourceObjectsToggle.value)
+ {
+ EditorGUI.indentLevel++;
+ EditorGUILayout.PropertyField(m_Target, Content.target);
+ EditorGUI.indentLevel--;
+ }
+ EditorGUILayout.EndFoldoutHeaderGroup();
+
+ m_SettingsToggle.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_SettingsToggle.value, CommonContent.settings);
+ if (m_SettingsToggle.value)
+ {
+ EditorGUI.indentLevel++;
+ MaintainOffsetHelper.DoDropdown(CommonContent.maintainIKTargetOffset, m_MaintainTargetPositionOffset, m_MaintainTargetRotationOffset);
+ EditorGUILayout.PropertyField(m_ChainRotationWeight, Content.chainRotationWeight);
+ EditorGUILayout.PropertyField(m_TipRotationWeight, Content.tipRotationWeight);
+ EditorGUILayout.PropertyField(m_MaxIterations, Content.maxIterations);
+ EditorGUILayout.PropertyField(m_Tolerance, Content.tolerance);
+ EditorGUI.indentLevel--;
+ }
+ EditorGUILayout.EndFoldoutHeaderGroup();
+
+ serializedObject.ApplyModifiedProperties();
+ }
+
+ [MenuItem("CONTEXT/ChainIKConstraint/Transfer motion to skeleton", false, 612)]
+ public static void TransferMotionToSkeleton(MenuCommand command)
+ {
+ var constraint = command.context as ChainIKConstraint;
+ BakeUtils.TransferMotionToSkeleton(constraint);
+ }
+
+ [MenuItem("CONTEXT/ChainIKConstraint/Transfer motion to skeleton", true)]
+ public static bool TransferMotionValidate(MenuCommand command)
+ {
+ var constraint = command.context as ChainIKConstraint;
+ return BakeUtils.TransferMotionValidate(constraint);
+ }
+ }
+
+ [BakeParameters(typeof(ChainIKConstraint))]
+ class ChainIKConstraintBakeParameters : BakeParameters
+ {
+ public override bool canBakeToSkeleton => true;
+ public override bool canBakeToConstraint => false;
+
+ public override IEnumerable GetSourceCurveBindings(RigBuilder rigBuilder, ChainIKConstraint constraint)
+ {
+ var bindings = new List();
+
+ EditorCurveBindingUtils.CollectTRBindings(rigBuilder.transform, constraint.data.target, bindings);
+
+ return bindings;
+ }
+
+ public override IEnumerable GetConstrainedCurveBindings(RigBuilder rigBuilder, ChainIKConstraint constraint)
+ {
+ var bindings = new List();
+
+ var root = constraint.data.root;
+ var tip = constraint.data.tip;
+
+ var tmp = tip;
+ while (tmp != root)
+ {
+ EditorCurveBindingUtils.CollectRotationBindings(rigBuilder.transform, tmp, bindings);
+ tmp = tmp.parent;
+ }
+ EditorCurveBindingUtils.CollectRotationBindings(rigBuilder.transform, root, bindings);
+
+ return bindings;
+ }
+ }
+}
diff --git a/Packages/com.unity.render-pipelines.core/Tests/Editor/Volumes/VolumeComponentVisibilityTests.cs.meta b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/ChainIKConstraintEditor.cs.meta
similarity index 83%
rename from Packages/com.unity.render-pipelines.core/Tests/Editor/Volumes/VolumeComponentVisibilityTests.cs.meta
rename to Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/ChainIKConstraintEditor.cs.meta
index 4361a499..21f656b3 100644
--- a/Packages/com.unity.render-pipelines.core/Tests/Editor/Volumes/VolumeComponentVisibilityTests.cs.meta
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/ChainIKConstraintEditor.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: 81dd1b9facda41f9a09fb997d6e64670
+guid: 63110210264e2ee4da7389733e5958ae
MonoImporter:
externalObjects: {}
serializedVersion: 2
diff --git a/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/DampedTransformEditor.cs b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/DampedTransformEditor.cs
new file mode 100644
index 00000000..63d2218b
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/DampedTransformEditor.cs
@@ -0,0 +1,122 @@
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Animations.Rigging;
+
+namespace UnityEditor.Animations.Rigging
+{
+ [CustomEditor(typeof(DampedTransform))]
+ [CanEditMultipleObjects]
+ class DampedTransformEditor : Editor
+ {
+ static class Content
+ {
+ public static readonly GUIContent source = EditorGUIUtility.TrTextContent(
+ "Source",
+ "The GameObject that influences the Constrained Object's transform."
+ );
+ public static readonly GUIContent dampPosition = EditorGUIUtility.TrTextContent(
+ "Damp Position",
+ "The weight of positional damping to apply to the Constrained Object."
+ );
+ public static readonly GUIContent dampRotation = EditorGUIUtility.TrTextContent(
+ "Damp Rotation",
+ "The weight of rotational damping to apply to the Constrained Object."
+ );
+ public static readonly GUIContent maintainAim = EditorGUIUtility.TrTextContent(
+ "Maintain Aim",
+ "Specifies whether to maintain the initial rotation offset between the Constrained Object and the Source Object."
+ );
+ }
+
+ SerializedProperty m_Weight;
+ SerializedProperty m_ConstrainedObject;
+ SerializedProperty m_Source;
+ SerializedProperty m_DampPosition;
+ SerializedProperty m_DampRotation;
+ SerializedProperty m_MaintainAim;
+
+ readonly FoldoutState m_SourceObjectsToggle = FoldoutState.ForSourceObjects();
+ readonly FoldoutState m_SettingsToggle = FoldoutState.ForSettings();
+
+ void OnEnable()
+ {
+ m_Weight = serializedObject.FindProperty("m_Weight");
+
+ var data = serializedObject.FindProperty("m_Data");
+ m_ConstrainedObject = data.FindPropertyRelative("m_ConstrainedObject");
+ m_Source = data.FindPropertyRelative("m_Source");
+ m_DampPosition = data.FindPropertyRelative("m_DampPosition");
+ m_DampRotation = data.FindPropertyRelative("m_DampRotation");
+ m_MaintainAim = data.FindPropertyRelative("m_MaintainAim");
+ }
+
+ public override void OnInspectorGUI()
+ {
+ serializedObject.Update();
+
+ EditorGUILayout.PropertyField(m_Weight, CommonContent.weight);
+ EditorGUILayout.PropertyField(m_ConstrainedObject, CommonContent.constrainedObject);
+
+ m_SourceObjectsToggle.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_SourceObjectsToggle.value, Content.source);
+ if (m_SourceObjectsToggle.value)
+ {
+ EditorGUI.indentLevel++;
+ EditorGUILayout.PropertyField(m_Source, Content.source);
+ EditorGUI.indentLevel--;
+ }
+ EditorGUILayout.EndFoldoutHeaderGroup();
+
+ m_SettingsToggle.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_SettingsToggle.value, CommonContent.settings);
+ if (m_SettingsToggle.value)
+ {
+ EditorGUI.indentLevel++;
+ EditorGUILayout.PropertyField(m_DampPosition, Content.dampPosition);
+ EditorGUILayout.PropertyField(m_DampRotation, Content.dampRotation);
+ EditorGUILayout.PropertyField(m_MaintainAim, Content.maintainAim);
+ EditorGUI.indentLevel--;
+ }
+ EditorGUILayout.EndFoldoutHeaderGroup();
+
+ serializedObject.ApplyModifiedProperties();
+ }
+
+ [MenuItem("CONTEXT/DampedTransform/Transfer motion to skeleton", false, 612)]
+ public static void TransferMotionToSkeleton(MenuCommand command)
+ {
+ var constraint = command.context as DampedTransform;
+ BakeUtils.TransferMotionToSkeleton(constraint);
+ }
+
+ [MenuItem("CONTEXT/DampedTransform/Transfer motion to skeleton", true)]
+ public static bool TransferMotionValidate(MenuCommand command)
+ {
+ var constraint = command.context as DampedTransform;
+ return BakeUtils.TransferMotionValidate(constraint);
+ }
+ }
+
+ [BakeParameters(typeof(DampedTransform))]
+ class DampedTransformBakeParameters : BakeParameters
+ {
+ public override bool canBakeToSkeleton => true;
+ public override bool canBakeToConstraint => false;
+
+ public override IEnumerable GetSourceCurveBindings(RigBuilder rigBuilder, DampedTransform constraint)
+ {
+ var bindings = new List();
+
+ EditorCurveBindingUtils.CollectTRBindings(rigBuilder.transform, constraint.data.sourceObject, bindings);
+
+ return bindings;
+ }
+
+ public override IEnumerable GetConstrainedCurveBindings(RigBuilder rigBuilder, DampedTransform constraint)
+ {
+ var bindings = new List();
+
+ EditorCurveBindingUtils.CollectTRBindings(rigBuilder.transform, constraint.data.constrainedObject, bindings);
+
+ return bindings;
+ }
+ }
+}
diff --git a/Packages/com.unity.render-pipelines.core/Tests/Runtime/TestVolume.cs.meta b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/DampedTransformEditor.cs.meta
similarity index 83%
rename from Packages/com.unity.render-pipelines.core/Tests/Runtime/TestVolume.cs.meta
rename to Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/DampedTransformEditor.cs.meta
index 3767065d..46555b33 100644
--- a/Packages/com.unity.render-pipelines.core/Tests/Runtime/TestVolume.cs.meta
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/DampedTransformEditor.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: 74955a4b0b4243bc87231e8b59ed9140
+guid: 99a3cbe2e69614541bdf264c5e905f48
MonoImporter:
externalObjects: {}
serializedVersion: 2
diff --git a/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiAimConstraintEditor.cs b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiAimConstraintEditor.cs
new file mode 100644
index 00000000..693217ae
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiAimConstraintEditor.cs
@@ -0,0 +1,197 @@
+using System.Collections.Generic;
+using System.Linq;
+using UnityEngine;
+using UnityEngine.Animations.Rigging;
+
+namespace UnityEditor.Animations.Rigging
+{
+ [CustomEditor(typeof(MultiAimConstraint))]
+ [CanEditMultipleObjects]
+ class MultiAimConstraintEditor : Editor
+ {
+ static class Content
+ {
+ public static readonly GUIContent[] axisLabels = new []{ "X", "-X", "Y", "-Y", "Z", "-Z" }
+ .Select(c => new GUIContent(c))
+ .ToArray();
+ public static readonly GUIContent aimAxis = EditorGUIUtility.TrTextContent(
+ "Aim Axis",
+ "Specifies the local aim axis of the Constrained Object to use in order to orient its forward direction to the Source Objects."
+ );
+ public static readonly GUIContent upAxis = EditorGUIUtility.TrTextContent(
+ "Up Axis",
+ "Specifies the local up axis of the Constrained Object to use in order to orient its upward direction (i.e., roll orientation)."
+ );
+ public static readonly GUIContent worldUpType = EditorGUIUtility.TrTextContent(
+ "World Up Type",
+ "Specifies which mode to use to stabilize the upward direction (i.e., roll orientation) of the Constrained Object."
+ );
+ public static readonly GUIContent worldUpAxis = EditorGUIUtility.TrTextContent(
+ "World Up Axis",
+ "A vector in some reference frame that is used to stabilize the upward direction of the Constrained Object. " +
+ "This value is used when World Up Type is either Vector or Object Rotation Up."
+ );
+ public static readonly GUIContent worldUpObject = EditorGUIUtility.TrTextContent(
+ "World Up Object",
+ "A GameObject used as a reference frame for World Up Axis. " +
+ "This value is used when World Up Type is either Object Up or Object Rotation Up."
+ );
+ public static readonly GUIContent sourceObjects = CommonContent.sourceObjectsWeightedRotation;
+ public static readonly GUIContent settings = CommonContent.settings;
+ public static readonly GUIContent maintainOffset = CommonContent.maintainRotationOffset;
+ public static readonly GUIContent minLimit = EditorGUIUtility.TrTextContent(
+ "Min Limit",
+ "Clamps the minimum rotation that may be applied about any of the constrained axes of rotation."
+ );
+ public static readonly GUIContent maxLimit = EditorGUIUtility.TrTextContent(
+ "Max Limit",
+ "Clamps the maximum rotation that may be applied about any of the constrained axes of rotation."
+ );
+ }
+
+ SerializedProperty m_Weight;
+ SerializedProperty m_ConstrainedObject;
+ SerializedProperty m_AimAxis;
+ SerializedProperty m_UpAxis;
+ SerializedProperty m_WorldUpType;
+ SerializedProperty m_WorldUpAxis;
+ SerializedProperty m_WorldUpObject;
+ SerializedProperty m_SourceObjects;
+ SerializedProperty m_MaintainOffset;
+ SerializedProperty m_Offset;
+ SerializedProperty m_ConstrainedAxes;
+ SerializedProperty m_MinLimit;
+ SerializedProperty m_MaxLimit;
+
+ readonly FoldoutState m_SettingsToggle = FoldoutState.ForSettings();
+
+ void OnEnable()
+ {
+ m_Weight = serializedObject.FindProperty("m_Weight");
+
+ var data = serializedObject.FindProperty("m_Data");
+ m_ConstrainedObject = data.FindPropertyRelative("m_ConstrainedObject");
+ m_AimAxis = data.FindPropertyRelative("m_AimAxis");
+ m_UpAxis = data.FindPropertyRelative("m_UpAxis");
+ m_WorldUpType = data.FindPropertyRelative("m_WorldUpType");
+ m_WorldUpAxis = data.FindPropertyRelative("m_WorldUpAxis");
+ m_WorldUpObject = data.FindPropertyRelative("m_WorldUpObject");
+ m_SourceObjects = data.FindPropertyRelative("m_SourceObjects");
+ m_MaintainOffset = data.FindPropertyRelative("m_MaintainOffset");
+ m_Offset = data.FindPropertyRelative("m_Offset");
+ m_ConstrainedAxes = data.FindPropertyRelative("m_ConstrainedAxes");
+ m_MinLimit = data.FindPropertyRelative("m_MinLimit");
+ m_MaxLimit = data.FindPropertyRelative("m_MaxLimit");
+ }
+
+ public override void OnInspectorGUI()
+ {
+ serializedObject.Update();
+
+ EditorGUILayout.PropertyField(m_Weight, CommonContent.weight);
+
+ EditorGUILayout.PropertyField(m_ConstrainedObject, CommonContent.constrainedObject);
+
+ ++EditorGUI.indentLevel;
+ DoAxisField(m_AimAxis, Content.aimAxis);
+ DoAxisField(m_UpAxis, Content.upAxis);
+ --EditorGUI.indentLevel;
+
+ EditorGUILayout.PropertyField(m_WorldUpType, Content.worldUpType);
+
+ var worldUpType = (MultiAimConstraintData.WorldUpType)m_WorldUpType.intValue;
+
+ ++EditorGUI.indentLevel;
+ using (new EditorGUI.DisabledGroupScope(worldUpType != MultiAimConstraintData.WorldUpType.ObjectRotationUp && worldUpType != MultiAimConstraintData.WorldUpType.Vector))
+ {
+ DoAxisField(m_WorldUpAxis, Content.worldUpAxis);
+ }
+ using (new EditorGUI.DisabledGroupScope(worldUpType != MultiAimConstraintData.WorldUpType.ObjectUp && worldUpType != MultiAimConstraintData.WorldUpType.ObjectRotationUp))
+ {
+ EditorGUILayout.PropertyField(m_WorldUpObject, Content.worldUpObject);
+ }
+ --EditorGUI.indentLevel;
+
+ EditorGUILayout.PropertyField(m_SourceObjects, Content.sourceObjects);
+
+ m_SettingsToggle.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_SettingsToggle.value, Content.settings);
+ if (m_SettingsToggle.value)
+ {
+ EditorGUI.indentLevel++;
+ EditorGUILayout.PropertyField(m_MaintainOffset, Content.maintainOffset);
+ EditorGUILayout.PropertyField(m_Offset, CommonContent.offsetRotation);
+ EditorGUILayout.PropertyField(m_ConstrainedAxes, CommonContent.constrainedAxesRotation);
+ EditorGUILayout.PropertyField(m_MinLimit, Content.minLimit);
+ EditorGUILayout.PropertyField(m_MaxLimit, Content.maxLimit);
+ EditorGUI.indentLevel--;
+ }
+ EditorGUILayout.EndFoldoutHeaderGroup();
+
+ serializedObject.ApplyModifiedProperties();
+ }
+
+ static void DoAxisField(SerializedProperty property, GUIContent label)
+ {
+ var rect = EditorGUILayout.GetControlRect();
+ EditorGUI.BeginProperty(rect, label, property);
+ EditorGUI.BeginChangeCheck();
+ var newValue = EditorGUI.Popup(rect, label, property.intValue, Content.axisLabels);
+ if (EditorGUI.EndChangeCheck())
+ property.intValue = newValue;
+ EditorGUI.EndProperty();
+ }
+
+ [MenuItem("CONTEXT/MultiAimConstraint/Transfer motion to constraint", false, 611)]
+ public static void TransferMotionToConstraint(MenuCommand command)
+ {
+ var constraint = command.context as MultiAimConstraint;
+ BakeUtils.TransferMotionToConstraint(constraint);
+ }
+
+ [MenuItem("CONTEXT/MultiAimConstraint/Transfer motion to skeleton", false, 612)]
+ public static void TransferMotionToSkeleton(MenuCommand command)
+ {
+ var constraint = command.context as MultiAimConstraint;
+ BakeUtils.TransferMotionToSkeleton(constraint);
+ }
+
+ [MenuItem("CONTEXT/MultiAimConstraint/Transfer motion to constraint", true)]
+ [MenuItem("CONTEXT/MultiAimConstraint/Transfer motion to skeleton", true)]
+ public static bool TransferMotionValidate(MenuCommand command)
+ {
+ var constraint = command.context as MultiAimConstraint;
+ return BakeUtils.TransferMotionValidate(constraint);
+ }
+ }
+
+ [BakeParameters(typeof(MultiAimConstraint))]
+ class MultiAimConstraintBakeParameters : BakeParameters
+ {
+ public override bool canBakeToSkeleton => true;
+ public override bool canBakeToConstraint => true;
+
+ public override IEnumerable GetSourceCurveBindings(RigBuilder rigBuilder, MultiAimConstraint constraint)
+ {
+ var bindings = new List();
+
+ for (int i = 0; i < constraint.data.sourceObjects.Count; ++i)
+ {
+ var sourceObject = constraint.data.sourceObjects[i];
+
+ EditorCurveBindingUtils.CollectPositionBindings(rigBuilder.transform, sourceObject.transform, bindings);
+ EditorCurveBindingUtils.CollectPropertyBindings(rigBuilder.transform, constraint, ((IMultiAimConstraintData)constraint.data).sourceObjectsProperty + ".m_Item" + i + ".weight", bindings);
+ }
+
+ return bindings;
+ }
+
+ public override IEnumerable GetConstrainedCurveBindings(RigBuilder rigBuilder, MultiAimConstraint constraint)
+ {
+ var bindings = new List();
+
+ EditorCurveBindingUtils.CollectRotationBindings(rigBuilder.transform, constraint.data.constrainedObject, bindings);
+
+ return bindings;
+ }
+ }
+}
diff --git a/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiAimConstraintEditor.cs.meta b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiAimConstraintEditor.cs.meta
new file mode 100644
index 00000000..cb5cc525
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiAimConstraintEditor.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 9a96277d4d9d2d04181fc5ce44119fdf
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiParentConstraintEditor.cs b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiParentConstraintEditor.cs
new file mode 100644
index 00000000..e44a15da
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiParentConstraintEditor.cs
@@ -0,0 +1,121 @@
+using UnityEngine;
+using UnityEngine.Animations.Rigging;
+using System.Collections.Generic;
+
+namespace UnityEditor.Animations.Rigging
+{
+ [CustomEditor(typeof(MultiParentConstraint))]
+ [CanEditMultipleObjects]
+ class MultiParentConstraintEditor : Editor
+ {
+ static class Content
+ {
+ public static readonly GUIContent constrainedPositionAxes = new GUIContent(
+ L10n.Tr("Constrained Position Axes"),
+ CommonContent.constrainedAxesPosition.tooltip
+ );
+ public static readonly GUIContent constrainedRotationAxes = new GUIContent(
+ L10n.Tr("Constrained Rotation Axes"),
+ CommonContent.constrainedAxesRotation.tooltip
+ );
+ }
+
+ SerializedProperty m_Weight;
+ SerializedProperty m_ConstrainedObject;
+ SerializedProperty m_ConstrainedPositionAxes;
+ SerializedProperty m_ConstrainedRotationAxes;
+ SerializedProperty m_SourceObjects;
+ SerializedProperty m_MaintainPositionOffset;
+ SerializedProperty m_MaintainRotationOffset;
+
+ readonly FoldoutState m_SettingsToggle = FoldoutState.ForSettings();
+
+ void OnEnable()
+ {
+ m_Weight = serializedObject.FindProperty("m_Weight");
+
+ var data = serializedObject.FindProperty("m_Data");
+ m_ConstrainedObject = data.FindPropertyRelative("m_ConstrainedObject");
+ m_ConstrainedPositionAxes = data.FindPropertyRelative("m_ConstrainedPositionAxes");
+ m_ConstrainedRotationAxes = data.FindPropertyRelative("m_ConstrainedRotationAxes");
+ m_SourceObjects = data.FindPropertyRelative("m_SourceObjects");
+ m_MaintainPositionOffset = data.FindPropertyRelative("m_MaintainPositionOffset");
+ m_MaintainRotationOffset = data.FindPropertyRelative("m_MaintainRotationOffset");
+ }
+
+ public override void OnInspectorGUI()
+ {
+ serializedObject.Update();
+
+ EditorGUILayout.PropertyField(m_Weight, CommonContent.weight);
+ EditorGUILayout.PropertyField(m_ConstrainedObject, CommonContent.constrainedObject);
+ EditorGUILayout.PropertyField(m_SourceObjects, CommonContent.sourceObjects);
+
+ m_SettingsToggle.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_SettingsToggle.value, CommonContent.settings);
+ if (m_SettingsToggle.value)
+ {
+ EditorGUI.indentLevel++;
+ MaintainOffsetHelper.DoDropdown(CommonContent.maintainOffset, m_MaintainPositionOffset, m_MaintainRotationOffset);
+ EditorGUILayout.PropertyField(m_ConstrainedPositionAxes, Content.constrainedPositionAxes);
+ EditorGUILayout.PropertyField(m_ConstrainedRotationAxes, Content.constrainedRotationAxes);
+ EditorGUI.indentLevel--;
+ }
+ EditorGUILayout.EndFoldoutHeaderGroup();
+
+ serializedObject.ApplyModifiedProperties();
+ }
+
+ [MenuItem("CONTEXT/MultiParentConstraint/Transfer motion to constraint", false, 611)]
+ public static void TransferMotionToConstraint(MenuCommand command)
+ {
+ var constraint = command.context as MultiParentConstraint;
+ BakeUtils.TransferMotionToConstraint(constraint);
+ }
+
+ [MenuItem("CONTEXT/MultiParentConstraint/Transfer motion to skeleton", false, 612)]
+ public static void TransferMotionToSkeleton(MenuCommand command)
+ {
+ var constraint = command.context as MultiParentConstraint;
+ BakeUtils.TransferMotionToSkeleton(constraint);
+ }
+
+ [MenuItem("CONTEXT/MultiParentConstraint/Transfer motion to constraint", true)]
+ [MenuItem("CONTEXT/MultiParentConstraint/Transfer motion to skeleton", true)]
+ public static bool TransferMotionValidate(MenuCommand command)
+ {
+ var constraint = command.context as MultiParentConstraint;
+ return BakeUtils.TransferMotionValidate(constraint);
+ }
+ }
+
+ [BakeParameters(typeof(MultiParentConstraint))]
+ class MultiParentConstraintParameters : BakeParameters
+ {
+ public override bool canBakeToSkeleton => true;
+ public override bool canBakeToConstraint => true;
+
+ public override IEnumerable GetSourceCurveBindings(RigBuilder rigBuilder, MultiParentConstraint constraint)
+ {
+ var bindings = new List();
+
+ for (int i = 0; i < constraint.data.sourceObjects.Count; ++i)
+ {
+ var sourceObject = constraint.data.sourceObjects[i];
+
+ EditorCurveBindingUtils.CollectPositionBindings(rigBuilder.transform, sourceObject.transform, bindings);
+ EditorCurveBindingUtils.CollectRotationBindings(rigBuilder.transform, sourceObject.transform, bindings);
+ EditorCurveBindingUtils.CollectPropertyBindings(rigBuilder.transform, constraint, ((IMultiParentConstraintData)constraint.data).sourceObjectsProperty + ".m_Item" + i + ".weight", bindings);
+ }
+
+ return bindings;
+ }
+
+ public override IEnumerable GetConstrainedCurveBindings(RigBuilder rigBuilder, MultiParentConstraint constraint)
+ {
+ var bindings = new List();
+ EditorCurveBindingUtils.CollectPositionBindings(rigBuilder.transform, constraint.data.constrainedObject, bindings);
+ EditorCurveBindingUtils.CollectRotationBindings(rigBuilder.transform, constraint.data.constrainedObject, bindings);
+ return bindings;
+ }
+ }
+}
diff --git a/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiParentConstraintEditor.cs.meta b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiParentConstraintEditor.cs.meta
new file mode 100644
index 00000000..be085b9f
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiParentConstraintEditor.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 2326ba71c8dbcba4ea941bf20e7e1bbc
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiPositionConstraintEditor.cs b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiPositionConstraintEditor.cs
new file mode 100644
index 00000000..716b0bdb
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiPositionConstraintEditor.cs
@@ -0,0 +1,118 @@
+using UnityEngine;
+using UnityEngine.Animations.Rigging;
+using System.Collections.Generic;
+
+namespace UnityEditor.Animations.Rigging
+{
+ [CustomEditor(typeof(MultiPositionConstraint))]
+ [CanEditMultipleObjects]
+ class MultiPositionConstraintEditor : Editor
+ {
+ SerializedProperty m_Weight;
+ SerializedProperty m_ConstrainedObject;
+ SerializedProperty m_ConstrainedAxes;
+ SerializedProperty m_SourceObjects;
+ SerializedProperty m_MaintainOffset;
+ SerializedProperty m_Offset;
+
+ readonly FoldoutState m_SettingsToggle = FoldoutState.ForSettings();
+
+ void OnEnable()
+ {
+ m_Weight = serializedObject.FindProperty("m_Weight");
+
+ var data = serializedObject.FindProperty("m_Data");
+ m_ConstrainedObject = data.FindPropertyRelative("m_ConstrainedObject");
+ m_ConstrainedAxes = data.FindPropertyRelative("m_ConstrainedAxes");
+ m_SourceObjects = data.FindPropertyRelative("m_SourceObjects");
+ m_MaintainOffset = data.FindPropertyRelative("m_MaintainOffset");
+ m_Offset = data.FindPropertyRelative("m_Offset");
+ }
+
+ public override void OnInspectorGUI()
+ {
+ serializedObject.Update();
+
+ EditorGUILayout.PropertyField(m_Weight, CommonContent.weight);
+ EditorGUILayout.PropertyField(m_ConstrainedObject, CommonContent.constrainedObject);
+ EditorGUILayout.PropertyField(m_ConstrainedAxes, CommonContent.constrainedAxesPosition);
+ EditorGUILayout.PropertyField(m_SourceObjects, CommonContent.sourceObjectsWeightedPosition);
+
+ m_SettingsToggle.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_SettingsToggle.value, CommonContent.settings);
+ if (m_SettingsToggle.value)
+ {
+ EditorGUI.indentLevel++;
+ EditorGUILayout.PropertyField(m_MaintainOffset, CommonContent.maintainPositionOffset);
+ EditorGUILayout.PropertyField(m_Offset, CommonContent.offsetPosition);
+ EditorGUI.indentLevel--;
+ }
+ EditorGUILayout.EndFoldoutHeaderGroup();
+
+ serializedObject.ApplyModifiedProperties();
+ }
+
+ [MenuItem("CONTEXT/MultiPositionConstraint/Transfer motion to constraint", false, 611)]
+ public static void TransferMotionToConstraint(MenuCommand command)
+ {
+ var constraint = command.context as MultiPositionConstraint;
+
+ var axesMask = new Vector3(
+ System.Convert.ToSingle(constraint.data.constrainedXAxis),
+ System.Convert.ToSingle(constraint.data.constrainedYAxis),
+ System.Convert.ToSingle(constraint.data.constrainedZAxis));
+
+ if (Vector3.Dot(axesMask, axesMask) < 3f)
+ {
+ Debug.LogWarning("Multi-Position constraint with one or more Constrained Axes toggled off may lose precision when transferring its motion to constraint.");
+ }
+
+ BakeUtils.TransferMotionToConstraint(constraint);
+ }
+
+ [MenuItem("CONTEXT/MultiPositionConstraint/Transfer motion to skeleton", false, 612)]
+ public static void TransferMotionToSkeleton(MenuCommand command)
+ {
+ var constraint = command.context as MultiPositionConstraint;
+ BakeUtils.TransferMotionToSkeleton(constraint);
+ }
+
+ [MenuItem("CONTEXT/MultiPositionConstraint/Transfer motion to constraint", true)]
+ [MenuItem("CONTEXT/MultiPositionConstraint/Transfer motion to skeleton", true)]
+ public static bool TransferMotionValidate(MenuCommand command)
+ {
+ var constraint = command.context as MultiPositionConstraint;
+ return BakeUtils.TransferMotionValidate(constraint);
+ }
+ }
+
+ [BakeParameters(typeof(MultiPositionConstraint))]
+ class MultiPositionConstraintBakeParameters : BakeParameters
+ {
+ public override bool canBakeToSkeleton => true;
+ public override bool canBakeToConstraint => true;
+
+ public override IEnumerable GetSourceCurveBindings(RigBuilder rigBuilder, MultiPositionConstraint constraint)
+ {
+ var bindings = new List();
+
+ for (int i = 0; i < constraint.data.sourceObjects.Count; ++i)
+ {
+ var sourceObject = constraint.data.sourceObjects[i];
+
+ EditorCurveBindingUtils.CollectPositionBindings(rigBuilder.transform, sourceObject.transform, bindings);
+ EditorCurveBindingUtils.CollectPropertyBindings(rigBuilder.transform, constraint, ((IMultiPositionConstraintData)constraint.data).sourceObjectsProperty + ".m_Item" + i + ".weight", bindings);
+ }
+
+ return bindings;
+ }
+
+ public override IEnumerable GetConstrainedCurveBindings(RigBuilder rigBuilder, MultiPositionConstraint constraint)
+ {
+ var bindings = new List();
+
+ EditorCurveBindingUtils.CollectPositionBindings(rigBuilder.transform, constraint.data.constrainedObject, bindings);
+
+ return bindings;
+ }
+ }
+}
diff --git a/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiPositionConstraintEditor.cs.meta b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiPositionConstraintEditor.cs.meta
new file mode 100644
index 00000000..a13c4826
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiPositionConstraintEditor.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 6ca0517db96fdfc41b4230a34d84b37c
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiReferentialConstraintEditor.cs b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiReferentialConstraintEditor.cs
new file mode 100644
index 00000000..b2349677
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiReferentialConstraintEditor.cs
@@ -0,0 +1,132 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Animations.Rigging;
+
+namespace UnityEditor.Animations.Rigging
+{
+ [CustomEditor(typeof(MultiReferentialConstraint))]
+ [CanEditMultipleObjects]
+ class MultiReferentialConstraintEditor : Editor
+ {
+ static class Content
+ {
+ public static readonly GUIContent driving = EditorGUIUtility.TrTextContent(
+ "Driving",
+ "An object from the list of Referenced Objects, whose motion drives that of all other Referenced Objects."
+ );
+ public static readonly GUIContent referenceObjects = EditorGUIUtility.TrTextContent(
+ "Reference Objects",
+ "A list of GameObjects to be driven by the specified Driving object."
+ );
+ }
+
+ SerializedProperty m_Weight;
+ SerializedProperty m_Driver;
+ SerializedProperty m_SourceObjects;
+ SerializedProperty m_SourceObjectsSize;
+
+ GUIContent[] m_DrivingLabels = Array.Empty();
+ int m_PreviousSourceSize;
+
+ void OnEnable()
+ {
+ m_Weight = serializedObject.FindProperty("m_Weight");
+
+ var data = serializedObject.FindProperty("m_Data");
+ m_Driver = data.FindPropertyRelative("m_Driver");
+ m_SourceObjects = data.FindPropertyRelative("m_SourceObjects");
+ m_SourceObjectsSize = m_SourceObjects.FindPropertyRelative("Array.size");
+ m_PreviousSourceSize = m_SourceObjectsSize.intValue;
+
+ UpdateDrivingLabels();
+ }
+
+ public override void OnInspectorGUI()
+ {
+ serializedObject.Update();
+
+ EditorGUILayout.PropertyField(m_Weight, CommonContent.weight);
+
+ Rect rect = EditorGUILayout.GetControlRect();
+ EditorGUI.BeginProperty(rect, Content.driving, m_Driver);
+ EditorGUI.BeginChangeCheck();
+ var newValue = EditorGUI.Popup(rect, Content.driving, m_Driver.intValue, m_DrivingLabels);
+ if (EditorGUI.EndChangeCheck())
+ m_Driver.intValue = newValue;
+ EditorGUI.EndProperty();
+
+ EditorGUI.BeginChangeCheck();
+ EditorGUILayout.PropertyField(m_SourceObjects, Content.referenceObjects);
+ // also check if size has changed, because drag/drop on default control and Reset do not trigger change
+ if (EditorGUI.EndChangeCheck() || m_PreviousSourceSize != m_SourceObjectsSize.intValue)
+ {
+ UpdateDrivingLabels();
+ m_PreviousSourceSize = m_SourceObjectsSize.intValue;
+ }
+
+ serializedObject.ApplyModifiedProperties();
+ }
+
+ void UpdateDrivingLabels()
+ {
+ Array.Resize(ref m_DrivingLabels, m_SourceObjects.arraySize);
+ for (int i = 0; i < m_DrivingLabels.Length; ++i)
+ {
+ var element = m_SourceObjects.GetArrayElementAtIndex(i);
+ var name = element.objectReferenceValue == null ? "None" : element.objectReferenceValue.name;
+ m_DrivingLabels[i] = new GUIContent($"{i} : {name}");
+ }
+ }
+
+ [MenuItem("CONTEXT/MultiReferentialConstraint/Transfer motion to constraint", false, 611)]
+ public static void TransferMotionToConstraint(MenuCommand command)
+ {
+ var constraint = command.context as MultiReferentialConstraint;
+ BakeUtils.TransferMotionToConstraint(constraint);
+ }
+
+ [MenuItem("CONTEXT/MultiReferentialConstraint/Transfer motion to skeleton", false, 612)]
+ public static void TransferMotionToSkeleton(MenuCommand command)
+ {
+ var constraint = command.context as MultiReferentialConstraint;
+ BakeUtils.TransferMotionToSkeleton(constraint);
+ }
+
+ [MenuItem("CONTEXT/MultiReferentialConstraint/Transfer motion to constraint", true)]
+ [MenuItem("CONTEXT/MultiReferentialConstraint/Transfer motion to skeleton", true)]
+ public static bool TransferMotionValidate(MenuCommand command)
+ {
+ var constraint = command.context as MultiReferentialConstraint;
+ return BakeUtils.TransferMotionValidate(constraint);
+ }
+ }
+
+ [BakeParameters(typeof(MultiReferentialConstraint))]
+ class MultiReferentialConstraintBakeParameters : BakeParameters
+ {
+ public override bool canBakeToSkeleton => true;
+ public override bool canBakeToConstraint => true;
+
+ public override IEnumerable GetSourceCurveBindings(RigBuilder rigBuilder, MultiReferentialConstraint constraint)
+ {
+ var bindings = new List();
+
+ var sources = constraint.data.sourceObjects;
+ for (int i = 1; i < sources.Count; ++i)
+ EditorCurveBindingUtils.CollectTRBindings(rigBuilder.transform, sources[i], bindings);
+
+ return bindings;
+ }
+
+ public override IEnumerable GetConstrainedCurveBindings(RigBuilder rigBuilder, MultiReferentialConstraint constraint)
+ {
+ var bindings = new List();
+
+ var transform = constraint.data.sourceObjects[0];
+ EditorCurveBindingUtils.CollectTRBindings(rigBuilder.transform, transform, bindings);
+
+ return bindings;
+ }
+ }
+}
diff --git a/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiReferentialConstraintEditor.cs.meta b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiReferentialConstraintEditor.cs.meta
new file mode 100644
index 00000000..f37db2ed
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiReferentialConstraintEditor.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 74cfdd6a1e6ff244496d38de0c2bbee5
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiRotationConstraintEditor.cs b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiRotationConstraintEditor.cs
new file mode 100644
index 00000000..7e04ebf7
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiRotationConstraintEditor.cs
@@ -0,0 +1,118 @@
+using UnityEngine;
+using UnityEngine.Animations.Rigging;
+using System.Collections.Generic;
+
+namespace UnityEditor.Animations.Rigging
+{
+ [CustomEditor(typeof(MultiRotationConstraint))]
+ [CanEditMultipleObjects]
+ class MultiRotationConstraintEditor : Editor
+ {
+ SerializedProperty m_Weight;
+ SerializedProperty m_ConstrainedObject;
+ SerializedProperty m_ConstrainedAxes;
+ SerializedProperty m_SourceObjects;
+ SerializedProperty m_MaintainOffset;
+ SerializedProperty m_Offset;
+
+ readonly FoldoutState m_SettingsToggle = FoldoutState.ForSettings();
+
+ void OnEnable()
+ {
+ m_Weight = serializedObject.FindProperty("m_Weight");
+
+ var data = serializedObject.FindProperty("m_Data");
+ m_ConstrainedObject = data.FindPropertyRelative("m_ConstrainedObject");
+ m_ConstrainedAxes = data.FindPropertyRelative("m_ConstrainedAxes");
+ m_SourceObjects = data.FindPropertyRelative("m_SourceObjects");
+ m_MaintainOffset = data.FindPropertyRelative("m_MaintainOffset");
+ m_Offset = data.FindPropertyRelative("m_Offset");
+ }
+
+ public override void OnInspectorGUI()
+ {
+ serializedObject.Update();
+
+ EditorGUILayout.PropertyField(m_Weight, CommonContent.weight);
+ EditorGUILayout.PropertyField(m_ConstrainedObject, CommonContent.constrainedObject);
+ EditorGUILayout.PropertyField(m_ConstrainedAxes, CommonContent.constrainedAxesRotation);
+ EditorGUILayout.PropertyField(m_SourceObjects, CommonContent.sourceObjectsWeightedRotation);
+
+ m_SettingsToggle.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_SettingsToggle.value, CommonContent.settings);
+ if (m_SettingsToggle.value)
+ {
+ EditorGUI.indentLevel++;
+ EditorGUILayout.PropertyField(m_MaintainOffset, CommonContent.maintainRotationOffset);
+ EditorGUILayout.PropertyField(m_Offset, CommonContent.offsetRotation);
+ EditorGUI.indentLevel--;
+ }
+ EditorGUILayout.EndFoldoutHeaderGroup();
+
+ serializedObject.ApplyModifiedProperties();
+ }
+
+ [MenuItem("CONTEXT/MultiRotationConstraint/Transfer motion to constraint", false, 611)]
+ public static void TransferMotionToConstraint(MenuCommand command)
+ {
+ var constraint = command.context as MultiRotationConstraint;
+
+ var axesMask = new Vector3(
+ System.Convert.ToSingle(constraint.data.constrainedXAxis),
+ System.Convert.ToSingle(constraint.data.constrainedYAxis),
+ System.Convert.ToSingle(constraint.data.constrainedZAxis));
+
+ if (Vector3.Dot(axesMask, axesMask) < 3f)
+ {
+ Debug.LogWarning("Multi-Rotation constraint with one or more Constrained Axes toggled off may lose precision when transferring its motion to constraint.");
+ }
+
+ BakeUtils.TransferMotionToConstraint(constraint);
+ }
+
+ [MenuItem("CONTEXT/MultiRotationConstraint/Transfer motion to skeleton", false, 612)]
+ public static void TransferMotionToSkeleton(MenuCommand command)
+ {
+ var constraint = command.context as MultiRotationConstraint;
+ BakeUtils.TransferMotionToSkeleton(constraint);
+ }
+
+ [MenuItem("CONTEXT/MultiRotationConstraint/Transfer motion to constraint", true)]
+ [MenuItem("CONTEXT/MultiRotationConstraint/Transfer motion to skeleton", true)]
+ public static bool TransferMotionValidate(MenuCommand command)
+ {
+ var constraint = command.context as MultiRotationConstraint;
+ return BakeUtils.TransferMotionValidate(constraint);
+ }
+ }
+
+ [BakeParameters(typeof(MultiRotationConstraint))]
+ class MultiRotationConstraintBakeParameters : BakeParameters
+ {
+ public override bool canBakeToSkeleton => true;
+ public override bool canBakeToConstraint => true;
+
+ public override IEnumerable GetSourceCurveBindings(RigBuilder rigBuilder, MultiRotationConstraint constraint)
+ {
+ var bindings = new List();
+
+ for (int i = 0; i < constraint.data.sourceObjects.Count; ++i)
+ {
+ var sourceObject = constraint.data.sourceObjects[i];
+
+ EditorCurveBindingUtils.CollectRotationBindings(rigBuilder.transform, sourceObject.transform, bindings);
+ EditorCurveBindingUtils.CollectPropertyBindings(rigBuilder.transform, constraint, ((IMultiRotationConstraintData)constraint.data).sourceObjectsProperty + ".m_Item" + i + ".weight", bindings);
+ }
+
+ return bindings;
+ }
+
+ public override IEnumerable GetConstrainedCurveBindings(RigBuilder rigBuilder, MultiRotationConstraint constraint)
+ {
+ var bindings = new List();
+
+ EditorCurveBindingUtils.CollectRotationBindings(rigBuilder.transform, constraint.data.constrainedObject, bindings);
+
+ return bindings;
+ }
+ }
+}
diff --git a/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiRotationConstraintEditor.cs.meta b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiRotationConstraintEditor.cs.meta
new file mode 100644
index 00000000..581d7e15
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiRotationConstraintEditor.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 91a61b91969f07d448049f1b2c1bf3c8
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/OverrideTransformEditor.cs b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/OverrideTransformEditor.cs
new file mode 100644
index 00000000..f078e31b
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/OverrideTransformEditor.cs
@@ -0,0 +1,152 @@
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Animations.Rigging;
+
+namespace UnityEditor.Animations.Rigging
+{
+ [CustomEditor(typeof(OverrideTransform))]
+ [CanEditMultipleObjects]
+ class OverrideTransformEditor : Editor
+ {
+ static class Content
+ {
+ public static readonly GUIContent sourceObjects = new GUIContent(CommonContent.sourceObjects.text);
+ public static readonly GUIContent overrideSource = EditorGUIUtility.TrTextContent(
+ "Override Source",
+ "The GameObject that influences the Constrained Object's transform. " +
+ "If specified, Override Position and Override Rotation fields are ignored."
+ );
+ public static readonly GUIContent overridePosition = EditorGUIUtility.TrTextContent(
+ "Override Position",
+ "A specific position value to apply to the Constrained Object. " +
+ "This value is ignored if an Override Source is specified."
+ );
+ public static readonly GUIContent overrideRotation = EditorGUIUtility.TrTextContent(
+ "Override Rotation",
+ "A specific rotation value to apply to the Constrained Object. " +
+ "This value is ignored if an Override Source is specified."
+ );
+ public static readonly GUIContent space = EditorGUIUtility.TrTextContent(
+ "Space",
+ "Specifies how the Override Source's local transform values (or manual Override Position and Rotation) should be applied to Constrained Object."
+ );
+ public static readonly GUIContent positionWeight = EditorGUIUtility.TrTextContent(
+ "Position Weight",
+ "The weight of the position influence."
+ );
+ public static readonly GUIContent rotationWeight = EditorGUIUtility.TrTextContent(
+ "Rotation Weight",
+ "The weight of the rotation influence."
+ );
+ }
+
+ SerializedProperty m_Weight;
+ SerializedProperty m_ConstrainedObject;
+ SerializedProperty m_OverrideSource;
+ SerializedProperty m_OverridePosition;
+ SerializedProperty m_OverrideRotation;
+ SerializedProperty m_Space;
+ SerializedProperty m_PositionWeight;
+ SerializedProperty m_RotationWeight;
+
+ readonly FoldoutState m_SourceObjectsToggle = FoldoutState.ForSourceObjects();
+ readonly FoldoutState m_SettingsToggle = FoldoutState.ForSettings();
+
+ void OnEnable()
+ {
+ m_Weight = serializedObject.FindProperty("m_Weight");
+
+ var data = serializedObject.FindProperty("m_Data");
+ m_ConstrainedObject = data.FindPropertyRelative("m_ConstrainedObject");
+ m_OverrideSource = data.FindPropertyRelative("m_OverrideSource");
+ m_OverridePosition = data.FindPropertyRelative("m_OverridePosition");
+ m_OverrideRotation = data.FindPropertyRelative("m_OverrideRotation");
+ m_Space = data.FindPropertyRelative("m_Space");
+ m_PositionWeight = data.FindPropertyRelative("m_PositionWeight");
+ m_RotationWeight = data.FindPropertyRelative("m_RotationWeight");
+ }
+
+ public override void OnInspectorGUI()
+ {
+ serializedObject.Update();
+
+ EditorGUILayout.PropertyField(m_Weight, CommonContent.weight);
+ EditorGUILayout.PropertyField(m_ConstrainedObject, CommonContent.constrainedObject);
+
+ m_SourceObjectsToggle.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_SourceObjectsToggle.value, Content.sourceObjects);
+ if (m_SourceObjectsToggle.value)
+ {
+ EditorGUI.indentLevel++;
+ EditorGUILayout.PropertyField(m_OverrideSource, Content.overrideSource);
+ using (new EditorGUI.DisabledScope(m_OverrideSource.objectReferenceValue != null))
+ {
+ EditorGUILayout.PropertyField(m_OverridePosition, Content.overridePosition);
+ EditorGUILayout.PropertyField(m_OverrideRotation, Content.overrideRotation);
+ }
+ EditorGUI.indentLevel--;
+ }
+ EditorGUILayout.EndFoldoutHeaderGroup();
+
+ m_SettingsToggle.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_SettingsToggle.value, CommonContent.settings);
+ if (m_SettingsToggle.value)
+ {
+ EditorGUI.indentLevel++;
+ EditorGUILayout.PropertyField(m_Space, Content.space);
+ EditorGUILayout.PropertyField(m_PositionWeight, Content.positionWeight);
+ EditorGUILayout.PropertyField(m_RotationWeight, Content.rotationWeight);
+ EditorGUI.indentLevel--;
+ }
+ EditorGUILayout.EndFoldoutHeaderGroup();
+
+ serializedObject.ApplyModifiedProperties();
+ }
+
+ [MenuItem("CONTEXT/OverrideTransform/Transfer motion to skeleton", false, 612)]
+ public static void TransferMotionToSkeleton(MenuCommand command)
+ {
+ var constraint = command.context as OverrideTransform;
+ BakeUtils.TransferMotionToSkeleton(constraint);
+ }
+
+ [MenuItem("CONTEXT/OverrideTransform/Transfer motion to skeleton", true)]
+ public static bool TransferMotionValidate(MenuCommand command)
+ {
+ var constraint = command.context as OverrideTransform;
+ return BakeUtils.TransferMotionValidate(constraint);
+ }
+ }
+
+ [BakeParameters(typeof(OverrideTransform))]
+ class OverrideTransformBakeParameters : BakeParameters
+ {
+ public override bool canBakeToSkeleton => true;
+ public override bool canBakeToConstraint => false;
+
+ public override IEnumerable GetSourceCurveBindings(RigBuilder rigBuilder, OverrideTransform constraint)
+ {
+ var bindings = new List();
+
+ if (constraint.data.sourceObject != null)
+ {
+ EditorCurveBindingUtils.CollectTRBindings(rigBuilder.transform, constraint.data.sourceObject, bindings);
+ }
+ else
+ {
+ var data = (IOverrideTransformData)constraint.data;
+ EditorCurveBindingUtils.CollectVector3Bindings(rigBuilder.transform, constraint, data.positionVector3Property, bindings);
+ EditorCurveBindingUtils.CollectVector3Bindings(rigBuilder.transform, constraint, data.rotationVector3Property, bindings);
+ }
+
+ return bindings;
+ }
+
+ public override IEnumerable GetConstrainedCurveBindings(RigBuilder rigBuilder, OverrideTransform constraint)
+ {
+ var bindings = new List();
+
+ EditorCurveBindingUtils.CollectTRSBindings(rigBuilder.transform, constraint.data.constrainedObject, bindings);
+
+ return bindings;
+ }
+ }
+}
diff --git a/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/OverrideTransformEditor.cs.meta b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/OverrideTransformEditor.cs.meta
new file mode 100644
index 00000000..58744aba
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/OverrideTransformEditor.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 16cd7f77b75e35946b191bd98757e5a2
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/TwistChainConstraintEditor.cs b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/TwistChainConstraintEditor.cs
new file mode 100644
index 00000000..5fe40f9d
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/TwistChainConstraintEditor.cs
@@ -0,0 +1,143 @@
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Animations.Rigging;
+
+namespace UnityEditor.Animations.Rigging
+{
+ [CustomEditor(typeof(TwistChainConstraint))]
+ [CanEditMultipleObjects]
+ class TwistChainConstraintEditor : Editor
+ {
+ static class Content
+ {
+ public static readonly GUIContent root = EditorGUIUtility.TrTextContent(
+ "Root",
+ "The root GameObject of the chain hierarchy."
+ );
+ public static readonly GUIContent tip = EditorGUIUtility.TrTextContent(
+ "Tip",
+ "The final GameObject of the chain hierarchy. It must be a descendant of the Root GameObject."
+ );
+ public static readonly GUIContent sourceObjects = new GUIContent(CommonContent.sourceObjects.text);
+ public static readonly GUIContent rootTarget = EditorGUIUtility.TrTextContent(
+ "Root Target",
+ "The GameObject that specifies the desired target rotation for the chain's Root."
+ );
+ public static readonly GUIContent tipTarget = EditorGUIUtility.TrTextContent(
+ "Tip Target",
+ "The GameObject that specifies the desired target rotation for the chain's Tip."
+ );
+ public static readonly GUIContent curve = EditorGUIUtility.TrTextContent(
+ "Curve",
+ "A curve with a normalized domain and range, specifying how the twist rotation should be distributed down the length of the chain."
+ );
+ }
+
+ SerializedProperty m_Weight;
+ SerializedProperty m_Root;
+ SerializedProperty m_Tip;
+ SerializedProperty m_RootTarget;
+ SerializedProperty m_TipTarget;
+ SerializedProperty m_Curve;
+
+ readonly FoldoutState m_SourceObjectsToggle = FoldoutState.ForSourceObjects();
+ readonly FoldoutState m_SettingsToggle = FoldoutState.ForSettings();
+
+ void OnEnable()
+ {
+ m_Weight = serializedObject.FindProperty("m_Weight");
+
+ var data = serializedObject.FindProperty("m_Data");
+ m_RootTarget = data.FindPropertyRelative("m_RootTarget");
+ m_TipTarget = data.FindPropertyRelative("m_TipTarget");
+ m_Root = data.FindPropertyRelative("m_Root");
+ m_Tip = data.FindPropertyRelative("m_Tip");
+ m_Curve = data.FindPropertyRelative("m_Curve");
+ }
+
+ public override void OnInspectorGUI()
+ {
+ serializedObject.Update();
+
+ EditorGUILayout.PropertyField(m_Weight, CommonContent.weight);
+ EditorGUILayout.PropertyField(m_Root, Content.root);
+ EditorGUILayout.PropertyField(m_Tip, Content.tip);
+
+ m_SourceObjectsToggle.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_SourceObjectsToggle.value, Content.sourceObjects);
+ if (m_SourceObjectsToggle.value)
+ {
+ EditorGUI.indentLevel++;
+ EditorGUILayout.PropertyField(m_RootTarget, Content.rootTarget);
+ EditorGUILayout.PropertyField(m_TipTarget, Content.tipTarget);
+ EditorGUI.indentLevel--;
+ }
+ EditorGUILayout.EndFoldoutHeaderGroup();
+
+ m_SettingsToggle.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_SettingsToggle.value, CommonContent.settings);
+ if (m_SettingsToggle.value)
+ {
+ EditorGUI.indentLevel++;
+ EditorGUILayout.PropertyField(m_Curve, Content.curve);
+ EditorGUI.indentLevel--;
+ }
+ EditorGUILayout.EndFoldoutHeaderGroup();
+
+ serializedObject.ApplyModifiedProperties();
+ }
+
+ [MenuItem("CONTEXT/TwistChainConstraint/Transfer motion to constraint", false, 611)]
+ public static void TransferMotionToConstraint(MenuCommand command)
+ {
+ var constraint = command.context as TwistChainConstraint;
+ BakeUtils.TransferMotionToConstraint(constraint);
+ }
+
+ [MenuItem("CONTEXT/TwistChainConstraint/Transfer motion to skeleton", false, 612)]
+ public static void TransferMotionToSkeleton(MenuCommand command)
+ {
+ var constraint = command.context as TwistChainConstraint;
+ BakeUtils.TransferMotionToSkeleton(constraint);
+ }
+
+ [MenuItem("CONTEXT/TwistChainConstraint/Transfer motion to constraint", true)]
+ [MenuItem("CONTEXT/TwistChainConstraint/Transfer motion to skeleton", true)]
+ public static bool TransferMotionValidate(MenuCommand command)
+ {
+ var constraint = command.context as TwistChainConstraint;
+ return BakeUtils.TransferMotionValidate(constraint);
+ }
+ }
+
+ [BakeParameters(typeof(TwistChainConstraint))]
+ class TwistChainConstraintBakeParameters : BakeParameters
+ {
+ public override bool canBakeToSkeleton => true;
+ public override bool canBakeToConstraint => true;
+
+ public override IEnumerable GetSourceCurveBindings(RigBuilder rigBuilder, TwistChainConstraint constraint)
+ {
+ var bindings = new List();
+
+ EditorCurveBindingUtils.CollectTRBindings(rigBuilder.transform, constraint.data.rootTarget, bindings);
+ EditorCurveBindingUtils.CollectTRBindings(rigBuilder.transform, constraint.data.tipTarget, bindings);
+
+ return bindings;
+ }
+
+ public override IEnumerable GetConstrainedCurveBindings(RigBuilder rigBuilder, TwistChainConstraint constraint)
+ {
+ var bindings = new List();
+
+ // Retrieve chain in-between root and tip transforms.
+ Transform[] chain = ConstraintsUtils.ExtractChain(constraint.data.root, constraint.data.tip);
+
+ for (int i = 0; i < chain.Length; ++i)
+ {
+ EditorCurveBindingUtils.CollectRotationBindings(rigBuilder.transform, chain[i], bindings);
+ }
+
+ return bindings;
+ }
+ }
+}
+
diff --git a/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/TwistChainConstraintEditor.cs.meta b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/TwistChainConstraintEditor.cs.meta
new file mode 100644
index 00000000..ec4e4a4c
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/TwistChainConstraintEditor.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 6f51e9e105d754014895d13788b539ae
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/TwistCorrectionEditor.cs b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/TwistCorrectionEditor.cs
new file mode 100644
index 00000000..dedaed1c
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/TwistCorrectionEditor.cs
@@ -0,0 +1,114 @@
+using UnityEngine;
+using UnityEngine.Animations.Rigging;
+using System.Collections.Generic;
+
+namespace UnityEditor.Animations.Rigging
+{
+ [CustomEditor(typeof(TwistCorrection))]
+ [CanEditMultipleObjects]
+ class TwistCorrectionEditor : Editor
+ {
+ static class Content
+ {
+ public static readonly GUIContent source = EditorGUIUtility.TrTextContent(
+ "Source",
+ "The GameObject that influences the Twist Nodes to rotate around a specific Twist Axis."
+ );
+ public static readonly GUIContent twistAxis = EditorGUIUtility.TrTextContent(
+ "Twist Axis",
+ "Specifies the axis on the Source object from which the rotation is extracted and then redistributed to the Twist Nodes."
+ );
+ public static readonly GUIContent twistNodes = EditorGUIUtility.TrTextContent(
+ "Twist Nodes",
+ "The list of GameObjects that will be influenced by the Source GameObject, and the cumulative percentage of the Source's twist rotation they should inherit. " +
+ "They are generally expected to all be leaf nodes in the hierarchy (i.e., they have a common parent and no children), and to have their twist axes oriented the same as the Source object in their initial pose."
+ );
+ }
+
+ SerializedProperty m_Weight;
+ SerializedProperty m_Source;
+ SerializedProperty m_TwistAxis;
+ SerializedProperty m_TwistNodes;
+ SerializedProperty m_TwistNodesLength;
+
+ readonly FoldoutState m_SourceObjectsToggle = FoldoutState.ForSourceObjects();
+
+ void OnEnable()
+ {
+ m_Weight = serializedObject.FindProperty("m_Weight");
+ var data = serializedObject.FindProperty("m_Data");
+ m_Source = data.FindPropertyRelative("m_Source");
+ m_TwistAxis = data.FindPropertyRelative("m_TwistAxis");
+ m_TwistNodes = data.FindPropertyRelative("m_TwistNodes");
+ m_TwistNodesLength = m_TwistNodes.FindPropertyRelative("m_Length");
+ }
+
+ public override void OnInspectorGUI()
+ {
+ serializedObject.Update();
+
+ EditorGUILayout.PropertyField(m_Weight, CommonContent.weight);
+
+ // by default, the first WeightedTransform element a user adds has a weight of 1
+ // for this constraint, the first twist node usually should not have a value of 1
+ // TODO: make drag/drop auto-distribute weights
+ EditorGUI.BeginChangeCheck();
+ var oldLength = m_TwistNodesLength.intValue;
+ EditorGUILayout.PropertyField(m_TwistNodes, Content.twistNodes);
+ if (EditorGUI.EndChangeCheck() && oldLength == 0 && m_TwistNodesLength.intValue != oldLength)
+ m_TwistNodes.FindPropertyRelative("m_Item0.weight").floatValue = 0f;
+
+ EditorGUILayout.PropertyField(m_TwistAxis, Content.twistAxis);
+
+ m_SourceObjectsToggle.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_SourceObjectsToggle.value, Content.source);
+ {
+ ++EditorGUI.indentLevel;
+ EditorGUILayout.PropertyField(m_Source);
+ --EditorGUI.indentLevel;
+ }
+ EditorGUILayout.EndFoldoutHeaderGroup();
+
+ serializedObject.ApplyModifiedProperties();
+ }
+
+ [MenuItem("CONTEXT/TwistCorrection/Transfer motion to skeleton", false, 612)]
+ public static void TransferMotionToSkeleton(MenuCommand command)
+ {
+ var constraint = command.context as TwistCorrection;
+ BakeUtils.TransferMotionToSkeleton(constraint);
+ }
+
+ [MenuItem("CONTEXT/TwistCorrection/Transfer motion to skeleton", true)]
+ public static bool TransferMotionValidate(MenuCommand command)
+ {
+ var constraint = command.context as TwistCorrection;
+ return BakeUtils.TransferMotionValidate(constraint);
+ }
+ }
+
+ [BakeParameters(typeof(TwistCorrection))]
+ class TwistCorrectionBakeParameters : BakeParameters
+ {
+ public override bool canBakeToSkeleton => true;
+ public override bool canBakeToConstraint => false;
+
+ public override IEnumerable GetSourceCurveBindings(RigBuilder rigBuilder, TwistCorrection constraint)
+ {
+ var bindings = new List();
+
+ EditorCurveBindingUtils.CollectRotationBindings(rigBuilder.transform, constraint.data.sourceObject, bindings);
+
+ return bindings;
+ }
+
+ public override IEnumerable GetConstrainedCurveBindings(RigBuilder rigBuilder, TwistCorrection constraint)
+ {
+ var bindings = new List();
+
+ foreach (var node in constraint.data.twistNodes)
+ EditorCurveBindingUtils.CollectRotationBindings(rigBuilder.transform, node.transform, bindings);
+
+ return bindings;
+ }
+ }
+}
diff --git a/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/TwistCorrectionEditor.cs.meta b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/TwistCorrectionEditor.cs.meta
new file mode 100644
index 00000000..1989cd56
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/TwistCorrectionEditor.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: e52e5d5c12dea4e4397e6781cbeac36d
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/TwoBoneIKConstraintEditor.cs b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/TwoBoneIKConstraintEditor.cs
new file mode 100644
index 00000000..094dca79
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/TwoBoneIKConstraintEditor.cs
@@ -0,0 +1,301 @@
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Animations.Rigging;
+
+namespace UnityEditor.Animations.Rigging
+{
+ [CustomEditor(typeof(TwoBoneIKConstraint))]
+ [CanEditMultipleObjects]
+ class TwoBoneIKConstraintEditor : Editor
+ {
+ static class Content
+ {
+ public static readonly GUIContent root = EditorGUIUtility.TrTextContent(
+ "Root",
+ "The root GameObject of the limb hierarchy."
+ );
+ public static readonly GUIContent mid = EditorGUIUtility.TrTextContent(
+ "Mid",
+ "The middle GameObject of the limb hierarchy. It must be a child of the Root GameObject."
+ );
+ public static readonly GUIContent tip = EditorGUIUtility.TrTextContent(
+ "Tip",
+ "The final GameObject of the limb hierarchy. It must be a child of the Mid GameObject."
+ );
+ public static readonly GUIContent sourceObjects = new GUIContent(CommonContent.sourceObjects.text);
+ public static readonly GUIContent target = EditorGUIUtility.TrTextContent(
+ "Target",
+ "Source GameObject that specifies the desired position of the Tip."
+ );
+ public static readonly GUIContent hint = EditorGUIUtility.TrTextContent(
+ "Hint",
+ "Optional Source GameObject, whose position is used to specify the direction the limb should be oriented when it bends."
+ );
+ public static readonly GUIContent targetPositionWeight = EditorGUIUtility.TrTextContent(
+ "Target Position Weight",
+ "The weight to apply for calculating the desired position when reaching for the Target."
+ );
+ public static readonly GUIContent targetRotationWeight = EditorGUIUtility.TrTextContent(
+ "Target Rotation Weight",
+ "The weight of the rotation applied to the Tip."
+ );
+ public static readonly GUIContent hintWeight = EditorGUIUtility.TrTextContent(
+ "Hint Weight",
+ "The amount of influence the Hint has on the configuration of the hierarchy."
+ );
+ }
+
+ SerializedProperty m_Weight;
+ SerializedProperty m_Root;
+ SerializedProperty m_Mid;
+ SerializedProperty m_Tip;
+ SerializedProperty m_Target;
+ SerializedProperty m_Hint;
+ SerializedProperty m_TargetPositionWeight;
+ SerializedProperty m_TargetRotationWeight;
+ SerializedProperty m_HintWeight;
+ SerializedProperty m_MaintainTargetPositionOffset;
+ SerializedProperty m_MaintainTargetRotationOffset;
+
+ readonly FoldoutState m_SourceObjectsToggle = FoldoutState.ForSourceObjects();
+ readonly FoldoutState m_SettingsToggle = FoldoutState.ForSettings();
+
+ void OnEnable()
+ {
+ m_Weight = serializedObject.FindProperty("m_Weight");
+
+ var data = serializedObject.FindProperty("m_Data");
+ m_Root = data.FindPropertyRelative("m_Root");
+ m_Mid = data.FindPropertyRelative("m_Mid");
+ m_Tip = data.FindPropertyRelative("m_Tip");
+ m_Target = data.FindPropertyRelative("m_Target");
+ m_Hint = data.FindPropertyRelative("m_Hint");
+ m_TargetPositionWeight = data.FindPropertyRelative("m_TargetPositionWeight");
+ m_TargetRotationWeight = data.FindPropertyRelative("m_TargetRotationWeight");
+ m_HintWeight = data.FindPropertyRelative("m_HintWeight");
+ m_MaintainTargetPositionOffset = data.FindPropertyRelative("m_MaintainTargetPositionOffset");
+ m_MaintainTargetRotationOffset = data.FindPropertyRelative("m_MaintainTargetRotationOffset");
+ }
+
+ public override void OnInspectorGUI()
+ {
+ serializedObject.Update();
+
+ EditorGUILayout.PropertyField(m_Weight, CommonContent.weight);
+ EditorGUILayout.PropertyField(m_Root, Content.root);
+ EditorGUILayout.PropertyField(m_Mid, Content.mid);
+ EditorGUILayout.PropertyField(m_Tip, Content.tip);
+
+ m_SourceObjectsToggle.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_SourceObjectsToggle.value, Content.sourceObjects);
+ if (m_SourceObjectsToggle.value)
+ {
+ EditorGUI.indentLevel++;
+ EditorGUILayout.PropertyField(m_Target, Content.target);
+ EditorGUILayout.PropertyField(m_Hint, Content.hint);
+ EditorGUI.indentLevel--;
+ }
+ EditorGUILayout.EndFoldoutHeaderGroup();
+
+ m_SettingsToggle.value = EditorGUILayout.BeginFoldoutHeaderGroup(m_SettingsToggle.value, CommonContent.settings);
+ if (m_SettingsToggle.value)
+ {
+ EditorGUI.indentLevel++;
+ MaintainOffsetHelper.DoDropdown(CommonContent.maintainIKTargetOffset, m_MaintainTargetPositionOffset, m_MaintainTargetRotationOffset);
+ EditorGUILayout.PropertyField(m_TargetPositionWeight, Content.targetPositionWeight);
+ EditorGUILayout.PropertyField(m_TargetRotationWeight, Content.targetRotationWeight);
+ EditorGUILayout.PropertyField(m_HintWeight, Content.hintWeight);
+ EditorGUI.indentLevel--;
+ }
+ EditorGUILayout.EndFoldoutHeaderGroup();
+
+ serializedObject.ApplyModifiedProperties();
+ }
+
+ [MenuItem("CONTEXT/TwoBoneIKConstraint/Transfer motion to constraint", false, 611)]
+ public static void TransferMotionToConstraint(MenuCommand command)
+ {
+ var constraint = command.context as TwoBoneIKConstraint;
+ BakeUtils.TransferMotionToConstraint(constraint);
+ }
+
+ [MenuItem("CONTEXT/TwoBoneIKConstraint/Transfer motion to skeleton", false, 612)]
+ public static void TransferMotionToSkeleton(MenuCommand command)
+ {
+ var constraint = command.context as TwoBoneIKConstraint;
+ BakeUtils.TransferMotionToSkeleton(constraint);
+ }
+
+ [MenuItem("CONTEXT/TwoBoneIKConstraint/Transfer motion to constraint", true)]
+ [MenuItem("CONTEXT/TwoBoneIKConstraint/Transfer motion to skeleton", true)]
+ public static bool TransferMotionValidate(MenuCommand command)
+ {
+ var constraint = command.context as TwoBoneIKConstraint;
+ return BakeUtils.TransferMotionValidate(constraint);
+ }
+
+ [MenuItem("CONTEXT/TwoBoneIKConstraint/Auto Setup from Tip Transform", false, 631)]
+ public static void TwoBoneIKAutoSetup(MenuCommand command)
+ {
+ var constraint = command.context as TwoBoneIKConstraint;
+ var tip = constraint.data.tip;
+ var animator = constraint.GetComponentInParent()?.transform;
+ var dirty = false;
+
+ if (!tip)
+ {
+ var selection = Selection.transforms;
+ var constraintInSelection = false;
+
+ // Take transform from selection that is part of the animator hierarchy & not the constraint transform.
+ if (animator)
+ {
+ for (int i = 0; i < selection.Length; i++)
+ {
+ if (selection[i].IsChildOf(animator))
+ {
+ if (selection[i] != constraint.transform)
+ {
+ tip = selection[i];
+ break;
+ }
+ else
+ {
+ constraintInSelection = true;
+ }
+ }
+ }
+ }
+
+ // If the constraint itself was selected and we haven't found anything use that.
+ if (!tip && constraintInSelection)
+ tip = constraint.transform;
+
+ // If there is still no tip return.
+ if (!tip)
+ {
+ Debug.LogWarning("Please provide a tip before running auto setup!");
+ return;
+ }
+ else
+ {
+ Undo.RecordObject(constraint, "Setup tip bone from user selection");
+ constraint.data.tip = tip;
+ dirty = true;
+ }
+ }
+
+ if (!constraint.data.mid)
+ {
+ Undo.RecordObject(constraint, "Setup mid bone for TwoBoneIK");
+ constraint.data.mid = tip.parent;
+ dirty = true;
+ }
+
+ if (!constraint.data.root)
+ {
+ Undo.RecordObject(constraint, "Setup root bone for TwoBoneIK");
+ constraint.data.root = tip.parent.parent;
+ dirty = true;
+ }
+
+ if (!constraint.data.target)
+ {
+ var target = constraint.transform.Find(constraint.gameObject.name + "_target");
+ if (target == null)
+ {
+ var t = new GameObject();
+ Undo.RegisterCreatedObjectUndo(t, "Created target");
+ t.name = constraint.gameObject.name + "_target";
+ t.transform.localScale = .1f * t.transform.localScale;
+ Undo.SetTransformParent(t.transform, constraint.transform, "Set new parent");
+ target = t.transform;
+ }
+ constraint.data.target = target;
+ dirty = true;
+ }
+
+ if (!constraint.data.hint)
+ {
+ var hint = constraint.transform.Find(constraint.gameObject.name + "_hint");
+ if (hint == null)
+ {
+ var t = new GameObject();
+ Undo.RegisterCreatedObjectUndo(t, "Created hint");
+ t.name = constraint.gameObject.name + "_hint";
+ t.transform.localScale = .1f * t.transform.localScale;
+ Undo.SetTransformParent(t.transform, constraint.transform, "Set new parent");
+ hint = t.transform;
+ }
+ constraint.data.hint = hint;
+ dirty = true;
+ }
+
+ Vector3 rootPosition = constraint.data.root.position;
+ Vector3 midPosition = constraint.data.mid.position;
+ Vector3 tipPosition = constraint.data.tip.position;
+ Quaternion tipRotation = constraint.data.tip.rotation;
+ Vector3 targetPosition = constraint.data.target.position;
+ Quaternion targetRotation = constraint.data.target.rotation;
+ Vector3 hintPosition = constraint.data.hint.position;
+ float posWeight = constraint.data.targetPositionWeight;
+ float rotWeight = constraint.data.targetRotationWeight;
+ float hintWeight = constraint.data.hintWeight;
+ AffineTransform targetOffset = new AffineTransform(Vector3.zero, Quaternion.identity);
+
+ AnimationRuntimeUtils.InverseSolveTwoBoneIK(rootPosition, midPosition, tipPosition, tipRotation,
+ ref targetPosition, ref targetRotation, ref hintPosition, true, posWeight, rotWeight, hintWeight, targetOffset);
+
+ constraint.data.target.position = targetPosition;
+ constraint.data.target.rotation = targetRotation;
+ constraint.data.hint.position = hintPosition;
+
+ Rig rig = constraint.GetComponentInParent();
+ if (rig != null)
+ {
+ RigEffectorData.Style targetStyle = RigEffector.defaultStyle;
+ targetStyle.shape = EditorHelper.LoadShape("BoxEffector.asset");
+ rig.AddEffector(constraint.data.target, targetStyle);
+ RigEffectorData.Style hintStyle = RigEffector.defaultStyle;
+ hintStyle.shape = EditorHelper.LoadShape("BallEffector.asset");
+ rig.AddEffector(constraint.data.hint, hintStyle);
+ }
+
+ if (dirty && PrefabUtility.IsPartOfPrefabInstance(constraint))
+ EditorUtility.SetDirty(constraint);
+ }
+ }
+
+ [BakeParameters(typeof(TwoBoneIKConstraint))]
+ class TwoBoneIKConstraintBakeParameters : BakeParameters
+ {
+ public override bool canBakeToSkeleton => true;
+ public override bool canBakeToConstraint => true;
+
+ public override IEnumerable GetSourceCurveBindings(RigBuilder rigBuilder, TwoBoneIKConstraint constraint)
+ {
+ var bindings = new List();
+
+ EditorCurveBindingUtils.CollectTRBindings(rigBuilder.transform, constraint.data.target, bindings);
+
+ if (constraint.data.hint != null)
+ EditorCurveBindingUtils.CollectPositionBindings(rigBuilder.transform, constraint.data.hint, bindings);
+
+ return bindings;
+ }
+
+ public override IEnumerable GetConstrainedCurveBindings(RigBuilder rigBuilder, TwoBoneIKConstraint constraint)
+ {
+ var bindings = new List();
+
+ var root = constraint.data.root;
+ var mid = constraint.data.mid;
+ var tip = constraint.data.tip;
+
+ EditorCurveBindingUtils.CollectRotationBindings(rigBuilder.transform, root, bindings);
+ EditorCurveBindingUtils.CollectRotationBindings(rigBuilder.transform, mid, bindings);
+ EditorCurveBindingUtils.CollectRotationBindings(rigBuilder.transform, tip, bindings);
+
+ return bindings;
+ }
+ }
+}
diff --git a/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/TwoBoneIKConstraintEditor.cs.meta b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/TwoBoneIKConstraintEditor.cs.meta
new file mode 100644
index 00000000..1d743596
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/TwoBoneIKConstraintEditor.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: d47d5b10876eed042af2bccb184f9a5b
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.animation.rigging/Editor/AnimationRig/RigBuilderEditor.cs b/Packages/com.unity.animation.rigging/Editor/AnimationRig/RigBuilderEditor.cs
new file mode 100644
index 00000000..884461b3
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/RigBuilderEditor.cs
@@ -0,0 +1,61 @@
+using UnityEngine;
+using UnityEngine.Animations.Rigging;
+using UnityEditorInternal;
+
+namespace UnityEditor.Animations.Rigging
+{
+ [CustomEditor(typeof(RigBuilder))]
+ class RigBuilderEditor : Editor
+ {
+ static readonly GUIContent k_RigLabel = new GUIContent("Rig Layers");
+
+ SerializedProperty m_Rigs;
+ ReorderableList m_ReorderableList;
+
+ void OnEnable()
+ {
+ m_Rigs = serializedObject.FindProperty("m_RigLayers");
+ m_ReorderableList = ReorderableListHelper.Create(serializedObject, m_Rigs, true, true);
+ if (m_ReorderableList.count == 0)
+ ((RigBuilder)serializedObject.targetObject).layers.Add(new RigLayer(null));
+
+ m_ReorderableList.drawHeaderCallback = (Rect rect) => EditorGUI.LabelField(rect, k_RigLabel);
+
+ m_ReorderableList.onAddCallback = (ReorderableList list) =>
+ {
+ ((RigBuilder)(serializedObject.targetObject)).layers.Add(new RigLayer(null, true));
+ };
+ }
+
+ public override void OnInspectorGUI()
+ {
+ serializedObject.Update();
+ EditorGUILayout.Separator();
+ m_ReorderableList.DoLayoutList();
+ serializedObject.ApplyModifiedProperties();
+ }
+
+ [MenuItem("CONTEXT/RigBuilder/Transfer motion to constraint", false, 611)]
+ public static void TransferMotionToConstraint(MenuCommand command)
+ {
+ var rigBuilder = command.context as RigBuilder;
+ BakeUtils.TransferMotionToConstraint(rigBuilder);
+ }
+
+ [MenuItem("CONTEXT/RigBuilder/Transfer motion to skeleton", false, 612)]
+ public static void TransferMotionToSkeleton(MenuCommand command)
+ {
+ var rigBuilder = command.context as RigBuilder;
+ BakeUtils.TransferMotionToSkeleton(rigBuilder);
+ }
+
+ [MenuItem("CONTEXT/RigBuilder/Transfer motion to constraint", true)]
+ [MenuItem("CONTEXT/RigBuilder/Transfer motion to skeleton", true)]
+ public static bool TransferMotionValidate(MenuCommand command)
+ {
+ var rigBuilder = command.context as RigBuilder;
+ return BakeUtils.TransferMotionValidate(rigBuilder);
+ }
+
+ }
+}
diff --git a/Packages/com.unity.animation.rigging/Editor/AnimationRig/RigBuilderEditor.cs.meta b/Packages/com.unity.animation.rigging/Editor/AnimationRig/RigBuilderEditor.cs.meta
new file mode 100644
index 00000000..2f332b36
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/RigBuilderEditor.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 5f920510daf5fba46b137a815f4e9a1b
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.animation.rigging/Editor/AnimationRig/RigEditor.cs b/Packages/com.unity.animation.rigging/Editor/AnimationRig/RigEditor.cs
new file mode 100644
index 00000000..04ef7351
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/RigEditor.cs
@@ -0,0 +1,76 @@
+using UnityEngine.Animations.Rigging;
+
+namespace UnityEditor.Animations.Rigging
+{
+ [CustomEditor(typeof(Rig))]
+ [CanEditMultipleObjects]
+ class RigEditor : Editor
+ {
+ SerializedProperty m_Weight;
+
+ void OnEnable()
+ {
+ m_Weight = serializedObject.FindProperty("m_Weight");
+ }
+
+ public override void OnInspectorGUI()
+ {
+ bool isEditingMultipleObjects = targets.Length > 1;
+
+ serializedObject.Update();
+ EditorGUILayout.Separator();
+ EditorGUILayout.PropertyField(m_Weight);
+ serializedObject.ApplyModifiedProperties();
+
+ if (!isEditingMultipleObjects)
+ {
+ var rig = target as Rig;
+ var rigBuilder = rig.GetComponentInParent();
+
+ if (rigBuilder == null)
+ {
+ EditorGUILayout.HelpBox("Rig component is not child of a GameObject with a RigBuilder component.", MessageType.Warning, true);
+ }
+ else
+ {
+ var inRigBuilder = false;
+ var layers = rigBuilder.layers;
+
+ for (int i = 0; i < layers.Count; ++i)
+ {
+ if (layers[i].rig == rig && layers[i].active)
+ {
+ inRigBuilder = true;
+ break;
+ }
+ }
+
+ if (!inRigBuilder)
+ EditorGUILayout.HelpBox("Rig component is not referenced or not active in the RigBuilder component.", MessageType.Warning, true);
+ }
+ }
+ }
+
+ [MenuItem("CONTEXT/Rig/Transfer motion to constraint", false, 611)]
+ public static void TransferMotionToConstraint(MenuCommand command)
+ {
+ var rig = command.context as Rig;
+ BakeUtils.TransferMotionToConstraint(rig);
+ }
+
+ [MenuItem("CONTEXT/Rig/Transfer motion to skeleton", false, 612)]
+ public static void TransferMotionToSkeleton(MenuCommand command)
+ {
+ var rig = command.context as Rig;
+ BakeUtils.TransferMotionToSkeleton(rig);
+ }
+
+ [MenuItem("CONTEXT/Rig/Transfer motion to constraint", true)]
+ [MenuItem("CONTEXT/Rig/Transfer motion to skeleton", true)]
+ public static bool TransferMotionValidate(MenuCommand command)
+ {
+ var rig = command.context as Rig;
+ return BakeUtils.TransferMotionValidate(rig);
+ }
+ }
+}
diff --git a/Packages/com.unity.animation.rigging/Editor/AnimationRig/RigEditor.cs.meta b/Packages/com.unity.animation.rigging/Editor/AnimationRig/RigEditor.cs.meta
new file mode 100644
index 00000000..a52e0e64
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/RigEditor.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 6856dd80c42d3244b9d9eb1844f8715f
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.animation.rigging/Editor/AnimationRig/RigLayerDrawer.cs b/Packages/com.unity.animation.rigging/Editor/AnimationRig/RigLayerDrawer.cs
new file mode 100644
index 00000000..d5c1db6a
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/RigLayerDrawer.cs
@@ -0,0 +1,40 @@
+using UnityEngine;
+using UnityEngine.Animations.Rigging;
+
+namespace UnityEditor.Animations.Rigging
+{
+ [CustomPropertyDrawer(typeof(RigLayer))]
+ class RigLayerDrawer : PropertyDrawer
+ {
+ const int k_Padding = 6;
+ const int k_TogglePadding = 30;
+
+ public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
+ {
+ return EditorGUIUtility.singleLineHeight;
+ }
+
+ public override void OnGUI(Rect rect, SerializedProperty property, GUIContent label)
+ {
+ EditorGUI.BeginProperty(rect, label, property);
+
+ var w = rect.width - k_TogglePadding;
+ var weightRect = new Rect(rect.x + w + k_Padding, rect.y, rect.width - w - k_Padding, rect.height);
+ rect.width = w;
+
+ EditorGUI.BeginChangeCheck();
+ EditorGUI.PropertyField(rect, property.FindPropertyRelative("m_Rig"), label);
+
+ var indentLvl = EditorGUI.indentLevel;
+ EditorGUI.indentLevel = 0;
+ EditorGUI.PropertyField(weightRect, property.FindPropertyRelative("m_Active"), GUIContent.none);
+ EditorGUI.indentLevel = indentLvl;
+
+ if (EditorGUI.EndChangeCheck())
+ property.serializedObject.ApplyModifiedProperties();
+
+ EditorGUI.EndProperty();
+ }
+ }
+}
+
diff --git a/Packages/com.unity.animation.rigging/Editor/AnimationRig/RigLayerDrawer.cs.meta b/Packages/com.unity.animation.rigging/Editor/AnimationRig/RigLayerDrawer.cs.meta
new file mode 100644
index 00000000..93d03ef2
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/RigLayerDrawer.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: cfddd68cbf078454ab5dfd53ed554127
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.animation.rigging/Editor/AnimationRig/RigTransformEditor.cs b/Packages/com.unity.animation.rigging/Editor/AnimationRig/RigTransformEditor.cs
new file mode 100644
index 00000000..ad3a84af
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/RigTransformEditor.cs
@@ -0,0 +1,12 @@
+using UnityEngine.Animations.Rigging;
+
+namespace UnityEditor.Animations.Rigging
+{
+ [CustomEditor(typeof(RigTransform))]
+ class RigTransformEditor : Editor
+ {
+ public override void OnInspectorGUI()
+ {
+ }
+ }
+}
diff --git a/Packages/com.unity.animation.rigging/Editor/AnimationRig/RigTransformEditor.cs.meta b/Packages/com.unity.animation.rigging/Editor/AnimationRig/RigTransformEditor.cs.meta
new file mode 100644
index 00000000..3b891bef
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/RigTransformEditor.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: ab480ae8b7295e54c9c72a011401317e
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.animation.rigging/Editor/AnimationRig/WeightedTransformArrayDrawer.cs b/Packages/com.unity.animation.rigging/Editor/AnimationRig/WeightedTransformArrayDrawer.cs
new file mode 100644
index 00000000..70a903ac
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/WeightedTransformArrayDrawer.cs
@@ -0,0 +1,249 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using UnityEditorInternal;
+using UnityEngine;
+using UnityEngine.Animations.Rigging;
+using UnityObject = UnityEngine.Object;
+
+namespace UnityEditor.Animations.Rigging
+{
+ [CustomPropertyDrawer(typeof(WeightedTransformArray))]
+ sealed class WeightedTransformArrayDrawer : PropertyDrawer
+ {
+ const string k_LengthPath = "m_Length";
+ const string k_ItemTransformPath = nameof(WeightedTransform.transform);
+ const string k_ItemWeightPath = nameof(WeightedTransform.weight);
+ static readonly string[] k_ItemPropertyPaths =
+ Enumerable.Range(0, WeightedTransformArray.k_MaxLength).Select(i => $"m_Item{i}").ToArray();
+
+ // one reorderable list per unique property path
+ readonly Dictionary m_GUIState =
+ new Dictionary();
+
+ // function to get WeightedTransform from item property
+ static WeightedTransform GetValueSingle(SerializedProperty item) => new WeightedTransform
+ {
+ transform = item.FindPropertyRelative(k_ItemTransformPath).objectReferenceValue as Transform,
+ weight = item.FindPropertyRelative(k_ItemWeightPath).floatValue
+ };
+
+ // function to modify a list of items per target
+ static void ModifyItemsSingle(SerializedProperty parentProperty, Action> modifyList)
+ {
+ foreach (var target in parentProperty.serializedObject.targetObjects)
+ {
+ using (var so = new SerializedObject(target))
+ {
+ var sp = so.FindProperty(parentProperty.propertyPath);
+ var length = sp.FindPropertyRelative(k_LengthPath);
+
+ // create a live list of items
+ var items =
+ Enumerable.Range(0, length.intValue)
+ .Select(i => GetValueSingle(sp.FindPropertyRelative(k_ItemPropertyPaths[i])))
+ .ToList();
+
+ // modify the list
+ modifyList(items);
+
+ // write the results back to the serialized data stream
+ for (var i = 0; i < items.Count; ++i)
+ {
+ var item = sp.FindPropertyRelative(k_ItemPropertyPaths[i]);
+ item.FindPropertyRelative(k_ItemTransformPath).objectReferenceValue = items[i].transform;
+ item.FindPropertyRelative(k_ItemWeightPath).floatValue = items[i].weight;
+ }
+ // clear other items
+ for (var i = items.Count; i < WeightedTransformArray.k_MaxLength; ++i)
+ {
+ var item = sp.FindPropertyRelative(k_ItemPropertyPaths[i]);
+ item.FindPropertyRelative(k_ItemTransformPath).objectReferenceValue = default;
+ item.FindPropertyRelative(k_ItemWeightPath).floatValue = default;
+ }
+
+ // synchronize length property
+ length.intValue = items.Count;
+
+ // write back results
+ so.ApplyModifiedProperties();
+ }
+ }
+ // update parent property's serialized data stream to get new (shared) values for all targets
+ parentProperty.serializedObject.Update();
+ }
+
+ (ReorderableList listControl, SerializedProperty lengthProperty) GetGUIState(SerializedProperty property, GUIContent label)
+ {
+ var lengthProperty = property.FindPropertyRelative(k_LengthPath);
+
+ // create a new reorderable list if one does not exist
+ if (!m_GUIState.TryGetValue(property.propertyPath, out var guiState))
+ {
+ // bind the control to a proxy list
+ var proxy = Enumerable.Range(0, lengthProperty.intValue)
+ .ToList();
+ var reorderableList = new ReorderableList(proxy, typeof(int));
+
+ reorderableList.headerHeight = Styles.minHeaderHeight;
+
+ // default array control only allocates single line height, but that leaves no spacing between object fields
+ reorderableList.elementHeight =
+ EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
+
+ var attr = fieldInfo.GetCustomAttribute();
+ var legacyAttr = fieldInfo.GetCustomAttribute();
+ var min = attr?.min ?? legacyAttr?.min ?? float.NaN;
+ var max = attr?.max ?? legacyAttr?.max ?? float.NaN;
+ var spacing = EditorGUIUtility.standardVerticalSpacing / 2f;
+ reorderableList.drawElementCallback += (rect, index, active, focused) =>
+ {
+ rect = new Rect(rect) { height = EditorGUIUtility.singleLineHeight, y = rect.y + spacing };
+ WeightedTransformDrawer.DoGUI(rect, property.FindPropertyRelative(k_ItemPropertyPaths[index]), min, max);
+ };
+
+ reorderableList.onCanAddCallback += list =>
+ !Application.isPlaying
+ && !AnimationMode.InAnimationMode()
+ && lengthProperty.intValue < WeightedTransformArray.k_MaxLength;
+
+ reorderableList.onCanRemoveCallback += list =>
+ !Application.isPlaying
+ && !AnimationMode.InAnimationMode()
+ && lengthProperty.intValue > 0;
+
+ reorderableList.onAddCallback += list =>
+ {
+ ModifyItemsSingle(property, items =>
+ {
+ int insertIndex = Math.Max(0, reorderableList.index >= 0 ? reorderableList.index : items.Count - 1);
+ if (items.Count < WeightedTransformArray.k_MaxLength)
+ items.Insert(insertIndex, insertIndex < items.Count ? items[insertIndex] : WeightedTransform.Default(1f));
+ });
+ proxy.Add(proxy.Count);
+ };
+
+ reorderableList.onRemoveCallback += list =>
+ {
+ ModifyItemsSingle(property, items =>
+ {
+ int removeIndex = Math.Max(0, reorderableList.index >= 0 ? reorderableList.index : items.Count - 1);
+ if (removeIndex >= 0)
+ items.RemoveAt(removeIndex);
+ });
+ proxy.RemoveAt(proxy.Count - 1);
+ };
+
+ reorderableList.onReorderCallbackWithDetails += (list, srcIndex, dstIndex) =>
+ ModifyItemsSingle(property, items =>
+ {
+ var moved = items[srcIndex];
+ items.RemoveAt(srcIndex);
+ items.Insert(dstIndex, moved);
+ });
+
+ guiState = m_GUIState[property.propertyPath] = (reorderableList, lengthProperty.Copy());
+ }
+
+ // synchronize proxy list to serialized length
+ var proxyList = guiState.listControl.list;
+ while (proxyList.Count < lengthProperty.intValue)
+ proxyList.Add(proxyList.Count);
+ while (proxyList.Count > lengthProperty.intValue)
+ proxyList.RemoveAt(proxyList.Count - 1);
+
+ return guiState;
+ }
+
+ static class Styles
+ {
+ // cf. ReorderableList.Defaults.minHeaderHeight;
+ public static float minHeaderHeight = 2f;
+ // cf. ReorderableListWrapper.cs
+ public const float headerPadding = 3f;
+ public const float arraySizeWidth = 50f; // 48 in ReorderableListWrapper, but EditorGUI.Slider() field is 50
+ public const float defaultFoldoutHeaderHeight = 18f;
+ public static readonly GUIContent sizeLabel = EditorGUIUtility.TrTextContent("", "Length");
+ }
+
+ public override float GetPropertyHeight(SerializedProperty property, GUIContent label) =>
+ Styles.defaultFoldoutHeaderHeight
+ + (property.isExpanded ? Styles.headerPadding + GetGUIState(property, label).listControl.GetHeight() : 0f);
+
+ public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
+ {
+ var guiState = GetGUIState(property, label);
+
+ Rect headerRect = new Rect(position) { height = EditorGUIUtility.singleLineHeight };
+ Rect sizeRect = new Rect(headerRect) { xMin = headerRect.xMax - Styles.arraySizeWidth };
+
+ EventType prevType = Event.current.type;
+ if (Event.current.type == EventType.MouseUp && sizeRect.Contains(Event.current.mousePosition))
+ {
+ Event.current.type = EventType.Used;
+ }
+
+ property.isExpanded = EditorGUI.BeginFoldoutHeaderGroup(headerRect, property.isExpanded, label);
+ EditorGUI.EndFoldoutHeaderGroup();
+
+ if (Event.current.type == EventType.Used && sizeRect.Contains(Event.current.mousePosition)) Event.current.type = prevType;
+
+ EditorGUI.BeginChangeCheck();
+ EditorGUI.DelayedIntField(sizeRect, guiState.lengthProperty, Styles.sizeLabel);
+ if (EditorGUI.EndChangeCheck())
+ guiState.lengthProperty.intValue = Mathf.Clamp(guiState.lengthProperty.intValue, 0, WeightedTransformArray.k_MaxLength);
+ EditorGUI.LabelField(sizeRect, Styles.sizeLabel);
+
+ if (headerRect.Contains(Event.current.mousePosition))
+ {
+ if (Event.current.type == EventType.DragUpdated || Event.current.type == EventType.DragPerform)
+ {
+ OnDropObjects(property, DragAndDrop.objectReferences, guiState.listControl);
+ DragAndDrop.AcceptDrag();
+ Event.current.Use();
+ }
+ }
+
+ if (Event.current.type == EventType.DragExited)
+ {
+ DragAndDrop.visualMode = DragAndDropVisualMode.None;
+ Event.current.Use();
+ }
+
+ if (property.isExpanded)
+ guiState.listControl.DoList(new Rect(position) { yMin = headerRect.yMax + Styles.headerPadding });
+ }
+
+ static void OnDropObjects(SerializedProperty property, UnityObject[] objectReferences, ReorderableList listControl)
+ {
+ foreach (var o in objectReferences)
+ {
+ var go = o as GameObject;
+ var c = o as Component;
+
+ if (go == null && c == null)
+ continue;
+
+ if (listControl.list.Count >= WeightedTransformArray.k_MaxLength)
+ {
+ DragAndDrop.visualMode = DragAndDropVisualMode.Rejected;
+ continue;
+ }
+
+ DragAndDrop.visualMode = DragAndDropVisualMode.Generic;
+
+ var t = c == null ? go.transform : c.transform;
+ if (Event.current.type == EventType.DragPerform)
+ {
+ ModifyItemsSingle(property, items =>
+ {
+ var weight = items.Count == 0 ? 1f : items[items.Count - 1].weight;
+ items.Add(new WeightedTransform(t, weight));
+ });
+ listControl.list.Add(listControl.list.Count);
+ }
+ }
+ }
+ }
+}
diff --git a/Packages/com.unity.animation.rigging/Editor/AnimationRig/WeightedTransformArrayDrawer.cs.meta b/Packages/com.unity.animation.rigging/Editor/AnimationRig/WeightedTransformArrayDrawer.cs.meta
new file mode 100644
index 00000000..637b707a
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/WeightedTransformArrayDrawer.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: ee7818cdc02e4548adb5ae6bc5901523
+timeCreated: 1607593832
\ No newline at end of file
diff --git a/Packages/com.unity.animation.rigging/Editor/AnimationRig/WeightedTransformDrawer.cs b/Packages/com.unity.animation.rigging/Editor/AnimationRig/WeightedTransformDrawer.cs
new file mode 100644
index 00000000..7bd617ec
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/WeightedTransformDrawer.cs
@@ -0,0 +1,59 @@
+using System.Reflection;
+using UnityEngine;
+using UnityEngine.Animations.Rigging;
+
+namespace UnityEditor.Animations.Rigging
+{
+ [CustomPropertyDrawer(typeof(WeightedTransform))]
+ class WeightedTransformDrawer : PropertyDrawer
+ {
+ public override float GetPropertyHeight(SerializedProperty property, GUIContent label) =>
+ EditorGUIUtility.singleLineHeight;
+
+ (WeightRangeAttribute attr, RangeAttribute legacyAttr)? m_RangeAttributes;
+
+ public override void OnGUI(Rect rect, SerializedProperty property, GUIContent label)
+ {
+ var (attr, legacyAttr) = m_RangeAttributes ??= (
+ fieldInfo.GetCustomAttribute(),
+ fieldInfo.GetCustomAttribute()
+ );
+
+ float min = attr?.min ?? legacyAttr?.min ?? float.NaN;
+ float max = attr?.max ?? legacyAttr?.max ?? float.NaN;
+
+ DoGUI(rect, property, min, max);
+ }
+
+ static class Styles
+ {
+ public static float transformFieldWidthScale = 0.65f;
+ public static readonly int horizontalMargin = (
+ EditorStyles.objectField.margin.right + GUI.skin.horizontalSlider.margin.left
+ ) / 2;
+ }
+
+ internal static void DoGUI(Rect rect, SerializedProperty property, float min, float max)
+ {
+ EditorGUI.BeginProperty(rect, GUIContent.none, property);
+
+ var w = rect.width * Styles.transformFieldWidthScale;
+ var weightRect = new Rect(rect.x + w, rect.y, rect.width - w, EditorGUIUtility.singleLineHeight);
+ rect.width = w;
+
+ var transformRect = new Rect(rect.x, rect.y, rect.width - Styles.horizontalMargin, EditorGUIUtility.singleLineHeight);
+
+ EditorGUI.PropertyField(transformRect, property.FindPropertyRelative("transform"), GUIContent.none);
+
+ var indentLvl = EditorGUI.indentLevel;
+ EditorGUI.indentLevel = 0;
+ if (float.IsNaN(max) || float.IsNaN(min))
+ EditorGUI.PropertyField(weightRect, property.FindPropertyRelative("weight"), GUIContent.none);
+ else
+ EditorGUI.Slider(weightRect, property.FindPropertyRelative("weight"), min, max, GUIContent.none);
+ EditorGUI.indentLevel = indentLvl;
+
+ EditorGUI.EndProperty();
+ }
+ }
+}
diff --git a/Packages/com.unity.animation.rigging/Editor/AnimationRig/WeightedTransformDrawer.cs.meta b/Packages/com.unity.animation.rigging/Editor/AnimationRig/WeightedTransformDrawer.cs.meta
new file mode 100644
index 00000000..5a8e32ee
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AnimationRig/WeightedTransformDrawer.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a015bc034afc6b742996a3d23fa85902
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.animation.rigging/Editor/AssemblyInfo.cs b/Packages/com.unity.animation.rigging/Editor/AssemblyInfo.cs
new file mode 100644
index 00000000..773a17ae
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AssemblyInfo.cs
@@ -0,0 +1,2 @@
+using System.Runtime.CompilerServices;
+[assembly: InternalsVisibleTo("Unity.Animation.Rigging.EditorTests")]
diff --git a/Packages/com.unity.animation.rigging/Editor/AssemblyInfo.cs.meta b/Packages/com.unity.animation.rigging/Editor/AssemblyInfo.cs.meta
new file mode 100644
index 00000000..6aee2bc8
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/AssemblyInfo.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 0e9f01c83e9859644bb453f6f07af6d6
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.animation.rigging/Editor/Attributes.meta b/Packages/com.unity.animation.rigging/Editor/Attributes.meta
new file mode 100644
index 00000000..54a394a4
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/Attributes.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: f53358c1055884db9ba27bfa39aae0a0
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.animation.rigging/Editor/Attributes/BakeParametersAttribute.cs b/Packages/com.unity.animation.rigging/Editor/Attributes/BakeParametersAttribute.cs
new file mode 100644
index 00000000..ced9a0d6
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/Attributes/BakeParametersAttribute.cs
@@ -0,0 +1,116 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Animations.Rigging;
+
+namespace UnityEditor.Animations.Rigging
+{
+ ///
+ /// Attribute that can be placed on BakeParameters. The attribute is used to declare to which RigConstraint the BakeParameters belong.
+ ///
+ [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
+ public sealed class BakeParametersAttribute : Attribute
+ {
+ ///
+ /// Constructor.
+ ///
+ /// The RigConstraint to which the BakeParameters belong.
+ public BakeParametersAttribute(Type constraintType)
+ {
+ if (constraintType == null || !typeof(IRigConstraint).IsAssignableFrom(constraintType))
+ Debug.LogError("Invalid constraint for InverseRigConstraint attribute.");
+
+ this.constraintType = constraintType;
+ }
+
+ ///
+ /// The RigConstraint to which the BakeParameters belong.
+ ///
+ public Type constraintType { get; }
+ }
+
+ ///
+ /// Class that holds bi-directional baking capabilities and curve bindings of a RigConstraint.
+ ///
+ /// The Type of RigConstraint the parameters belong to.
+ public abstract class BakeParameters : IBakeParameters
+ where T : IRigConstraint
+ {
+ ///
+ /// Boolean used to determine if the RigConstraint can transfer motion from itself to the skeleton
+ ///
+ public abstract bool canBakeToSkeleton { get; }
+ ///
+ /// Boolean used to determine if the RigConstraint can transfer motion to itself from the skeleton.
+ ///
+ public abstract bool canBakeToConstraint { get; }
+
+ ///
+ /// Collects the editor curve bindings for all the properties that this RigConstraint modifies when transferring motion to the skeleton.
+ ///
+ /// The RigBuilder which the constraint is part of.
+ /// The RigConstraint for which the bindings should be collected.
+ ///
+ public abstract IEnumerable GetSourceCurveBindings(RigBuilder rigBuilder, T constraint);
+ ///
+ /// Collects the editor curve bindings for all the properties that this RigConstraint modifies when transferring motion to this constraint.
+ ///
+ /// The RigBuilder which the constraint is part of.
+ /// The RigConstraint for which the bindings should be collected.
+ ///
+ public abstract IEnumerable GetConstrainedCurveBindings(RigBuilder rigBuilder, T constraint);
+
+
+ ///
+ bool IBakeParameters.canBakeToSkeleton => canBakeToSkeleton;
+ ///
+ bool IBakeParameters.canBakeToConstraint => canBakeToConstraint;
+
+ ///
+ IEnumerable IBakeParameters.GetSourceCurveBindings(RigBuilder rigBuilder, IRigConstraint constraint)
+ {
+ Debug.Assert(constraint is T);
+ T tConstraint = (T)constraint;
+ return GetSourceCurveBindings(rigBuilder, tConstraint);
+ }
+
+ ///
+ IEnumerable IBakeParameters.GetConstrainedCurveBindings(RigBuilder rigBuilder, IRigConstraint constraint)
+ {
+ Debug.Assert(constraint is T);
+ T tConstraint = (T)constraint;
+ return GetConstrainedCurveBindings(rigBuilder, tConstraint);
+ }
+ }
+
+ ///
+ /// This is the base interface for BakeParameters.
+ ///
+ public interface IBakeParameters
+ {
+ ///
+ /// Boolean used to determine if the RigConstraint can transfer motion from itself to the skeleton
+ ///
+ bool canBakeToSkeleton { get; }
+ ///
+ /// Boolean used to determine if the RigConstraint can transfer motion to itself from the skeleton.
+ ///
+ bool canBakeToConstraint { get; }
+
+ ///
+ /// Collects the editor curve bindings for all the properties that this RigConstraint modifies when transferring motion to the skeleton.
+ ///
+ /// The RigBuilder which the constraint is part of.
+ /// The RigConstraint for which the bindings should be collected.
+ ///
+ IEnumerable GetSourceCurveBindings(RigBuilder rigBuilder, IRigConstraint constraint);
+ ///
+ /// Collects the editor curve bindings for all the properties that this RigConstraint modifies when transferring motion to this constraint.
+ ///
+ /// The RigBuilder which the constraint is part of.
+ /// The RigConstraint for which the bindings should be collected.
+ ///
+ IEnumerable GetConstrainedCurveBindings(RigBuilder rigBuilder, IRigConstraint constraint);
+ }
+
+}
diff --git a/Packages/com.unity.animation.rigging/Editor/Attributes/BakeParametersAttribute.cs.meta b/Packages/com.unity.animation.rigging/Editor/Attributes/BakeParametersAttribute.cs.meta
new file mode 100644
index 00000000..bff83cb2
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/Attributes/BakeParametersAttribute.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: bc4c7bdb3fbef4e6f8eb6ea619b7c442
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.animation.rigging/Editor/Attributes/CustomOverlayAttribute.cs b/Packages/com.unity.animation.rigging/Editor/Attributes/CustomOverlayAttribute.cs
new file mode 100644
index 00000000..0ca3a772
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/Attributes/CustomOverlayAttribute.cs
@@ -0,0 +1,18 @@
+using System;
+using UnityEngine;
+
+namespace UnityEditor.Animations.Rigging
+{
+ [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
+ internal sealed class CustomOverlayAttribute : Attribute
+ {
+ private Type m_EffectorType;
+
+ public CustomOverlayAttribute(Type effectorType)
+ {
+ m_EffectorType = effectorType;
+ }
+
+ public Type effectorType { get => m_EffectorType; }
+ }
+}
diff --git a/Packages/com.unity.animation.rigging/Editor/Attributes/CustomOverlayAttribute.cs.meta b/Packages/com.unity.animation.rigging/Editor/Attributes/CustomOverlayAttribute.cs.meta
new file mode 100644
index 00000000..8256fb71
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/Attributes/CustomOverlayAttribute.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 54d375d3ab6254023a5ab55153af9c84
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.animation.rigging/Editor/Attributes/InverseRigConstraintAttribute.cs b/Packages/com.unity.animation.rigging/Editor/Attributes/InverseRigConstraintAttribute.cs
new file mode 100644
index 00000000..e888aee7
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/Attributes/InverseRigConstraintAttribute.cs
@@ -0,0 +1,32 @@
+using System;
+using UnityEngine;
+using UnityEngine.Animations.Rigging;
+
+namespace UnityEditor.Animations.Rigging
+{
+ ///
+ /// The [InverseRigConstraint] attribute allows to match an inverse constraint (inverse solve) to its
+ /// base constraint (forward solve) counterpart. This is used in bi-directional baking to override
+ /// constraints when baking animations to constraints.
+ ///
+ [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
+ public sealed class InverseRigConstraintAttribute : Attribute
+ {
+ ///
+ /// Constructor.
+ ///
+ /// The base constraint type.
+ public InverseRigConstraintAttribute(Type targetBinderType)
+ {
+ if (targetBinderType == null || !typeof(IRigConstraint).IsAssignableFrom(targetBinderType))
+ Debug.LogError("Invalid constraint for InverseRigConstraint attribute.");
+
+ this.baseConstraint = targetBinderType;
+ }
+
+ ///
+ /// Retrieves the base constraint type.
+ ///
+ public Type baseConstraint { get; }
+ }
+}
diff --git a/Packages/com.unity.animation.rigging/Editor/Attributes/InverseRigConstraintAttribute.cs.meta b/Packages/com.unity.animation.rigging/Editor/Attributes/InverseRigConstraintAttribute.cs.meta
new file mode 100644
index 00000000..bf2253d9
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/Attributes/InverseRigConstraintAttribute.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 28f235e117a7e453fa6d4c1cb6094700
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.animation.rigging/Editor/Effectors.meta b/Packages/com.unity.animation.rigging/Editor/Effectors.meta
new file mode 100644
index 00000000..6f62dea0
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/Effectors.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: fbd5015e3b81f464aa1b87826a3eaf55
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.animation.rigging/Editor/Effectors/IRigEffector.cs b/Packages/com.unity.animation.rigging/Editor/Effectors/IRigEffector.cs
new file mode 100644
index 00000000..59171879
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/Effectors/IRigEffector.cs
@@ -0,0 +1,12 @@
+using UnityEngine;
+
+namespace UnityEditor.Animations.Rigging
+{
+ internal interface IRigEffector
+ {
+ Transform transform { get; }
+ bool visible { get; set; }
+
+ void OnSceneGUI();
+ }
+}
diff --git a/Packages/com.unity.animation.rigging/Editor/Effectors/IRigEffector.cs.meta b/Packages/com.unity.animation.rigging/Editor/Effectors/IRigEffector.cs.meta
new file mode 100644
index 00000000..7cb4778d
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/Effectors/IRigEffector.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 5aa7c79e34bb34aab80024d95fafe526
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.animation.rigging/Editor/Effectors/IRigEffectorOverlay.cs b/Packages/com.unity.animation.rigging/Editor/Effectors/IRigEffectorOverlay.cs
new file mode 100644
index 00000000..5d09955e
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/Effectors/IRigEffectorOverlay.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace UnityEditor.Animations.Rigging
+{
+ interface IRigEffectorOverlay : IDisposable
+ {
+ bool IsValid();
+ void OnSceneGUIOverlay();
+ }
+}
diff --git a/Packages/com.unity.animation.rigging/Editor/Effectors/IRigEffectorOverlay.cs.meta b/Packages/com.unity.animation.rigging/Editor/Effectors/IRigEffectorOverlay.cs.meta
new file mode 100644
index 00000000..2bb28123
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/Effectors/IRigEffectorOverlay.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 4231b7e96c3094051a12f91bae5c7c90
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.animation.rigging/Editor/Effectors/RigEffector.cs b/Packages/com.unity.animation.rigging/Editor/Effectors/RigEffector.cs
new file mode 100644
index 00000000..f6b0c1b8
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/Effectors/RigEffector.cs
@@ -0,0 +1,307 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Animations.Rigging;
+
+namespace UnityEditor.Animations.Rigging
+{
+ [Serializable]
+ internal class RigEffector : ScriptableObject, IRigEffector
+ {
+ [SerializeField] private RigEffectorData m_Data;
+
+ public Transform transform
+ {
+ get => m_Data.transform;
+ }
+
+ public bool visible
+ {
+ get => m_Data.visible;
+ set => m_Data.visible = value;
+ }
+
+ private static int s_ButtonHash = "RigEffector".GetHashCode();
+
+ public void Initialize(RigEffectorData data)
+ {
+ m_Data = data;
+ }
+
+ private static Material s_Material;
+
+ public static Material material
+ {
+ get
+ {
+ if (!s_Material)
+ {
+ var shader = EditorHelper.LoadShader("BoneHandles.shader");
+ s_Material = new Material(shader);
+ s_Material.hideFlags = HideFlags.HideAndDontSave;
+ }
+
+ return s_Material;
+ }
+ }
+
+ public static RigEffectorData.Style defaultStyle
+ {
+ get
+ {
+ var style = new RigEffectorData.Style()
+ {
+ shape = EditorHelper.LoadShape("LocatorEffector.asset"),
+ color = new Color(1f, 0f, 0f, 0.5f),
+ size = 0.10f,
+ position = Vector3.zero,
+ rotation = Vector3.zero
+ };
+
+ return style;
+ }
+ }
+
+ public void OnSceneGUI()
+ {
+ if (!m_Data.visible)
+ return;
+
+ // Might happen if we delete transform while effector still exists.
+ if (transform == null)
+ return;
+
+ var style = m_Data.style;
+
+ // Disregard effectors without shapes.
+ if (style.shape == null)
+ return;
+
+ if (SceneVisibilityManager.instance.IsHidden(transform.gameObject, false))
+ return;
+
+ var mask = UnityEditor.Tools.visibleLayers;
+ if ((mask & (1 << transform.gameObject.layer)) == 0)
+ return;
+
+ int id = GUIUtility.GetControlID(s_ButtonHash, FocusType.Passive);
+ Event evt = Event.current;
+
+ switch (evt.GetTypeForControl(id))
+ {
+ case EventType.Layout:
+ {
+ HandleUtility.AddControl(id, DistanceToEffector(transform, style.shape, style.position, style.rotation, style.size));
+ break;
+ }
+ case EventType.MouseDown:
+ {
+ if (evt.alt)
+ break;
+
+ if (HandleUtility.nearestControl == id && evt.button == 0)
+ {
+ GameObject targetGameObject = transform.gameObject;
+ if (!SceneVisibilityManager.instance.IsPickingDisabled(targetGameObject, false))
+ {
+ GUIUtility.hotControl = id; // Grab mouse focus
+ EditorHelper.HandleClickSelection(targetGameObject, evt);
+ evt.Use();
+ }
+ }
+ break;
+ }
+ case EventType.MouseDrag:
+ {
+ if (!evt.alt && GUIUtility.hotControl == id)
+ {
+ GameObject targetGameObject = transform.gameObject;
+ if (!SceneVisibilityManager.instance.IsPickingDisabled(targetGameObject, false))
+ {
+ DragAndDrop.PrepareStartDrag();
+ DragAndDrop.objectReferences = new UnityEngine.Object[] {transform};
+ DragAndDrop.StartDrag(ObjectNames.GetDragAndDropTitle(transform));
+
+ GUIUtility.hotControl = 0;
+
+ evt.Use();
+ }
+ }
+ break;
+ }
+ case EventType.MouseUp:
+ {
+ if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2))
+ {
+ GUIUtility.hotControl = 0;
+ evt.Use();
+ }
+ break;
+ }
+ case EventType.Repaint:
+ {
+ Matrix4x4 matrix = GetEffectorMatrix(transform, style.position, style.rotation, style.size);
+
+ Color highlight = style.color;
+
+ bool hoveringEffector = GUIUtility.hotControl == 0 && HandleUtility.nearestControl == id;
+ hoveringEffector = hoveringEffector &&
+ !SceneVisibilityManager.instance.IsPickingDisabled(transform.gameObject, false);
+
+ if (hoveringEffector)
+ {
+ highlight = Handles.preselectionColor;
+ }
+ else if (Selection.Contains(transform.gameObject) || Selection.activeObject == transform.gameObject)
+ {
+ highlight = Handles.selectedColor;
+ }
+
+ try
+ {
+ Material mat = material;
+
+ 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)
+ {
+ 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(0);
+ bool isFilled = (topology == MeshTopology.Triangles || topology == MeshTopology.Quads);
+
+ mat.SetColor("_Color", isFilled ? shapeHighlight : wireHighlight);
+ mat.SetPass(0);
+
+ Graphics.DrawMeshNow(style.shape, matrix);
+ }
+ }
+ catch (Exception exception)
+ {
+ Debug.LogException(exception);
+ }
+ }
+ break;
+ }
+ }
+
+ private bool FindMeshTopology(Mesh shape, IEnumerable topologies)
+ {
+ if (shape.subMeshCount > 0)
+ {
+ for (int i = 0; i < shape.subMeshCount; ++i)
+ {
+ MeshTopology topology = shape.GetTopology(i);
+ foreach (var topologyQuery in topologies)
+ {
+ if (topologyQuery == topology)
+ return true;
+ }
+ }
+ }
+ else
+ {
+ var topology = shape.GetTopology(0);
+ foreach (var topologyQuery in topologies)
+ {
+ if (topologyQuery == topology)
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private bool MeshHasFilledShapes(Mesh shape) =>
+ FindMeshTopology(shape, new MeshTopology[] {MeshTopology.Triangles, MeshTopology.Quads});
+
+ private bool MeshHasWireframeShapes(Mesh shape) =>
+ FindMeshTopology(shape, new MeshTopology[] {MeshTopology.Lines, MeshTopology.LineStrip});
+
+ private Matrix4x4 GetEffectorMatrix(Transform transform, Vector3 position, Vector3 rotation, float size)
+ {
+ return Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one) * Matrix4x4.TRS(position, Quaternion.Euler(rotation), new Vector3(size, size, size));
+ }
+
+ private float DistanceToEffector(Transform transform, Mesh shape, Vector3 position, Vector3 rotation, float size)
+ {
+ Matrix4x4 matrix = GetEffectorMatrix(transform, position, rotation, size);
+ Vector3 origin = matrix.MultiplyPoint(Vector3.zero);
+
+ if (shape == null)
+ return HandleUtility.DistanceToCircle(origin, size * 0.5f);
+
+ if (MeshHasFilledShapes(shape))
+ {
+ var bounds = shape.bounds;
+ var extents = Mathf.Max( Mathf.Max(bounds.extents.x, bounds.extents.y), bounds.extents.z);
+ return HandleUtility.DistanceToCircle(origin + bounds.center * size, extents * size);
+ }
+
+ float nearestDistance = Mathf.Infinity;
+
+ Vector3[] vertices = shape.vertices;
+
+ for (int i = 0; i < shape.subMeshCount; ++i)
+ {
+ MeshTopology topology = shape.GetTopology(i);
+ if (topology == MeshTopology.Lines)
+ {
+ int[] indices = shape.GetIndices(i);
+
+ int count = 0;
+ while (count < indices.Length)
+ {
+ float d = HandleUtility.DistanceToLine(matrix.MultiplyPoint(vertices[indices[count]]), matrix.MultiplyPoint(vertices[indices[count+1]]));
+ if (d < nearestDistance)
+ nearestDistance = d;
+
+ count += 2;
+ }
+ }
+ else if (topology == MeshTopology.LineStrip)
+ {
+ int[] indices = shape.GetIndices(i);
+
+ if (indices.Length > 0)
+ {
+ int count = 0;
+ float d = 0f;
+ Vector3 v0 = matrix.MultiplyPoint(vertices[indices[count]]);
+ Vector3 v1 = v0;
+
+ while (++count < indices.Length)
+ {
+ Vector3 v2 = matrix.MultiplyPoint(vertices[indices[count]]);
+
+ d = HandleUtility.DistanceToLine(v1, v2);
+ if (d < nearestDistance)
+ nearestDistance = d;
+
+ v1 = v2;
+ }
+
+ d = HandleUtility.DistanceToLine(v1, v0);
+ if (d < nearestDistance)
+ nearestDistance = d;
+ }
+ }
+ }
+
+ return nearestDistance;
+ }
+ }
+}
diff --git a/Packages/com.unity.animation.rigging/Editor/Effectors/RigEffector.cs.meta b/Packages/com.unity.animation.rigging/Editor/Effectors/RigEffector.cs.meta
new file mode 100644
index 00000000..1aa0f3cb
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/Effectors/RigEffector.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: ff03b96c5bd3745c28814ed6eb4341cb
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.animation.rigging/Editor/Effectors/RigEffectorOverlay.cs b/Packages/com.unity.animation.rigging/Editor/Effectors/RigEffectorOverlay.cs
new file mode 100644
index 00000000..a384838f
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/Effectors/RigEffectorOverlay.cs
@@ -0,0 +1,190 @@
+using UnityEngine;
+using UnityEngine.Animations.Rigging;
+
+namespace UnityEditor.Animations.Rigging
+{
+ [CustomOverlay(typeof(RigEffector))]
+ class RigEffectorOverlay : IRigEffectorOverlay
+ {
+ private Object[] m_TargetObjects;
+ private SerializedObject m_SerializedObject;
+
+ private SerializedProperty m_Visible;
+ private SerializedProperty m_Shape;
+ private SerializedProperty m_Color;
+ private SerializedProperty m_Size;
+ private SerializedProperty m_Position;
+ private SerializedProperty m_Rotation;
+
+ private bool m_ExpandOverlay;
+
+ private static GUIContent s_VisibleLabel = new GUIContent("Visible");
+ private static GUIContent s_ShapeLabel = new GUIContent("Shape");
+ private static GUIContent s_ColorLabel = new GUIContent("Color");
+ private static GUIContent s_SizeLabel = new GUIContent("Size");
+ private static GUIContent s_PositionLabel = new GUIContent("Position");
+ private static GUIContent s_RotationLabel = new GUIContent("Rotation");
+
+ private static GUIContent s_RemoveLabel = new GUIContent("Remove");
+
+ private static string s_ExpandOverlayPrefKey = "AnimationRigging.ExpandOverlay";
+
+ private static GUILayoutOption s_FixedWidth = GUILayout.Width(210f);
+
+ public void Initialize(Object[] effectors)
+ {
+ m_TargetObjects = effectors;
+ m_SerializedObject = new SerializedObject(effectors);
+
+ SerializedProperty data = m_SerializedObject.FindProperty("m_Data");
+
+ m_Visible = data.FindPropertyRelative("m_Visible");
+
+ SerializedProperty style = data.FindPropertyRelative("m_Style");
+
+ m_Shape = style.FindPropertyRelative("shape");
+ m_Color = style.FindPropertyRelative("color");
+ m_Size = style.FindPropertyRelative("size");
+ m_Position = style.FindPropertyRelative("position");
+ m_Rotation = style.FindPropertyRelative("rotation");
+
+ m_ExpandOverlay = EditorPrefs.GetBool(s_ExpandOverlayPrefKey, true);
+ }
+
+ private IRigEffectorHolder FetchRigEffectorHolder(Transform transform)
+ {
+ var rigBuilder = EditorHelper.GetClosestComponent(transform);
+ var rig = EditorHelper.GetClosestComponent(transform, (rigBuilder != null) ? rigBuilder.transform : null);
+
+ if (rigBuilder.ContainsEffector(transform))
+ {
+ return rigBuilder;
+ }
+ else if (rig.ContainsEffector(transform))
+ {
+ return rig;
+ }
+
+ return null;
+ }
+
+ public bool IsValid() => m_SerializedObject.targetObject != null;
+
+ public void OnSceneGUIOverlay()
+ {
+ if (!IsValid())
+ return;
+
+ m_SerializedObject.Update();
+
+ GameObject targetGameObject = null;
+ if (!m_SerializedObject.isEditingMultipleObjects)
+ {
+ RigEffector rigEffector = m_SerializedObject.targetObject as RigEffector;
+ if (rigEffector != null && rigEffector.transform != null)
+ {
+ targetGameObject = rigEffector.transform.gameObject;
+ }
+ }
+
+ GUILayout.BeginHorizontal(s_FixedWidth);
+
+ EditorGUI.BeginChangeCheck();
+ m_ExpandOverlay = EditorGUILayout.Toggle(m_ExpandOverlay, EditorStyles.foldout, GUILayout.Width(12));
+ if (EditorGUI.EndChangeCheck())
+ {
+ EditorPrefs.SetBool(s_ExpandOverlayPrefKey, m_ExpandOverlay);
+ }
+
+ GUILayout.BeginHorizontal(EditorStyles.toolbar);
+
+ EditorGUILayout.PropertyField(m_Visible, GUIContent.none, GUILayout.Width(17));
+
+ GUILayout.Label((targetGameObject != null) ? targetGameObject.name : "(Multiple objects)");
+
+ if (GUILayout.Button(GUIContent.none, "OL Minus", GUILayout.Width(17)))
+ {
+ UnityEngine.Object[] targetObjects = m_SerializedObject.targetObjects;
+ foreach(var targetObject in targetObjects)
+ {
+ var effector = targetObject as IRigEffector;
+ Transform transform = effector.transform;
+
+ IRigEffectorHolder holder = FetchRigEffectorHolder(transform);
+ if (holder != null)
+ {
+ var holderObject = holder as UnityEngine.Object;
+
+ Undo.RecordObject(holderObject, "Remove Effector");
+
+ if (PrefabUtility.IsPartOfPrefabInstance(holderObject))
+ EditorUtility.SetDirty(holderObject);
+
+ holder.RemoveEffector(transform);
+ }
+ }
+ }
+
+ GUILayout.EndHorizontal();
+ GUILayout.EndHorizontal();
+
+ if (m_ExpandOverlay)
+ {
+ EditorGUILayout.LabelField(s_ShapeLabel, s_FixedWidth);
+ EditorGUILayout.PropertyField(m_Shape, GUIContent.none, s_FixedWidth);
+
+ Rect rect = GUILayoutUtility.GetRect(s_ColorLabel, EditorStyles.colorField, s_FixedWidth);
+
+ // Shenanigans to bypass color picker bug.
+ var evt = Event.current;
+ if (evt.type == EventType.MouseUp)
+ {
+ if (rect.Contains(evt.mousePosition))
+ {
+ GUIUtility.hotControl = 0;
+ }
+ }
+
+ EditorGUI.BeginProperty(rect, s_ColorLabel, m_Color);
+ EditorGUI.BeginChangeCheck();
+ Color newColor = EditorGUI.ColorField(rect, s_ColorLabel, m_Color.colorValue, false, true, false);
+ if (EditorGUI.EndChangeCheck())
+ {
+ m_Color.colorValue = newColor;
+ }
+ EditorGUI.EndProperty();
+
+ EditorGUILayout.PropertyField(m_Size, s_SizeLabel, s_FixedWidth);
+ EditorGUILayout.PropertyField(m_Position, s_PositionLabel, s_FixedWidth);
+ EditorGUILayout.PropertyField(m_Rotation, s_RotationLabel, s_FixedWidth);
+ }
+
+ if (m_SerializedObject.hasModifiedProperties)
+ {
+ UnityEngine.Object[] targetObjects = m_SerializedObject.targetObjects;
+ foreach(var targetObject in targetObjects)
+ {
+ var effector = targetObject as IRigEffector;
+ Transform transform = effector.transform;
+
+ IRigEffectorHolder holder = FetchRigEffectorHolder(transform);
+ if (holder != null)
+ {
+ var holderObject = holder as UnityEngine.Object;
+ Undo.RecordObject(holderObject, "Edit Effector");
+
+ if (PrefabUtility.IsPartOfPrefabInstance(holderObject))
+ EditorUtility.SetDirty(holderObject);
+ }
+ }
+
+ m_SerializedObject.ApplyModifiedProperties();
+ }
+ }
+
+ public void Dispose()
+ {
+ m_SerializedObject?.Dispose();
+ }
+ }
+}
diff --git a/Packages/com.unity.animation.rigging/Editor/Effectors/RigEffectorOverlay.cs.meta b/Packages/com.unity.animation.rigging/Editor/Effectors/RigEffectorOverlay.cs.meta
new file mode 100644
index 00000000..d481b8b7
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/Effectors/RigEffectorOverlay.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 128d92bb7c7e949569b14ae35b4b229e
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/com.unity.animation.rigging/Editor/Effectors/RigEffectorRenderer.cs b/Packages/com.unity.animation.rigging/Editor/Effectors/RigEffectorRenderer.cs
new file mode 100644
index 00000000..bfde8047
--- /dev/null
+++ b/Packages/com.unity.animation.rigging/Editor/Effectors/RigEffectorRenderer.cs
@@ -0,0 +1,235 @@
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Animations.Rigging;
+#if SUPPORTS_SCENE_VIEW_OVERLAYS
+using UnityEditor.Overlays;
+#endif
+using UnityEditor.Experimental.SceneManagement; // required for 2020.2
+using UnityEditor.SceneManagement;
+
+namespace UnityEditor.Animations.Rigging
+{
+ [InitializeOnLoad]
+ static class RigEffectorRenderer
+ {
+ const string k_OverlayId = "Scene View/Animation Rigging";
+ const string k_DisplayName = "Animation Rigging";
+
+ static GUIContent s_OverlayTitle = new GUIContent(k_DisplayName);
+
+ static List s_RigBuilders = new List();
+ static Dictionary s_Effectors = new Dictionary();
+
+ static Transform[] s_ActiveSelection = null;
+ static List 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)
+ {
+ foreach(var effectorData in holder.effectors)
+ {
+ if (s_Effectors.ContainsKey(effectorData))
+ {
+ s_ActiveEffectors.Add(s_Effectors[effectorData]);
+ }
+ else
+ {
+ var newEffector = ScriptableObject.CreateInstance();
+ newEffector.Initialize(effectorData);
+
+ s_Effectors.Add(effectorData, newEffector);
+ s_ActiveEffectors.Add(newEffector);
+ }
+ }
+ }
+
+ static void FetchOrCreateEffectors()
+ {
+ s_ActiveEffectors = new List();
+
+ PrefabStage prefabStage = PrefabStageUtility.GetCurrentPrefabStage();
+
+ for (int i = 0; i < s_RigBuilders.Count; i++)
+ {
+ var rigBuilder = s_RigBuilders[i];
+
+ if (rigBuilder == null)
+ continue;
+
+ if (prefabStage != null)
+ {
+ StageHandle stageHandle = prefabStage.stageHandle;
+ if (stageHandle.IsValid() && !stageHandle.Contains(rigBuilder.gameObject))
+ continue;
+ }
+
+ FetchOrCreateEffectors(rigBuilder);
+
+ var rigs = rigBuilder.GetComponentsInChildren();
+ if (rigs != null)
+ {
+ foreach(var rig in rigs)
+ {
+ FetchOrCreateEffectors(rig);
+ }
+ }
+ }
+ }
+
+ 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