def duplicate_jointchain( self, *_tags, **kwargs ) : # make a deep copy of self # loop through bones and replace rigjoint with a new one # loop through minorbones and replace minorbone with bone.duplicate # we could duplicate the top joint and then compare with original to find the minorjoints # creating each joint individually seems to be more direct though try : _simple = kwargs[ '_simple' ] except : _simple = False dupjointchain = copy.deepcopy( self ) dupjointchain.copymother = self lastrigjoint = None pm.select( None ) for i, rigjoint in enumerate( dupjointchain.rigjoints ) : duprigjointname = utils.name_from_tags( rigjoint, *_tags ) duprigjoint = rigjoint.duplicate( n=duprigjointname )[0] dupjointchain.rigjoints[i] = duprigjoint duprigjoint.setParent( lastrigjoint ) lastrigjoint = duprigjoint # _simple copies only major rigjoints if( not _simple ) : dupjointchain.minorrigjoints[ duprigjoint ] = [] # duplicate each minorrigjoint, add it to it's duplicated major rigjoint array of minor rigjoints for minorrigjoint in dupjointchain.minorrigjoints[ rigjoint ] : dupminorrigjointname = utils.name_from_tags( minorrigjoint, *_tags ) dupminorrigjoint = minorrigjoint.duplicate( n=dupminorrigjointname )[0] dupjointchain.minorrigjoints[ duprigjoint ].append( dupminorrigjoint) dupminorrigjoint.setParent( lastrigjoint ) lastrigjoint = dupminorrigjoint # delete the original rigjoint entry in the dict del dupjointchain.minorrigjoints[ rigjoint ] self.duplicates.append( dupjointchain ) # we'll reset the partname here in case the mother jointchain hs had its changed dupjointchain.PARTNAME = dupjointchain.__class__.PARTNAME return dupjointchain
def create( self ) : # distribute the twist along the axis of each major joint # amongst the minor joints above it super( DistributedTwistAddin, self ).create() for relevantobject in self._relevant_objects_generator( self.jointchains ) : # create a multdiv to temper control's rotation by 1/len(minorjoints) multdiv = pm.nodetypes.MultiplyDivide( n=utils.name_from_tags( relevantobject.rigjoint, 'rotateaddin', 'multiplydivide', _replacelast=False ) ) factor = 1.0 / ( len( relevantobject.minorrigjoints ) + 1 ) multdiv.input2.set( [factor] * 3 ) relevantobject.control.attr( self.attribute ) >> multdiv.attr( 'input1' + self.primaryaxis ) # connect the multdiv to rigjoint and minorjoints for joint in [ relevantobject.rigjoint ] + relevantobject.minorrigjoints : multdiv.attr( 'output' + self.primaryaxis ) >> joint.attr( self.attribute )
def _preCreateVirtual( cls, shape_type='default', **kwargs ) : if 'n' in kwargs : name = kwargs.pop( 'n' ) elif 'name' in kwargs : name = kwargs.get( 'name' ) else : name = cls.PARTNAME name = utils.name_from_tags( name, 'control', _replacelast=False ) kwargs[ 'name' ] = name if 'st' in kwargs : shape_type = kwargs.pop( 'st' ) elif 'shape_type' in kwargs : shape_type = kwargs.get( 'shape_type' ) kwargs[ 'shape_type' ] = shape_type pkwargs = { 'shape_type' : shape_type } return kwargs, pkwargs
def connect_rigs( self, _blendcontrol=None ) : # get the object the blend attr should be added to blendcontrol = _blendcontrol if( not blendcontrol ) : blendcontrolname = utils.name_from_tags( settings.staticcontrols[ 'ikfkblend' ], 'control' ) blendcontrol = pm.PyNode( blendcontrolname ) try : # create the blend attr blendattrname = utils.name_from_tags( self.tree_root().name, 'blend' ) self.blendattr = utils.add_set_attr( blendcontrol, blendattrname, 0.0 ) except : utils.err( 'Could not create blend attribute on %s' % ( blendcontrol ) ) return False # blend between rigs onto blendjointchain jointchains = self.tree_children( 'jointchain' ) if( len( jointchains ) != 1 ) : utils.err( '%s does not have ONE jointchain in it\'s children. Not sure which to use as the blend chain.' % ( self ) ) return False blendjoints = jointchains[0].all_joints() rigs = self.tree_children( '.*Rig' ) multdivdict = {} # set min/max values for blendattr self.blendattr.setMin( 0 ) self.blendattr.setMax( len( self.tree_children( '.*Rig' ) ) - 1 ) for i, rig in enumerate( rigs ) : for jointchain in rig.tree_children( 'jointchain' ) : rigjoints = jointchain.all_joints() if( len( rigjoints ) != len( blendjoints ) ) : utils.wrn( '%s has a different number of joints to %s. Skipping...' % ( jointchain, jointchains[0] ) ) continue # create a triangle curve with float time offset by j # by overlapping each triangle, n number of rigs can be blended # _/\____ # __/\___ this is how 3 rigs would blend together # ___/\__ animcurve = pm.nodetypes.AnimCurveUL() animcurve.rename( utils.name_from_tags( self.tree_root().name, 'blend', rig.PARTNAME, 'animcurveUL' ) ) offset = i pm.setKeyframe( animcurve, f=-1 + offset, v=0 ) pm.setKeyframe( animcurve, f=0 + offset, v=1 ) pm.setKeyframe( animcurve, f=1 + offset, v=0 ) self.blendattr >> animcurve.input multdivdict[ rig ] = [] for rigjoint in rigjoints : # vary input of joints rotation by animcurve output multdiv = pm.nodetypes.MultiplyDivide() multdiv.rename( utils.name_from_tags( rigjoint, 'blend', rig.PARTNAME, 'multiplydivide' ) ) multdivdict[ rig ].append( multdiv ) # connect animcurev and rotate to multdiv animcurve.output >> multdiv.input1X animcurve.output >> multdiv.input1Y animcurve.output >> multdiv.input1Z rigjoint.rotate >> multdiv.input2 for j, blendjoint in enumerate( blendjoints ) : # use a PMA node to blend between the rigs pma = pm.nodetypes.PlusMinusAverage() pma.rename( utils.name_from_tags( blendjoint, 'blend', rig.PARTNAME, 'plusminusaverage' ) ) pma.operation.set( 1 ) # connect everything up k = 0 for rig, multdivlist in multdivdict.iteritems() : multdivlist[j].output >> pma.input3D[k] k += 1 pma.output3D >> blendjoint.rotate
def create( self, _jointchain=None ) : super( SplineIkRig, self ).create( _jointchain ) jointchain = self.tree_children( 'jointchain' )[0] # get start and end joints rigjoints = jointchain.rigjoints # # create controls and store start/end controls/rigjoints controlsdriverslist = [] for i, rigjoint in enumerate( [ rigjoints[0], rigjoints[-1] ] ) : # create control control = RigControl( n=rigjoint.name() ) control.setRotationOrder( utils.aim_axis_to_rotate_order( settings.rotationorder ), False ) control.position_to_object( rigjoint ) self.add_child( control ) # create driver joint and store it with it's corresponding control driverrigjoint = rigjoint.duplicate( n=utils.name_from_tags( rigjoint, 'spline', 'driver' ) )[0] self.add_child( driverrigjoint ) controlsdriverslist.append( ( control, driverrigjoint ) ) startjoint = jointchain.rigjoints[0] startdriver = controlsdriverslist[0][1] endjoint = jointchain.rigjoints[-1] enddriver = controlsdriverslist[-1][1] # create ik spline between them ikhandlename = utils.name_from_tags( startjoint, 'ikhandle' ) ikhandle, ikeffector, ikcurve = pm.ikHandle( startJoint=startjoint, endEffector=endjoint, solver='ikSplineSolver', numSpans=len( jointchain.rigjoints ) - 1, name=ikhandlename ) ikeffector.rename( utils.name_from_tags( endjoint, 'ikeffector' ) ) ikcurve.rename( utils.name_from_tags( startjoint, 'curve' ) ) self.add_child( ikhandle ) self.add_child( ikcurve ) # bind curve to driver joints tobind = [ ikcurve ] + [ i[1] for i in controlsdriverslist ] pm.skinCluster( tobind, bindMethod=0, maximumInfluences=len( tobind ) - 1, ) # set twist control ikhandle.dTwistControlEnable.set( True ) ikhandle.dWorldUpType.set( 4 ) startdriver.worldMatrix[0] >> ikhandle.dWorldUpMatrix enddriver.worldMatrix[0] >> ikhandle.dWorldUpMatrixEnd # parent drivers to controls for control, driver in controlsdriverslist : pm.parentConstraint( [ control, driver ], mo=False )
def create( self, _jointchain=None ) : super( IkRig, self ).create( _jointchain ) jointchains = self.tree_children( 'jointchain' ) if( len( jointchains ) != 1 ) : utils.err( 'IkRig children includes more than ONE jointchain. Not sure which to use. Skipping...' ) return False jointchain = jointchains[0] # create a simple joint chain simplejointchain = jointchain.duplicate_jointchain( self.PARTNAME, 'driver', _simple=True ) self.add_child( simplejointchain ) pm.PyNode( 'leftUpperArm_1_IKJ_DRIVER' ).hide() pm.PyNode( 'leftUpperArm_1_j' ).hide() for i in range( len( simplejointchain.rigjoints ) - 1 ) : # create a curve between each pair of simple rigjoints rigjoint1 = simplejointchain.rigjoints[i] rigjoint2 = simplejointchain.rigjoints[i+1] v1 = pm.datatypes.Vector( rigjoint1.getTranslation( space='world' ) ) v2 = pm.datatypes.Vector( rigjoint2.getTranslation( space='world' ) ) curvelength = float( v1.distanceTo( v2 ) ) dirvector = [ a * b for a, b in zip( ( curvelength, curvelength, curvelength ), utils.aim_axis_to_vectors( settings.rotationorder )[0] ) ] curve = pm.curve( degree=1, point=[ ( 0, 0, 0 ), dirvector # v1, v2 ], name=utils.name_from_tags( rigjoint1, 'curve' ) ) # rebuild with numspan 2 and 3 degree pm.rebuildCurve( curve, degree=3, spans=2 ) # move vtx[1] and vtx[-2] to respective ends of curve curve.cv[1].setPosition( curve.cv[0].getPosition( space='world' ), space='world' ) curve.cv[-2].setPosition( curve.cv[-1].getPosition( space='world' ), space='world' ) ribbonlength = 0.2 ribbon = pm.extrude( curve, polygon=0, useProfileNormal=1, extrudeType=0, length=ribbonlength, ch=False, name=utils.name_from_tags( rigjoint1, 'nurbs' ) )[0] ribbon.setTranslation( ( 0, 0, -(ribbonlength)/2 ) ) ribbon.setPivots( ( 0, 0, 0 ), worldSpace=True ) pm.makeIdentity( ribbon, apply=True ) pm.delete( ribbon, ch=True ) pm.delete( curve ) utils.create_zero_sdk_groups( ribbon, _replacelast=False ) startcluster = pm.cluster( ribbon.cv[0:1][0:1], name=utils.name_from_tags( rigjoint1, 'start', 'cluster') )[1] midcluster = pm.cluster( ribbon.cv[2][0:1], name=utils.name_from_tags( rigjoint1, 'mid', 'cluster' ) )[1] endcluster = pm.cluster( ribbon.cv[-2:][0:1], name=utils.name_from_tags( rigjoint1, 'end', 'cluster' ) )[1] # parent clusters to respective rigjoints pm.parentConstraint( [ rigjoint1, startcluster ], mo=False ) pm.parentConstraint( [ rigjoint2, endcluster ], mo=False ) # group then point/parent constrain middle cluster to end clusters sdkgroup, zerogroup = utils.create_zero_sdk_groups( midcluster, _replacelast=False ) zerogroup.setRotation( rigjoint1.getRotation( space='world' ), space='world' ) pm.pointConstraint( [ rigjoint1, rigjoint2, zerogroup ], mo=False ) pm.orientConstraint( [ rigjoint1, zerogroup ], mo=False ) jointsToAttachToCurve = [ jointchain.rigjoints[i] ] jointsToAttachToCurve += jointchain.minorrigjoints[ jointsToAttachToCurve[0] ] jointsToAttachToCurve += [ jointchain.rigjoints[i+1] ] for rigjoint in jointsToAttachToCurve : p = rigjoint.getTranslation( space='world' ) posi = pm.nodetypes.ClosestPointOnSurface() ribbon.worldSpace >> posi.inputSurface posi.inPosition.set( p ) u = min( max( posi.u.get(), 0.001 ), 0.999 ) v = min( max( posi.v.get(), 0.001 ), 0.999 ) pm.delete( posi ) follicleshape = pm.nodetypes.Follicle() ribbon.local >> follicleshape.inputSurface ribbon.worldMatrix[0] >> follicleshape.inputWorldMatrix follicleshape.parameterU.set( u ) follicleshape.parameterV.set( v ) follicle = follicleshape.getParent() follicle.rename( utils.name_from_tags( rigjoint, 'follicle' ) ) follicleshape.rename( follicle.name() + 'Shape' ) follicleshape.outRotate >> follicle.rotate follicleshape.outTranslate >> follicle.translate # remove any constraints already on the joint pm.delete( rigjoint.getChildren( type='constraint' ) ) pm.parentConstraint( [ follicle, rigjoint ], mo=True ) return True