first commit

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

View File

@@ -0,0 +1,50 @@
* text=auto eol=lf
# EOL
*.py eol=lf
*.pl eol=lf
*.pm eol=lf
*.t eol=lf
*.it eol=lf
*.h eol=lf
*.cpp eol=lf
*.cs eol=lf
*.c eol=lf
*.txt eol=lf
*.bindings eol=lf
*.sh eol=lf
*.jam eol=lf
*.as eol=lf
*.boo eol=lf
*.java eol=lf
*.js eol=lf
Makefile eol=lf
*.shader eol=lf
*.cginc eol=lf
*.glslinc eol=lf
*.meta eol=lf
*.mm eol=lf
*.md eol=lf
Runtime/Export/common_* eol=lf
Repositories.ini eol=lf
.hgignore eol=lf
# vs can handle these as lf, but really wants them as crlf
*.vcproj eol=crlf
*.vcxproj eol=crlf
*.vcxproj.filters eol=crlf
*.csproj eol=crlf
*.props eol=crlf
*.targets eol=crlf
*.sln eol=crlf
*.sln.template eol=crlf
*.bat eol=crlf
*.cmd eol=crlf
*.xaml eol=crlf
# the templating parser will actually fail on lf, inexplicably setting every #line directive as '1'
*.tt eol=crlf
*.t4 eol=crlf
*.ttinclude eol=crlf

View File

@@ -0,0 +1,5 @@
{
"timestamp": 1675097346,
"signature": "sLaf7UbDWeIQ1rbAZUqsDzJE5/0srDNWDpraziCbDW4CB1xkeWHyWhc+dfHkeB/vaJfm8lU2RHER8PwViFYDfsJoP6KzEpL2dlfFew2kyc5SldgxNylVg6dzfUy28niNlErhEd8nVizxROaTfUTDE8Qe3A66zdGWqUqz0j9R1TWAiuOLHVQOI4VzbkyjF3CL+b67Y2tRI9IBc9KcY5Mc7UCTji1QI1OQNAkVMbMOmdEBPkoiujnA5Vn3YLYYY24trSvNG0NGsFOOWWyus9QDJDWOjeMImiYl8Vc9k4s/pz11LLtVqKslsbRDc4V5AeD1mWV+p/QI2WlkDvdlKOLjt6/ITPp07LDNIJy5+A8E6VXAXCepcJ9z9Vm5HozelqU4WoPnScA1o2tVxeGVMXZjEesK/0WaMXTlqjOWNKEKtJtqoRcpdvGvqKnV7JTVTq/oWZDjcjdcNmE8ee6C2x6rijc/oYEsHbBVonco5OnOX1jynHW9gYquOcOkiPlojGeQ",
"publicKey": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQm9qQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FZOEFNSUlCaWdLQ0FZRUFzdUhXYUhsZ0I1cVF4ZEJjTlJKSAordHR4SmoxcVY1NTdvMlZaRE1XaXhYRVBkRTBEMVFkT1JIRXNSS1RscmplUXlERU83ZlNQS0ZwZ1A3MU5TTnJCCkFHM2NFSU45aHNQVDhOVmllZmdWem5QTkVMenFkVmdEbFhpb2VpUnV6OERKWFgvblpmU1JWKytwbk9ySTRibG4KS0twelJlNW14OTc1SjhxZ1FvRktKT0NNRlpHdkJMR2MxSzZZaEIzOHJFODZCZzgzbUovWjBEYkVmQjBxZm13cgo2ZDVFUXFsd0E5Y3JZT1YyV1VpWXprSnBLNmJZNzRZNmM1TmpBcEFKeGNiaTFOaDlRVEhUcU44N0ZtMDF0R1ZwCjVNd1pXSWZuYVRUemEvTGZLelR5U0pka0tldEZMVGdkYXpMYlpzUEE2aHBSK0FJRTJhc0tLTi84UUk1N3UzU2cKL2xyMnZKS1IvU2l5eEN1Q20vQWJkYnJMbXk0WjlSdm1jMGdpclA4T0lLQWxBRWZ2TzV5Z2hSKy8vd1RpTFlzUQp1SllDM0V2UE16ZGdKUzdGR2FscnFLZzlPTCsxVzROY05yNWdveVdSUUJ0cktKaWlTZEJVWmVxb0RvSUY5NHpCCndGbzJJT1JFdXFqcU51M3diMWZIM3p1dGdtalFra3IxVjJhd3hmcExLWlROQWdNQkFBRT0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg"
}

View File

@@ -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

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 39c18d859abc65e41b8e5bf2267e013d
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@@ -0,0 +1,39 @@
using UnityEngine;
using UnityEngine.Animations.Rigging;
using UnityEngine.Playables;
namespace DocCodeExamples
{
/// <summary>
/// Custom evaluator that manually evaluates the PlayableGraph in LateUpdate.
/// </summary>
#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<RigBuilder>();
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.SyncLayers();
m_PlayableGraph.Evaluate(Time.deltaTime);
}
}
#endregion
}

View File

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

View File

@@ -0,0 +1,35 @@
using UnityEngine;
using UnityEngine.Animations.Rigging;
using UnityEngine.Playables;
namespace DocCodeExamples
{
/// <summary>
/// Custom Evaluator that manually evaluates the RigBuilder in LateUpdate.
/// </summary>
#region custom-rig-builder-evaluator
[RequireComponent(typeof(RigBuilder))]
public class CustomRigBuilderEvaluator : MonoBehaviour
{
private RigBuilder m_RigBuilder;
void OnEnable()
{
m_RigBuilder = GetComponent<RigBuilder>();
// 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
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: dc9f69976d6143e489b841bec6ac5cfd
timeCreated: 1636580728

View File

@@ -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
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: c2a5362f5f25b455f8f4eeea25441772
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,36 @@
# Animation Rigging Menu
The top-level Animation Rigging menu contains useful utilities to help with rigging workflows.
## Align
Use Align to align the Transform, Position, or Rotation of a GameObject to another GameObject. This is particularly useful when aligning effectors to bones, or props to an effector.
To use Align, select the GameObject you want to align and then select the GameObject with the transform that you want to align to. In the Animation Rigging menu, select the appropriate align option.
|Tool|Description|
|---|---|
|Align Transform|Updates the Position and Rotation of the GameObject.|
|Align Rotation|Updates the Rotation of the GameObject.|
|Align Position|Updates the Position of the GameObject.|
## Restore Bind Pose
Use the Restore Bind Pose option to restore the Skinned Mesh Renderer bind pose that was originally imported. This is useful for restoring the original character pose of a skinned mesh. This option will only restore poses for bones that are used by skinning. The restore bind pose option may not work as expected for setups where the mesh is only skinned to some bones in the hierarchy.
## Rig Setup
Use the Rig Setup option to set up the required components for Animation Rigging on the selected object.
To use Rig Setup, select a GameObject hierarchy with an Animator component on which you want to create the constraints. Then, select the Rig Setup option.
This creates a RigBuilder component on the selected GameObject and a child GameObject named "Rig 1" with a Rig component that will be assigned to the RigBuilder layers.
Note: Rig Setup is also found in the Animator component options.
## Bone Renderer Setup
Use the Bone Renderer Setup option to create a BoneRenderer component with bones extracted from children SkinnedMeshRenderer components in the selected GameObject hierarchy.
To use Bone Renderer Setup, select the root GameObject and select Bone Renderer Setup.
Note: Bone Renderer Setup is also found in the Animator component options.

View File

@@ -0,0 +1,28 @@
# Bidirectional Motion Transfer
Bidirectional motion transfer is an authoring workflow that lets you transfer existing motion onto active constraints, and inversely, transfer the motion from active constraints back to the original motion source while preserving visual fidelity of the motion.
This workflow makes use of the Animation Window to select the desired clip and preview the constrained result in the Scene View.
Both **“Transfer motion to skeleton”** and **“Transfer motion to constraint”** are available as options on the **constraint components**. You should use either the **Rig component** to Transfer motion of an entire Rig, or the **RigBuilder component** to transfer motion of the entire hierarchy.
![Bidirectional baking menu](images/bidirectional_baking/baking_option_menu.png)
Bidirectional motion transfer can be used on generic character hierarchies. Humanoid is not supported at the moment.
Not all constraints can Transfer motion to constraints. Physics-based constraints like Damped Transform cannot be inferred from existing motion.
Other constraints can be transferred but with limitations. For example, the Twist Chain constraint constrains rotations. It overrides positions and in-between chain rotations. The result of transferring motion does not precisely represent the source animation.
The following constraints support "Transfer motion to constraint" with limitations:
|Constraint|Limitations|
|---|---|
|Two Bone IK Constraint|No limitations.|
|Multi-Aim Constraint|Roll-Axis motion is not guaranteed to be the same.|
|Multi-Parent Constraint|No limitations.|
|Multi-Position Constraint|Disabling constrained axes may change end result|
|Multi-Referential Constraint|No limitations.|
|Multi-Rotation Constraint|Disabling constrained axes may change end result.|
|Twist Chain Constraint|In-between chain transforms are overridden.|

View File

@@ -0,0 +1,18 @@
# Constraint Components
The Animation Rigging package includes the following predefined constraints that you can use to define your Animation rigs:
- [Blend Constraint](./constraints/BlendConstraint.md)
- [Chain IK Constraint](./constraints/ChainIKConstraint.md)
- [Damped Transform](./constraints/DampedTransform.md)
- [Multi-Aim Constraint](./constraints/MultiAimConstraint.md)
- [Multi-Parent Constraint](./constraints/MultiParentConstraint.md)
- [Multi-Position Constraint](./constraints/MultiPositionConstraint.md)
- [Multi-Referential Constraint](./constraints/MultiReferentialConstraint.md)
- [Multi-Rotation Constraint](./constraints/MultiRotationConstraint.md)
- [Override Transform](./constraints/OverrideTransform.md)
- [Twist Chain Constraint](./constraints/TwistChainConstraint.md)
- [Twist Correction](./constraints/TwistCorrection.md)
- [Two Bone IK Constraint](./constraints/TwoBoneIKConstraint.md)
The constraints in the Animation Rigging package are based on the C# Animation Jobs API.

View File

@@ -0,0 +1,108 @@
# Rigging Workflow
This document describes all of the steps and components required to create a custom Animation Rig. This [**video**](https://youtu.be/DzW_jQGO1dc) also demonstrates the process.
## Core Components
Animation Rigs in Unity make use of four key components:
* **Animator:** When added to some root GameObject, this built-in component designates that a hierarchy is animatable. _Animation Rigging works on top of Unity's animation system, and so requires an Animator._
* **Rig Builder:** When added to the root GameObject, this component allows the animated hierarchy to be modified by one or more Rigs, which it assembles into layers.
* **Rig:** When added to GameObjects in an animatable hierarchy, Rigs act as containers for source objects and Constraints that modify the animated hierarchy's pose. You can adjust the weight of a Rig to control its contribution to the final pose.
* **Constraints:** When added to Rig GameObjects or their children, these components specify operations a Rig will perform.
The following illustration depicts a schematic overview of the interdependencies among all of the required types of components.
![Rig Setup Overview](images/rig_setup/rig_setup_overview.png)
Once you have added a Rig Builder component to an animatable hierarchy's root GameObject, you can create a Rig GameObject as a child of this root _(ex: Rig Setup)_. To enable animation rigging, the Rig GameObject must have a Rig component. To then connect the Rig to the Animator, you must assign this Rig component to a Rig Layer on the Rig Builder component.
![Rig Setup](images/rig_setup/rig_setup.gif)
After you connect the Rig GameObject to the Rig Builder component, you can add rig elements (i.e., GameObjects with Constraint components) under the Rig GameObject hierarchy. Different rig elements can be organized and hierarchically structured to accommodate any rigging requirement.
Source objects for Constraints, such as Target Effectors or Hint Effectors, can be placed under their associated Rig GameObject. In the following illustration, _Left Leg IK_ has a **Two Bone IK Constraint** component and is acting as a rig element. It is the parent of both the _LeftFootEffector_ and _LeftLegHint_ source objects.
![Source Object Example](images/rig_setup/source_object_example.png)
### Rig Builder Component
The Rig Builder component lives alongside the Animator component and creates a Playable Graph that is appended to the existing Animator state machine.
The Rig Builder component needs to be added to the GameObject that has the Animator component. Rig Builder needs to affect the same hierarchy as the Animator.
![Rig Builder Setup](images/rig_builder/rig_builder_setup.gif)
Using Rig Layers, the Rig Builder component allows for stacking of multiple Rigs that can be enabled/disabled at any time.
![Rig Builder Layers](images/rig_builder/rig_builder_layers.gif)
### Rig Component
The Rig component is the main entry point for all Constraints in a given control rig.
Note there should only be one Rig component per control rig hierarchy, which you must assign to a Rig Layer on the Rig Builder component.
To use multiple control rigs with a single hierarchy, you must assign each Rig to a different Rig Layer, and enable/disable them independently.
From a technical standpoint, the main purpose of a Rig component is to collect all Constraint components in its local hierarchy.
The component generates an ordered list of _IAnimationJobs_, which are applied to the Animator's pose after its normal evaluation.
The Rig component gathers constraints using _GetComponentsInChildren_, and so the order of components in the Rig's hierarchy determines the evaluation order of the jobs.
This method follows depth-first traversal as shown below:
![Rig Constraint Evaluation Order](images/rig/eval_order.png)
In other words, grouping constraints under a GameObject allows you to manage the evaluation order of these constraints
by modifying the hierarchy.
Control rig hierarchies should hold all the necessary rig elements such as effectors, constraints, and other objects/elements required by the constraint definitions.
The root of a control rig hierarchy should be at the same level as the skeleton root, both under the Game Object holding the Animator.
_In other words, it should not be in the skeleton hierarchy, but rather live beside it._
![Rig Setup](images/rig/rig_setup.gif)
![Rig Weight](images/rig/rig_weight.gif)
Rig components, like all Constraint components, have a Weight property that can be used, animated, and scripted to enable/disable
or ease-in/ease-out an entire control rig hierarchy.
## Other Utilities
### Bone Renderer Component
The Bone Renderer component allows you to define a transform hierarchy to be drawn as bones for visualization and selection during the rigging process.
These bones are not visible in the Game view. This allows you to define your character deformation skeletons for rigging purposes.
![Bone Renderer Setup](images/bone_renderer/bone_renderer_setup.gif)
![Bone Renderer Component](images/bone_renderer/bone_renderer_component.gif)
You can customize the appearance of the bones by modifying Bone Size, Shape and Color.
The package provides these default shapes: Line, Pyramid, and Box.
You can also display tripods of local axes and adjust their size to suit your preference.
![Bone Look Pyramid](images/bone_renderer/bone_looks.png)
### Rig Effectors
Similarly to bones, Rig Effectors allow you to add gizmos to transforms for visualization and selection.
You can add them to any transform in the same hierarchy as a Rig Builder or Rig component.
Like bones, Effectors are not visible in the Game view.
A special Scene View overlay allows you to manage and customize effectors in the Rig hierarchy.
![Rig Effector Overlay](images/rig_effector/rig_effector_setup.gif)
You can also customize the appearance of the effectors by modifying Effector Size, Shape, Color, Offset Position and Offset Rotation.
The shape can be any Mesh asset available in the project.
You can create, delete, or edit multiple effectors at once.
![Rig Effector Shapes](images/rig_effector/rig_effector_shapes.png)
### Rig Transform
When a specific GameObject in your rig's hierarchy is important for manipulation but not referenced by any rig constraints, you must add a **RigTransform** component, found under _Animation Rigging/Setup_.
As shown in the video below, in order to manipulate both the left and right foot IK targets (_lfik_ and _rfik_) of the _2BoneIK_ sample using
their parent transform (_ik_ ), you must add this component to get the expected behavior.
![Rig Transform](images/rig_transform/rig_transform_manipulation.gif)

View File

@@ -0,0 +1,17 @@
* [Animation Rigging](index.md)
* [Rigging workflow](RiggingWorkflow.md)
* [Animation Rigging Menu](AnimationRiggingMenu.md)
* [Bidirectional Motion Transfer](BidirectionalMotionTransfer.md)
* [Constraint components](ConstraintComponents.md)
* [Blend Constraint](constraints/BlendConstraint.md)
* [Chain IK Constraint](constraints/ChainIKConstraint.md)
* [Damped Transform](constraints/DampedTransform.md)
* [Multi-Aim Constraint](constraints/MultiAimConstraint.md)
* [Multi-Parent Constraint](constraints/MultiParentConstraint.md)
* [Multi-Position Constraint](constraints/MultiPositionConstraint.md)
* [Multi-Referential Constraint](constraints/MultiReferentialConstraint.md)
* [Multi-Rotation Constraint](constraints/MultiRotationConstraint.md)
* [Override Transform](constraints/OverrideTransform.md)
* [Twist Chain Constraint](constraints/TwistChainConstraint.md)
* [Twist Correction](constraints/TwistCorrection.md)
* [Two Bone IK Constraint](constraints/TwoBoneIKConstraint.md)

View File

@@ -0,0 +1,19 @@
# Blend Constraint
![Example](../images/constraint_blend/blend_constraint.gif)
A blend constraint allows the constrained GameObject to blend between GameObject Source A Position
and GameObject Source B Position as well as blending between GameObject Source A Rotation
and GameObject Source B Rotation.
![Component](../images/constraint_blend/blend_constraint_component.png)
|Properties|Description|
|---|---|
|Weight|The overall weight of the constraint. If set to 0, the constraint has no influence on the Constrained Object. When set to 1, it applies full influence with the current settings. Intermediate values are interpolated linearly.|
|Constrained Object|The GameObject affected by the Source Objects.|
|Source A|The first source GameObject that influences the position and rotation of the Constrained Object.|
|Source B|The second source GameObject that influences the position and rotation of the Constrained Object.|
|Maintain Offset|Specifies whether to maintain the initial offset between the Constrained Object and the Source Objects. You can retain any combination of either Position and/or Rotation offset.|
|Blend A &#124; B Position|If enabled, the constrained GameObject's position blends between those of Source A and Source B by the specified amount. As with the constraint's overall weight, intermediate values are interpolated linearly.|
|Blend A &#124; B Rotation|If enabled, the constrained GameObject's rotation blends between those of Source A and Source B by the specified amount. As with the constraint's overall weight, intermediate values are interpolated linearly.|

View File

@@ -0,0 +1,24 @@
# ChainIK Constraint
![Example](../images/constraint_chainik/chainik.gif)
The Chain IK constraint allows you to invert the control of a hierarchy of GameObjects, so the end of the chain can reach a target position.
By defining Root and Tip GameObjects, the Chain IK constraint can find and constrain all GameObjects in between.
This constraint implements the FABRIK solver (Forward and Backward Reaching Inverse Kinematic).
More details can be found [here](http://www.andreasaristidou.com/FABRIK.html).
![Component](../images/constraint_chainik/chainik_component.png)
|Properties|Description|
|---|---|
|Weight|The overall weight of the constraint. If set to 0, the constraint has no influence on the chain elements. When set to 1, it applies full influence with the current settings. Intermediate values are interpolated linearly.|
|Root|The root GameObject of the chain hierarchy.|
|Tip|The final GameObject of the chain hierarchy. It must be a descendant of the Root GameObject.|
|Target|The GameObject that specifies the desired target transform for the chain's Tip.|
|Maintain Target Offset|Specifies whether to maintain the initial offset between the Tip and the Target. You can retain any combination of either Position and/or Rotation offset.|
|Chain Rotation Weight|The weight of rotations applied throughout the chain. If set to 1, the chain will fully reach for its target goal. As with the constraint's overall weight, intermediate values are interpolated linearly.|
|Tip Rotation Weight|The weight of the rotation applied to the Tip. If set to 1, the Tip aligns its rotation to the specified Target. As with the constraint's overall weight, intermediate values are interpolated linearly.|
|Max Iterations|The maximum number of solver iterations to perform to try to make the Tip reach the Target within the specified Tolerance threshold.|
|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.|

View File

@@ -0,0 +1,17 @@
# Damped Transform
![Example](../images/constraint_damped_transform/damped_transform.gif)
The damped transform constraint allows damping the position and rotation transform values from the source GameObject to the constrained GameObject.
The Maintain Aim option forces the constrained object to always aim at the source object.
![Component](../images/constraint_damped_transform/damped_transform_component.png)
|Properties|Description|
|---|---|
|Weight|The overall weight of the constraint. If set to 0, the constraint has no influence on the Constrained Object. When set to 1, it applies full influence with the current settings. Intermediate values are interpolated linearly.|
|Constrained Object|The GameObject affected by the Source GameObjects.|
|Source|The GameObject that influences the Constrained Object's transform.|
|Damp Position|The weight of positional damping to apply to the Constrained Object. If set to 0, the Constrained Object follows the Source object's position with no damping. If set to 1, the Constrained Object's position is fully damped. As with the constraint's overall weight, intermediate values are interpolated linearly.|
|Damp Rotation|The weight of rotational damping to apply to the Constrained Object. If set to 0, the Constrained Object follows the Source object's rotation with no damping. If set to 1, the Constrained Object's rotation is fully damped. As with the constraint's overall weight, intermediate values are interpolated linearly.|
|Maintain Aim|Specifies whether to maintain the initial rotation offset between the Constrained Object and the Source Object.|

View File

@@ -0,0 +1,41 @@
# Multi-Aim Constraint
![Example](../images/constraint_multi_aim/multi_aim.gif)
A Multi-Aim Constraint rotates a Constrained Object to face a target position specified by one or more Source Objects.
It is typically used to make a GameObject look at objects of interest, such as nearby interactable props or the position of the cursor.
You can specify the aim direction by selecting which Aim Axis to use on the Constrained Object (X, -X, Y, -Y, Z, -Z).
You can optionally specify World Up parameters to help the Constrained Object maintain stable roll orientation.
_Note that this constraint's handling of multiple targets is different from that of most third-party 3D animation software.
Specifically, it calculates an aim rotation to each target, and then produces a weighted sum of all these rotations.
This approach allows you to easily blend in or out the effects of individual targets, since their weight values are not normalized prior to calculation.
To replicate the behavior of other 3D animation software, you should use a single Source Object that is constrained to multiple targets via a [MultiPositionConstraint](./MultiPositionConstraint.md)._
![Component](../images/constraint_multi_aim/multi_aim_component.png)
|Properties|Description|
|---|---|
|Weight|The overall weight of the constraint. If set to 0, the constraint has no influence on the Constrained Object. When set to 1, it applies full influence with the current settings. Intermediate values are interpolated linearly.|
|Constrained Object|The GameObject affected by the Source Objects.|
|Aim Axis|Specifies the local aim axis of the Constrained Object to use in order to orient its forward direction to the Source Objects.|
|Up Axis|Specifies the local up axis of the Constrained Object to use in order to orient its upward direction (i.e., roll orientation).|
|World Up Type|Specifies which mode to use to stabilize the upward direction (i.e., roll orientation) of the Constrained Object.|
|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. In those cases, the reference frame is either the world or another object, respectively.
|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.|
|Source Objects|The list of GameObjects that influence the Constrained Object's orientation, and the amount of weight they contribute to the final pose. The constraint calculates rotation toward each target to produce a weighted sum. _The order of Source Objects does not affect the result._|
|Maintain Rotation Offset|Specifies whether to maintain the initial rotation offset between the Constrained Object and the Source Objects.|
|Offset|Specifies an additional local space rotation offset to apply to the Constrained Object, after it has been rotated toward its target.|
|Constrained Axes|Specifies the axes to which the constraint can apply rotation.|
|Min Limit|Clamps the minimum rotation that may be applied about any of the constrained axes of rotation.|
|Max Limit|Clamps the maximum rotation that may be applied about any of the constrained axes of rotation.|
World Up Type can have the following values:
|Values|Description|
|---|---|
|None|Do not use a World Up vector.|
|Scene Up|The Y-axis of the scene.|
|Object Up|The Y-axis of the GameObject specified by World Up Object.|
|Object Up Rotation|The axis specified by World Up Vector, in the space of the GameObject specified by World Up Object.|
|Vector|The World Up Vector.|

View File

@@ -0,0 +1,23 @@
# Multi-Parent Constraint
![Example](../images/constraint_multi_parent/multi_parent.gif)
A Multi-Parent Constraint moves and rotates a GameObject as if it is the child of another GameObject in the Hierarchy window.
Because using this constraint does not actually change the GameObject hierarchy, it offers some advantages:
- It does not affect scale.
- The Constrained Object can have multiple Source Objects (i.e., parents).
- The Constrained Object does not have to be a child of any of the Source Objects.
- You can vary the effect of the constraint by specifying an overall weight, as well as individual weights for each of the Source Objects.
- You can still apply normal animation to the Constrained Object's children as normal.
![Component](../images/constraint_multi_parent/multi_parent_component.png)
|Properties|Description|
|---|---|
|Weight|The overall weight of the constraint. If set to 0, the constraint has no influence on the Constrained Object. When set to 1, it applies full influence with the current settings. Intermediate values are interpolated linearly.|
|Constrained Object|The GameObject affected by the Source Objects.|
|Source Objects|The list of GameObjects that influence the Constrained Object's position and orientation, and the amount of weight they contribute to the final pose. The constraint applies linearly interpolated, weighted translation and rotation toward each target. _The order of Source Objects does not affect the result._|
|Maintain Offset|Specifies whether to maintain the initial offset between the Constrained Object and the Source Objects. You can retain any combination of either Position and/or Rotation offset.|
|Constrained Position Axes|Specifies the axes to which the constraint can apply translation.|
|Constrained Rotation Axes|Specifies the axes to which the constraint can apply rotation.|

View File

@@ -0,0 +1,16 @@
# Multi-Position Constraint
![Example](../images/constraint_multi_position/multi_position.gif)
A Multi-Position Constraint component moves a Constrained Object to follow its Source Objects.
![Component](../images/constraint_multi_position/multi_position_component.png)
|Properties|Description|
|---|---|
|Weight|The overall weight of the constraint. If set to 0, the constraint has no influence on the Constrained Object. When set to 1, it applies full influence with the current settings. Intermediate values are interpolated linearly.|
|Constrained Object|The GameObject affected by the Source Objects.|
|Constrained Axes|Specifies the axes to which the constraint can apply translation.|
|Source Objects|The list of GameObjects that influence the Constrained Object's position, and the amount of weight they contribute to the final pose. The constraint calculates translation toward each target to produce a weighted sum. _The order of Source Objects does not affect the result._|
|Maintain Position Offset|Specifies whether to maintain the initial position offset between the Constrained Object and the Source Objects.|
|Offset|Specifies an additional local space translation offset to apply to the Constrained Object, after it has been moved toward its target.|

View File

@@ -0,0 +1,16 @@
# Multi-Referential Constraint
![Example](../images/constraint_multi_referential/multi_ref.gif)
The Multi-Referential Constraint allows you to configure a group of GameObjects to have dynamic parent-child-like behavior.
The movement of the Driving object influences all of the other Reference Objects as if it were their parent.
Use this constraint to simulate dynamic parenting changes without modifying your hierarchy.
For example, you could configure a character's hand to sometimes control the motion of a prop, and the prop to sometimes control the motion of the hand.
![Component](../images/constraint_multi_referential/multi_ref_component.png)
|Properties|Description|
|---|---|
|Weight|The overall weight of the constraint. If set to 0, the constraint has no influence on the Reference Objects. When set to 1, it applies full influence with the current settings. Intermediate values are interpolated linearly.|
|Driving|An object from the list of Referenced Objects, whose motion drives that of all other Referenced Objects.|
|Referenced Objects|A list of GameObjects to be driven by the specified Driving object.|

View File

@@ -0,0 +1,17 @@
# Multi-Rotation Constraint
![Example](../images/constraint_multi_rotation/multi_rotation.gif)
A Multi-Rotation Constraint component rotates a Constrained Object to match the rotation of its Source Objects.
The constraint applies rotation about the shortest path to each target.
![Example](../images/constraint_multi_rotation/multi_rotation_component.png)
|Properties|Description|
|---|---|
|Weight|The overall weight of the constraint. If set to 0, the constraint has no influence on the Constrained Object. When set to 1, it applies full influence with the current settings. Intermediate values are interpolated linearly.|
|Constrained Object|The GameObject affected by the Source Objects.|
|Constrained Axes|Specifies the axes to which the constraint can apply rotation.|
|Source Objects|The list of GameObjects that influence the Constrained Object's orientation, and the amount of weight they contribute to the final pose. The constraint calculates rotation toward each target to produce a weighted sum. _The order of Source Objects does not affect the result._|
|Maintain Rotation Offset|Specifies whether to maintain the initial rotation offset between the Constrained Object and the Source Objects.|
|Offset|Specifies an additional local space rotation offset to apply to the Constrained Object, after it has been rotated toward its target.|

View File

@@ -0,0 +1,28 @@
# Override Transform
![Example](../images/constraint_override_transform/override_transform.gif)
An Override Transform constraint allows you to override the Constrained Object's transform with a value coming from an Override Source, or from manually specified values.
![Example](../images/constraint_override_transform/override_transform_component.png)
|Properties|Description|
|---|---|
|Weight|The overall weight of the constraint. If set to 0, the constraint has no influence on the Constrained Object. When set to 1, it applies full influence with the current settings. Intermediate values are interpolated linearly.|
|Constrained Object|The GameObject affected by the Override source.|
|Override Source|The GameObject that influences the Constrained Object's transform. If specified, Override Position and Override Rotation fields are ignored.|
|Override Position|A specific position value to apply to the Constrained Object. This value is ignored if an Override Source is specified.|
|Override Rotation|A specific rotation value to apply to the Constrained Object. This value is ignored if an Override Source is specified.|
|Space|Specifies how the Override Source's local transform values (or manual Override Position and Rotation) should be applied to Constrained Object.|
|Position Weight|The weight of the position influence. A weight of 1 causes the constrained GameObject to be fully influenced by its Override source.|
|Rotation Weight|The weight of the rotation influence. A weight of 1 causes the constrained GameObject to be fully influenced by its Override source.|
Space can have the following values:
|Values|Description|
|---|---|
|World|The displacement of the Override Source's local transform values _replace_ the Constrained Object's global transform values.|
|Local|The displacement of the Override Source's local transform values _replace_ the Constrained Object's local transform values.|
|Pivot|The displacement of the Override Source's local transform values are _added to_ The Constrained Object's local transform values.|
_In each case, the initial position of the Override Source GameObject at the time the constraint is created, is treated as the point of reference for calculating its displacement._

View File

@@ -0,0 +1,17 @@
# TwistChain Constraint
![Example](../images/constraint_twistchain/twistchain.gif)
The Twist Chain constraint allows you to control world rotations on both ends of a GameObject chain hierarchy.
The constraint calculates interpolated rotations for intermediate transforms between a Root and Tip to create a smooth animated hierarchy.
![Component](../images/constraint_twistchain/twistchain_component.png)
|Properties|Description|
|---|---|
|Weight|The overall weight of the constraint. If set to 0, the constraint has no influence on the chain elements. When set to 1, it applies full influence with the current settings. Intermediate values are interpolated linearly.|
|Root|The root GameObject of the chain hierarchy.|
|Tip|The final GameObject of the chain hierarchy. It must be a descendant of the Root GameObject.|
|Root Target|The GameObject that specifies the desired target rotation for the chain's Root.|
|Tip Target|The GameObject that specifies the desired target rotation for the chain's Tip.|
|Curve|A curve with a normalized domain and range, specifying how the twist rotation should be distributed down the length of the chain.|

View File

@@ -0,0 +1,15 @@
# Twist Correction
![Example](../images/constraint_twist_correction/twist_correction.gif)
The Twist Correction constraint redistributes a percentage of a Source's rotation to one or more Twist Nodes in order to correct the twist deformation of a body part that rotates on multiple axes.
Common use cases are shoulders, wrists, and upper legs.
![Component](../images/constraint_twist_correction/twist_correction_component.png)
|Properties|Description|
|---|---|
|Weight|The overall weight of the constraint. If set to 0, the constraint has no influence on the Twist Nodes. When set to 1, it applies full influence with the current settings. Intermediate values are interpolated linearly.|
|Source|The GameObject that influences the Twist Nodes to rotate around a specific Twist Axis.|
|Twist Axis|Specifies the axis on the Source object from which the rotation is extracted and then redistributed to the Twist Nodes.|
|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.|

View File

@@ -0,0 +1,31 @@
# Two Bone IK
![Example](../images/constraint_two_bone_ik/two_bone_ik.gif)
The Two Bone IK constraint allows you to invert the control of a simple hierarchy of two GameObjects, so the Tip of a limb can reach a Target position.
An additional Hint GameObject allows you to specify the direction the limb should be oriented when it bends.
![Component](../images/constraint_two_bone_ik/two_bone_ik_component.png)
|Properties|Description|
|---|---|
|Weight|The overall weight of the constraint. If set to 0, the constraint has no influence on the limb elements. When set to 1, it applies full influence with the current settings. Intermediate values are interpolated linearly.|
|Root|The root GameObject of the limb hierarchy.|
|Mid|The middle GameObject of the limb hierarchy. It must be a child of the Root GameObject.|
|Tip|The final GameObject of the limb hierarchy. It must be a child of the Mid GameObject.|
|Target|Source GameObject that specifies the desired position of the Tip.|
|Hint|Optional Source GameObject, whose position is used to specify the direction the limb should be oriented when it bends.|
|Maintain Target Offset|Specifies whether to maintain the initial offset between the Tip and the Target. You can retain any combination of either Position and/or Rotation offset.|
|Target Position Weight|The weight to apply for calculating the desired position when reaching for the Target. If set to 1, the Root and Mid objects will extend as far as necessary to try to reach the specified Target position. As with the constraint's overall weight, intermediate values are interpolated linearly.|
|Target Rotation Weight|The weight of the rotation applied to the Tip. If set to 1, the Tip aligns it rotation to the specified Target. As with the constraint's overall weight, intermediate values are interpolated linearly.|
|Hint Weight|The amount of influence the Hint has on the configuration of the hierarchy. When set to 1, the Hint fully influences the hierarchy configuration. If no Hint GameObject is specified, the hint weight is ignored.|
## Auto Setup from Tip Transform
The component's context menu available from its header in the Inspector provides a "Auto Setup from Tip Transform" option.
This menu command will automatically create and assign both a Target and Hint GameObject in your Rig's hierarchy.
To use this option:
1. Add a Two Bone IK Constraint to a GameObject in your Rig hierarchy.
2. Assign the Tip GameObject.
3. Select "Auto Setup from Tip Transform" from the component's context menu.

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 302 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

View File

@@ -0,0 +1,29 @@
# Animation Rigging
Use Animation Rigging to create and organize **animation rigs**, or sets of constraints for adding procedural motion to animated objects. Examples include:
* _Deformation rigs_ to control secondary animation of character armor, props, and accessories.
* _World Interaction rigs_ (sets of IK and Aim constraints) to make interactive adjustments for targeting or for correcting animation compression artifacts.
This documentation describes how to set up a simple Animation Rig for use in a variety of workflows. It also includes detailed information on the constraints included in the Animation Rigging package.
* The [Rigging Workflow](RiggingWorkflow.md) topic is the best place to get started. It describes the main components necessary for defining and using an animation rig. It includes suggestions on additional components and constraints that you can define for props, accessories, or other rig controls.
* The [Animation Rigging Menu](AnimationRiggingMenu.md) topic describes utilities that help with the rigging workflow.
* The [Bidirectional Motion Transfer](BidirectionalMotionTransfer.md) topic describes an additional workflow option for transferring motion back and forth between an animation rig and a skeleton.
* The [Constraint Components](ConstraintComponents.md) topic contains detailed information on all of the built-in Constraint components.
# Technical details
## Requirements
This version of Animation Rigging is compatible with the following versions of the Unity Editor:
* 2023.2 and later
## Document revision history
|Date|Reason|
|---|---|
|Jan 21, 2020|Editing pass and restructure of package documentation|
|Nov 12, 2019|Added Bidirectional Motion Transfer workflow and updated images|
|Nov 23, 2018|First draft of package documentation|

View File

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

View File

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

View File

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

View File

@@ -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<BlendConstraintEditor>();
readonly FoldoutState m_SettingsToggle = FoldoutState.ForSettings<BlendConstraintEditor>();
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<BlendConstraint>
{
public override bool canBakeToSkeleton => true;
public override bool canBakeToConstraint => false;
public override IEnumerable<EditorCurveBinding> GetSourceCurveBindings(RigBuilder rigBuilder, BlendConstraint constraint)
{
var bindings = new List<EditorCurveBinding>();
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<EditorCurveBinding> GetConstrainedCurveBindings(RigBuilder rigBuilder, BlendConstraint constraint)
{
var bindings = new List<EditorCurveBinding>();
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;
}
}
}

View File

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

View File

@@ -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<ChainIKConstraintEditor>();
readonly FoldoutState m_SettingsToggle = FoldoutState.ForSettings<ChainIKConstraintEditor>();
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<ChainIKConstraint>
{
public override bool canBakeToSkeleton => true;
public override bool canBakeToConstraint => false;
public override IEnumerable<EditorCurveBinding> GetSourceCurveBindings(RigBuilder rigBuilder, ChainIKConstraint constraint)
{
var bindings = new List<EditorCurveBinding>();
EditorCurveBindingUtils.CollectTRBindings(rigBuilder.transform, constraint.data.target, bindings);
return bindings;
}
public override IEnumerable<EditorCurveBinding> GetConstrainedCurveBindings(RigBuilder rigBuilder, ChainIKConstraint constraint)
{
var bindings = new List<EditorCurveBinding>();
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;
}
}
}

View File

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

View File

@@ -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<DampedTransformEditor>();
readonly FoldoutState m_SettingsToggle = FoldoutState.ForSettings<DampedTransformEditor>();
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<DampedTransform>
{
public override bool canBakeToSkeleton => true;
public override bool canBakeToConstraint => false;
public override IEnumerable<EditorCurveBinding> GetSourceCurveBindings(RigBuilder rigBuilder, DampedTransform constraint)
{
var bindings = new List<EditorCurveBinding>();
EditorCurveBindingUtils.CollectTRBindings(rigBuilder.transform, constraint.data.sourceObject, bindings);
return bindings;
}
public override IEnumerable<EditorCurveBinding> GetConstrainedCurveBindings(RigBuilder rigBuilder, DampedTransform constraint)
{
var bindings = new List<EditorCurveBinding>();
EditorCurveBindingUtils.CollectTRBindings(rigBuilder.transform, constraint.data.constrainedObject, bindings);
return bindings;
}
}
}

View File

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

View File

@@ -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<MultiAimConstraintEditor>();
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<MultiAimConstraint>
{
public override bool canBakeToSkeleton => true;
public override bool canBakeToConstraint => true;
public override IEnumerable<EditorCurveBinding> GetSourceCurveBindings(RigBuilder rigBuilder, MultiAimConstraint constraint)
{
var bindings = new List<EditorCurveBinding>();
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<EditorCurveBinding> GetConstrainedCurveBindings(RigBuilder rigBuilder, MultiAimConstraint constraint)
{
var bindings = new List<EditorCurveBinding>();
EditorCurveBindingUtils.CollectRotationBindings(rigBuilder.transform, constraint.data.constrainedObject, bindings);
return bindings;
}
}
}

View File

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

View File

@@ -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<MultiParentConstraintEditor>();
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<MultiParentConstraint>
{
public override bool canBakeToSkeleton => true;
public override bool canBakeToConstraint => true;
public override IEnumerable<EditorCurveBinding> GetSourceCurveBindings(RigBuilder rigBuilder, MultiParentConstraint constraint)
{
var bindings = new List<EditorCurveBinding>();
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<EditorCurveBinding> GetConstrainedCurveBindings(RigBuilder rigBuilder, MultiParentConstraint constraint)
{
var bindings = new List<EditorCurveBinding>();
EditorCurveBindingUtils.CollectPositionBindings(rigBuilder.transform, constraint.data.constrainedObject, bindings);
EditorCurveBindingUtils.CollectRotationBindings(rigBuilder.transform, constraint.data.constrainedObject, bindings);
return bindings;
}
}
}

View File

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

View File

@@ -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<MultiPositionConstraintEditor>();
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<MultiPositionConstraint>
{
public override bool canBakeToSkeleton => true;
public override bool canBakeToConstraint => true;
public override IEnumerable<EditorCurveBinding> GetSourceCurveBindings(RigBuilder rigBuilder, MultiPositionConstraint constraint)
{
var bindings = new List<EditorCurveBinding>();
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<EditorCurveBinding> GetConstrainedCurveBindings(RigBuilder rigBuilder, MultiPositionConstraint constraint)
{
var bindings = new List<EditorCurveBinding>();
EditorCurveBindingUtils.CollectPositionBindings(rigBuilder.transform, constraint.data.constrainedObject, bindings);
return bindings;
}
}
}

View File

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

View File

@@ -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<GUIContent>();
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<MultiReferentialConstraint>
{
public override bool canBakeToSkeleton => true;
public override bool canBakeToConstraint => true;
public override IEnumerable<EditorCurveBinding> GetSourceCurveBindings(RigBuilder rigBuilder, MultiReferentialConstraint constraint)
{
var bindings = new List<EditorCurveBinding>();
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<EditorCurveBinding> GetConstrainedCurveBindings(RigBuilder rigBuilder, MultiReferentialConstraint constraint)
{
var bindings = new List<EditorCurveBinding>();
var transform = constraint.data.sourceObjects[0];
EditorCurveBindingUtils.CollectTRBindings(rigBuilder.transform, transform, bindings);
return bindings;
}
}
}

View File

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

View File

@@ -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<MultiRotationConstraintEditor>();
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<MultiRotationConstraint>
{
public override bool canBakeToSkeleton => true;
public override bool canBakeToConstraint => true;
public override IEnumerable<EditorCurveBinding> GetSourceCurveBindings(RigBuilder rigBuilder, MultiRotationConstraint constraint)
{
var bindings = new List<EditorCurveBinding>();
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<EditorCurveBinding> GetConstrainedCurveBindings(RigBuilder rigBuilder, MultiRotationConstraint constraint)
{
var bindings = new List<EditorCurveBinding>();
EditorCurveBindingUtils.CollectRotationBindings(rigBuilder.transform, constraint.data.constrainedObject, bindings);
return bindings;
}
}
}

View File

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

View File

@@ -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<OverrideTransformEditor>();
readonly FoldoutState m_SettingsToggle = FoldoutState.ForSettings<OverrideTransformEditor>();
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<OverrideTransform>
{
public override bool canBakeToSkeleton => true;
public override bool canBakeToConstraint => false;
public override IEnumerable<EditorCurveBinding> GetSourceCurveBindings(RigBuilder rigBuilder, OverrideTransform constraint)
{
var bindings = new List<EditorCurveBinding>();
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<EditorCurveBinding> GetConstrainedCurveBindings(RigBuilder rigBuilder, OverrideTransform constraint)
{
var bindings = new List<EditorCurveBinding>();
EditorCurveBindingUtils.CollectTRSBindings(rigBuilder.transform, constraint.data.constrainedObject, bindings);
return bindings;
}
}
}

View File

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

View File

@@ -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<TwistChainConstraintEditor>();
readonly FoldoutState m_SettingsToggle = FoldoutState.ForSettings<TwistChainConstraintEditor>();
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<TwistChainConstraint>
{
public override bool canBakeToSkeleton => true;
public override bool canBakeToConstraint => true;
public override IEnumerable<EditorCurveBinding> GetSourceCurveBindings(RigBuilder rigBuilder, TwistChainConstraint constraint)
{
var bindings = new List<EditorCurveBinding>();
EditorCurveBindingUtils.CollectTRBindings(rigBuilder.transform, constraint.data.rootTarget, bindings);
EditorCurveBindingUtils.CollectTRBindings(rigBuilder.transform, constraint.data.tipTarget, bindings);
return bindings;
}
public override IEnumerable<EditorCurveBinding> GetConstrainedCurveBindings(RigBuilder rigBuilder, TwistChainConstraint constraint)
{
var bindings = new List<EditorCurveBinding>();
// 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;
}
}
}

View File

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

View File

@@ -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<TwistChainConstraintEditor>();
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<TwistCorrection>
{
public override bool canBakeToSkeleton => true;
public override bool canBakeToConstraint => false;
public override IEnumerable<EditorCurveBinding> GetSourceCurveBindings(RigBuilder rigBuilder, TwistCorrection constraint)
{
var bindings = new List<EditorCurveBinding>();
EditorCurveBindingUtils.CollectRotationBindings(rigBuilder.transform, constraint.data.sourceObject, bindings);
return bindings;
}
public override IEnumerable<EditorCurveBinding> GetConstrainedCurveBindings(RigBuilder rigBuilder, TwistCorrection constraint)
{
var bindings = new List<EditorCurveBinding>();
foreach (var node in constraint.data.twistNodes)
EditorCurveBindingUtils.CollectRotationBindings(rigBuilder.transform, node.transform, bindings);
return bindings;
}
}
}

View File

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

View File

@@ -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<TwoBoneIKConstraintEditor>();
readonly FoldoutState m_SettingsToggle = FoldoutState.ForSettings<TwoBoneIKConstraintEditor>();
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<Animator>()?.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<Rig>();
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<TwoBoneIKConstraint>
{
public override bool canBakeToSkeleton => true;
public override bool canBakeToConstraint => true;
public override IEnumerable<EditorCurveBinding> GetSourceCurveBindings(RigBuilder rigBuilder, TwoBoneIKConstraint constraint)
{
var bindings = new List<EditorCurveBinding>();
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<EditorCurveBinding> GetConstrainedCurveBindings(RigBuilder rigBuilder, TwoBoneIKConstraint constraint)
{
var bindings = new List<EditorCurveBinding>();
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;
}
}
}

View File

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

View File

@@ -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);
}
}
}

View File

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

View File

@@ -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<RigBuilder>();
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);
}
}
}

View File

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

Some files were not shown because too many files have changed in this diff Show More