419 changed files with 19991 additions and 3000 deletions
-
5Packages/com.unity.animation.rigging/.signature
-
208Packages/com.unity.animation.rigging/CHANGELOG.md
-
7Packages/com.unity.animation.rigging/CHANGELOG.md.meta
-
8Packages/com.unity.animation.rigging/DocCodeExamples.meta
-
40Packages/com.unity.animation.rigging/DocCodeExamples/CustomPlayableGraphEvaluator.cs
-
2Packages/com.unity.animation.rigging/DocCodeExamples/CustomPlayableGraphEvaluator.cs.meta
-
35Packages/com.unity.animation.rigging/DocCodeExamples/CustomRigBuilderEvaluator.cs
-
3Packages/com.unity.animation.rigging/DocCodeExamples/CustomRigBuilderEvaluator.cs.meta
-
16Packages/com.unity.animation.rigging/DocCodeExamples/Unity.Animation.Rigging.DocCodeExamples.asmdef
-
7Packages/com.unity.animation.rigging/DocCodeExamples/Unity.Animation.Rigging.DocCodeExamples.asmdef.meta
-
8Packages/com.unity.animation.rigging/Editor.meta
-
8Packages/com.unity.animation.rigging/Editor/AnimationRig.meta
-
8Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints.meta
-
163Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/BlendConstraintEditor.cs
-
2Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/BlendConstraintEditor.cs.meta
-
156Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/ChainIKConstraintEditor.cs
-
2Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/ChainIKConstraintEditor.cs.meta
-
122Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/DampedTransformEditor.cs
-
2Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/DampedTransformEditor.cs.meta
-
197Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiAimConstraintEditor.cs
-
11Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiAimConstraintEditor.cs.meta
-
121Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiParentConstraintEditor.cs
-
11Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiParentConstraintEditor.cs.meta
-
118Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiPositionConstraintEditor.cs
-
11Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiPositionConstraintEditor.cs.meta
-
132Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiReferentialConstraintEditor.cs
-
11Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiReferentialConstraintEditor.cs.meta
-
118Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiRotationConstraintEditor.cs
-
11Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/MultiRotationConstraintEditor.cs.meta
-
152Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/OverrideTransformEditor.cs
-
11Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/OverrideTransformEditor.cs.meta
-
143Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/TwistChainConstraintEditor.cs
-
11Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/TwistChainConstraintEditor.cs.meta
-
114Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/TwistCorrectionEditor.cs
-
11Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/TwistCorrectionEditor.cs.meta
-
301Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/TwoBoneIKConstraintEditor.cs
-
11Packages/com.unity.animation.rigging/Editor/AnimationRig/Constraints/TwoBoneIKConstraintEditor.cs.meta
-
61Packages/com.unity.animation.rigging/Editor/AnimationRig/RigBuilderEditor.cs
-
11Packages/com.unity.animation.rigging/Editor/AnimationRig/RigBuilderEditor.cs.meta
-
76Packages/com.unity.animation.rigging/Editor/AnimationRig/RigEditor.cs
-
11Packages/com.unity.animation.rigging/Editor/AnimationRig/RigEditor.cs.meta
-
40Packages/com.unity.animation.rigging/Editor/AnimationRig/RigLayerDrawer.cs
-
11Packages/com.unity.animation.rigging/Editor/AnimationRig/RigLayerDrawer.cs.meta
-
12Packages/com.unity.animation.rigging/Editor/AnimationRig/RigTransformEditor.cs
-
11Packages/com.unity.animation.rigging/Editor/AnimationRig/RigTransformEditor.cs.meta
-
249Packages/com.unity.animation.rigging/Editor/AnimationRig/WeightedTransformArrayDrawer.cs
-
3Packages/com.unity.animation.rigging/Editor/AnimationRig/WeightedTransformArrayDrawer.cs.meta
-
59Packages/com.unity.animation.rigging/Editor/AnimationRig/WeightedTransformDrawer.cs
-
11Packages/com.unity.animation.rigging/Editor/AnimationRig/WeightedTransformDrawer.cs.meta
-
2Packages/com.unity.animation.rigging/Editor/AssemblyInfo.cs
-
11Packages/com.unity.animation.rigging/Editor/AssemblyInfo.cs.meta
-
8Packages/com.unity.animation.rigging/Editor/Attributes.meta
-
116Packages/com.unity.animation.rigging/Editor/Attributes/BakeParametersAttribute.cs
-
11Packages/com.unity.animation.rigging/Editor/Attributes/BakeParametersAttribute.cs.meta
-
18Packages/com.unity.animation.rigging/Editor/Attributes/CustomOverlayAttribute.cs
-
11Packages/com.unity.animation.rigging/Editor/Attributes/CustomOverlayAttribute.cs.meta
-
32Packages/com.unity.animation.rigging/Editor/Attributes/InverseRigConstraintAttribute.cs
-
11Packages/com.unity.animation.rigging/Editor/Attributes/InverseRigConstraintAttribute.cs.meta
-
8Packages/com.unity.animation.rigging/Editor/Effectors.meta
-
12Packages/com.unity.animation.rigging/Editor/Effectors/IRigEffector.cs
-
11Packages/com.unity.animation.rigging/Editor/Effectors/IRigEffector.cs.meta
-
10Packages/com.unity.animation.rigging/Editor/Effectors/IRigEffectorOverlay.cs
-
11Packages/com.unity.animation.rigging/Editor/Effectors/IRigEffectorOverlay.cs.meta
-
307Packages/com.unity.animation.rigging/Editor/Effectors/RigEffector.cs
-
11Packages/com.unity.animation.rigging/Editor/Effectors/RigEffector.cs.meta
-
190Packages/com.unity.animation.rigging/Editor/Effectors/RigEffectorOverlay.cs
-
11Packages/com.unity.animation.rigging/Editor/Effectors/RigEffectorOverlay.cs.meta
-
235Packages/com.unity.animation.rigging/Editor/Effectors/RigEffectorRenderer.cs
-
11Packages/com.unity.animation.rigging/Editor/Effectors/RigEffectorRenderer.cs.meta
-
68Packages/com.unity.animation.rigging/Editor/Effectors/RigEffectorWizard.cs
-
11Packages/com.unity.animation.rigging/Editor/Effectors/RigEffectorWizard.cs.meta
-
8Packages/com.unity.animation.rigging/Editor/Icons.meta
-
BINPackages/com.unity.animation.rigging/Editor/Icons/RuntimeRig@128.png
-
120Packages/com.unity.animation.rigging/Editor/Icons/RuntimeRig@128.png.meta
-
8Packages/com.unity.animation.rigging/Editor/InverseSolve.meta
-
8Packages/com.unity.animation.rigging/Editor/InverseSolve/AnimationJobs.meta
-
130Packages/com.unity.animation.rigging/Editor/InverseSolve/AnimationJobs/MultiAimInverseConstraintJob.cs
-
11Packages/com.unity.animation.rigging/Editor/InverseSolve/AnimationJobs/MultiAimInverseConstraintJob.cs.meta
-
116Packages/com.unity.animation.rigging/Editor/InverseSolve/AnimationJobs/MultiParentInverseConstraintJob.cs
-
11Packages/com.unity.animation.rigging/Editor/InverseSolve/AnimationJobs/MultiParentInverseConstraintJob.cs.meta
-
116Packages/com.unity.animation.rigging/Editor/InverseSolve/AnimationJobs/MultiPositionInverseConstraintJob.cs
-
11Packages/com.unity.animation.rigging/Editor/InverseSolve/AnimationJobs/MultiPositionInverseConstraintJob.cs.meta
-
96Packages/com.unity.animation.rigging/Editor/InverseSolve/AnimationJobs/MultiReferentialInverseConstraintJob.cs
-
11Packages/com.unity.animation.rigging/Editor/InverseSolve/AnimationJobs/MultiReferentialInverseConstraintJob.cs.meta
-
120Packages/com.unity.animation.rigging/Editor/InverseSolve/AnimationJobs/MultiRotationInverseConstraintJob.cs
-
11Packages/com.unity.animation.rigging/Editor/InverseSolve/AnimationJobs/MultiRotationInverseConstraintJob.cs.meta
-
74Packages/com.unity.animation.rigging/Editor/InverseSolve/AnimationJobs/TwistChainInverseConstraintJob.cs
-
11Packages/com.unity.animation.rigging/Editor/InverseSolve/AnimationJobs/TwistChainInverseConstraintJob.cs.meta
-
99Packages/com.unity.animation.rigging/Editor/InverseSolve/AnimationJobs/TwoBoneIKInverseConstraintJob.cs
-
11Packages/com.unity.animation.rigging/Editor/InverseSolve/AnimationJobs/TwoBoneIKInverseConstraintJob.cs.meta
-
8Packages/com.unity.animation.rigging/Editor/InverseSolve/Constraints.meta
-
24Packages/com.unity.animation.rigging/Editor/InverseSolve/Constraints/MultiAimInverseConstraint.cs
-
11Packages/com.unity.animation.rigging/Editor/InverseSolve/Constraints/MultiAimInverseConstraint.cs.meta
-
25Packages/com.unity.animation.rigging/Editor/InverseSolve/Constraints/MultiParentInverseConstraint.cs
-
11Packages/com.unity.animation.rigging/Editor/InverseSolve/Constraints/MultiParentInverseConstraint.cs.meta
-
24Packages/com.unity.animation.rigging/Editor/InverseSolve/Constraints/MultiPositionInverseConstraint.cs
-
11Packages/com.unity.animation.rigging/Editor/InverseSolve/Constraints/MultiPositionInverseConstraint.cs.meta
-
23Packages/com.unity.animation.rigging/Editor/InverseSolve/Constraints/MultiReferentialInverseConstraint.cs
-
11Packages/com.unity.animation.rigging/Editor/InverseSolve/Constraints/MultiReferentialInverseConstraint.cs.meta
-
24Packages/com.unity.animation.rigging/Editor/InverseSolve/Constraints/MultiRotationInverseConstraint.cs
@ -0,0 +1,5 @@ |
|||||
|
{ |
||||
|
"timestamp": 1675097346, |
||||
|
"signature": "sLaf7UbDWeIQ1rbAZUqsDzJE5/0srDNWDpraziCbDW4CB1xkeWHyWhc+dfHkeB/vaJfm8lU2RHER8PwViFYDfsJoP6KzEpL2dlfFew2kyc5SldgxNylVg6dzfUy28niNlErhEd8nVizxROaTfUTDE8Qe3A66zdGWqUqz0j9R1TWAiuOLHVQOI4VzbkyjF3CL+b67Y2tRI9IBc9KcY5Mc7UCTji1QI1OQNAkVMbMOmdEBPkoiujnA5Vn3YLYYY24trSvNG0NGsFOOWWyus9QDJDWOjeMImiYl8Vc9k4s/pz11LLtVqKslsbRDc4V5AeD1mWV+p/QI2WlkDvdlKOLjt6/ITPp07LDNIJy5+A8E6VXAXCepcJ9z9Vm5HozelqU4WoPnScA1o2tVxeGVMXZjEesK/0WaMXTlqjOWNKEKtJtqoRcpdvGvqKnV7JTVTq/oWZDjcjdcNmE8ee6C2x6rijc/oYEsHbBVonco5OnOX1jynHW9gYquOcOkiPlojGeQ", |
||||
|
"publicKey": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQm9qQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FZOEFNSUlCaWdLQ0FZRUFzdUhXYUhsZ0I1cVF4ZEJjTlJKSAordHR4SmoxcVY1NTdvMlZaRE1XaXhYRVBkRTBEMVFkT1JIRXNSS1RscmplUXlERU83ZlNQS0ZwZ1A3MU5TTnJCCkFHM2NFSU45aHNQVDhOVmllZmdWem5QTkVMenFkVmdEbFhpb2VpUnV6OERKWFgvblpmU1JWKytwbk9ySTRibG4KS0twelJlNW14OTc1SjhxZ1FvRktKT0NNRlpHdkJMR2MxSzZZaEIzOHJFODZCZzgzbUovWjBEYkVmQjBxZm13cgo2ZDVFUXFsd0E5Y3JZT1YyV1VpWXprSnBLNmJZNzRZNmM1TmpBcEFKeGNiaTFOaDlRVEhUcU44N0ZtMDF0R1ZwCjVNd1pXSWZuYVRUemEvTGZLelR5U0pka0tldEZMVGdkYXpMYlpzUEE2aHBSK0FJRTJhc0tLTi84UUk1N3UzU2cKL2xyMnZKS1IvU2l5eEN1Q20vQWJkYnJMbXk0WjlSdm1jMGdpclA4T0lLQWxBRWZ2TzV5Z2hSKy8vd1RpTFlzUQp1SllDM0V2UE16ZGdKUzdGR2FscnFLZzlPTCsxVzROY05yNWdveVdSUUJ0cktKaWlTZEJVWmVxb0RvSUY5NHpCCndGbzJJT1JFdXFqcU51M3diMWZIM3p1dGdtalFra3IxVjJhd3hmcExLWlROQWdNQkFBRT0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg" |
||||
|
} |
||||
@ -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 |
||||
@ -0,0 +1,7 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 39c18d859abc65e41b8e5bf2267e013d |
||||
|
TextScriptImporter: |
||||
|
externalObjects: {} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,8 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: be78dea739b9e4fa68fe04d39c94b597 |
||||
|
folderAsset: yes |
||||
|
DefaultImporter: |
||||
|
externalObjects: {} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,40 @@ |
|||||
|
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.UpdateLayers(); |
||||
|
m_PlayableGraph.Evaluate(Time.deltaTime); |
||||
|
m_RigBuilder.LateUpdateLayers(); |
||||
|
} |
||||
|
} |
||||
|
#endregion
|
||||
|
} |
||||
@ -1,5 +1,5 @@ |
|||||
fileFormatVersion: 2 |
fileFormatVersion: 2 |
||||
guid: 0fd9ee276a1023e439cf7a9c393195fa |
|
||||
|
guid: a2411ac2c7bbd4f58aaae3e6cefda2aa |
||||
MonoImporter: |
MonoImporter: |
||||
externalObjects: {} |
externalObjects: {} |
||||
serializedVersion: 2 |
serializedVersion: 2 |
||||
@ -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
|
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: dc9f69976d6143e489b841bec6ac5cfd |
||||
|
timeCreated: 1636580728 |
||||
@ -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 |
||||
|
} |
||||
@ -0,0 +1,7 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: c2a5362f5f25b455f8f4eeea25441772 |
||||
|
AssemblyDefinitionImporter: |
||||
|
externalObjects: {} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,8 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 25a1bcc63261564418263e1b1fa0a713 |
||||
|
folderAsset: yes |
||||
|
DefaultImporter: |
||||
|
externalObjects: {} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,8 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: eade225a3b4a03d49af6485534a9dc23 |
||||
|
folderAsset: yes |
||||
|
DefaultImporter: |
||||
|
externalObjects: {} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,8 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 754562bd98582a44e875ea6d688127ac |
||||
|
folderAsset: yes |
||||
|
DefaultImporter: |
||||
|
externalObjects: {} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,5 +1,5 @@ |
|||||
fileFormatVersion: 2 |
fileFormatVersion: 2 |
||||
guid: ff5ab0e3d6cd4a5bab92dab9c63e8962 |
|
||||
|
guid: a8670d948642f1546a4835c189aea303 |
||||
MonoImporter: |
MonoImporter: |
||||
externalObjects: {} |
externalObjects: {} |
||||
serializedVersion: 2 |
serializedVersion: 2 |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,5 +1,5 @@ |
|||||
fileFormatVersion: 2 |
fileFormatVersion: 2 |
||||
guid: 81dd1b9facda41f9a09fb997d6e64670 |
|
||||
|
guid: 63110210264e2ee4da7389733e5958ae |
||||
MonoImporter: |
MonoImporter: |
||||
externalObjects: {} |
externalObjects: {} |
||||
serializedVersion: 2 |
serializedVersion: 2 |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,5 +1,5 @@ |
|||||
fileFormatVersion: 2 |
fileFormatVersion: 2 |
||||
guid: 172ced047a38440389ff238ad1d347ce |
|
||||
|
guid: 99a3cbe2e69614541bdf264c5e905f48 |
||||
MonoImporter: |
MonoImporter: |
||||
externalObjects: {} |
externalObjects: {} |
||||
serializedVersion: 2 |
serializedVersion: 2 |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 9a96277d4d9d2d04181fc5ce44119fdf |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 2326ba71c8dbcba4ea941bf20e7e1bbc |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 6ca0517db96fdfc41b4230a34d84b37c |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 74cfdd6a1e6ff244496d38de0c2bbee5 |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 91a61b91969f07d448049f1b2c1bf3c8 |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 16cd7f77b75e35946b191bd98757e5a2 |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 6f51e9e105d754014895d13788b539ae |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: e52e5d5c12dea4e4397e6781cbeac36d |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: d47d5b10876eed042af2bccb184f9a5b |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -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); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 5f920510daf5fba46b137a815f4e9a1b |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 6856dd80c42d3244b9d9eb1844f8715f |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,40 @@ |
|||||
|
using UnityEngine; |
||||
|
using UnityEngine.Animations.Rigging; |
||||
|
|
||||
|
namespace UnityEditor.Animations.Rigging |
||||
|
{ |
||||
|
[CustomPropertyDrawer(typeof(RigLayer))] |
||||
|
class RigLayerDrawer : PropertyDrawer |
||||
|
{ |
||||
|
const int k_Padding = 6; |
||||
|
const int k_TogglePadding = 30; |
||||
|
|
||||
|
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) |
||||
|
{ |
||||
|
return EditorGUIUtility.singleLineHeight; |
||||
|
} |
||||
|
|
||||
|
public override void OnGUI(Rect rect, SerializedProperty property, GUIContent label) |
||||
|
{ |
||||
|
EditorGUI.BeginProperty(rect, label, property); |
||||
|
|
||||
|
var w = rect.width - k_TogglePadding; |
||||
|
var weightRect = new Rect(rect.x + w + k_Padding, rect.y, rect.width - w - k_Padding, rect.height); |
||||
|
rect.width = w; |
||||
|
|
||||
|
EditorGUI.BeginChangeCheck(); |
||||
|
EditorGUI.PropertyField(rect, property.FindPropertyRelative("m_Rig"), label); |
||||
|
|
||||
|
var indentLvl = EditorGUI.indentLevel; |
||||
|
EditorGUI.indentLevel = 0; |
||||
|
EditorGUI.PropertyField(weightRect, property.FindPropertyRelative("m_Active"), GUIContent.none); |
||||
|
EditorGUI.indentLevel = indentLvl; |
||||
|
|
||||
|
if (EditorGUI.EndChangeCheck()) |
||||
|
property.serializedObject.ApplyModifiedProperties(); |
||||
|
|
||||
|
EditorGUI.EndProperty(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: cfddd68cbf078454ab5dfd53ed554127 |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,12 @@ |
|||||
|
using UnityEngine.Animations.Rigging; |
||||
|
|
||||
|
namespace UnityEditor.Animations.Rigging |
||||
|
{ |
||||
|
[CustomEditor(typeof(RigTransform))] |
||||
|
class RigTransformEditor : Editor |
||||
|
{ |
||||
|
public override void OnInspectorGUI() |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: ab480ae8b7295e54c9c72a011401317e |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,249 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Reflection; |
||||
|
using UnityEditorInternal; |
||||
|
using UnityEngine; |
||||
|
using UnityEngine.Animations.Rigging; |
||||
|
using UnityObject = UnityEngine.Object; |
||||
|
|
||||
|
namespace UnityEditor.Animations.Rigging |
||||
|
{ |
||||
|
[CustomPropertyDrawer(typeof(WeightedTransformArray))] |
||||
|
sealed class WeightedTransformArrayDrawer : PropertyDrawer |
||||
|
{ |
||||
|
const string k_LengthPath = "m_Length"; |
||||
|
const string k_ItemTransformPath = nameof(WeightedTransform.transform); |
||||
|
const string k_ItemWeightPath = nameof(WeightedTransform.weight); |
||||
|
static readonly string[] k_ItemPropertyPaths = |
||||
|
Enumerable.Range(0, WeightedTransformArray.k_MaxLength).Select(i => $"m_Item{i}").ToArray(); |
||||
|
|
||||
|
// one reorderable list per unique property path
|
||||
|
readonly Dictionary<string, (ReorderableList listControl, SerializedProperty lengthProperty)> m_GUIState = |
||||
|
new Dictionary<string, (ReorderableList listControl, SerializedProperty lengthProperty)>(); |
||||
|
|
||||
|
// function to get WeightedTransform from item property
|
||||
|
static WeightedTransform GetValueSingle(SerializedProperty item) => new WeightedTransform |
||||
|
{ |
||||
|
transform = item.FindPropertyRelative(k_ItemTransformPath).objectReferenceValue as Transform, |
||||
|
weight = item.FindPropertyRelative(k_ItemWeightPath).floatValue |
||||
|
}; |
||||
|
|
||||
|
// function to modify a list of items per target
|
||||
|
static void ModifyItemsSingle(SerializedProperty parentProperty, Action<List<WeightedTransform>> modifyList) |
||||
|
{ |
||||
|
foreach (var target in parentProperty.serializedObject.targetObjects) |
||||
|
{ |
||||
|
using (var so = new SerializedObject(target)) |
||||
|
{ |
||||
|
var sp = so.FindProperty(parentProperty.propertyPath); |
||||
|
var length = sp.FindPropertyRelative(k_LengthPath); |
||||
|
|
||||
|
// create a live list of items
|
||||
|
var items = |
||||
|
Enumerable.Range(0, length.intValue) |
||||
|
.Select(i => GetValueSingle(sp.FindPropertyRelative(k_ItemPropertyPaths[i]))) |
||||
|
.ToList(); |
||||
|
|
||||
|
// modify the list
|
||||
|
modifyList(items); |
||||
|
|
||||
|
// write the results back to the serialized data stream
|
||||
|
for (var i = 0; i < items.Count; ++i) |
||||
|
{ |
||||
|
var item = sp.FindPropertyRelative(k_ItemPropertyPaths[i]); |
||||
|
item.FindPropertyRelative(k_ItemTransformPath).objectReferenceValue = items[i].transform; |
||||
|
item.FindPropertyRelative(k_ItemWeightPath).floatValue = items[i].weight; |
||||
|
} |
||||
|
// clear other items
|
||||
|
for (var i = items.Count; i < WeightedTransformArray.k_MaxLength; ++i) |
||||
|
{ |
||||
|
var item = sp.FindPropertyRelative(k_ItemPropertyPaths[i]); |
||||
|
item.FindPropertyRelative(k_ItemTransformPath).objectReferenceValue = default; |
||||
|
item.FindPropertyRelative(k_ItemWeightPath).floatValue = default; |
||||
|
} |
||||
|
|
||||
|
// synchronize length property
|
||||
|
length.intValue = items.Count; |
||||
|
|
||||
|
// write back results
|
||||
|
so.ApplyModifiedProperties(); |
||||
|
} |
||||
|
} |
||||
|
// update parent property's serialized data stream to get new (shared) values for all targets
|
||||
|
parentProperty.serializedObject.Update(); |
||||
|
} |
||||
|
|
||||
|
(ReorderableList listControl, SerializedProperty lengthProperty) GetGUIState(SerializedProperty property, GUIContent label) |
||||
|
{ |
||||
|
var lengthProperty = property.FindPropertyRelative(k_LengthPath); |
||||
|
|
||||
|
// create a new reorderable list if one does not exist
|
||||
|
if (!m_GUIState.TryGetValue(property.propertyPath, out var guiState)) |
||||
|
{ |
||||
|
// bind the control to a proxy list
|
||||
|
var proxy = Enumerable.Range(0, lengthProperty.intValue) |
||||
|
.ToList(); |
||||
|
var reorderableList = new ReorderableList(proxy, typeof(int)); |
||||
|
|
||||
|
reorderableList.headerHeight = Styles.minHeaderHeight; |
||||
|
|
||||
|
// default array control only allocates single line height, but that leaves no spacing between object fields
|
||||
|
reorderableList.elementHeight = |
||||
|
EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; |
||||
|
|
||||
|
var attr = fieldInfo.GetCustomAttribute<WeightRangeAttribute>(); |
||||
|
var legacyAttr = fieldInfo.GetCustomAttribute<RangeAttribute>(); |
||||
|
var min = attr?.min ?? legacyAttr?.min ?? float.NaN; |
||||
|
var max = attr?.max ?? legacyAttr?.max ?? float.NaN; |
||||
|
var spacing = EditorGUIUtility.standardVerticalSpacing / 2f; |
||||
|
reorderableList.drawElementCallback += (rect, index, active, focused) => |
||||
|
{ |
||||
|
rect = new Rect(rect) { height = EditorGUIUtility.singleLineHeight, y = rect.y + spacing }; |
||||
|
WeightedTransformDrawer.DoGUI(rect, property.FindPropertyRelative(k_ItemPropertyPaths[index]), min, max); |
||||
|
}; |
||||
|
|
||||
|
reorderableList.onCanAddCallback += list => |
||||
|
!Application.isPlaying |
||||
|
&& !AnimationMode.InAnimationMode() |
||||
|
&& lengthProperty.intValue < WeightedTransformArray.k_MaxLength; |
||||
|
|
||||
|
reorderableList.onCanRemoveCallback += list => |
||||
|
!Application.isPlaying |
||||
|
&& !AnimationMode.InAnimationMode() |
||||
|
&& lengthProperty.intValue > 0; |
||||
|
|
||||
|
reorderableList.onAddCallback += list => |
||||
|
{ |
||||
|
ModifyItemsSingle(property, items => |
||||
|
{ |
||||
|
int insertIndex = Math.Max(0, reorderableList.index >= 0 ? reorderableList.index : items.Count - 1); |
||||
|
if (items.Count < WeightedTransformArray.k_MaxLength) |
||||
|
items.Insert(insertIndex, insertIndex < items.Count ? items[insertIndex] : WeightedTransform.Default(1f)); |
||||
|
}); |
||||
|
proxy.Add(proxy.Count); |
||||
|
}; |
||||
|
|
||||
|
reorderableList.onRemoveCallback += list => |
||||
|
{ |
||||
|
ModifyItemsSingle(property, items => |
||||
|
{ |
||||
|
int removeIndex = Math.Max(0, reorderableList.index >= 0 ? reorderableList.index : items.Count - 1); |
||||
|
if (removeIndex >= 0) |
||||
|
items.RemoveAt(removeIndex); |
||||
|
}); |
||||
|
proxy.RemoveAt(proxy.Count - 1); |
||||
|
}; |
||||
|
|
||||
|
reorderableList.onReorderCallbackWithDetails += (list, srcIndex, dstIndex) => |
||||
|
ModifyItemsSingle(property, items => |
||||
|
{ |
||||
|
var moved = items[srcIndex]; |
||||
|
items.RemoveAt(srcIndex); |
||||
|
items.Insert(dstIndex, moved); |
||||
|
}); |
||||
|
|
||||
|
guiState = m_GUIState[property.propertyPath] = (reorderableList, lengthProperty.Copy()); |
||||
|
} |
||||
|
|
||||
|
// synchronize proxy list to serialized length
|
||||
|
var proxyList = guiState.listControl.list; |
||||
|
while (proxyList.Count < lengthProperty.intValue) |
||||
|
proxyList.Add(proxyList.Count); |
||||
|
while (proxyList.Count > lengthProperty.intValue) |
||||
|
proxyList.RemoveAt(proxyList.Count - 1); |
||||
|
|
||||
|
return guiState; |
||||
|
} |
||||
|
|
||||
|
static class Styles |
||||
|
{ |
||||
|
// cf. ReorderableList.Defaults.minHeaderHeight;
|
||||
|
public static float minHeaderHeight = 2f; |
||||
|
// cf. ReorderableListWrapper.cs
|
||||
|
public const float headerPadding = 3f; |
||||
|
public const float arraySizeWidth = 50f; // 48 in ReorderableListWrapper, but EditorGUI.Slider() field is 50
|
||||
|
public const float defaultFoldoutHeaderHeight = 18f; |
||||
|
public static readonly GUIContent sizeLabel = EditorGUIUtility.TrTextContent("", "Length"); |
||||
|
} |
||||
|
|
||||
|
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) => |
||||
|
Styles.defaultFoldoutHeaderHeight |
||||
|
+ (property.isExpanded ? Styles.headerPadding + GetGUIState(property, label).listControl.GetHeight() : 0f); |
||||
|
|
||||
|
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) |
||||
|
{ |
||||
|
var guiState = GetGUIState(property, label); |
||||
|
|
||||
|
Rect headerRect = new Rect(position) { height = EditorGUIUtility.singleLineHeight }; |
||||
|
Rect sizeRect = new Rect(headerRect) { xMin = headerRect.xMax - Styles.arraySizeWidth }; |
||||
|
|
||||
|
EventType prevType = Event.current.type; |
||||
|
if (Event.current.type == EventType.MouseUp && sizeRect.Contains(Event.current.mousePosition)) |
||||
|
{ |
||||
|
Event.current.type = EventType.Used; |
||||
|
} |
||||
|
|
||||
|
property.isExpanded = EditorGUI.BeginFoldoutHeaderGroup(headerRect, property.isExpanded, label); |
||||
|
EditorGUI.EndFoldoutHeaderGroup(); |
||||
|
|
||||
|
if (Event.current.type == EventType.Used && sizeRect.Contains(Event.current.mousePosition)) Event.current.type = prevType; |
||||
|
|
||||
|
EditorGUI.BeginChangeCheck(); |
||||
|
EditorGUI.DelayedIntField(sizeRect, guiState.lengthProperty, Styles.sizeLabel); |
||||
|
if (EditorGUI.EndChangeCheck()) |
||||
|
guiState.lengthProperty.intValue = Mathf.Clamp(guiState.lengthProperty.intValue, 0, WeightedTransformArray.k_MaxLength); |
||||
|
EditorGUI.LabelField(sizeRect, Styles.sizeLabel); |
||||
|
|
||||
|
if (headerRect.Contains(Event.current.mousePosition)) |
||||
|
{ |
||||
|
if (Event.current.type == EventType.DragUpdated || Event.current.type == EventType.DragPerform) |
||||
|
{ |
||||
|
OnDropObjects(property, DragAndDrop.objectReferences, guiState.listControl); |
||||
|
DragAndDrop.AcceptDrag(); |
||||
|
Event.current.Use(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (Event.current.type == EventType.DragExited) |
||||
|
{ |
||||
|
DragAndDrop.visualMode = DragAndDropVisualMode.None; |
||||
|
Event.current.Use(); |
||||
|
} |
||||
|
|
||||
|
if (property.isExpanded) |
||||
|
guiState.listControl.DoList(new Rect(position) { yMin = headerRect.yMax + Styles.headerPadding }); |
||||
|
} |
||||
|
|
||||
|
static void OnDropObjects(SerializedProperty property, UnityObject[] objectReferences, ReorderableList listControl) |
||||
|
{ |
||||
|
foreach (var o in objectReferences) |
||||
|
{ |
||||
|
var go = o as GameObject; |
||||
|
var c = o as Component; |
||||
|
|
||||
|
if (go == null && c == null) |
||||
|
continue; |
||||
|
|
||||
|
if (listControl.list.Count >= WeightedTransformArray.k_MaxLength) |
||||
|
{ |
||||
|
DragAndDrop.visualMode = DragAndDropVisualMode.Rejected; |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
DragAndDrop.visualMode = DragAndDropVisualMode.Generic; |
||||
|
|
||||
|
var t = c == null ? go.transform : c.transform; |
||||
|
if (Event.current.type == EventType.DragPerform) |
||||
|
{ |
||||
|
ModifyItemsSingle(property, items => |
||||
|
{ |
||||
|
var weight = items.Count == 0 ? 1f : items[items.Count - 1].weight; |
||||
|
items.Add(new WeightedTransform(t, weight)); |
||||
|
}); |
||||
|
listControl.list.Add(listControl.list.Count); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: ee7818cdc02e4548adb5ae6bc5901523 |
||||
|
timeCreated: 1607593832 |
||||
@ -0,0 +1,59 @@ |
|||||
|
using System.Reflection; |
||||
|
using UnityEngine; |
||||
|
using UnityEngine.Animations.Rigging; |
||||
|
|
||||
|
namespace UnityEditor.Animations.Rigging |
||||
|
{ |
||||
|
[CustomPropertyDrawer(typeof(WeightedTransform))] |
||||
|
class WeightedTransformDrawer : PropertyDrawer |
||||
|
{ |
||||
|
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) => |
||||
|
EditorGUIUtility.singleLineHeight; |
||||
|
|
||||
|
(WeightRangeAttribute attr, RangeAttribute legacyAttr)? m_RangeAttributes; |
||||
|
|
||||
|
public override void OnGUI(Rect rect, SerializedProperty property, GUIContent label) |
||||
|
{ |
||||
|
var (attr, legacyAttr) = m_RangeAttributes ??= ( |
||||
|
fieldInfo.GetCustomAttribute<WeightRangeAttribute>(), |
||||
|
fieldInfo.GetCustomAttribute<RangeAttribute>() |
||||
|
); |
||||
|
|
||||
|
float min = attr?.min ?? legacyAttr?.min ?? float.NaN; |
||||
|
float max = attr?.max ?? legacyAttr?.max ?? float.NaN; |
||||
|
|
||||
|
DoGUI(rect, property, min, max); |
||||
|
} |
||||
|
|
||||
|
static class Styles |
||||
|
{ |
||||
|
public static float transformFieldWidthScale = 0.65f; |
||||
|
public static readonly int horizontalMargin = ( |
||||
|
EditorStyles.objectField.margin.right + GUI.skin.horizontalSlider.margin.left |
||||
|
) / 2; |
||||
|
} |
||||
|
|
||||
|
internal static void DoGUI(Rect rect, SerializedProperty property, float min, float max) |
||||
|
{ |
||||
|
EditorGUI.BeginProperty(rect, GUIContent.none, property); |
||||
|
|
||||
|
var w = rect.width * Styles.transformFieldWidthScale; |
||||
|
var weightRect = new Rect(rect.x + w, rect.y, rect.width - w, EditorGUIUtility.singleLineHeight); |
||||
|
rect.width = w; |
||||
|
|
||||
|
var transformRect = new Rect(rect.x, rect.y, rect.width - Styles.horizontalMargin, EditorGUIUtility.singleLineHeight); |
||||
|
|
||||
|
EditorGUI.PropertyField(transformRect, property.FindPropertyRelative("transform"), GUIContent.none); |
||||
|
|
||||
|
var indentLvl = EditorGUI.indentLevel; |
||||
|
EditorGUI.indentLevel = 0; |
||||
|
if (float.IsNaN(max) || float.IsNaN(min)) |
||||
|
EditorGUI.PropertyField(weightRect, property.FindPropertyRelative("weight"), GUIContent.none); |
||||
|
else |
||||
|
EditorGUI.Slider(weightRect, property.FindPropertyRelative("weight"), min, max, GUIContent.none); |
||||
|
EditorGUI.indentLevel = indentLvl; |
||||
|
|
||||
|
EditorGUI.EndProperty(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: a015bc034afc6b742996a3d23fa85902 |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,2 @@ |
|||||
|
using System.Runtime.CompilerServices; |
||||
|
[assembly: InternalsVisibleTo("Unity.Animation.Rigging.EditorTests")] |
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 0e9f01c83e9859644bb453f6f07af6d6 |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,8 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: f53358c1055884db9ba27bfa39aae0a0 |
||||
|
folderAsset: yes |
||||
|
DefaultImporter: |
||||
|
externalObjects: {} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,116 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using UnityEngine; |
||||
|
using UnityEngine.Animations.Rigging; |
||||
|
|
||||
|
namespace UnityEditor.Animations.Rigging |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Attribute that can be placed on BakeParameters. The attribute is used to declare to which RigConstraint the BakeParameters belong.
|
||||
|
/// </summary>
|
||||
|
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] |
||||
|
public sealed class BakeParametersAttribute : Attribute |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Constructor.
|
||||
|
/// </summary>
|
||||
|
/// <param name="constraintType">The RigConstraint to which the BakeParameters belong.</param>
|
||||
|
public BakeParametersAttribute(Type constraintType) |
||||
|
{ |
||||
|
if (constraintType == null || !typeof(IRigConstraint).IsAssignableFrom(constraintType)) |
||||
|
Debug.LogError("Invalid constraint for InverseRigConstraint attribute."); |
||||
|
|
||||
|
this.constraintType = constraintType; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// The RigConstraint to which the BakeParameters belong.
|
||||
|
/// </summary>
|
||||
|
public Type constraintType { get; } |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Class that holds bi-directional baking capabilities and curve bindings of a RigConstraint.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="T">The Type of RigConstraint the parameters belong to.</typeparam>
|
||||
|
public abstract class BakeParameters<T> : IBakeParameters |
||||
|
where T : IRigConstraint |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Boolean used to determine if the RigConstraint can transfer motion from itself to the skeleton
|
||||
|
/// </summary>
|
||||
|
public abstract bool canBakeToSkeleton { get; } |
||||
|
/// <summary>
|
||||
|
/// Boolean used to determine if the RigConstraint can transfer motion to itself from the skeleton.
|
||||
|
/// </summary>
|
||||
|
public abstract bool canBakeToConstraint { get; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Collects the editor curve bindings for all the properties that this RigConstraint modifies when transferring motion to the skeleton.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rigBuilder">The RigBuilder which the constraint is part of.</param>
|
||||
|
/// <param name="constraint">The RigConstraint for which the bindings should be collected.</param>
|
||||
|
/// <returns></returns>
|
||||
|
public abstract IEnumerable<EditorCurveBinding> GetSourceCurveBindings(RigBuilder rigBuilder, T constraint); |
||||
|
/// <summary>
|
||||
|
/// Collects the editor curve bindings for all the properties that this RigConstraint modifies when transferring motion to this constraint.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rigBuilder">The RigBuilder which the constraint is part of.</param>
|
||||
|
/// <param name="constraint">The RigConstraint for which the bindings should be collected.</param>
|
||||
|
/// <returns></returns>
|
||||
|
public abstract IEnumerable<EditorCurveBinding> GetConstrainedCurveBindings(RigBuilder rigBuilder, T constraint); |
||||
|
|
||||
|
|
||||
|
/// <inheritdoc />
|
||||
|
bool IBakeParameters.canBakeToSkeleton => canBakeToSkeleton; |
||||
|
/// <inheritdoc />
|
||||
|
bool IBakeParameters.canBakeToConstraint => canBakeToConstraint; |
||||
|
|
||||
|
/// <inheritdoc />
|
||||
|
IEnumerable<EditorCurveBinding> IBakeParameters.GetSourceCurveBindings(RigBuilder rigBuilder, IRigConstraint constraint) |
||||
|
{ |
||||
|
Debug.Assert(constraint is T); |
||||
|
T tConstraint = (T)constraint; |
||||
|
return GetSourceCurveBindings(rigBuilder, tConstraint); |
||||
|
} |
||||
|
|
||||
|
/// <inheritdoc />
|
||||
|
IEnumerable<EditorCurveBinding> IBakeParameters.GetConstrainedCurveBindings(RigBuilder rigBuilder, IRigConstraint constraint) |
||||
|
{ |
||||
|
Debug.Assert(constraint is T); |
||||
|
T tConstraint = (T)constraint; |
||||
|
return GetConstrainedCurveBindings(rigBuilder, tConstraint); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// This is the base interface for BakeParameters.
|
||||
|
/// </summary>
|
||||
|
public interface IBakeParameters |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Boolean used to determine if the RigConstraint can transfer motion from itself to the skeleton
|
||||
|
/// </summary>
|
||||
|
bool canBakeToSkeleton { get; } |
||||
|
/// <summary>
|
||||
|
/// Boolean used to determine if the RigConstraint can transfer motion to itself from the skeleton.
|
||||
|
/// </summary>
|
||||
|
bool canBakeToConstraint { get; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Collects the editor curve bindings for all the properties that this RigConstraint modifies when transferring motion to the skeleton.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rigBuilder">The RigBuilder which the constraint is part of.</param>
|
||||
|
/// <param name="constraint">The RigConstraint for which the bindings should be collected.</param>
|
||||
|
/// <returns></returns>
|
||||
|
IEnumerable<EditorCurveBinding> GetSourceCurveBindings(RigBuilder rigBuilder, IRigConstraint constraint); |
||||
|
/// <summary>
|
||||
|
/// Collects the editor curve bindings for all the properties that this RigConstraint modifies when transferring motion to this constraint.
|
||||
|
/// </summary>
|
||||
|
/// <param name="rigBuilder">The RigBuilder which the constraint is part of.</param>
|
||||
|
/// <param name="constraint">The RigConstraint for which the bindings should be collected.</param>
|
||||
|
/// <returns></returns>
|
||||
|
IEnumerable<EditorCurveBinding> GetConstrainedCurveBindings(RigBuilder rigBuilder, IRigConstraint constraint); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: bc4c7bdb3fbef4e6f8eb6ea619b7c442 |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,18 @@ |
|||||
|
using System; |
||||
|
using UnityEngine; |
||||
|
|
||||
|
namespace UnityEditor.Animations.Rigging |
||||
|
{ |
||||
|
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] |
||||
|
internal sealed class CustomOverlayAttribute : Attribute |
||||
|
{ |
||||
|
private Type m_EffectorType; |
||||
|
|
||||
|
public CustomOverlayAttribute(Type effectorType) |
||||
|
{ |
||||
|
m_EffectorType = effectorType; |
||||
|
} |
||||
|
|
||||
|
public Type effectorType { get => m_EffectorType; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 54d375d3ab6254023a5ab55153af9c84 |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,32 @@ |
|||||
|
using System; |
||||
|
using UnityEngine; |
||||
|
using UnityEngine.Animations.Rigging; |
||||
|
|
||||
|
namespace UnityEditor.Animations.Rigging |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The [InverseRigConstraint] attribute allows to match an inverse constraint (inverse solve) to its
|
||||
|
/// base constraint (forward solve) counterpart. This is used in bi-directional baking to override
|
||||
|
/// constraints when baking animations to constraints.
|
||||
|
/// </summary>
|
||||
|
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] |
||||
|
public sealed class InverseRigConstraintAttribute : Attribute |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Constructor.
|
||||
|
/// </summary>
|
||||
|
/// <param name="targetBinderType">The base constraint type.</param>
|
||||
|
public InverseRigConstraintAttribute(Type targetBinderType) |
||||
|
{ |
||||
|
if (targetBinderType == null || !typeof(IRigConstraint).IsAssignableFrom(targetBinderType)) |
||||
|
Debug.LogError("Invalid constraint for InverseRigConstraint attribute."); |
||||
|
|
||||
|
this.baseConstraint = targetBinderType; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Retrieves the base constraint type.
|
||||
|
/// </summary>
|
||||
|
public Type baseConstraint { get; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 28f235e117a7e453fa6d4c1cb6094700 |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,8 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: fbd5015e3b81f464aa1b87826a3eaf55 |
||||
|
folderAsset: yes |
||||
|
DefaultImporter: |
||||
|
externalObjects: {} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,12 @@ |
|||||
|
using UnityEngine; |
||||
|
|
||||
|
namespace UnityEditor.Animations.Rigging |
||||
|
{ |
||||
|
internal interface IRigEffector |
||||
|
{ |
||||
|
Transform transform { get; } |
||||
|
bool visible { get; set; } |
||||
|
|
||||
|
void OnSceneGUI(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 5aa7c79e34bb34aab80024d95fafe526 |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,10 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace UnityEditor.Animations.Rigging |
||||
|
{ |
||||
|
interface IRigEffectorOverlay : IDisposable |
||||
|
{ |
||||
|
bool IsValid(); |
||||
|
void OnSceneGUIOverlay(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 4231b7e96c3094051a12f91bae5c7c90 |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,307 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using UnityEngine; |
||||
|
using UnityEngine.Animations.Rigging; |
||||
|
|
||||
|
namespace UnityEditor.Animations.Rigging |
||||
|
{ |
||||
|
[Serializable] |
||||
|
internal class RigEffector : ScriptableObject, IRigEffector |
||||
|
{ |
||||
|
[SerializeField] private RigEffectorData m_Data; |
||||
|
|
||||
|
public Transform transform |
||||
|
{ |
||||
|
get => m_Data.transform; |
||||
|
} |
||||
|
|
||||
|
public bool visible |
||||
|
{ |
||||
|
get => m_Data.visible; |
||||
|
set => m_Data.visible = value; |
||||
|
} |
||||
|
|
||||
|
private static int s_ButtonHash = "RigEffector".GetHashCode(); |
||||
|
|
||||
|
public void Initialize(RigEffectorData data) |
||||
|
{ |
||||
|
m_Data = data; |
||||
|
} |
||||
|
|
||||
|
private static Material s_Material; |
||||
|
|
||||
|
public static Material material |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
if (!s_Material) |
||||
|
{ |
||||
|
var shader = EditorHelper.LoadShader("BoneHandles.shader"); |
||||
|
s_Material = new Material(shader); |
||||
|
s_Material.hideFlags = HideFlags.HideAndDontSave; |
||||
|
} |
||||
|
|
||||
|
return s_Material; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public static RigEffectorData.Style defaultStyle |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
var style = new RigEffectorData.Style() |
||||
|
{ |
||||
|
shape = EditorHelper.LoadShape("LocatorEffector.asset"), |
||||
|
color = new Color(1f, 0f, 0f, 0.5f), |
||||
|
size = 0.10f, |
||||
|
position = Vector3.zero, |
||||
|
rotation = Vector3.zero |
||||
|
}; |
||||
|
|
||||
|
return style; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public void OnSceneGUI() |
||||
|
{ |
||||
|
if (!m_Data.visible) |
||||
|
return; |
||||
|
|
||||
|
// Might happen if we delete transform while effector still exists.
|
||||
|
if (transform == null) |
||||
|
return; |
||||
|
|
||||
|
var style = m_Data.style; |
||||
|
|
||||
|
// Disregard effectors without shapes.
|
||||
|
if (style.shape == null) |
||||
|
return; |
||||
|
|
||||
|
if (SceneVisibilityManager.instance.IsHidden(transform.gameObject, false)) |
||||
|
return; |
||||
|
|
||||
|
var mask = UnityEditor.Tools.visibleLayers; |
||||
|
if ((mask & (1 << transform.gameObject.layer)) == 0) |
||||
|
return; |
||||
|
|
||||
|
int id = GUIUtility.GetControlID(s_ButtonHash, FocusType.Passive); |
||||
|
Event evt = Event.current; |
||||
|
|
||||
|
switch (evt.GetTypeForControl(id)) |
||||
|
{ |
||||
|
case EventType.Layout: |
||||
|
{ |
||||
|
HandleUtility.AddControl(id, DistanceToEffector(transform, style.shape, style.position, style.rotation, style.size)); |
||||
|
break; |
||||
|
} |
||||
|
case EventType.MouseDown: |
||||
|
{ |
||||
|
if (evt.alt) |
||||
|
break; |
||||
|
|
||||
|
if (HandleUtility.nearestControl == id && evt.button == 0) |
||||
|
{ |
||||
|
GameObject targetGameObject = transform.gameObject; |
||||
|
if (!SceneVisibilityManager.instance.IsPickingDisabled(targetGameObject, false)) |
||||
|
{ |
||||
|
GUIUtility.hotControl = id; // Grab mouse focus
|
||||
|
EditorHelper.HandleClickSelection(targetGameObject, evt); |
||||
|
evt.Use(); |
||||
|
} |
||||
|
} |
||||
|
break; |
||||
|
} |
||||
|
case EventType.MouseDrag: |
||||
|
{ |
||||
|
if (!evt.alt && GUIUtility.hotControl == id) |
||||
|
{ |
||||
|
GameObject targetGameObject = transform.gameObject; |
||||
|
if (!SceneVisibilityManager.instance.IsPickingDisabled(targetGameObject, false)) |
||||
|
{ |
||||
|
DragAndDrop.PrepareStartDrag(); |
||||
|
DragAndDrop.objectReferences = new UnityEngine.Object[] {transform}; |
||||
|
DragAndDrop.StartDrag(ObjectNames.GetDragAndDropTitle(transform)); |
||||
|
|
||||
|
GUIUtility.hotControl = 0; |
||||
|
|
||||
|
evt.Use(); |
||||
|
} |
||||
|
} |
||||
|
break; |
||||
|
} |
||||
|
case EventType.MouseUp: |
||||
|
{ |
||||
|
if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2)) |
||||
|
{ |
||||
|
GUIUtility.hotControl = 0; |
||||
|
evt.Use(); |
||||
|
} |
||||
|
break; |
||||
|
} |
||||
|
case EventType.Repaint: |
||||
|
{ |
||||
|
Matrix4x4 matrix = GetEffectorMatrix(transform, style.position, style.rotation, style.size); |
||||
|
|
||||
|
Color highlight = style.color; |
||||
|
|
||||
|
bool hoveringEffector = GUIUtility.hotControl == 0 && HandleUtility.nearestControl == id; |
||||
|
hoveringEffector = hoveringEffector && |
||||
|
!SceneVisibilityManager.instance.IsPickingDisabled(transform.gameObject, false); |
||||
|
|
||||
|
if (hoveringEffector) |
||||
|
{ |
||||
|
highlight = Handles.preselectionColor; |
||||
|
} |
||||
|
else if (Selection.Contains(transform.gameObject) || Selection.activeObject == transform.gameObject) |
||||
|
{ |
||||
|
highlight = Handles.selectedColor; |
||||
|
} |
||||
|
|
||||
|
try |
||||
|
{ |
||||
|
Material mat = material; |
||||
|
|
||||
|
var shapeHighlight = MeshHasWireframeShapes(style.shape) ? style.color : highlight; |
||||
|
var wireHighlight = new Color(highlight.r, highlight.g, highlight.b, 1f); |
||||
|
|
||||
|
if (style.shape.subMeshCount > 0) |
||||
|
{ |
||||
|
// Draw every sub meshes separately to control highlight vs shape colors.
|
||||
|
for (int i = 0; i < style.shape.subMeshCount; ++i) |
||||
|
{ |
||||
|
MeshTopology topology = style.shape.GetTopology(i); |
||||
|
bool isFilled = (topology == MeshTopology.Triangles || topology == MeshTopology.Quads); |
||||
|
|
||||
|
mat.SetColor("_Color", isFilled ? shapeHighlight : wireHighlight); |
||||
|
mat.SetPass(0); |
||||
|
|
||||
|
Graphics.DrawMeshNow(style.shape, matrix, i); |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
MeshTopology topology = style.shape.GetTopology(0); |
||||
|
bool isFilled = (topology == MeshTopology.Triangles || topology == MeshTopology.Quads); |
||||
|
|
||||
|
mat.SetColor("_Color", isFilled ? shapeHighlight : wireHighlight); |
||||
|
mat.SetPass(0); |
||||
|
|
||||
|
Graphics.DrawMeshNow(style.shape, matrix); |
||||
|
} |
||||
|
} |
||||
|
catch (Exception exception) |
||||
|
{ |
||||
|
Debug.LogException(exception); |
||||
|
} |
||||
|
} |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private bool FindMeshTopology(Mesh shape, IEnumerable<MeshTopology> topologies) |
||||
|
{ |
||||
|
if (shape.subMeshCount > 0) |
||||
|
{ |
||||
|
for (int i = 0; i < shape.subMeshCount; ++i) |
||||
|
{ |
||||
|
MeshTopology topology = shape.GetTopology(i); |
||||
|
foreach (var topologyQuery in topologies) |
||||
|
{ |
||||
|
if (topologyQuery == topology) |
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
var topology = shape.GetTopology(0); |
||||
|
foreach (var topologyQuery in topologies) |
||||
|
{ |
||||
|
if (topologyQuery == topology) |
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
private bool MeshHasFilledShapes(Mesh shape) => |
||||
|
FindMeshTopology(shape, new MeshTopology[] {MeshTopology.Triangles, MeshTopology.Quads}); |
||||
|
|
||||
|
private bool MeshHasWireframeShapes(Mesh shape) => |
||||
|
FindMeshTopology(shape, new MeshTopology[] {MeshTopology.Lines, MeshTopology.LineStrip}); |
||||
|
|
||||
|
private Matrix4x4 GetEffectorMatrix(Transform transform, Vector3 position, Vector3 rotation, float size) |
||||
|
{ |
||||
|
return Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one) * Matrix4x4.TRS(position, Quaternion.Euler(rotation), new Vector3(size, size, size)); |
||||
|
} |
||||
|
|
||||
|
private float DistanceToEffector(Transform transform, Mesh shape, Vector3 position, Vector3 rotation, float size) |
||||
|
{ |
||||
|
Matrix4x4 matrix = GetEffectorMatrix(transform, position, rotation, size); |
||||
|
Vector3 origin = matrix.MultiplyPoint(Vector3.zero); |
||||
|
|
||||
|
if (shape == null) |
||||
|
return HandleUtility.DistanceToCircle(origin, size * 0.5f); |
||||
|
|
||||
|
if (MeshHasFilledShapes(shape)) |
||||
|
{ |
||||
|
var bounds = shape.bounds; |
||||
|
var extents = Mathf.Max( Mathf.Max(bounds.extents.x, bounds.extents.y), bounds.extents.z); |
||||
|
return HandleUtility.DistanceToCircle(origin + bounds.center * size, extents * size); |
||||
|
} |
||||
|
|
||||
|
float nearestDistance = Mathf.Infinity; |
||||
|
|
||||
|
Vector3[] vertices = shape.vertices; |
||||
|
|
||||
|
for (int i = 0; i < shape.subMeshCount; ++i) |
||||
|
{ |
||||
|
MeshTopology topology = shape.GetTopology(i); |
||||
|
if (topology == MeshTopology.Lines) |
||||
|
{ |
||||
|
int[] indices = shape.GetIndices(i); |
||||
|
|
||||
|
int count = 0; |
||||
|
while (count < indices.Length) |
||||
|
{ |
||||
|
float d = HandleUtility.DistanceToLine(matrix.MultiplyPoint(vertices[indices[count]]), matrix.MultiplyPoint(vertices[indices[count+1]])); |
||||
|
if (d < nearestDistance) |
||||
|
nearestDistance = d; |
||||
|
|
||||
|
count += 2; |
||||
|
} |
||||
|
} |
||||
|
else if (topology == MeshTopology.LineStrip) |
||||
|
{ |
||||
|
int[] indices = shape.GetIndices(i); |
||||
|
|
||||
|
if (indices.Length > 0) |
||||
|
{ |
||||
|
int count = 0; |
||||
|
float d = 0f; |
||||
|
Vector3 v0 = matrix.MultiplyPoint(vertices[indices[count]]); |
||||
|
Vector3 v1 = v0; |
||||
|
|
||||
|
while (++count < indices.Length) |
||||
|
{ |
||||
|
Vector3 v2 = matrix.MultiplyPoint(vertices[indices[count]]); |
||||
|
|
||||
|
d = HandleUtility.DistanceToLine(v1, v2); |
||||
|
if (d < nearestDistance) |
||||
|
nearestDistance = d; |
||||
|
|
||||
|
v1 = v2; |
||||
|
} |
||||
|
|
||||
|
d = HandleUtility.DistanceToLine(v1, v0); |
||||
|
if (d < nearestDistance) |
||||
|
nearestDistance = d; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return nearestDistance; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: ff03b96c5bd3745c28814ed6eb4341cb |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,190 @@ |
|||||
|
using UnityEngine; |
||||
|
using UnityEngine.Animations.Rigging; |
||||
|
|
||||
|
namespace UnityEditor.Animations.Rigging |
||||
|
{ |
||||
|
[CustomOverlay(typeof(RigEffector))] |
||||
|
class RigEffectorOverlay : IRigEffectorOverlay |
||||
|
{ |
||||
|
private Object[] m_TargetObjects; |
||||
|
private SerializedObject m_SerializedObject; |
||||
|
|
||||
|
private SerializedProperty m_Visible; |
||||
|
private SerializedProperty m_Shape; |
||||
|
private SerializedProperty m_Color; |
||||
|
private SerializedProperty m_Size; |
||||
|
private SerializedProperty m_Position; |
||||
|
private SerializedProperty m_Rotation; |
||||
|
|
||||
|
private bool m_ExpandOverlay; |
||||
|
|
||||
|
private static GUIContent s_VisibleLabel = new GUIContent("Visible"); |
||||
|
private static GUIContent s_ShapeLabel = new GUIContent("Shape"); |
||||
|
private static GUIContent s_ColorLabel = new GUIContent("Color"); |
||||
|
private static GUIContent s_SizeLabel = new GUIContent("Size"); |
||||
|
private static GUIContent s_PositionLabel = new GUIContent("Position"); |
||||
|
private static GUIContent s_RotationLabel = new GUIContent("Rotation"); |
||||
|
|
||||
|
private static GUIContent s_RemoveLabel = new GUIContent("Remove"); |
||||
|
|
||||
|
private static string s_ExpandOverlayPrefKey = "AnimationRigging.ExpandOverlay"; |
||||
|
|
||||
|
private static GUILayoutOption s_FixedWidth = GUILayout.Width(210f); |
||||
|
|
||||
|
public void Initialize(Object[] effectors) |
||||
|
{ |
||||
|
m_TargetObjects = effectors; |
||||
|
m_SerializedObject = new SerializedObject(effectors); |
||||
|
|
||||
|
SerializedProperty data = m_SerializedObject.FindProperty("m_Data"); |
||||
|
|
||||
|
m_Visible = data.FindPropertyRelative("m_Visible"); |
||||
|
|
||||
|
SerializedProperty style = data.FindPropertyRelative("m_Style"); |
||||
|
|
||||
|
m_Shape = style.FindPropertyRelative("shape"); |
||||
|
m_Color = style.FindPropertyRelative("color"); |
||||
|
m_Size = style.FindPropertyRelative("size"); |
||||
|
m_Position = style.FindPropertyRelative("position"); |
||||
|
m_Rotation = style.FindPropertyRelative("rotation"); |
||||
|
|
||||
|
m_ExpandOverlay = EditorPrefs.GetBool(s_ExpandOverlayPrefKey, true); |
||||
|
} |
||||
|
|
||||
|
private IRigEffectorHolder FetchRigEffectorHolder(Transform transform) |
||||
|
{ |
||||
|
var rigBuilder = EditorHelper.GetClosestComponent<RigBuilder>(transform); |
||||
|
var rig = EditorHelper.GetClosestComponent<Rig>(transform, (rigBuilder != null) ? rigBuilder.transform : null); |
||||
|
|
||||
|
if (rigBuilder.ContainsEffector(transform)) |
||||
|
{ |
||||
|
return rigBuilder; |
||||
|
} |
||||
|
else if (rig.ContainsEffector(transform)) |
||||
|
{ |
||||
|
return rig; |
||||
|
} |
||||
|
|
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
public bool IsValid() => m_SerializedObject.targetObject != null; |
||||
|
|
||||
|
public void OnSceneGUIOverlay() |
||||
|
{ |
||||
|
if (!IsValid()) |
||||
|
return; |
||||
|
|
||||
|
m_SerializedObject.Update(); |
||||
|
|
||||
|
GameObject targetGameObject = null; |
||||
|
if (!m_SerializedObject.isEditingMultipleObjects) |
||||
|
{ |
||||
|
RigEffector rigEffector = m_SerializedObject.targetObject as RigEffector; |
||||
|
if (rigEffector != null && rigEffector.transform != null) |
||||
|
{ |
||||
|
targetGameObject = rigEffector.transform.gameObject; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
GUILayout.BeginHorizontal(s_FixedWidth); |
||||
|
|
||||
|
EditorGUI.BeginChangeCheck(); |
||||
|
m_ExpandOverlay = EditorGUILayout.Toggle(m_ExpandOverlay, EditorStyles.foldout, GUILayout.Width(12)); |
||||
|
if (EditorGUI.EndChangeCheck()) |
||||
|
{ |
||||
|
EditorPrefs.SetBool(s_ExpandOverlayPrefKey, m_ExpandOverlay); |
||||
|
} |
||||
|
|
||||
|
GUILayout.BeginHorizontal(EditorStyles.toolbar); |
||||
|
|
||||
|
EditorGUILayout.PropertyField(m_Visible, GUIContent.none, GUILayout.Width(17)); |
||||
|
|
||||
|
GUILayout.Label((targetGameObject != null) ? targetGameObject.name : "(Multiple objects)"); |
||||
|
|
||||
|
if (GUILayout.Button(GUIContent.none, "OL Minus", GUILayout.Width(17))) |
||||
|
{ |
||||
|
UnityEngine.Object[] targetObjects = m_SerializedObject.targetObjects; |
||||
|
foreach(var targetObject in targetObjects) |
||||
|
{ |
||||
|
var effector = targetObject as IRigEffector; |
||||
|
Transform transform = effector.transform; |
||||
|
|
||||
|
IRigEffectorHolder holder = FetchRigEffectorHolder(transform); |
||||
|
if (holder != null) |
||||
|
{ |
||||
|
var holderObject = holder as UnityEngine.Object; |
||||
|
|
||||
|
Undo.RecordObject(holderObject, "Remove Effector"); |
||||
|
|
||||
|
if (PrefabUtility.IsPartOfPrefabInstance(holderObject)) |
||||
|
EditorUtility.SetDirty(holderObject); |
||||
|
|
||||
|
holder.RemoveEffector(transform); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
GUILayout.EndHorizontal(); |
||||
|
GUILayout.EndHorizontal(); |
||||
|
|
||||
|
if (m_ExpandOverlay) |
||||
|
{ |
||||
|
EditorGUILayout.LabelField(s_ShapeLabel, s_FixedWidth); |
||||
|
EditorGUILayout.PropertyField(m_Shape, GUIContent.none, s_FixedWidth); |
||||
|
|
||||
|
Rect rect = GUILayoutUtility.GetRect(s_ColorLabel, EditorStyles.colorField, s_FixedWidth); |
||||
|
|
||||
|
// Shenanigans to bypass color picker bug.
|
||||
|
var evt = Event.current; |
||||
|
if (evt.type == EventType.MouseUp) |
||||
|
{ |
||||
|
if (rect.Contains(evt.mousePosition)) |
||||
|
{ |
||||
|
GUIUtility.hotControl = 0; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
EditorGUI.BeginProperty(rect, s_ColorLabel, m_Color); |
||||
|
EditorGUI.BeginChangeCheck(); |
||||
|
Color newColor = EditorGUI.ColorField(rect, s_ColorLabel, m_Color.colorValue, false, true, false); |
||||
|
if (EditorGUI.EndChangeCheck()) |
||||
|
{ |
||||
|
m_Color.colorValue = newColor; |
||||
|
} |
||||
|
EditorGUI.EndProperty(); |
||||
|
|
||||
|
EditorGUILayout.PropertyField(m_Size, s_SizeLabel, s_FixedWidth); |
||||
|
EditorGUILayout.PropertyField(m_Position, s_PositionLabel, s_FixedWidth); |
||||
|
EditorGUILayout.PropertyField(m_Rotation, s_RotationLabel, s_FixedWidth); |
||||
|
} |
||||
|
|
||||
|
if (m_SerializedObject.hasModifiedProperties) |
||||
|
{ |
||||
|
UnityEngine.Object[] targetObjects = m_SerializedObject.targetObjects; |
||||
|
foreach(var targetObject in targetObjects) |
||||
|
{ |
||||
|
var effector = targetObject as IRigEffector; |
||||
|
Transform transform = effector.transform; |
||||
|
|
||||
|
IRigEffectorHolder holder = FetchRigEffectorHolder(transform); |
||||
|
if (holder != null) |
||||
|
{ |
||||
|
var holderObject = holder as UnityEngine.Object; |
||||
|
Undo.RecordObject(holderObject, "Edit Effector"); |
||||
|
|
||||
|
if (PrefabUtility.IsPartOfPrefabInstance(holderObject)) |
||||
|
EditorUtility.SetDirty(holderObject); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
m_SerializedObject.ApplyModifiedProperties(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public void Dispose() |
||||
|
{ |
||||
|
m_SerializedObject?.Dispose(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 128d92bb7c7e949569b14ae35b4b229e |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,235 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using UnityEngine; |
||||
|
using UnityEngine.Animations.Rigging; |
||||
|
#if SUPPORTS_SCENE_VIEW_OVERLAYS
|
||||
|
using UnityEditor.Overlays; |
||||
|
#endif
|
||||
|
using UnityEditor.Experimental.SceneManagement; // required for 2020.2
|
||||
|
using UnityEditor.SceneManagement; |
||||
|
|
||||
|
namespace UnityEditor.Animations.Rigging |
||||
|
{ |
||||
|
[InitializeOnLoad] |
||||
|
static class RigEffectorRenderer |
||||
|
{ |
||||
|
const string k_OverlayId = "Scene View/Animation Rigging"; |
||||
|
const string k_DisplayName = "Animation Rigging"; |
||||
|
|
||||
|
static GUIContent s_OverlayTitle = new GUIContent(k_DisplayName); |
||||
|
|
||||
|
static List<RigBuilder> s_RigBuilders = new List<RigBuilder>(); |
||||
|
static Dictionary<RigEffectorData, RigEffector> s_Effectors = new Dictionary<RigEffectorData, RigEffector>(); |
||||
|
|
||||
|
static Transform[] s_ActiveSelection = null; |
||||
|
static List<RigEffector> s_ActiveEffectors = null; |
||||
|
static IRigEffectorOverlay s_ActiveOverlay = null; |
||||
|
|
||||
|
static bool s_ActiveOverlayDirtied = true; |
||||
|
|
||||
|
static RigEffectorRenderer() |
||||
|
{ |
||||
|
RigBuilder.onAddRigBuilder += OnAddRigBuilder; |
||||
|
RigBuilder.onRemoveRigBuilder += OnRemoveRigBuilder; |
||||
|
|
||||
|
SceneView.duringSceneGui += OnSceneGUI; |
||||
|
Selection.selectionChanged += OnSelectionChange; |
||||
|
ObjectFactory.componentWasAdded += OnComponentAdded; |
||||
|
} |
||||
|
|
||||
|
static void OnSelectionChange() |
||||
|
{ |
||||
|
s_ActiveOverlayDirtied = true; |
||||
|
} |
||||
|
|
||||
|
static void OnComponentAdded(Component component) |
||||
|
{ |
||||
|
if (!(component is Rig) && !(component is RigBuilder)) |
||||
|
return; |
||||
|
|
||||
|
s_ActiveOverlayDirtied = true; |
||||
|
} |
||||
|
|
||||
|
static void FetchOrCreateEffectors(IRigEffectorHolder holder) |
||||
|
{ |
||||
|
foreach(var effectorData in holder.effectors) |
||||
|
{ |
||||
|
if (s_Effectors.ContainsKey(effectorData)) |
||||
|
{ |
||||
|
s_ActiveEffectors.Add(s_Effectors[effectorData]); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
var newEffector = ScriptableObject.CreateInstance<RigEffector>(); |
||||
|
newEffector.Initialize(effectorData); |
||||
|
|
||||
|
s_Effectors.Add(effectorData, newEffector); |
||||
|
s_ActiveEffectors.Add(newEffector); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
static void FetchOrCreateEffectors() |
||||
|
{ |
||||
|
s_ActiveEffectors = new List<RigEffector>(); |
||||
|
|
||||
|
PrefabStage prefabStage = PrefabStageUtility.GetCurrentPrefabStage(); |
||||
|
|
||||
|
for (int i = 0; i < s_RigBuilders.Count; i++) |
||||
|
{ |
||||
|
var rigBuilder = s_RigBuilders[i]; |
||||
|
|
||||
|
if (rigBuilder == null) |
||||
|
continue; |
||||
|
|
||||
|
if (prefabStage != null) |
||||
|
{ |
||||
|
StageHandle stageHandle = prefabStage.stageHandle; |
||||
|
if (stageHandle.IsValid() && !stageHandle.Contains(rigBuilder.gameObject)) |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
FetchOrCreateEffectors(rigBuilder); |
||||
|
|
||||
|
var rigs = rigBuilder.GetComponentsInChildren<Rig>(); |
||||
|
if (rigs != null) |
||||
|
{ |
||||
|
foreach(var rig in rigs) |
||||
|
{ |
||||
|
FetchOrCreateEffectors(rig); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
static IRigEffectorOverlay FetchOrCreateEffectorOverlay() |
||||
|
{ |
||||
|
if (!s_ActiveOverlayDirtied && s_ActiveOverlay != null && s_ActiveOverlay.IsValid()) |
||||
|
return s_ActiveOverlay; |
||||
|
|
||||
|
s_ActiveOverlay?.Dispose(); |
||||
|
|
||||
|
Transform[] transforms = Selection.GetTransforms(SelectionMode.ExcludePrefab | SelectionMode.Editable); |
||||
|
var inspectedEffectors = new List<Object>(); |
||||
|
|
||||
|
for (int i = 0; i < s_ActiveEffectors.Count; ++i) |
||||
|
{ |
||||
|
var effector = s_ActiveEffectors[i]; |
||||
|
if (effector != null && effector.transform != null) |
||||
|
{ |
||||
|
if (Selection.Contains(effector.transform) || Selection.Contains(effector.transform.gameObject)) |
||||
|
{ |
||||
|
inspectedEffectors.Add(s_ActiveEffectors[i]); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (inspectedEffectors.Count > 0) |
||||
|
{ |
||||
|
var overlay = new RigEffectorOverlay(); |
||||
|
overlay.Initialize(inspectedEffectors.ToArray()); |
||||
|
|
||||
|
s_ActiveOverlay = overlay; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
RigEffectorWizard wizard = null; |
||||
|
|
||||
|
foreach(var transform in transforms) |
||||
|
{ |
||||
|
RigBuilder rigBuilder = EditorHelper.GetClosestComponent<RigBuilder>(transform); |
||||
|
Rig rig = EditorHelper.GetClosestComponent<Rig>(transform, (rigBuilder != null) ? rigBuilder.transform : null); |
||||
|
IRigEffectorHolder holder = (rig != null) ? (IRigEffectorHolder)rig : (IRigEffectorHolder)rigBuilder; |
||||
|
|
||||
|
if (holder == null) |
||||
|
continue; |
||||
|
|
||||
|
if (wizard == null) |
||||
|
wizard = new RigEffectorWizard(); |
||||
|
|
||||
|
wizard.Add(holder, transform); |
||||
|
} |
||||
|
|
||||
|
if (wizard != null) |
||||
|
{ |
||||
|
s_ActiveOverlay = wizard; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
s_ActiveOverlay = null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
s_ActiveSelection = transforms; |
||||
|
|
||||
|
s_ActiveOverlayDirtied = false; |
||||
|
return s_ActiveOverlay; |
||||
|
} |
||||
|
|
||||
|
static void OnSceneGUI(SceneView sceneView) |
||||
|
{ |
||||
|
// Fetch effectors and overlay once in Layout before processing events.
|
||||
|
if (Event.current.type == EventType.Layout) |
||||
|
{ |
||||
|
FetchOrCreateEffectors(); |
||||
|
FetchOrCreateEffectorOverlay(); |
||||
|
} |
||||
|
|
||||
|
// Process effector events.
|
||||
|
if (s_ActiveEffectors != null) |
||||
|
{ |
||||
|
for (int i = 0; i < s_ActiveEffectors.Count; ++i) |
||||
|
{ |
||||
|
var effector = s_ActiveEffectors[i]; |
||||
|
if (effector == null) |
||||
|
continue; |
||||
|
|
||||
|
effector.OnSceneGUI(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
#if !SUPPORTS_SCENE_VIEW_OVERLAYS
|
||||
|
// Process overlay events.
|
||||
|
if (s_ActiveOverlay != null) |
||||
|
{ |
||||
|
SceneViewOverlay.Begin(sceneView); |
||||
|
SceneViewOverlay.Window(s_OverlayTitle, SceneViewGUICallback, 1200); |
||||
|
SceneViewOverlay.End(); |
||||
|
} |
||||
|
#endif
|
||||
|
} |
||||
|
|
||||
|
static void OnAddRigBuilder(RigBuilder rigBuilder) |
||||
|
{ |
||||
|
s_RigBuilders.Add(rigBuilder); |
||||
|
} |
||||
|
|
||||
|
static void OnRemoveRigBuilder(RigBuilder rigBuilder) |
||||
|
{ |
||||
|
s_RigBuilders.Remove(rigBuilder); |
||||
|
s_Effectors.Clear(); |
||||
|
} |
||||
|
|
||||
|
private static void SceneViewGUICallback(UnityEngine.Object target, SceneView sceneView) |
||||
|
{ |
||||
|
if (s_ActiveOverlay != null) |
||||
|
s_ActiveOverlay.OnSceneGUIOverlay(); |
||||
|
} |
||||
|
|
||||
|
#if SUPPORTS_SCENE_VIEW_OVERLAYS
|
||||
|
[Overlay(typeof(SceneView), k_OverlayId, k_DisplayName)] |
||||
|
class Overlay : IMGUIOverlay, ITransientOverlay |
||||
|
{ |
||||
|
public bool visible |
||||
|
{ |
||||
|
get => s_ActiveOverlay != null; |
||||
|
} |
||||
|
|
||||
|
public override void OnGUI() |
||||
|
{ |
||||
|
if (s_ActiveOverlay != null) |
||||
|
s_ActiveOverlay.OnSceneGUIOverlay(); |
||||
|
} |
||||
|
} |
||||
|
#endif
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: aedff7ad35cc7477a9786519f4791c00 |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,68 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using UnityEngine; |
||||
|
using UnityEngine.Animations.Rigging; |
||||
|
|
||||
|
namespace UnityEditor.Animations.Rigging |
||||
|
{ |
||||
|
class RigEffectorWizard : IRigEffectorOverlay |
||||
|
{ |
||||
|
private static GUIContent s_CreateEffectorLabel = new GUIContent("Create Effector"); |
||||
|
|
||||
|
private struct HolderTransformPair |
||||
|
{ |
||||
|
public IRigEffectorHolder holder; |
||||
|
public Transform transform; |
||||
|
} |
||||
|
|
||||
|
private List<HolderTransformPair> m_Transforms = new List<HolderTransformPair>(); |
||||
|
|
||||
|
public void Add(IRigEffectorHolder holder, Transform transform) |
||||
|
{ |
||||
|
m_Transforms.Add(new HolderTransformPair() { holder = holder, transform = transform }); |
||||
|
} |
||||
|
|
||||
|
public bool IsValid() => true; |
||||
|
|
||||
|
public void OnSceneGUIOverlay() |
||||
|
{ |
||||
|
string labelName = "(no selection)"; |
||||
|
if (m_Transforms.Count > 1) |
||||
|
{ |
||||
|
labelName = "(Multiple objects)"; |
||||
|
} |
||||
|
else if (m_Transforms.Count > 0) |
||||
|
{ |
||||
|
if (m_Transforms[0].transform.gameObject != null) |
||||
|
{ |
||||
|
labelName = m_Transforms[0].transform.gameObject.name; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
GUILayout.BeginHorizontal(EditorStyles.toolbar, GUILayout.Width(210.0f)); |
||||
|
|
||||
|
GUILayout.Label(labelName); |
||||
|
|
||||
|
if (GUILayout.Button(GUIContent.none, "OL Plus", GUILayout.Width(17))) |
||||
|
{ |
||||
|
foreach (var pair in m_Transforms) |
||||
|
{ |
||||
|
var targetObject = pair.holder as UnityEngine.Object; |
||||
|
|
||||
|
Undo.RecordObject(targetObject, "Add Effector"); |
||||
|
|
||||
|
if (PrefabUtility.IsPartOfPrefabInstance(targetObject)) |
||||
|
EditorUtility.SetDirty(targetObject); |
||||
|
|
||||
|
pair.holder.AddEffector(pair.transform, RigEffector.defaultStyle); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
GUILayout.EndHorizontal(); |
||||
|
} |
||||
|
|
||||
|
public void Dispose() |
||||
|
{ |
||||
|
// nothing to do.
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 51459fd0b87be44cbb33be7842186a5e |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,8 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 756c4b6dd3c75480781e03b559e98355 |
||||
|
folderAsset: yes |
||||
|
DefaultImporter: |
||||
|
externalObjects: {} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
|
After Width: 128 | Height: 128 | Size: 5.9 KiB |
@ -0,0 +1,120 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: ca41524ec86f0d84ab5675c9622cc1a2 |
||||
|
TextureImporter: |
||||
|
internalIDToNameTable: [] |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 11 |
||||
|
mipmaps: |
||||
|
mipMapMode: 0 |
||||
|
enableMipMap: 1 |
||||
|
sRGBTexture: 1 |
||||
|
linearTexture: 0 |
||||
|
fadeOut: 0 |
||||
|
borderMipMap: 0 |
||||
|
mipMapsPreserveCoverage: 0 |
||||
|
alphaTestReferenceValue: 0.5 |
||||
|
mipMapFadeDistanceStart: 1 |
||||
|
mipMapFadeDistanceEnd: 3 |
||||
|
bumpmap: |
||||
|
convertToNormalMap: 0 |
||||
|
externalNormalMap: 0 |
||||
|
heightScale: 0.25 |
||||
|
normalMapFilter: 0 |
||||
|
isReadable: 0 |
||||
|
streamingMipmaps: 0 |
||||
|
streamingMipmapsPriority: 0 |
||||
|
vTOnly: 0 |
||||
|
grayScaleToAlpha: 0 |
||||
|
generateCubemap: 6 |
||||
|
cubemapConvolution: 0 |
||||
|
seamlessCubemap: 0 |
||||
|
textureFormat: 1 |
||||
|
maxTextureSize: 2048 |
||||
|
textureSettings: |
||||
|
serializedVersion: 2 |
||||
|
filterMode: 1 |
||||
|
aniso: 0 |
||||
|
mipBias: 0 |
||||
|
wrapU: 1 |
||||
|
wrapV: 1 |
||||
|
wrapW: 1 |
||||
|
nPOTScale: 0 |
||||
|
lightmap: 0 |
||||
|
compressionQuality: 50 |
||||
|
spriteMode: 0 |
||||
|
spriteExtrude: 1 |
||||
|
spriteMeshType: 1 |
||||
|
alignment: 0 |
||||
|
spritePivot: {x: 0.5, y: 0.5} |
||||
|
spritePixelsToUnits: 100 |
||||
|
spriteBorder: {x: 0, y: 0, z: 0, w: 0} |
||||
|
spriteGenerateFallbackPhysicsShape: 1 |
||||
|
alphaUsage: 1 |
||||
|
alphaIsTransparency: 1 |
||||
|
spriteTessellationDetail: -1 |
||||
|
textureType: 2 |
||||
|
textureShape: 1 |
||||
|
singleChannelComponent: 0 |
||||
|
flipbookRows: 1 |
||||
|
flipbookColumns: 1 |
||||
|
maxTextureSizeSet: 0 |
||||
|
compressionQualitySet: 0 |
||||
|
textureFormatSet: 0 |
||||
|
ignorePngGamma: 0 |
||||
|
applyGammaDecoding: 1 |
||||
|
platformSettings: |
||||
|
- serializedVersion: 3 |
||||
|
buildTarget: DefaultTexturePlatform |
||||
|
maxTextureSize: 2048 |
||||
|
resizeAlgorithm: 0 |
||||
|
textureFormat: -1 |
||||
|
textureCompression: 0 |
||||
|
compressionQuality: 50 |
||||
|
crunchedCompression: 0 |
||||
|
allowsAlphaSplitting: 0 |
||||
|
overridden: 0 |
||||
|
androidETC2FallbackOverride: 0 |
||||
|
forceMaximumCompressionQuality_BC6H_BC7: 0 |
||||
|
- serializedVersion: 3 |
||||
|
buildTarget: Standalone |
||||
|
maxTextureSize: 2048 |
||||
|
resizeAlgorithm: 0 |
||||
|
textureFormat: -1 |
||||
|
textureCompression: 0 |
||||
|
compressionQuality: 50 |
||||
|
crunchedCompression: 0 |
||||
|
allowsAlphaSplitting: 0 |
||||
|
overridden: 0 |
||||
|
androidETC2FallbackOverride: 0 |
||||
|
forceMaximumCompressionQuality_BC6H_BC7: 0 |
||||
|
- serializedVersion: 3 |
||||
|
buildTarget: WebGL |
||||
|
maxTextureSize: 2048 |
||||
|
resizeAlgorithm: 0 |
||||
|
textureFormat: -1 |
||||
|
textureCompression: 0 |
||||
|
compressionQuality: 50 |
||||
|
crunchedCompression: 0 |
||||
|
allowsAlphaSplitting: 0 |
||||
|
overridden: 0 |
||||
|
androidETC2FallbackOverride: 0 |
||||
|
forceMaximumCompressionQuality_BC6H_BC7: 0 |
||||
|
spriteSheet: |
||||
|
serializedVersion: 2 |
||||
|
sprites: [] |
||||
|
outline: [] |
||||
|
physicsShape: [] |
||||
|
bones: [] |
||||
|
spriteID: |
||||
|
internalID: 0 |
||||
|
vertices: [] |
||||
|
indices: |
||||
|
edges: [] |
||||
|
weights: [] |
||||
|
secondaryTextures: [] |
||||
|
spritePackingTag: |
||||
|
pSDRemoveMatte: 0 |
||||
|
pSDShowRemoveMatteOption: 0 |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,8 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: afac13c76cd0741e4b5af60059fba0e8 |
||||
|
folderAsset: yes |
||||
|
DefaultImporter: |
||||
|
externalObjects: {} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,8 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: f72a409037e7942fc86acf5dcd9f4716 |
||||
|
folderAsset: yes |
||||
|
DefaultImporter: |
||||
|
externalObjects: {} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,130 @@ |
|||||
|
using Unity.Collections; |
||||
|
using UnityEngine; |
||||
|
using UnityEngine.Animations; |
||||
|
using UnityEngine.Animations.Rigging; |
||||
|
|
||||
|
namespace UnityEditor.Animations.Rigging |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The MultiAim inverse constraint job.
|
||||
|
/// </summary>
|
||||
|
[Unity.Burst.BurstCompile] |
||||
|
public struct MultiAimInverseConstraintJob : IWeightedAnimationJob |
||||
|
{ |
||||
|
const float k_Epsilon = 1e-5f; |
||||
|
|
||||
|
/// <summary>The Transform handle for the constrained object Transform.</summary>
|
||||
|
public ReadOnlyTransformHandle driven; |
||||
|
/// <summary>The Transform handle for the constrained object parent Transform.</summary>
|
||||
|
public ReadOnlyTransformHandle drivenParent; |
||||
|
/// <summary>The post-rotation offset applied to the constrained object.</summary>
|
||||
|
public Vector3Property drivenOffset; |
||||
|
|
||||
|
/// <summary>List of Transform handles for the source objects.</summary>
|
||||
|
public NativeArray<ReadWriteTransformHandle> sourceTransforms; |
||||
|
/// <summary>List of weights for the source objects.</summary>
|
||||
|
public NativeArray<PropertyStreamHandle> sourceWeights; |
||||
|
/// <summary>List of offsets to apply to source rotations if maintainOffset is enabled.</summary>
|
||||
|
public NativeArray<Quaternion> sourceOffsets; |
||||
|
|
||||
|
/// <summary>Buffer used to store weights during job execution.</summary>
|
||||
|
public NativeArray<float> weightBuffer; |
||||
|
|
||||
|
/// <summary>Local axis of the constrained object Transform.</summary>
|
||||
|
public Vector3 aimAxis; |
||||
|
|
||||
|
/// <inheritdoc />
|
||||
|
public FloatProperty jobWeight { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Defines what to do when processing the root motion.
|
||||
|
/// </summary>
|
||||
|
/// <param name="stream">The animation stream to work on.</param>
|
||||
|
public void ProcessRootMotion(AnimationStream stream) { } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Defines what to do when processing the animation.
|
||||
|
/// </summary>
|
||||
|
/// <param name="stream">The animation stream to work on.</param>
|
||||
|
public void ProcessAnimation(AnimationStream stream) |
||||
|
{ |
||||
|
jobWeight.Set(stream, 1f); |
||||
|
|
||||
|
var lRot = driven.GetLocalRotation(stream); |
||||
|
var offset = drivenOffset.Get(stream); |
||||
|
|
||||
|
if (Vector3.Dot(offset, offset) > 0f) |
||||
|
lRot *= Quaternion.Inverse(Quaternion.Euler(offset)); |
||||
|
|
||||
|
var localToWorld = Quaternion.identity; |
||||
|
var wPos = driven.GetPosition(stream); |
||||
|
if (drivenParent.IsValid(stream)) |
||||
|
localToWorld = drivenParent.GetRotation(stream); |
||||
|
|
||||
|
for (int i = 0; i < sourceTransforms.Length; ++i) |
||||
|
{ |
||||
|
sourceWeights[i].SetFloat(stream, 1f); |
||||
|
|
||||
|
var sourceTransform = sourceTransforms[i]; |
||||
|
|
||||
|
sourceTransform.SetPosition(stream, wPos + localToWorld * sourceOffsets[i] * lRot * aimAxis); |
||||
|
|
||||
|
// Required to update handles with binding info.
|
||||
|
sourceTransforms[i] = sourceTransform; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// The MultiAim inverse constraint job binder.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="T">The constraint data type</typeparam>
|
||||
|
public class MultiAimInverseConstraintJobBinder<T> : AnimationJobBinder<MultiAimInverseConstraintJob, T> |
||||
|
where T : struct, IAnimationJobData, IMultiAimConstraintData |
||||
|
{ |
||||
|
/// <inheritdoc />
|
||||
|
public override MultiAimInverseConstraintJob Create(Animator animator, ref T data, Component component) |
||||
|
{ |
||||
|
var job = new MultiAimInverseConstraintJob(); |
||||
|
|
||||
|
job.driven = ReadOnlyTransformHandle.Bind(animator, data.constrainedObject); |
||||
|
job.drivenParent = ReadOnlyTransformHandle.Bind(animator, data.constrainedObject.parent); |
||||
|
job.drivenOffset = Vector3Property.Bind(animator, component, data.offsetVector3Property); |
||||
|
job.aimAxis = data.aimAxis; |
||||
|
|
||||
|
WeightedTransformArray sourceObjects = data.sourceObjects; |
||||
|
|
||||
|
WeightedTransformArrayBinder.BindReadWriteTransforms(animator, component, sourceObjects, out job.sourceTransforms); |
||||
|
WeightedTransformArrayBinder.BindWeights(animator, component, sourceObjects, data.sourceObjectsProperty, out job.sourceWeights); |
||||
|
|
||||
|
job.sourceOffsets = new NativeArray<Quaternion>(sourceObjects.Count, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); |
||||
|
for (int i = 0; i < sourceObjects.Count; ++i) |
||||
|
{ |
||||
|
if (data.maintainOffset) |
||||
|
{ |
||||
|
var aimDirection = data.constrainedObject.rotation * data.aimAxis; |
||||
|
var dataToSource = sourceObjects[i].transform.position - data.constrainedObject.position; |
||||
|
var rot = QuaternionExt.FromToRotation(dataToSource, aimDirection); |
||||
|
job.sourceOffsets[i] = Quaternion.Inverse(rot); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
job.sourceOffsets[i] = Quaternion.identity; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
job.weightBuffer = new NativeArray<float>(sourceObjects.Count, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); |
||||
|
|
||||
|
return job; |
||||
|
} |
||||
|
|
||||
|
/// <inheritdoc />
|
||||
|
public override void Destroy(MultiAimInverseConstraintJob job) |
||||
|
{ |
||||
|
job.sourceTransforms.Dispose(); |
||||
|
job.sourceWeights.Dispose(); |
||||
|
job.sourceOffsets.Dispose(); |
||||
|
job.weightBuffer.Dispose(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 05face438934c204d87b0e772c7c0a71 |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,116 @@ |
|||||
|
using Unity.Collections; |
||||
|
using UnityEngine; |
||||
|
using UnityEngine.Animations; |
||||
|
using UnityEngine.Animations.Rigging; |
||||
|
|
||||
|
namespace UnityEditor.Animations.Rigging |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The MultiParent inverse constraint job.
|
||||
|
/// </summary>
|
||||
|
[Unity.Burst.BurstCompile] |
||||
|
public struct MultiParentInverseConstraintJob : IWeightedAnimationJob |
||||
|
{ |
||||
|
const float k_Epsilon = 1e-5f; |
||||
|
|
||||
|
/// <summary>The Transform handle for the constrained object Transform.</summary>
|
||||
|
public ReadOnlyTransformHandle driven; |
||||
|
/// <summary>The Transform handle for the constrained object parent Transform.</summary>
|
||||
|
public ReadOnlyTransformHandle drivenParent; |
||||
|
|
||||
|
/// <summary>List of Transform handles for the source objects.</summary>
|
||||
|
public NativeArray<ReadWriteTransformHandle> sourceTransforms; |
||||
|
/// <summary>List of weights for the source objects.</summary>
|
||||
|
public NativeArray<PropertyStreamHandle> sourceWeights; |
||||
|
/// <summary>List of offsets to apply to source rotations if maintainOffset is enabled.</summary>
|
||||
|
public NativeArray<AffineTransform> sourceOffsets; |
||||
|
|
||||
|
/// <inheritdoc />
|
||||
|
public FloatProperty jobWeight { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Defines what to do when processing the root motion.
|
||||
|
/// </summary>
|
||||
|
/// <param name="stream">The animation stream to work on.</param>
|
||||
|
public void ProcessRootMotion(AnimationStream stream) { } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Defines what to do when processing the animation.
|
||||
|
/// </summary>
|
||||
|
/// <param name="stream">The animation stream to work on.</param>
|
||||
|
public void ProcessAnimation(AnimationStream stream) |
||||
|
{ |
||||
|
jobWeight.Set(stream, 1f); |
||||
|
|
||||
|
driven.GetGlobalTR(stream, out Vector3 currentWPos, out Quaternion currentWRot); |
||||
|
var drivenTx = new AffineTransform(currentWPos, currentWRot); |
||||
|
|
||||
|
for (int i = 0; i < sourceTransforms.Length; ++i) |
||||
|
{ |
||||
|
sourceWeights[i].SetFloat(stream, 1f); |
||||
|
|
||||
|
var sourceTransform = sourceTransforms[i]; |
||||
|
sourceTransform.GetGlobalTR(stream, out var sourcePosition, out var sourceRotation); |
||||
|
|
||||
|
var result = drivenTx; |
||||
|
result *= sourceOffsets[i]; |
||||
|
|
||||
|
sourceTransform.SetGlobalTR(stream, result.translation, result.rotation); |
||||
|
sourceTransforms[i] = sourceTransform; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// The MultiParent inverse constraint job binder.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="T">The constraint data type</typeparam>
|
||||
|
public class MultiParentInverseConstraintJobBinder<T> : AnimationJobBinder<MultiParentInverseConstraintJob, T> |
||||
|
where T : struct, IAnimationJobData, IMultiParentConstraintData |
||||
|
{ |
||||
|
/// <inheritdoc />
|
||||
|
public override MultiParentInverseConstraintJob Create(Animator animator, ref T data, Component component) |
||||
|
{ |
||||
|
var job = new MultiParentInverseConstraintJob(); |
||||
|
|
||||
|
job.driven = ReadOnlyTransformHandle.Bind(animator, data.constrainedObject); |
||||
|
job.drivenParent = ReadOnlyTransformHandle.Bind(animator, data.constrainedObject.parent); |
||||
|
|
||||
|
WeightedTransformArray sourceObjects = data.sourceObjects; |
||||
|
|
||||
|
WeightedTransformArrayBinder.BindReadWriteTransforms(animator, component, sourceObjects, out job.sourceTransforms); |
||||
|
WeightedTransformArrayBinder.BindWeights(animator, component, sourceObjects, data.sourceObjectsProperty, out job.sourceWeights); |
||||
|
|
||||
|
job.sourceOffsets = new NativeArray<AffineTransform>(sourceObjects.Count, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); |
||||
|
|
||||
|
var drivenTx = new AffineTransform(data.constrainedObject.position, data.constrainedObject.rotation); |
||||
|
for (int i = 0; i < sourceObjects.Count; ++i) |
||||
|
{ |
||||
|
var sourceTransform = sourceObjects[i].transform; |
||||
|
|
||||
|
var srcTx = new AffineTransform(sourceTransform.position, sourceTransform.rotation); |
||||
|
var srcOffset = AffineTransform.identity; |
||||
|
var tmp = srcTx.InverseMul(drivenTx); |
||||
|
|
||||
|
if (data.maintainPositionOffset) |
||||
|
srcOffset.translation = tmp.translation; |
||||
|
if (data.maintainRotationOffset) |
||||
|
srcOffset.rotation = tmp.rotation; |
||||
|
|
||||
|
srcOffset = srcOffset.Inverse(); |
||||
|
|
||||
|
job.sourceOffsets[i] = srcOffset; |
||||
|
} |
||||
|
|
||||
|
return job; |
||||
|
} |
||||
|
|
||||
|
/// <inheritdoc />
|
||||
|
public override void Destroy(MultiParentInverseConstraintJob job) |
||||
|
{ |
||||
|
job.sourceTransforms.Dispose(); |
||||
|
job.sourceWeights.Dispose(); |
||||
|
job.sourceOffsets.Dispose(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 288c55302720e3e498d76fcd7909373d |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,116 @@ |
|||||
|
using Unity.Collections; |
||||
|
using UnityEngine; |
||||
|
using UnityEngine.Animations; |
||||
|
using UnityEngine.Animations.Rigging; |
||||
|
|
||||
|
namespace UnityEditor.Animations.Rigging |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The MultiPosition inverse constraint job.
|
||||
|
/// </summary>
|
||||
|
[Unity.Burst.BurstCompile] |
||||
|
public struct MultiPositionInverseConstraintJob : IWeightedAnimationJob |
||||
|
{ |
||||
|
const float k_Epsilon = 1e-5f; |
||||
|
|
||||
|
/// <summary>The Transform handle for the constrained object Transform.</summary>
|
||||
|
public ReadOnlyTransformHandle driven; |
||||
|
/// <summary>The Transform handle for the constrained object parent Transform.</summary>
|
||||
|
public ReadOnlyTransformHandle drivenParent; |
||||
|
/// <summary>The post-translation offset applied to the constrained object.</summary>
|
||||
|
public Vector3Property drivenOffset; |
||||
|
|
||||
|
/// <summary>List of Transform handles for the source objects.</summary>
|
||||
|
public NativeArray<ReadWriteTransformHandle> sourceTransforms; |
||||
|
/// <summary>List of weights for the source objects.</summary>
|
||||
|
public NativeArray<PropertyStreamHandle> sourceWeights; |
||||
|
/// <summary>List of offsets to apply to source rotations if maintainOffset is enabled.</summary>
|
||||
|
public NativeArray<Vector3> sourceOffsets; |
||||
|
|
||||
|
/// <inheritdoc />
|
||||
|
public FloatProperty jobWeight { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Defines what to do when processing the root motion.
|
||||
|
/// </summary>
|
||||
|
/// <param name="stream">The animation stream to work on.</param>
|
||||
|
public void ProcessRootMotion(AnimationStream stream) { } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Defines what to do when processing the animation.
|
||||
|
/// </summary>
|
||||
|
/// <param name="stream">The animation stream to work on.</param>
|
||||
|
public void ProcessAnimation(AnimationStream stream) |
||||
|
{ |
||||
|
jobWeight.Set(stream, 1f); |
||||
|
|
||||
|
var parentTx = new AffineTransform(); |
||||
|
if (drivenParent.IsValid(stream)) |
||||
|
{ |
||||
|
drivenParent.GetGlobalTR(stream, out Vector3 parentWPos, out Quaternion parentWRot); |
||||
|
parentTx = new AffineTransform(parentWPos, parentWRot); |
||||
|
} |
||||
|
|
||||
|
var drivenPos = driven.GetPosition(stream); |
||||
|
drivenPos = parentTx.InverseTransform(drivenPos); |
||||
|
|
||||
|
var offset = drivenOffset.Get(stream); |
||||
|
|
||||
|
var lPos = drivenPos - offset; |
||||
|
|
||||
|
var wPos = parentTx.Transform(lPos); |
||||
|
for (int i = 0; i < sourceTransforms.Length; ++i) |
||||
|
{ |
||||
|
sourceWeights[i].SetFloat(stream, 1f); |
||||
|
|
||||
|
ReadWriteTransformHandle sourceTransform = sourceTransforms[i]; |
||||
|
|
||||
|
sourceTransform.SetPosition(stream, wPos - sourceOffsets[i]); |
||||
|
|
||||
|
// Required to update handles with binding info.
|
||||
|
sourceTransforms[i] = sourceTransform; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// The MultiPosition inverse constraint job binder.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="T">The constraint data type</typeparam>
|
||||
|
public class MultiPositionInverseConstraintJobBinder<T> : AnimationJobBinder<MultiPositionInverseConstraintJob, T> |
||||
|
where T : struct, IAnimationJobData, IMultiPositionConstraintData |
||||
|
{ |
||||
|
/// <inheritdoc />
|
||||
|
public override MultiPositionInverseConstraintJob Create(Animator animator, ref T data, Component component) |
||||
|
{ |
||||
|
var job = new MultiPositionInverseConstraintJob(); |
||||
|
|
||||
|
job.driven = ReadOnlyTransformHandle.Bind(animator, data.constrainedObject); |
||||
|
job.drivenParent = ReadOnlyTransformHandle.Bind(animator, data.constrainedObject.parent); |
||||
|
job.drivenOffset = Vector3Property.Bind(animator, component, data.offsetVector3Property); |
||||
|
|
||||
|
WeightedTransformArray sourceObjects = data.sourceObjects; |
||||
|
|
||||
|
WeightedTransformArrayBinder.BindReadWriteTransforms(animator, component, sourceObjects, out job.sourceTransforms); |
||||
|
WeightedTransformArrayBinder.BindWeights(animator, component, sourceObjects, data.sourceObjectsProperty, out job.sourceWeights); |
||||
|
|
||||
|
job.sourceOffsets = new NativeArray<Vector3>(sourceObjects.Count, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); |
||||
|
|
||||
|
Vector3 drivenPos = data.constrainedObject.position; |
||||
|
for (int i = 0; i < sourceObjects.Count; ++i) |
||||
|
{ |
||||
|
job.sourceOffsets[i] = data.maintainOffset ? (drivenPos - sourceObjects[i].transform.position) : Vector3.zero; |
||||
|
} |
||||
|
|
||||
|
return job; |
||||
|
} |
||||
|
|
||||
|
/// <inheritdoc />
|
||||
|
public override void Destroy(MultiPositionInverseConstraintJob job) |
||||
|
{ |
||||
|
job.sourceTransforms.Dispose(); |
||||
|
job.sourceWeights.Dispose(); |
||||
|
job.sourceOffsets.Dispose(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: dd9bd1ef777641d4b8ec163f15579bf2 |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,96 @@ |
|||||
|
using UnityEngine; |
||||
|
using UnityEngine.Animations; |
||||
|
using UnityEngine.Animations.Rigging; |
||||
|
using Unity.Collections; |
||||
|
|
||||
|
namespace UnityEditor.Animations.Rigging |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The MultiReferential inverse constraint job.
|
||||
|
/// </summary>
|
||||
|
[Unity.Burst.BurstCompile] |
||||
|
public struct MultiReferentialInverseConstraintJob : IWeightedAnimationJob |
||||
|
{ |
||||
|
/// <summary>The list of Transforms that are affected by the specified driver.</summary>
|
||||
|
public NativeArray<ReadWriteTransformHandle> sources; |
||||
|
/// <summary>List of AffineTransform to apply to driven source objects.</summary>
|
||||
|
public NativeArray<AffineTransform> offsetTx; |
||||
|
|
||||
|
/// <inheritdoc />
|
||||
|
public FloatProperty jobWeight { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Defines what to do when processing the root motion.
|
||||
|
/// </summary>
|
||||
|
/// <param name="stream">The animation stream to work on.</param>
|
||||
|
public void ProcessRootMotion(AnimationStream stream) { } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Defines what to do when processing the animation.
|
||||
|
/// </summary>
|
||||
|
/// <param name="stream">The animation stream to work on.</param>
|
||||
|
public void ProcessAnimation(AnimationStream stream) |
||||
|
{ |
||||
|
jobWeight.Set(stream, 1f); |
||||
|
|
||||
|
sources[0].GetGlobalTR(stream, out Vector3 driverWPos, out Quaternion driverWRot); |
||||
|
var driverTx = new AffineTransform(driverWPos, driverWRot); |
||||
|
|
||||
|
int offset = 0; |
||||
|
for (int i = 1; i < sources.Length; ++i) |
||||
|
{ |
||||
|
var tx = driverTx * offsetTx[offset]; |
||||
|
|
||||
|
var src = sources[i]; |
||||
|
src.GetGlobalTR(stream, out Vector3 srcWPos, out Quaternion srcWRot); |
||||
|
src.SetGlobalTR(stream, tx.translation, tx.rotation); |
||||
|
offset++; |
||||
|
|
||||
|
sources[i] = src; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// The MultiReferential inverse constraint job binder.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="T">The constraint data type</typeparam>
|
||||
|
public class MultiReferentialInverseConstraintJobBinder<T> : AnimationJobBinder<MultiReferentialInverseConstraintJob, T> |
||||
|
where T : struct, IAnimationJobData, IMultiReferentialConstraintData |
||||
|
{ |
||||
|
/// <inheritdoc />
|
||||
|
public override MultiReferentialInverseConstraintJob Create(Animator animator, ref T data, Component component) |
||||
|
{ |
||||
|
var job = new MultiReferentialInverseConstraintJob(); |
||||
|
|
||||
|
var sources = data.sourceObjects; |
||||
|
job.sources = new NativeArray<ReadWriteTransformHandle>(sources.Length, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); |
||||
|
job.offsetTx = new NativeArray<AffineTransform>(sources.Length - 1, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); |
||||
|
|
||||
|
var sourceBindTx = new AffineTransform[sources.Length]; |
||||
|
|
||||
|
for (int i = 0; i < sources.Length; ++i) |
||||
|
{ |
||||
|
job.sources[i] = ReadWriteTransformHandle.Bind(animator, sources[i].transform); |
||||
|
sourceBindTx[i] = new AffineTransform(sources[i].position, sources[i].rotation); |
||||
|
} |
||||
|
|
||||
|
int offset = 0; |
||||
|
var invDriverTx = sourceBindTx[0].Inverse(); |
||||
|
for (int i = 1; i < sourceBindTx.Length; ++i) |
||||
|
{ |
||||
|
job.offsetTx[offset] = invDriverTx * sourceBindTx[i]; |
||||
|
offset++; |
||||
|
} |
||||
|
|
||||
|
return job; |
||||
|
} |
||||
|
|
||||
|
/// <inheritdoc />
|
||||
|
public override void Destroy(MultiReferentialInverseConstraintJob job) |
||||
|
{ |
||||
|
job.sources.Dispose(); |
||||
|
job.offsetTx.Dispose(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 07e9ec99cb928a0428b3391e587dfa9c |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,120 @@ |
|||||
|
using Unity.Collections; |
||||
|
using UnityEngine; |
||||
|
using UnityEngine.Animations; |
||||
|
using UnityEngine.Animations.Rigging; |
||||
|
|
||||
|
namespace UnityEditor.Animations.Rigging |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The MultiRotation inverse constraint job.
|
||||
|
/// </summary>
|
||||
|
[Unity.Burst.BurstCompile] |
||||
|
public struct MultiRotationInverseConstraintJob : IWeightedAnimationJob |
||||
|
{ |
||||
|
const float k_Epsilon = 1e-5f; |
||||
|
|
||||
|
/// <summary>The Transform handle for the constrained object Transform.</summary>
|
||||
|
public ReadOnlyTransformHandle driven; |
||||
|
/// <summary>The Transform handle for the constrained object parent Transform.</summary>
|
||||
|
public ReadOnlyTransformHandle drivenParent; |
||||
|
/// <summary>The post-rotation offset applied to the constrained object.</summary>
|
||||
|
public Vector3Property drivenOffset; |
||||
|
|
||||
|
/// <summary>List of Transform handles for the source objects.</summary>
|
||||
|
public NativeArray<ReadWriteTransformHandle> sourceTransforms; |
||||
|
/// <summary>List of weights for the source objects.</summary>
|
||||
|
public NativeArray<PropertyStreamHandle> sourceWeights; |
||||
|
/// <summary>List of offsets to apply to source rotations if maintainOffset is enabled.</summary>
|
||||
|
public NativeArray<Quaternion> sourceOffsets; |
||||
|
|
||||
|
/// <summary>Buffer used to store weights during job execution.</summary>
|
||||
|
public NativeArray<float> weightBuffer; |
||||
|
|
||||
|
/// <inheritdoc />
|
||||
|
public FloatProperty jobWeight { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Defines what to do when processing the root motion.
|
||||
|
/// </summary>
|
||||
|
/// <param name="stream">The animation stream to work on.</param>
|
||||
|
public void ProcessRootMotion(AnimationStream stream) { } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Defines what to do when processing the animation.
|
||||
|
/// </summary>
|
||||
|
/// <param name="stream">The animation stream to work on.</param>
|
||||
|
public void ProcessAnimation(AnimationStream stream) |
||||
|
{ |
||||
|
jobWeight.Set(stream, 1f); |
||||
|
|
||||
|
var lRot = driven.GetLocalRotation(stream); |
||||
|
var offset = drivenOffset.Get(stream); |
||||
|
|
||||
|
if (Vector3.Dot(offset, offset) > 0f) |
||||
|
lRot *= Quaternion.Inverse(Quaternion.Euler(offset)); |
||||
|
|
||||
|
var wRot = lRot; |
||||
|
if (drivenParent.IsValid(stream)) |
||||
|
{ |
||||
|
wRot = drivenParent.GetRotation(stream) * wRot; |
||||
|
} |
||||
|
|
||||
|
for (int i = 0; i < sourceTransforms.Length; ++i) |
||||
|
{ |
||||
|
sourceWeights[i].SetFloat(stream, 1f); |
||||
|
|
||||
|
ReadWriteTransformHandle sourceTransform = sourceTransforms[i]; |
||||
|
|
||||
|
sourceTransform.SetRotation(stream, wRot * sourceOffsets[i]); |
||||
|
|
||||
|
// Required to update handles with binding info.
|
||||
|
sourceTransforms[i] = sourceTransform; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// The MultiRotation inverse constraint job binder.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="T">The constraint data type</typeparam>
|
||||
|
public class MultiRotationInverseConstraintJobBinder<T> : AnimationJobBinder<MultiRotationInverseConstraintJob, T> |
||||
|
where T : struct, IAnimationJobData, IMultiRotationConstraintData |
||||
|
{ |
||||
|
/// <inheritdoc />
|
||||
|
public override MultiRotationInverseConstraintJob Create(Animator animator, ref T data, Component component) |
||||
|
{ |
||||
|
var job = new MultiRotationInverseConstraintJob(); |
||||
|
|
||||
|
job.driven = ReadOnlyTransformHandle.Bind(animator, data.constrainedObject); |
||||
|
job.drivenParent = ReadOnlyTransformHandle.Bind(animator, data.constrainedObject.parent); |
||||
|
job.drivenOffset = Vector3Property.Bind(animator, component, data.offsetVector3Property); |
||||
|
|
||||
|
WeightedTransformArray sourceObjects = data.sourceObjects; |
||||
|
|
||||
|
WeightedTransformArrayBinder.BindReadWriteTransforms(animator, component, sourceObjects, out job.sourceTransforms); |
||||
|
WeightedTransformArrayBinder.BindWeights(animator, component, sourceObjects, data.sourceObjectsProperty, out job.sourceWeights); |
||||
|
|
||||
|
job.sourceOffsets = new NativeArray<Quaternion>(sourceObjects.Count, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); |
||||
|
|
||||
|
job.weightBuffer = new NativeArray<float>(sourceObjects.Count, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); |
||||
|
|
||||
|
Quaternion drivenRotInv = Quaternion.Inverse(data.constrainedObject.rotation); |
||||
|
for (int i = 0; i < sourceObjects.Count; ++i) |
||||
|
{ |
||||
|
job.sourceOffsets[i] = data.maintainOffset ? |
||||
|
(drivenRotInv * sourceObjects[i].transform.rotation) : Quaternion.identity; |
||||
|
} |
||||
|
|
||||
|
return job; |
||||
|
} |
||||
|
|
||||
|
/// <inheritdoc />
|
||||
|
public override void Destroy(MultiRotationInverseConstraintJob job) |
||||
|
{ |
||||
|
job.sourceTransforms.Dispose(); |
||||
|
job.sourceWeights.Dispose(); |
||||
|
job.sourceOffsets.Dispose(); |
||||
|
job.weightBuffer.Dispose(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: e68f0e2daa979074da79ea4fa6e40660 |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,74 @@ |
|||||
|
using UnityEngine; |
||||
|
using UnityEngine.Animations; |
||||
|
using UnityEngine.Animations.Rigging; |
||||
|
|
||||
|
namespace UnityEditor.Animations.Rigging |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The TwistChain inverse constraint job.
|
||||
|
/// </summary>
|
||||
|
[Unity.Burst.BurstCompile] |
||||
|
public struct TwistChainInverseConstraintJob : IWeightedAnimationJob |
||||
|
{ |
||||
|
/// <summary>The Transform handle for the root Transform of the chain.</summary>
|
||||
|
public ReadOnlyTransformHandle root; |
||||
|
/// <summary>The Transform handle for the tip Transform of the chain.</summary>
|
||||
|
public ReadOnlyTransformHandle tip; |
||||
|
|
||||
|
/// <summary>The Transform handle for the root target Transform.</summary>
|
||||
|
public ReadWriteTransformHandle rootTarget; |
||||
|
/// <summary>The Transform handle for the tip target Transform.</summary>
|
||||
|
public ReadWriteTransformHandle tipTarget; |
||||
|
|
||||
|
/// <inheritdoc />
|
||||
|
public FloatProperty jobWeight { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Defines what to do when processing the root motion.
|
||||
|
/// </summary>
|
||||
|
/// <param name="stream">The animation stream to work on.</param>
|
||||
|
public void ProcessRootMotion(AnimationStream stream) { } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Defines what to do when processing the animation.
|
||||
|
/// </summary>
|
||||
|
/// <param name="stream">The animation stream to work on.</param>
|
||||
|
public void ProcessAnimation(AnimationStream stream) |
||||
|
{ |
||||
|
jobWeight.Set(stream, 1f); |
||||
|
|
||||
|
rootTarget.SetPosition(stream, root.GetPosition(stream)); |
||||
|
rootTarget.SetRotation(stream, root.GetRotation(stream)); |
||||
|
|
||||
|
tipTarget.SetPosition(stream, tip.GetPosition(stream)); |
||||
|
tipTarget.SetRotation(stream, tip.GetRotation(stream)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// The TwistChain inverse constraint job binder.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="T">The constraint data type</typeparam>
|
||||
|
public class TwistChainInverseConstraintJobBinder<T> : AnimationJobBinder<TwistChainInverseConstraintJob, T> |
||||
|
where T : struct, IAnimationJobData, ITwistChainConstraintData |
||||
|
{ |
||||
|
/// <inheritdoc />
|
||||
|
public override TwistChainInverseConstraintJob Create(Animator animator, ref T data, Component component) |
||||
|
{ |
||||
|
var job = new TwistChainInverseConstraintJob(); |
||||
|
|
||||
|
job.root = ReadOnlyTransformHandle.Bind(animator, data.root); |
||||
|
job.tip = ReadOnlyTransformHandle.Bind(animator, data.tip); |
||||
|
|
||||
|
job.rootTarget = ReadWriteTransformHandle.Bind(animator, data.rootTarget); |
||||
|
job.tipTarget = ReadWriteTransformHandle.Bind(animator, data.tipTarget); |
||||
|
|
||||
|
return job; |
||||
|
} |
||||
|
|
||||
|
/// <inheritdoc />
|
||||
|
public override void Destroy(TwistChainInverseConstraintJob job) |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 2c669908f1bcf4a829cb78b6398d008f |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,99 @@ |
|||||
|
using UnityEngine; |
||||
|
using UnityEngine.Animations; |
||||
|
using UnityEngine.Animations.Rigging; |
||||
|
|
||||
|
namespace UnityEditor.Animations.Rigging |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The TwoBoneIK inverse constraint job.
|
||||
|
/// </summary>
|
||||
|
[Unity.Burst.BurstCompile] |
||||
|
public struct TwoBoneIKInverseConstraintJob : IWeightedAnimationJob |
||||
|
{ |
||||
|
const float k_SqrEpsilon = 1e-8f; |
||||
|
|
||||
|
/// <summary>The transform handle for the root transform.</summary>
|
||||
|
public ReadOnlyTransformHandle root; |
||||
|
/// <summary>The transform handle for the mid transform.</summary>
|
||||
|
public ReadOnlyTransformHandle mid; |
||||
|
/// <summary>The transform handle for the tip transform.</summary>
|
||||
|
public ReadOnlyTransformHandle tip; |
||||
|
|
||||
|
/// <summary>The transform handle for the hint transform.</summary>
|
||||
|
public ReadWriteTransformHandle hint; |
||||
|
/// <summary>The transform handle for the target transform.</summary>
|
||||
|
public ReadWriteTransformHandle target; |
||||
|
|
||||
|
/// <summary>The offset applied to the target transform if maintainTargetPositionOffset or maintainTargetRotationOffset is enabled.</summary>
|
||||
|
public AffineTransform targetOffset; |
||||
|
|
||||
|
/// <summary>The weight for which target position has an effect on IK calculations. This is a value in between 0 and 1.</summary>
|
||||
|
public FloatProperty targetPositionWeight; |
||||
|
/// <summary>The weight for which target rotation has an effect on IK calculations. This is a value in between 0 and 1.</summary>
|
||||
|
public FloatProperty targetRotationWeight; |
||||
|
/// <summary>The weight for which hint transform has an effect on IK calculations. This is a value in between 0 and 1.</summary>
|
||||
|
public FloatProperty hintWeight; |
||||
|
|
||||
|
/// <inheritdoc />
|
||||
|
public FloatProperty jobWeight { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Defines what to do when processing the root motion.
|
||||
|
/// </summary>
|
||||
|
/// <param name="stream">The animation stream to work on.</param>
|
||||
|
public void ProcessRootMotion(AnimationStream stream) { } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Defines what to do when processing the animation.
|
||||
|
/// </summary>
|
||||
|
/// <param name="stream">The animation stream to work on.</param>
|
||||
|
public void ProcessAnimation(AnimationStream stream) |
||||
|
{ |
||||
|
jobWeight.Set(stream, 1f); |
||||
|
|
||||
|
AnimationRuntimeUtils.InverseSolveTwoBoneIK(stream, root, mid, tip, target, hint, |
||||
|
targetPositionWeight.Get(stream), |
||||
|
targetRotationWeight.Get(stream), |
||||
|
hintWeight.Get(stream), targetOffset); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// The TwoBoneIK inverse constraint job binder.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="T">The constraint data type</typeparam>
|
||||
|
public class TwoBoneIKInverseConstraintJobBinder<T> : AnimationJobBinder<TwoBoneIKInverseConstraintJob, T> |
||||
|
where T : struct, IAnimationJobData, ITwoBoneIKConstraintData |
||||
|
{ |
||||
|
/// <inheritdoc />
|
||||
|
public override TwoBoneIKInverseConstraintJob Create(Animator animator, ref T data, Component component) |
||||
|
{ |
||||
|
var job = new TwoBoneIKInverseConstraintJob(); |
||||
|
|
||||
|
job.root = ReadOnlyTransformHandle.Bind(animator, data.root); |
||||
|
job.mid = ReadOnlyTransformHandle.Bind(animator, data.mid); |
||||
|
job.tip = ReadOnlyTransformHandle.Bind(animator, data.tip); |
||||
|
job.target = ReadWriteTransformHandle.Bind(animator, data.target); |
||||
|
|
||||
|
if (data.hint != null) |
||||
|
job.hint = ReadWriteTransformHandle.Bind(animator, data.hint); |
||||
|
|
||||
|
job.targetOffset = AffineTransform.identity; |
||||
|
if (data.maintainTargetPositionOffset) |
||||
|
job.targetOffset.translation = -(data.tip.position - data.target.position); |
||||
|
if (data.maintainTargetRotationOffset) |
||||
|
job.targetOffset.rotation = Quaternion.Inverse(data.tip.rotation) * data.target.rotation; |
||||
|
|
||||
|
job.targetPositionWeight = FloatProperty.Bind(animator, component, data.targetPositionWeightFloatProperty); |
||||
|
job.targetRotationWeight = FloatProperty.Bind(animator, component, data.targetRotationWeightFloatProperty); |
||||
|
job.hintWeight = FloatProperty.Bind(animator, component, data.hintWeightFloatProperty); |
||||
|
|
||||
|
return job; |
||||
|
} |
||||
|
|
||||
|
/// <inheritdoc />
|
||||
|
public override void Destroy(TwoBoneIKInverseConstraintJob job) |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 97b56b4e0dccdff47b19d995fcc12954 |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,8 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 63607c45d964e47a18e3197ffb465217 |
||||
|
folderAsset: yes |
||||
|
DefaultImporter: |
||||
|
externalObjects: {} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,24 @@ |
|||||
|
using UnityEngine.Animations.Rigging; |
||||
|
|
||||
|
namespace UnityEditor.Animations.Rigging |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// MultiAim inverse constraint.
|
||||
|
/// </summary>
|
||||
|
/// <seealso cref="MultiAimConstraint"/>
|
||||
|
[InverseRigConstraint(typeof(MultiAimConstraint))] |
||||
|
public class MultiAimInverseConstraint : OverrideRigConstraint< |
||||
|
MultiAimConstraint, |
||||
|
MultiAimInverseConstraintJob, |
||||
|
MultiAimConstraintData, |
||||
|
MultiAimInverseConstraintJobBinder<MultiAimConstraintData> |
||||
|
> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Constructor.
|
||||
|
/// </summary>
|
||||
|
/// <param name="baseConstraint">Base constraint to override.</param>
|
||||
|
public MultiAimInverseConstraint(MultiAimConstraint baseConstraint) : base(baseConstraint) {} |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 55179714ce28f4fad97dbe8831d7b7b5 |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,25 @@ |
|||||
|
using UnityEngine; |
||||
|
using UnityEngine.Animations; |
||||
|
using UnityEngine.Animations.Rigging; |
||||
|
|
||||
|
namespace UnityEditor.Animations.Rigging |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// MultiParent inverse constraint.
|
||||
|
/// </summary>
|
||||
|
/// <seealso cref="MultiParentConstraint"/>
|
||||
|
[InverseRigConstraint(typeof(MultiParentConstraint))] |
||||
|
public class MultiParentInverseConstraint : OverrideRigConstraint< |
||||
|
MultiParentConstraint, |
||||
|
MultiParentInverseConstraintJob, |
||||
|
MultiParentConstraintData, |
||||
|
MultiParentInverseConstraintJobBinder<MultiParentConstraintData> |
||||
|
> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Constructor.
|
||||
|
/// </summary>
|
||||
|
/// <param name="baseConstraint">Base constraint to override.</param>
|
||||
|
public MultiParentInverseConstraint(MultiParentConstraint baseConstraint) : base(baseConstraint) { } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: b0bc68cc00b8ce547b1cc869a707c8b9 |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {fileID: 2800000, guid: ca41524ec86f0d84ab5675c9622cc1a2, type: 3} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,24 @@ |
|||||
|
using UnityEngine.Animations.Rigging; |
||||
|
|
||||
|
namespace UnityEditor.Animations.Rigging |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// MultiPosition inverse constraint.
|
||||
|
/// </summary>
|
||||
|
/// <seealso cref="MultiPositionConstraint"/>
|
||||
|
[InverseRigConstraint(typeof(MultiPositionConstraint))] |
||||
|
public class MultiPositionInverseConstraint : OverrideRigConstraint< |
||||
|
MultiPositionConstraint, |
||||
|
MultiPositionInverseConstraintJob, |
||||
|
MultiPositionConstraintData, |
||||
|
MultiPositionInverseConstraintJobBinder<MultiPositionConstraintData> |
||||
|
> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Constructor.
|
||||
|
/// </summary>
|
||||
|
/// <param name="baseConstraint">Base constraint to override.</param>
|
||||
|
public MultiPositionInverseConstraint(MultiPositionConstraint baseConstraint) : base(baseConstraint) {} |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: f565b137dff19490c925f69f8fbfb243 |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,23 @@ |
|||||
|
using UnityEngine.Animations.Rigging; |
||||
|
|
||||
|
namespace UnityEditor.Animations.Rigging |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// MultiReferential inverse constraint.
|
||||
|
/// </summary>
|
||||
|
[InverseRigConstraint(typeof(MultiReferentialConstraint))] |
||||
|
public class MultiReferentialInverseConstraint : OverrideRigConstraint< |
||||
|
MultiReferentialConstraint, |
||||
|
MultiReferentialInverseConstraintJob, |
||||
|
MultiReferentialConstraintData, |
||||
|
MultiReferentialInverseConstraintJobBinder<MultiReferentialConstraintData> |
||||
|
> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Constructor.
|
||||
|
/// </summary>
|
||||
|
/// <param name="baseConstraint">Base constraint to override.</param>
|
||||
|
public MultiReferentialInverseConstraint(MultiReferentialConstraint baseConstraint) : base(baseConstraint) {} |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 246edcdada8bcb14cb045a083c910774 |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
@ -0,0 +1,24 @@ |
|||||
|
using UnityEngine.Animations.Rigging; |
||||
|
|
||||
|
namespace UnityEditor.Animations.Rigging |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// MultiRotation inverse constraint.
|
||||
|
/// </summary>
|
||||
|
/// <seealso cref="MultiRotationConstraint"/>
|
||||
|
[InverseRigConstraint(typeof(MultiRotationConstraint))] |
||||
|
public class MultiRotationInverseConstraint : OverrideRigConstraint< |
||||
|
MultiRotationConstraint, |
||||
|
MultiRotationInverseConstraintJob, |
||||
|
MultiRotationConstraintData, |
||||
|
MultiRotationInverseConstraintJobBinder<MultiRotationConstraintData> |
||||
|
> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Constructor.
|
||||
|
/// </summary>
|
||||
|
/// <param name="baseConstraint">Base constraint to override.</param>
|
||||
|
public MultiRotationInverseConstraint(MultiRotationConstraint baseConstraint) : base(baseConstraint) {} |
||||
|
} |
||||
|
} |
||||
|
|
||||
Some files were not shown because too many files changed in this diff
Write
Preview
Loading…
Cancel
Save
Reference in new issue