10using System.Collections;
11using System.Collections.Generic;
26 [FormerlySerializedAs(
"DeformPositionsInFingers")]
27 [OnEditorChange(
"deformPositionsInFingers")]
28 private bool _deformPositionsInFingers =
true;
30 get {
return _deformPositionsInFingers; }
32 _deformPositionsInFingers = value;
33 updateDeformPositionsInFingers();
37 [Tooltip(
"Because bones only exist at their roots in model rigs, the length " +
38 "of the last fingertip bone is lost when placing bones at positions in the " +
40 "This option scales the last bone along its X axis (length axis) to match " +
41 "its bone length to the tracked bone length. This option only has an " +
42 "effect if Deform Positions In Fingers is enabled.")]
43 [
DisableIf(
"_deformPositionsInFingers", isEqualTo:
false)]
45 [OnEditorChange(
"scaleLastFingerBones")]
46 private bool _scaleLastFingerBones =
true;
48 get {
return _scaleLastFingerBones; }
50 _scaleLastFingerBones = value;
51 updateScaleLastFingerBoneInFingers();
55 [Tooltip(
"Hands are typically rigged in 3D packages with the palm transform near the wrist. Uncheck this if your model's palm transform is at the center of the palm similar to Leap API hands.")]
56 [FormerlySerializedAs(
"ModelPalmAtLeapWrist")]
59 [Tooltip(
"Set to True if each finger has an extra trasform between palm and base of the finger.")]
60 [FormerlySerializedAs(
"UseMetaCarpals")]
63 #pragma warning disable 0414
65 [Header(
"Values for Stored Start Pose")]
67 private List<Transform> jointList =
new List<Transform>();
69 private List<Quaternion> localRotations =
new List<Quaternion>();
71 private List<Vector3> localPositions =
new List<Vector3>();
72 #pragma warning restore 0414
74 [Tooltip(
"If non-zero, this vector and the modelPalmFacing vector " +
75 "will be used to re-orient the Transform bones in the hand rig, to " +
76 "compensate for bone axis discrepancies between Leap Bones and model " +
79 [Tooltip(
"If non-zero, this vector and the modelFingerPointing vector " +
80 "will be used to re-orient the Transform bones in the hand rig, to " +
81 "compensate for bone axis discrepancies between Leap Bones and model " +
89 return Quaternion.identity;
91 return Quaternion.Inverse(
97 updateDeformPositionsInFingers();
98 updateScaleLastFingerBoneInFingers();
119 for (
int i = 0; i <
fingers.Length; ++i) {
128 [ContextMenu(
"Setup Rigged Hand")]
130 Debug.Log(
"Using transform naming to setup RiggedHand on " + transform.name);
133 assignRiggedFingersByName();
134 setupRiggedFingers();
137 setFingerPalmFacing();
142 Debug.Log(
"Using Mecanim mapping to setup RiggedHand on " + transform.name);
145 setupRiggedFingers();
148 setFingerPalmFacing();
152 private void assignRiggedFingersByName(){
153 List<string> palmStrings =
new List<string> {
"palm"};
154 List<string> thumbStrings =
new List<string> {
"thumb",
"tmb" };
155 List<string> indexStrings =
new List<string> {
"index",
"idx"};
156 List<string> middleStrings =
new List<string> {
"middle",
"mid"};
157 List<string> ringStrings =
new List<string> {
"ring"};
158 List<string> pinkyStrings =
new List<string> {
"pinky",
"pin"};
161 Transform thumb =
null;
162 Transform index =
null;
163 Transform middle =
null;
164 Transform ring =
null;
165 Transform pinky =
null;
166 Transform[] children = transform.GetComponentsInChildren<Transform>();
167 if (palmStrings.Any(w => transform.name.ToLower().Contains(w))){
168 base.palm = transform;
171 foreach (Transform t
in children) {
172 if (palmStrings.Any(w => t.name.ToLower().Contains(w)) ==
true) {
182 foreach (Transform t
in children) {
184 preExistingRiggedFinger = t.GetComponent<
RiggedFinger>();
185 string lowercaseName = t.name.ToLower();
186 if (!preExistingRiggedFinger) {
187 if (thumbStrings.Any(w => lowercaseName.Contains(w)) && t.parent ==
palm) {
192 if (indexStrings.Any(w => lowercaseName.Contains(w)) && t.parent ==
palm) {
197 if (middleStrings.Any(w => lowercaseName.Contains(w)) && t.parent ==
palm) {
202 if (ringStrings.Any(w => lowercaseName.Contains(w)) && t.parent ==
palm) {
207 if (pinkyStrings.Any(w => lowercaseName.Contains(w)) && t.parent ==
palm) {
218 private void setupRiggedFingers() {
219 RiggedFinger[] fingerModelList = GetComponentsInChildren<RiggedFinger>();
220 for (
int i = 0; i < 5; i++) {
221 int fingersIndex = fingerModelList[i].
fingerType.indexOf();
222 fingers[fingersIndex] = fingerModelList[i];
228 private void setFingerPalmFacing() {
229 RiggedFinger[] fingerModelList = GetComponentsInChildren<RiggedFinger>();
230 for (
int i = 0; i < 5; i++) {
231 int fingersIndex = fingerModelList[i].
fingerType.indexOf();
232 fingers[fingersIndex] = fingerModelList[i];
238 private Vector3 calculateModelPalmFacing(Transform
palm, Transform finger1,
242 Vector3 b =
palm.transform.InverseTransformPoint(finger1.position);
243 Vector3 c =
palm.transform.InverseTransformPoint(finger2.position);
250 perpendicular =
Vector3.Cross(side1, side2);
252 else perpendicular =
Vector3.Cross(side2, side1);
255 return calculatedPalmFacing;
259 private Vector3 calculateModelFingerPointing() {
260 Vector3 distance =
palm.transform.InverseTransformPoint(
fingers[2].transform.GetChild(0).transform.position) -
palm.transform.InverseTransformPoint(
palm.position);
262 return calculatedFingerPointing * -1f;
267 var zeroed =
new Vector3();
268 float max = Mathf.Max(Mathf.Abs(vectorToZero.x), Mathf.Abs(vectorToZero.y), Mathf.Abs(vectorToZero.z));
269 if (Mathf.Abs(vectorToZero.x) == max) {
270 zeroed = (vectorToZero.x < 0) ?
new Vector3(1, 0, 0) :
new Vector3(-1, 0, 0);
272 if (Mathf.Abs(vectorToZero.y) == max) {
273 zeroed = (vectorToZero.y < 0) ?
new Vector3(0, 1, 0) :
new Vector3(0, -1, 0);
275 if (Mathf.Abs(vectorToZero.z) == max) {
276 zeroed = (vectorToZero.z < 0) ?
new Vector3(0, 0, 1) :
new Vector3(0, 0, -1);
302 private void updateDeformPositionsInFingers() {
303 var riggedFingers = GetComponentsInChildren<RiggedFinger>();
304 foreach (var finger
in riggedFingers){
309 private void updateScaleLastFingerBoneInFingers() {
310 var riggedFingers = GetComponentsInChildren<RiggedFinger>();
311 foreach (var finger
in riggedFingers) {
323 return calculateRotation(trs);
326 return palm.rotation;
The Finger class represents a tracked finger.
FingerType
Enumerates the names of the fingers.
LeapTransform Basis
The transform of the hand.
Finger.FingerType fingerType
abstract void UpdateFinger()
Vector3 GetWristPosition()
Vector3 GetPalmPosition()
Quaternion GetArmRotation()
override Chirality Handedness
Manages the position and orientation of the bones in a model rigged for skeletal animation.
void SetupRiggedFinger(bool useMetaCarpals)
A skinned and jointed 3D HandModel.
bool modelPalmAtLeapWrist
bool scaleLastFingerBones
static Vector3 CalculateZeroedVector(Vector3 vectorToZero)
void AutoRigRiggedHand(Transform palm, Transform finger1, Transform finger2)
Quaternion userBoneRotation
Rotation derived from the modelFingerPointing and modelPalmFacing vectors in the RiggedHand inspector...
override bool SupportsEditorPersistence()
Returns whether or not this hand model supports editor persistence. This is false by default and must...
override ModelType HandModelType
Vector3 modelFingerPointing
override void UpdateHand()
bool deformPositionsInFingers