-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathskeletonPart_hand.py
126 lines (95 loc) · 4.19 KB
/
skeletonPart_hand.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
from baseSkeletonBuilder import *
class Hand(SkeletonPart):
HAS_PARITY = True
AUTO_NAME = False #this part will handle its own naming...
#odd indices are left sided, even are right sided
FINGER_IDX_NAMES = ( 'Thumb', 'Index', 'Mid', 'Ring', 'Pinky',
'Sixth' 'Seventh', 'Eighth', 'Ninth', 'Tenth' )
PLACER_NAMES = FINGER_IDX_NAMES
def getParity( self ):
'''
the parity of a hand comes from the limb its parented to, not the idx of
the finger part itself...
'''
parent = self.getParent()
try:
#if the parent has parity use it
parentPart = SkeletonPart.InitFromItem( parent )
except SkeletonError:
#otherwise use the instance's index for parity...
return super( self, Hand ).getParity()
return Parity( parentPart.getParity() )
def iterFingerChains( self ):
'''
iterates over each finger chain in the hand - a chain is simply a list of
joint names ordered hierarchically
'''
for base in self.bases:
children = listRelatives( base, ad=True, path=True, type='joint' ) or []
children = [ base ] + sortByHierarchy( children )
yield children
@classmethod
def _build( cls, parent=None, fingerCount=5, fingerJointCount=3, **kw ):
idx = Parity( kw[ 'idx' ] )
partScale = kw[ 'partScale' ]
parent = getParent( parent )
parentPart = SkeletonPart.InitFromItem( parent )
#try to determine a "parity index" based on the parent part. Ideally we want to inherit the parity of the parent part
#instead of from this part's index
limbIdx = 0
if parentPart.hasParity():
limbIdx = parentPart.getParity()
#if the parent part has no parity, then use the instance's index for parity...
else:
limbIdx = self.getParity()
#for the first two hands this is an empty string - but for each additional hand pair, this is incremented. ie the
#second two hands are called Hand1, the next two hands are called Hand2 etc...
typePairCountStr = str( idx/2 ) if idx > 1 else ''
minPos, maxPos = -cls.PART_SCALE / 25.0, cls.PART_SCALE / 25.0
posRange = float( maxPos - minPos )
allJoints = []
length = partScale / 3 / fingerJointCount
lengthInc = cls.ParityMultiplier( limbIdx ) * (length / fingerJointCount)
limbName = Parity.NAMES[ limbIdx ]
for nameIdx in range( fingerCount ):
fingerName = cls.FINGER_IDX_NAMES[ nameIdx ]
prevParent = parent
for n in range( fingerJointCount ):
j = createJoint( '%s%s_%d%s' % (fingerName, typePairCountStr, n, limbName) )
cmd.parent( j, prevParent, r=True )
move( lengthInc, 0, 0, j, r=True, os=True )
if n == 0:
move( lengthInc, 0, -maxPos + (posRange * nameIdx / (fingerCount - 1)), j, r=True, os=True )
else:
setAttr( '%s.ty' % j, lock=True )
allJoints.append( j )
prevParent = j
return allJoints
def visualize( self ):
scale = self.getActualScale() / 1.5
for base in self.bases:
plane = polyPlane( w=scale, h=scale / 2.0, sx=1, sy=1, ax=(0, 1, 0), cuv=2, ch=False )[ 0 ]
cmd.parent( plane, base, relative=True )
setAttr( '%s.tx' % plane, self.getParityMultiplier() * scale / 2 )
makeIdentity( plane, a=True, t=True )
cmd.parent( listRelatives( plane, shapes=True, pa=True ), base, add=True, shape=True )
delete( plane )
def _align( self, _initialAlign=False ):
parity = self.getParity()
wrist = self.getParent()
parityMult = self.getParityMultiplier()
defactoUpVector = rigUtils.getObjectBasisVectors( wrist )[ 2 ]
for chain in self.iterFingerChains():
upVector = defactoUpVector
#if there are three joints or more in teh chain, try to determine the normal to the plane they live on
if len( chain ) >= 3:
midJoint = chain[ len( chain ) / 2 ]
upVector = getPlaneNormalForObjects( chain[ 0 ], midJoint, chain[ -1 ], defactoUpVector )
#otherwise assume the user has aligned the base joint properly
else:
upVector = rigUtils.getObjectBasisVectors( chain[ 0 ] )[ BONE_ROTATE_AXIS ]
upVector = upVector * parityMult
for n, item in enumerate( chain[ :-1 ] ):
alignAimAtItem( item, chain[ n+1 ], parity, worldUpVector=upVector )
autoAlignItem( chain[ -1 ], parity, worldUpVector=upVector )
#end