def reorderDeformersByOrderedList(obj, deformerOrder): """ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> DESCRIPTION: Reorders deformers on an object by a list of deformers ARGUMENTS: obj(string) deformerOrder(list) - list of the order youw ant RETURNS: Success(bool) >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> """ deformers = returnObjectDeformers(obj) orderedDeformers = [] existsCheck = True if deformers: # pair up the list orderedDeformerPairs = lists.parseListToPairs(deformerOrder) for pair in orderedDeformerPairs: mc.reorderDeformers(pair[0],pair[1],obj) return True else: print ('No deformers on ' + obj) return False
def aimObjects(objList, objAim, objUp, worldUp, **kw): """ Aim snap tool function for a list of objects Arg: objList(list) -- list of objects objAim(string) -- string format of aim axis. ex. 'x+' objUp(string) -- string format of up axis. worldUp(string) -- string format of world up Kw: any keyword arguments for an aim constraint """ worldUpType = kw.pop('worldUpType', 'vector') for o in objList: assert mc.ls(o, type='transform' ), "'%s' doesn't have a transform, erroring out." % o assert len( objList ) >= 2, "moveAimObjects should only be used on lists of objects more than two items" objAim = dictionary.validateDirectionVector(objAim) objUp = dictionary.validateDirectionVector(objUp) worldUp = dictionary.validateDirectionVector(worldUp) assert type(objAim) is list, "invalid objAim argument" assert type(objUp) is list, "invalid objUp argument" assert type(worldUp) is list, "invalid worldUp argument" pairList = lists.parseListToPairs(objList) for pair in pairList: #>>> Set up constraints constraintBuffer = mc.aimConstraint(pair[1], pair[0], maintainOffset=False, weight=1, aimVector=objAim, upVector=objUp, worldUpVector=worldUp, worldUpType=worldUpType, **kw) mc.delete(constraintBuffer) #>>> For the last object in the chain for obj in objList[-1:]: constraintBuffer = mc.orientConstraint(objList[-2], obj, maintainOffset=False, weight=1) mc.delete(constraintBuffer)
def returnAverageDistanceBetweenPositionList (posList): """ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> DESCRIPTION: Pass an list of objects into it, it measures distances and returns an average. ARGUMENTS: objList(list) - list of objects to measure between RETURNS: averageDistance (float) >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> """ pairList = lists.parseListToPairs(posList) distanceList = [] for pair in pairList: distanceList.append(returnDistanceBetweenPoints(pair[0],pair[1])) average = float(sum(distanceList)) / len(distanceList) return average
def aimObjects(objList,objAim,objUp,worldUp,**kw): """ Aim snap tool function for a list of objects Arg: objList(list) -- list of objects objAim(string) -- string format of aim axis. ex. 'x+' objUp(string) -- string format of up axis. worldUp(string) -- string format of world up Kw: any keyword arguments for an aim constraint """ worldUpType = kw.pop('worldUpType','vector') for o in objList: assert mc.ls(o,type = 'transform'),"'%s' doesn't have a transform, erroring out."%o assert len(objList) >= 2,"moveAimObjects should only be used on lists of objects more than two items" objAim = dictionary.validateDirectionVector(objAim) objUp = dictionary.validateDirectionVector(objUp) worldUp = dictionary.validateDirectionVector(worldUp) assert type(objAim) is list,"invalid objAim argument" assert type(objUp) is list,"invalid objUp argument" assert type(worldUp) is list,"invalid worldUp argument" pairList = lists.parseListToPairs(objList) for pair in pairList: #>>> Set up constraints constraintBuffer = mc.aimConstraint(pair[1],pair[0],maintainOffset = False, weight = 1, aimVector = objAim, upVector = objUp, worldUpVector = worldUp, worldUpType=worldUpType,**kw) mc.delete(constraintBuffer) #>>> For the last object in the chain for obj in objList[-1:]: constraintBuffer = mc.orientConstraint(objList[-2],obj,maintainOffset = False, weight = 1) mc.delete(constraintBuffer)
def reorderDeformersByType(obj, deformerOrder = ['skinCluster','blendShape','tweak']): """ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ACKNOWLEDGEMENT Reorders deformers on an object by deformer type DESCRIPTION: Returns a list of deformers on an object in order from top to bottom ARGUMENTS: obj(string) deformerOrder(list) - (['skinCluster','blendShape','tweak']) >>>> Options are sculpt, cluster, jointCluster, lattice, wire, jointLattice, boneLattice, blendShape. RETURNS: Success(bool) >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> """ deformers = returnObjectDeformers(obj) orderedDeformers = [] if deformers: for deformerType in deformerOrder: for deformer in deformers: if search.returnObjectType(deformer) == deformerType: orderedDeformers.append(deformer) deformers.remove(deformer) for deformer in deformers: orderedDeformers.append(deformer) # pair up the list orderedDeformerPairs = lists.parseListToPairs(orderedDeformers) for pair in orderedDeformerPairs: mc.reorderDeformers(pair[0],pair[1],obj) return True else: print ('No deformers on ' + obj) return False
def makeJointControlSurfaceFish(startJoint,controlJointList,outChannel,name): """ Makes a ricgmon surface for ricgmon rigging """ heirarchyJoints = [] heirarchyJoints.append (startJoint) childrenBuffer = [] controlJointGroups = [] """ Makes some transform groups for our groups""" """ Get joint list """ for jnt in (mc.listRelatives (startJoint, ad = True, type = 'joint')): childrenBuffer.append (jnt) childrenBuffer.reverse () heirarchyJoints += childrenBuffer """ return a good length for out loft curves """ length = (distance.returnDistanceBetweenObjects (heirarchyJoints[0], heirarchyJoints[-1])/2) loftCurveList = [] crvPosBuffer = [] crvPosBuffer.append ([0,0,0]) if outChannel == 'x': crvPosBuffer.append ([length,0,0]) elif outChannel == 'y': crvPosBuffer.append ([0,length,0]) elif outChannel == 'z': crvPosBuffer.append ([0,0,length]) crvPosBuffer.reverse () """ for each joint, make a loft curve and snap it to the joint it goes with """ for jnt in heirarchyJoints: crvBuffer = mc.curve (d=1, p = crvPosBuffer , os=True, n=(jnt+'_tmpCrv')) mc.xform (crvBuffer, cp = True) posBuffer = distance.returnWorldSpacePosition (jnt) cnstBuffer = mc.parentConstraint ([jnt], [crvBuffer], maintainOffset = False) mc.delete (cnstBuffer) loftCurveList.append (crvBuffer) controlSurface = mc.loft (loftCurveList, reverseSurfaceNormals = True, ch = False, uniform = True, degree = 3, n = (name+'_surf') ) """ deletes our loft curve list""" for crv in loftCurveList: mc.delete (crv) cvList = (mc.ls ([controlSurface[0]+'.cv[*]'],flatten=True)) """ Time to set skin our surface to our control joints """ surfaceSkinCluster = mc.skinCluster (controlJointList,controlSurface[0],tsb=True, n=(controlSurface[0]+'_skinCluster'),maximumInfluences = 3, normalizeWeights = 1, dropoffRate=2,smoothWeights=.5,obeyMaxInfluences=True, weight = 1) #surfaceSkinCluster = mc.skinCluster (controlJointList,controlSurface,tsb=True, n=(controlSurface[0]+'_skinCluster'),maximumInfluences = 5, normalizeWeights = 2, dropoffRate=4,smoothWeights=.5,forceNormalizeWeights=True) """ Make our groups to follow the surface and drive out """ posGroups = [] upGroups = [] cnt = 0 for jnt in heirarchyJoints: posGroups.append (mc.group (n= ('%s%s' % (jnt,'_Pos_grp')), w=True, empty=True)) upGroups.append (mc.group (n= ('%s%s' % (jnt,'_Up_grp')), w=True, empty=True)) mc.parent (upGroups[cnt],posGroups[cnt]) cnt +=1 """ Make our v values for our position info groups""" vValues = [] vValues.append (.5) cnt = 0 for item in heirarchyJoints: vValues.append (cnt + 1) cnt += 1 """ Make our position info nodes""" posInfoNodes = [] cnt = 0 for grp in posGroups: node = mc.createNode ('pointOnSurfaceInfo',name= (grp+'_posInfoNode')) print node posInfoNodes.append (node) """ Connect the info node to the surface """ mc.connectAttr ((controlSurface[0]+'Shape.worldSpace'),(posInfoNodes[cnt]+'.inputSurface')) """ Contect the pos group to the info node""" mc.connectAttr ((posInfoNodes[cnt]+'.position'),(grp+'.translate')) """ Connect the U tangent attribute to the child of our first group """ mc.connectAttr ((posInfoNodes[cnt]+'.tangentU'),(upGroups[cnt]+'.translate')) mc.setAttr ((posInfoNodes[cnt]+'.parameterU'),.5) mc.setAttr ((posInfoNodes[cnt]+'.parameterV'),(vValues[cnt])) cnt += 1 """ Make our measure nodes to keep joint position """ posPairsList = lists.parseListToPairs (posInfoNodes) posDistConnections = [] poseDistNameList = [] for pair in posPairsList: distanceInfoBuffer = distance.createDistanceNodeBetweenPosInfoNodes (pair[0],pair[1]) posDistConnections.append(distanceInfoBuffer[2]) poseDistNameList.append(distanceInfoBuffer[0]) """ connect the distances to our stretch translation channels on our joints """ """ connect the distances to our stretch translation channels on our joints """ #find it directionCap = 'X' cnt = 0 jointLengths = [] mdNodes = [] """ need to make our master scale connector""" scaleHolderGrp= (controlSurface[0]+'_scaleHolder_grp') masterScaleAttrBuffer = (scaleHolderGrp+'.worldScale') if mc.objExists (scaleHolderGrp): pass else: mc.group (n= scaleHolderGrp, w=True, empty=True) mc.addAttr (scaleHolderGrp, ln = 'worldScale', at = 'float', hidden=False ) mc.setAttr(masterScaleAttrBuffer,1) """ return our default lengths and store them,then run them through an md node to return our scale values """ for jnt in heirarchyJoints[0:-1]: lengthBuffer = mc.getAttr (posDistConnections[cnt]) jointLengths.append (lengthBuffer) #mc.addAttr (jnt, ln = 'baseLength', at = 'float') mc.addAttr (scaleHolderGrp, ln = (jnt+'_baseLength'), at = 'float') jntAttrBuffer = (scaleHolderGrp+'.'+jnt+'_baseLength') mc.setAttr (jntAttrBuffer,jointLengths[cnt]) mdNodeBuffer = nodes.createNamedNode ((jnt+'_jntScale'), 'multiplyDivide') mdNodes.append(mdNodeBuffer) mc.setAttr ((mdNodeBuffer+'.operation'),2) mc.connectAttr((posDistConnections[cnt]),(mdNodeBuffer+'.input1X')) mc.connectAttr((jntAttrBuffer),(mdNodeBuffer+'.input2X')) mc.connectAttr(masterScaleAttrBuffer,(jnt+'.scaleY')) mc.connectAttr(masterScaleAttrBuffer,(jnt+'.scaleZ')) mc.connectAttr((mdNodeBuffer+'.output.outputX'),(jnt+'.scale'+directionCap)) cnt+=1 """ """ #mc.connectAttr ( """ SET SPECIAL CONDITION FOR FIRST POS GROUP """ #mc.setAttr ((posInfoNodes[0]+'.parameterV'),0) """Clean up stuff """ cleanupGrp = mc.group (n= 'surfacePosFollowStuff_grp', w=True, empty=True) for grp in posGroups: mc.parent (grp, cleanupGrp) """ make some IK effectors and connect everything up""" effectorList = [] cnt = (len(heirarchyJoints) - 1) firstTermCount = 0 secondTermCount = 1 while cnt > 0: effector = mc.ikHandle (name = (heirarchyJoints[firstTermCount]+'_ikHandle') , startJoint=heirarchyJoints[firstTermCount], endEffector = heirarchyJoints[secondTermCount], setupForRPsolver = True, solver = 'ikRPsolver', enableHandles=True ) """ if it's the not the last effector, do this """ if cnt > 1: mc.parent (effector[0],posGroups[secondTermCount]) """ if it is, parent it to the last controlJoint """ if cnt == 1: mc.parent (effector[0],posGroups[secondTermCount]) effectorList.append (effector[0]) cnt-=1 firstTermCount += 1 secondTermCount += 1 if cnt == 0: break """ let's make some pole vector constraints""" #----------->>>>> Need to find a good way of "discovering" correct twist for the effectors cnt = 0 """ Connect first joint to surface """ mc.connectAttr ((posGroups[0]+'.translate'),(heirarchyJoints[0]+'.translate')) for effector in effectorList: #print ('Constrain '+effector+' to '+ upGroups[cnt]) poleVector = mc.poleVectorConstraint (upGroups[cnt],effector,name = (effector+'_pvConst')) """ fix the twist""" if (len(effectorList) - cnt) == 0: mc.setAttr ((effector+'.twist'),-180) elif cnt == 0: mc.setAttr ((effector+'.twist'),0) else: mc.setAttr ((effector+'.twist'),-90) cnt+=1 # """return all our data together to return""" """ clean up measure stuff """ if mc.objExists (name+'_measureStuff_grp'): distCleanupGrp = (name+'_measureStuff_grp') else: distCleanupGrp = mc.group (n= (name+'_measureStuff_grp'), w=True, empty=True) for dist in poseDistNameList: mc.parent (dist, distCleanupGrp) mc.setAttr ((dist+'.v'),0) mc.parent (distCleanupGrp, 'rigStuff_grp') mc.parent (cleanupGrp, 'rigStuff_grp') mc.parent (scaleHolderGrp, 'rigStuff_grp') """ connect master scale to the master """ mc.connectAttr(('placement_anim.sy'),masterScaleAttrBuffer) return controlSurface
def orientSegment(limbJoints, posTemplateObjects, orientation): """ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> DESCRIPTION: Basic limb skeletonizer ARGUMENTS: limbJoints(list) templeateObjects(list) orientation(string) - ['xyz','yzx','zxy','xzy','yxz','zyx'] RETURNS: limbJoints(list) >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> """ """ orientation vectors""" orientationVectors = search.returnAimUpOutVectorsFromOrientation( orientation) wantedAimVector = orientationVectors[0] wantedUpVector = orientationVectors[1] """put objects in order of closeness to root""" limbJoints = distance.returnDistanceSortedList(limbJoints[0], limbJoints) #>>> Segment our joint list by names jointSegmentsList = [] cullList = [] """ gonna be culling items from the list so need to rebuild it, just doing a list1 = list2 somehow keeps the relationship....odd """ for obj in limbJoints: cullList.append(obj) while len(cullList) > 0: matchTerm = search.returnTagInfo(cullList[0], 'cgmName') objSet = search.returnMatchedTagsFromObjectList( cullList, 'cgmName', matchTerm) jointSegmentsList.append(objSet) for obj in objSet: cullList.remove(obj) #>>> get our orientation helpers helperObjects = [] for obj in posTemplateObjects: templateObj = attributes.returnMessageObject(obj, 'cgmName') helperObjects.append( attributes.returnMessageObject(templateObj, 'orientHelper')) #>>> un parenting the chain for joint in limbJoints[1:]: mc.parent(joint, world=True) #>>>per segment stuff cnt = 0 for segment in jointSegmentsList: if len(segment) > 1: """ creat our up object from from the helper object """ helperObjectCurvesShapes = mc.listRelatives(helperObjects[cnt], shapes=True) upLoc = locators.locMeCvFromCvIndex(helperObjectCurvesShapes[0], 30) print upLoc """ make a pair list""" pairList = lists.parseListToPairs(segment) for pair in pairList: """ set up constraints """ constraintBuffer = mc.aimConstraint(pair[1], pair[0], maintainOffset=False, weight=1, aimVector=wantedAimVector, upVector=wantedUpVector, worldUpVector=[0, 1, 0], worldUpObject=upLoc, worldUpType='object') mc.delete(constraintBuffer[0]) for obj in segment[-1:]: constraintBuffer = mc.orientConstraint(segment[-2], obj, maintainOffset=False, weight=1) mc.delete(constraintBuffer[0]) """ increment and delete the up loc """ cnt += 1 mc.delete(upLoc) else: helperObjectCurvesShapes = mc.listRelatives(helperObjects[cnt], shapes=True) upLoc = locators.locMeCvFromCvIndex(helperObjectCurvesShapes[0], 30) """ make an aim object """ aimLoc = locators.locMeObject(helperObjects[cnt]) aimLocGroup = rigging.groupMeObject(aimLoc) mc.move(10, 0, 0, aimLoc, localSpace=True) constraintBuffer = mc.aimConstraint(aimLoc, segment[0], maintainOffset=False, weight=1, aimVector=wantedAimVector, upVector=wantedUpVector, worldUpVector=[0, 1, 0], worldUpObject=upLoc, worldUpType='object') mc.delete(constraintBuffer[0]) mc.delete(aimLocGroup) mc.delete(upLoc) cnt += 1 #>>>reconnect the joints pairList = lists.parseListToPairs(limbJoints) for pair in pairList: mc.parent(pair[1], pair[0]) """ Freeze the rotations """ mc.makeIdentity(limbJoints[0], apply=True, r=True) return limbJoints
try:#Reparent joints """ ml_skinJoints = self.rig_getSkinJoints() last_i_jnt = False for i,i_jnt in enumerate(ml_skinJoints): if i_jnt.hasAttr('cgmName'): if last_i_jnt:i_jnt.parent = last_i_jnt.mNode last_i_jnt = i_jnt""" ml_moduleJoints = self._mi_module.rigNull.msgList_get('moduleJoints') #Get the module joints ml_skinJoints = [] ml_handleJoints = self._mi_module.rig_getHandleJoints() if addHelpers: ml_pairs = lists.parseListToPairs(ml_moduleJoints)#...halfHold #jUtils.add_defHelpJoint(ml_pairs[1][0],ml_pairs[1][1],helperType = 'childRootHold',orientation=self.str_jointOrientation) for ml_pair in ml_pairs[1:]: #jUtils.add_defHelpJoint(ml_pair[0],ml_pair[1],helperType = 'halfHold', #orientation=self.str_jointOrientation) jUtils.add_defHelpJoint(ml_pair[0],ml_pair[1],helperType = 'childRootHold', orientation=self.str_jointOrientation) """ for i,i_jnt in enumerate(ml_moduleJoints): ml_skinJoints.append(i_jnt) if i_jnt.hasAttr('d_jointFlags'): if i_jnt.d_jointFlags.get('isHandle'): if i == 0:i_jnt.parent = ml_moduleJoints[0].mNode#Parent head to root i_dupJnt = i_jnt.doDuplicate()#Duplicate i_dupJnt.addAttr('cgmNameModifier','extra')#Tag
def addOrientationHelpers(self): """ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> DESCRIPTION: Adds orientation helpers to a template chain ARGUMENTS: objects(list) root(string) - root control of the limb chain moduleType(string) RETURNS: returnList(list) = [rootHelper(string),helperObjects(list),helperObjectGroups(list)] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> """ moduleColors = modules.returnModuleColors(self.ModuleNull.nameLong) helperObjects = [] helperObjectGroups = [] returnBuffer = [] root = self.msgTemplateRoot.getMessage() visAttr = "%s.visOrientHelpers" % self.infoNulls['visibilityOptions'].get() objects = self.templatePosObjectsBuffer.bufferList #>>> Direction and size Stuff """ Directional data derived from joints """ generalDirection = logic.returnHorizontalOrVertical(objects) if generalDirection == 'vertical' and 'leg' not in self.afModuleType.get(): worldUpVector = [0, 0, -1] elif generalDirection == 'vertical' and 'leg' in self.afModuleType.get(): worldUpVector = [0, 0, 1] else: worldUpVector = [0, 1, 0] #Get Size size = (distance.returnBoundingBoxSizeToAverage(objects[0]) * 2) #>>> Master Orient helper createBuffer = curves.createControlCurve('circleArrow1', (size * 2), 'z+') # make the curve curves.setCurveColorByName(createBuffer, moduleColors[0]) attributes.storeInfo(createBuffer, 'cgmType', 'templateOrientRoot') #copy the name attr mainOrientHelperObj = NameFactory.doNameObject(createBuffer) attributes.storeObjectToMessage( mainOrientHelperObj, self.msgTemplateRoot.get(), 'orientHelper') #store the object to it's respective object returnBuffer.append(mainOrientHelperObj) # Snapping position.movePointSnap(mainOrientHelperObj, root) constBuffer = mc.aimConstraint(objects[1], mainOrientHelperObj, maintainOffset=False, weight=1, aimVector=[1, 0, 0], upVector=[0, 1, 0], worldUpVector=worldUpVector, worldUpType='vector') mc.delete(constBuffer[0]) # Follow Groups mainOrientHelperGroupBuffer = rigging.groupMeObject(mainOrientHelperObj) mainOrientHelperGroupBuffer = NameFactory.doNameObject( mainOrientHelperGroupBuffer) mainOrientHelperGroup = rigging.doParentReturnName( mainOrientHelperGroupBuffer, root) mc.pointConstraint(objects[0], mainOrientHelperGroupBuffer, maintainOffset=False) helperObjectGroups.append(mainOrientHelperGroup) # set up constraints mc.aimConstraint(objects[-1], mainOrientHelperGroup, maintainOffset=True, weight=1, aimVector=[1, 0, 0], upVector=[0, 1, 0], worldUpObject=root, worldUpType='objectRotation') # lock and hide stuff attributes.doSetLockHideKeyableAttr( mainOrientHelperObj, True, False, False, ['tx', 'ty', 'tz', 'rz', 'ry', 'sx', 'sy', 'sz', 'v']) #>>> The sub helpers """ make our pair lists """ pairList = lists.parseListToPairs(objects) """ make our controls """ helperObjects = [] for pair in pairList: """ Get Size """ size = (distance.returnBoundingBoxSizeToAverage(pair[0]) * 2) """ make the curve""" createBuffer = curves.createControlCurve('circleArrow2Axis', size, 'y-') curves.setCurveColorByName(createBuffer, moduleColors[1]) """ copy the name attr""" attributes.copyUserAttrs(pair[0], createBuffer, ['cgmName']) attributes.storeInfo(createBuffer, 'cgmType', 'templateOrientObject') helperObj = NameFactory.doNameObject(createBuffer) """ store the object to it's respective object and to an object list """ attributes.storeObjectToMessage(helperObj, pair[0], 'orientHelper') helperObjects.append(helperObj) """ initial snapping """ position.movePointSnap(helperObj, pair[0]) constBuffer = mc.aimConstraint(pair[1], helperObj, maintainOffset=False, weight=1, aimVector=[1, 0, 0], upVector=[0, 1, 0], worldUpVector=worldUpVector, worldUpType='vector') mc.delete(constBuffer[0]) """ follow groups """ helperGroupBuffer = rigging.groupMeObject(helperObj) helperGroup = NameFactory.doNameObject(helperGroupBuffer) helperGroup = rigging.doParentReturnName(helperGroup, pair[0]) helperObjectGroups.append(helperGroup) """ set up constraints """ mc.aimConstraint(pair[1], helperGroup, maintainOffset=False, weight=1, aimVector=[1, 0, 0], upVector=[0, 1, 0], worldUpVector=[0, 1, 0], worldUpObject=mainOrientHelperObj, worldUpType='objectrotation') """ lock and hide stuff """ helperObj = attributes.returnMessageObject(pair[0], 'orientHelper') mc.connectAttr((visAttr), (helperObj + '.v')) attributes.doSetLockHideKeyableAttr( helperObj, True, False, False, ['tx', 'ty', 'tz', 'ry', 'rz', 'sx', 'sy', 'sz', 'v']) #>>> For the last object in the chain for obj in objects[-1:]: """ Get Size """ size = (distance.returnBoundingBoxSizeToAverage(obj) * 2) """ make the curve""" createBuffer = curves.createControlCurve('circleArrow2Axis', size, 'y-') curves.setCurveColorByName(createBuffer, moduleColors[1]) """ copy the name attr""" attributes.copyUserAttrs(obj, createBuffer, ['cgmName']) attributes.storeInfo(createBuffer, 'cgmType', 'templateOrientObject') helperObj = NameFactory.doNameObject(createBuffer) """ store the object to it's respective object """ attributes.storeObjectToMessage(helperObj, obj, 'orientHelper') """ initial snapping """ position.movePointSnap(helperObj, obj) constBuffer = mc.aimConstraint(objects[-2], helperObj, maintainOffset=False, weight=1, aimVector=[1, 0, 0], upVector=[0, 1, 0], worldUpVector=worldUpVector, worldUpType='vector') mc.delete(constBuffer[0]) """ follow groups """ helperGroupBuffer = rigging.groupMeObject(helperObj) helperGroup = NameFactory.doNameObject(helperGroupBuffer) helperGroup = rigging.doParentReturnName(helperGroup, obj) helperObjectGroups.append(helperGroup) """ set up constraints """ secondToLastHelperObject = attributes.returnMessageObject( objects[-2], 'orientHelper') mc.orientConstraint(secondToLastHelperObject, helperGroup, maintainOffset=False, weight=1) """ lock and hide stuff """ helperObj = attributes.returnMessageObject(obj, 'orientHelper') mc.connectAttr((visAttr), (helperObj + '.v')) attributes.doSetLockHideKeyableAttr( helperObj, True, False, False, ['tx', 'ty', 'tz', 'sx', 'sy', 'sz', 'v']) helperObjects.append(helperObj) returnBuffer.append(helperObjects) returnBuffer.append(helperObjectGroups) return returnBuffer