def add(self,objectList): ''' Adds the channel state attr to all specified objects @param objectList: List of objects to add flags to @type objectList: list ''' # Add Channel State Attrs for obj in objectList: # Check obj if not mc.objExists(obj): raise Exception('Object "'+obj+'" does not exist!') if not glTools.utils.transform.isTransform(obj): raise Exception('Object "'+obj+'" is not a valid transform!') if mc.objExists(obj+'.channelState'): print ('Object "'+obj+'" already has a "channelState" attribute! Skipping...') # Add channelState attr #mc.addAttr(obj,ln='channelState',at='enum',en=':Keyable:NonKeyable:Locked:',m=1,dv=-1) mc.addAttr(obj,ln='channelState',at='enum',en=':Keyable:NonKeyable:Locked:',m=1) # Set channelState flag values for i in range(len(self.channel)): if mc.getAttr(obj+'.'+self.channel[i],l=1): # Set Locked State mc.setAttr(obj+'.channelState['+str(i)+']',2) elif not mc.getAttr(obj+'.'+self.channel[i],k=1): # Set NonKeyable State mc.setAttr(obj+'.channelState['+str(i)+']',1) else: # Set Keyable State mc.setAttr(obj+'.channelState['+str(i)+']',0) # Alias Attribute mc.aliasAttr(self.channel[i]+'_state',obj+'.channelState['+str(i)+']')
def addPose(tangentBlend, baseGeo='', offsetGeo='', poseName=''): """ @param tangentBlend: @param baseGeo: @param offsetGeo: @param poseName: """ # Define suffix tags tangentBlend_baseTag = '_poseBase' tangentBlend_offsetTag = '_poseOffset' # Get connected geometry geo = findAffectedGeometry(tangentBlend) # Check pose geometry if not baseGeo: baseGeo = duplicateGeo(geo, geo + tangentBlend_baseTag) if not offsetGeo: baseGeo = duplicateGeo(geo, geo + tangentBlend_offsetTag) # Connect to deformer poseIndex = connectPose(baseGeo, offsetGeo, tangentBlend) # Alias pose name and set keyable if poseName: cmds.aliasAttr(poseName, tangentBlend + '.pose[' + str(poseIndex) + '].poseWeight') cmds.setAttr(tangentBlend + '.pose[' + str(poseIndex) + '].poseWeight', cb=True) cmds.setAttr(tangentBlend + '.pose[' + str(poseIndex) + '].poseWeight', k=True) return [baseGeo, offsetGeo]
def _disconnectAndRemoveAttr(attr, remove=False): """Disconnects inputs and outputs from the given attribute.""" sel = cmds.ls(sl=True) cmds.select(cl=True) # unlock if needed cmds.setAttr(attr, l=False) # if any connection, disconnect srcAttrs = cmds.listConnections(attr, d=False, p=True) or [] destAttrs = cmds.listConnections(attr, s=False, p=True) or [] for srcAttr in srcAttrs: cmds.disconnectAttr(srcAttr, attr) for destAttr in destAttrs: cmds.disconnectAttr(attr, destAttr) # remove element if remove: cmds.removeMultiInstance(attr) # remove alias if cmds.aliasAttr(attr, q=True): cmds.aliasAttr(attr, rm=True) cmds.select(sel or None)
def doAlias(self,arg): """ Set the alias of an attribute Keyword arguments: arg(string) -- name you want to use as an alias """ assert type(arg) is str or unicode,"Must pass string argument into doAlias" if arg: try: if arg != self.nameAlias: if mc.aliasAttr(arg,self.nameCombined): self.nameAlias = arg else: guiFactory.report("'%s.%s' already has that alias!"%(self.obj.nameShort,self.attr,arg)) except: guiFactory.warning("'%s.%s' failed to set alias of '%s'!"%(self.obj.nameShort,self.attr,arg)) else: if self.nameAlias: self.attr = self.nameLong mc.aliasAttr(self.nameCombined,remove=True) self.nameAlias = False self.updateData()
def setDefaultAttrState(objList,attrList,valueList=[]): ''' Set default attribute state values for a specified list of object attributes. @param objList: List of objects to store default attribute state values for. @type objList: list @param attrList: List of attributes to store default attribute state values for. @type attrList: list @param valueList: List of attributes values to assign to the default attribute states. If empty, use current object attribute values. @type valueList: list ''' # Check Object List if not objList: return if not attrList: return if len(attrList) != len(valueList): print ('Attribute and value list mis-match! Recording existing attribute values.') valueList = [] # Define defaultAttrState attribute name defAttr = 'defaultAttrState' aliasSuffix = 'defaultState' # For each object in list for obj in objList: # Check Object if not mc.objExists(obj): raise Exception('Object "'+obj+'" does not exist!') if not mc.attributeQuery(defAttr,n=obj,ex=True): addDefaultAttrState([obj]) # For each attribute in list for i in range(len(attrList)): # Get current attribute attr = attrList[i] attrAlias = attr+'_'+aliasSuffix # Check attribute if not mc.attributeQuery(attr,n=obj,ex=True): raise Exception('Object "'+obj+'" has no attribute "'+attr+'"!') # Get attribute value if valueList: value = valueList[i] else: value = mc.getAttr(obj+'.'+attr) # Add default attribute state if not mc.attributeQuery(attrAlias,n=obj,ex=True): try: index = mc.getAttr(obj+'.'+defAttr,s=True) except: print('Error getting multi length from "'+obj+'.'+defAttr+'"') mc.setAttr(obj+'.'+defAttr+'['+str(index)+']',0) try: mc.aliasAttr(attrAlias,obj+'.'+defAttr+'['+str(index)+']') except: print('Error setting attribute alias ("'+attrAlias+'") for node attr "'+obj+'.'+defAttr+'['+str(index)+']"') # Set default attribute state try: mc.setAttr(obj+'.'+attrAlias,value) except: print('Unable to set default attr state ("'+attrAlias+'") for object "'+obj+'" to value ('+str(value)+')!')
def init_module_trans(self,root_pos): ctrl_grp_file = os.environ["mlrig_tool"]+"/controlobjects/blueprint/controlGroup_control.ma" cmds.file(ctrl_grp_file, i=True) self.module_trans = cmds.rename("controlGroup_control", self.module_namespace+":module_transform") cmds.xform(self.module_trans, worldSpace=True, absolute=True, translation=root_pos) # mirroring method if self.mirrored: duplicate_transform = cmds.duplicate(self.original_module+":module_transform", parentOnly=True, name="TEMP_TRANSFORM")[0] empty_group = cmds.group(empty=True) cmds.parent(duplicate_transform, empty_group, absolute=True) scale_attr = ".scaleX" if self.mirror_plane == "XZ": scale_attr = ".scaleY" elif self.mirror_plane == "XY": scale_attr = ".scaleZ" cmds.setAttr(empty_group+scale_attr, -1) parent_constraint = cmds.parentConstraint(duplicate_transform, self.module_trans, maintainOffset=False) cmds.delete(parent_constraint) cmds.delete(empty_group) temp_locator = cmds.spaceLocator()[0] scale_constraint = cmds.scaleConstraint(self.original_module+":module_transform", temp_locator, maintainOffset=False)[0] scale = cmds.getAttr(temp_locator+".scaleX") cmds.delete([temp_locator, scale_constraint]) cmds.xform(self.module_trans, objectSpace=True, scale=[scale, scale, scale]) utils.add_node_to_container(self.container_name, self.module_trans, ihb=True) # Setup global scaling cmds.connectAttr(self.module_trans+".scaleY", self.module_trans+".scaleX") cmds.connectAttr(self.module_trans+".scaleY", self.module_trans+".scaleZ") cmds.aliasAttr("globalScale", self.module_trans+".scaleY") cmds.container(self.container_name, edit=True, publishAndBind=[self.module_trans+".translate", "moduleTransform_T"]) cmds.container(self.container_name, edit=True, publishAndBind=[self.module_trans+".rotate", "moduleTransform_R"]) cmds.container(self.container_name, edit=True, publishAndBind=[self.module_trans+".globalScale", "moduleTransform_globalScale"])
def createTemporaryGroupRepresentation(self): controlGrpFile = os.environ['RIGGING_TOOL_ROOT'] + '/ControlObjects/Blueprint/controlGroup_control.ma' cmds.file(controlGrpFile, i=True) self.tempGroupTransform = cmds.rename('controlGroup_control', 'Group_tempGroupTransform__') cmds.connectAttr((self.tempGroupTransform + '.scaleY'),(self.tempGroupTransform + '.scaleX')) cmds.connectAttr((self.tempGroupTransform + '.scaleY'),(self.tempGroupTransform + '.scaleZ')) for attr in ['scaleX', 'scaleZ','visibility']: cmds.setAttr((self.tempGroupTransform + '.' + attr), l=True, k=False) cmds.aliasAttr('globalScale', (self.tempGroupTransform + '.scaleY'))
def rename( self, oldName, newName ): '''will rename a blend shape target - if the target doesn't exist, the method does nothing...''' names = self.targets aliasList = cmd.aliasAttr(self.name,query=True) if oldName in names: idx = aliasList.index(oldName) aliasList[idx] = newName for n in range(1,len(aliasList),2): aliasList[n] = self.name +'.'+ aliasList[n] #now remove all the alias' for name in names: cmd.aliasAttr(self.name +'.'+ name,remove=True) #finally rebuild the alias' cmdStr = 'aliasAttr ' + ' '.join(aliasList) +';' maya.mel.eval(cmdStr)
def createTemporaryGroupRepresentation(self): #063 # Import a new transform controlGrpFile = os.environ["GEPPETTO"] + "/ControlObjects/Blueprint/controlGroup_control.ma" cmds.file(controlGrpFile, i=True) # rename the transform self.tempGroupTransform = cmds.rename("controlGroup_control", "Group__tempGroupTransform__") # Hook all scale attributes to scaleY cmds.connectAttr(self.tempGroupTransform+".scaleY", self.tempGroupTransform+".scaleX") cmds.connectAttr(self.tempGroupTransform+".scaleY", self.tempGroupTransform+".scaleZ") # Lock unused attributes for attr in ["scaleX", "scaleZ", "visibility"]: cmds.setAttr(self.tempGroupTransform+"."+attr, l=True, k=False) cmds.aliasAttr("globalScale", self.tempGroupTransform+".scaleY")
def create_temp_grp_representation(self): control_group_file = os.environ["mlrig_tool"]+"/controlobjects/blueprint/controlGroup_control.ma" cmds.file(control_group_file, i=True) self.temp_group_transform = cmds.rename("controlGroup_control", "Group__tempGroupTransform__") cmds.connectAttr(self.temp_group_transform+".scaleY", self.temp_group_transform+".scaleX") cmds.connectAttr(self.temp_group_transform+".scaleY", self.temp_group_transform+".scaleZ") for attr in ["scaleX", "scaleZ", "visibility"]: cmds.setAttr(self.temp_group_transform+"."+attr, keyable=False, lock=True) cmds.aliasAttr("globalScale", self.temp_group_transform+".scaleY")
def loadModuleControl(self, rootJoint): path = environ.ControlObjectsPath + "module_control.ma" cmds.file(path, i = True, ignoreVersion = True, renameAll=True, mergeNamespacesOnClash=True, namespace=':', options='v=0;') self.moduleControl = cmds.rename("module_control", self.moduleName + ":module_control") cmds.xform(self.moduleControl, ws = True, translation = cmds.xform(rootJoint, q = True, ws = True, a = True, translation = True) ) cmds.connectAttr(self.moduleControl + '.scaleY', self.moduleControl + '.scaleX') cmds.connectAttr(self.moduleControl + '.scaleY', self.moduleControl + '.scaleZ') cmds.aliasAttr('globalScale', self.moduleControl + '.scaleY') return
def connectInbetween( blendShapeObject = '' , blendShapeNode = '' , inbetweenBlendShape = '' , targetBlendShapeName = '' , weightValue = '' ) : # Add inbetween blend shape. aliasAttrList = mc.aliasAttr( blendShapeNode , q=True ) for each in aliasAttrList : if each == targetBlendShapeName : idx = aliasAttrList.index( each ) wStr = str( aliasAttrList[ idx+1 ] ) wIdx = re.findall( r'\d+' , wStr )[0] cmd = 'blendShape -e -ib -t %s %s %s %s %s;' % ( blendShapeObject , wIdx , inbetweenBlendShape , weightValue , blendShapeNode ) mm.eval( cmd )
def getObjAttrNames( obj, attrNamesToSkip=() ): #grab attributes objAttrs = cmd.listAttr( obj, keyable=True, visible=True, scalar=True ) or [] #also grab alias' - its possible to pass in an alias name, so we need to test against them as well aliass = cmd.aliasAttr( obj, q=True ) or [] #because the aliasAttr cmd returns a list with the alias, attr pairs in a flat list, we need to iterate over the list, skipping every second entry itAliass = iter( aliass ) for attr in itAliass: objAttrs.append( attr ) itAliass.next() filteredAttrs = [] for attr in objAttrs: skipAttr = False for skipName in attrNamesToSkip: if attr == skipName: skipAttr = True elif attr.startswith( skipName +'[' ) or attr.startswith( skipName +'.' ): skipAttr = True if skipAttr: continue filteredAttrs.append( attr ) return filteredAttrs
def getTargetIndex(blendShape, target): """ Get the target index of the specified blendShape and target name @param blendShape: Name of blendShape to get target index for @type blendShape: str @param target: BlendShape target to get the index for @type target: str """ # Check blendShape if not isBlendShape(blendShape): raise Exception('Object "' + blendShape + '" is not a valid blendShape node!') # Check target if not cmds.objExists(blendShape + '.' + target): raise Exception('Blendshape "' + blendShape + '" has no target "' + target + '"!') # Get attribute alias aliasList = cmds.aliasAttr(blendShape, q=True) aliasIndex = aliasList.index(target) aliasAttr = aliasList[aliasIndex + 1] # Get index targetIndex = int(aliasAttr.split('[')[-1].split(']')[0]) # Return result return targetIndex
def _buildPoseDict(self, nodes): ''' Build the internal poseDict up from the given nodes. This is the core of the Pose System ''' if self.metaPose: getMetaDict=self.metaRig.getNodeConnectionMetaDataMap # optimisation for i,node in enumerate(nodes): key=r9Core.nodeNameStrip(node) self.poseDict[key]={} self.poseDict[key]['ID']=i # selection order index self.poseDict[key]['longName']=node # longNode name if self.metaPose: self.poseDict[key]['metaData']=getMetaDict(node) # metaSystem the node is wired too channels=r9Anim.getSettableChannels(node,incStatics=True) if channels: self.poseDict[key]['attrs']={} for attr in channels: try: if cmds.getAttr('%s.%s' % (node,attr),type=True)=='TdataCompound': # blendShape weights support attrs=cmds.aliasAttr(node, q=True)[::2] # extract the target channels from the multi for attr in attrs: self.poseDict[key]['attrs'][attr]=cmds.getAttr('%s.%s' % (node,attr)) else: self.poseDict[key]['attrs'][attr]=cmds.getAttr('%s.%s' % (node,attr)) except: log.debug('%s : attr is invalid in this instance' % attr)
def _buildPoseDict(self, nodes): """ Build the internal poseDict up from the given nodes. This is the core of the Pose System """ if self.metaPose: getMetaDict = self.metaRig.getNodeConnectionMetaDataMap # optimisation for i, node in enumerate(nodes): key = r9Core.nodeNameStrip(node) self.poseDict[key] = {} self.poseDict[key]["ID"] = i # selection order index self.poseDict[key]["longName"] = node # longNode name if self.metaPose: self.poseDict[key]["metaData"] = getMetaDict(node) # metaSystem the node is wired too channels = r9Anim.getSettableChannels(node, incStatics=True) if channels: self.poseDict[key]["attrs"] = {} for attr in channels: if attr in self.skipAttrs: log.debug("Skipping attr as requested : %s" % attr) continue try: if ( cmds.getAttr("%s.%s" % (node, attr), type=True) == "TdataCompound" ): # blendShape weights support attrs = cmds.aliasAttr(node, q=True)[::2] # extract the target channels from the multi for attr in attrs: self.poseDict[key]["attrs"][attr] = cmds.getAttr("%s.%s" % (node, attr)) else: self.poseDict[key]["attrs"][attr] = cmds.getAttr("%s.%s" % (node, attr)) except: log.debug("%s : attr is invalid in this instance" % attr)
def initialiseModuleTransform(self, rootPos): controlGrpFile = os.environ['RIGGING_TOOL_ROOT'] + '/ControlObjects/Blueprint/controlGroup_control.ma' cmds.file(controlGrpFile, i=True) self.moduleTransform = cmds.rename('controlGroup_control', self.moduleNamespace + ':module_transform') cmds.xform(self.moduleTransform, worldSpace=True, absolute=True, translation=rootPos) if self.mirrored: duplicateTransform = cmds.duplicate(self.originalModule + ':module_transform', parentOnly=True,name='TEMP_TRANSFORM')[0] emptyGroup = cmds.group(empty=True) cmds.parent(duplicateTransform, emptyGroup, absolute=True) scaleAttr = '.scaleX' if self.mirrorPlane == 'XZ': scaleAttr = '.scaleY' elif self.mirrorPlane == 'XY': scaleAttr = '.scaleZ' cmds.setAttr((emptyGroup + scaleAttr), -1) parentConstraint = cmds.parentConstraint(duplicateTransform, self.moduleTransform, maintainOffset=False) cmds.delete(parentConstraint) cmds.delete(emptyGroup) tempLocator = cmds.spaceLocator()[0] scaleConstraint = cmds.scaleConstraint(self.originalModule + ':module_transform', tempLocator,maintainOffset=False)[0] scale = cmds.getAttr(tempLocator + '.scaleX') cmds.delete([tempLocator,scaleConstraint]) cmds.xform(self.moduleTransform, objectSpace=True, scale=[scale,scale,scale]) utils.addNodeToContainer(self.containerName, self.moduleTransform, ihb=True) #Setup global scaling cmds.connectAttr((self.moduleTransform + '.scaleY'),(self.moduleTransform + '.scaleX')) cmds.connectAttr((self.moduleTransform + '.scaleY'),(self.moduleTransform + '.scaleZ')) cmds.aliasAttr('globalScale', (self.moduleTransform + '.scaleY')) cmds.container(self.containerName, edit=True, publishAndBind=[(self.moduleTransform + '.translate'),'moduleTransform_T']) cmds.container(self.containerName, edit=True, publishAndBind=[(self.moduleTransform + '.rotate'),'moduleTransform_R']) cmds.container(self.containerName, edit=True, publishAndBind=[(self.moduleTransform + '.globalScale'),'moduleTransform_globalScale'])
def on_btn_builde_clicked(self, args=None): if args==None:return geometry = str(self.LET_Geometry.text()) blendShape = str(self.LET_BlendShape.text()) if not mc.objExists(geometry):return if not mc.objExists(blendShape):return #buildTargents(geometry, blendShape) targentList = mc.aliasAttr(blendShape, q=True) targentDict = {} for i in range(len(targentList)): if i % 2 != 0:continue targentDict[targentList[i]] = re.search('\d+', targentList[i+1]).group() #=========================================================== self.progressBar.setMinimum(0) self.progressBar.setMaximum(len(targentDict)) self.progressLabel.setText('0 / %d'%len(targentDict)) mc.setAttr('%s.en'%blendShape, 0) #=========================================================== #- builde v = 0 for name, index in targentDict.iteritems(): targent = mc.duplicate(geometry, n=name)[0] buildTargent(blendShape, targent, index) targentShape = mc.listRelatives(targent, s=True, path=True) mc.connectAttr('%s.worldMesh[0]'%targentShape[0], '%s.it[0].itg[%s].iti[6000].igt'%(blendShape, index), f=True) #-------------------------------------------------------------- v += 1 self.progressBar.setValue(v) self.progressLabel.setText('%d / %d'%(v, len(targentDict))) self.progressName.setText(targent) #-------------------------------------------------------------- #- move targents = targentList[::2] targents.sort() W = mc.getAttr('%s.bbmx'%geometry)[0][0] - mc.getAttr('%s.bbmn'%geometry)[0][0] H = mc.getAttr('%s.bbmx'%geometry)[0][1] - mc.getAttr('%s.bbmn'%geometry)[0][1] for i, targent in enumerate(targents): for attr in ('tx', 'ty', 'tz', 'rx', 'ry', 'rz', 'sx', 'sy', 'sz'): mc.setAttr('%s.%s'%(targent, attr), l=False, k=True, cb=True) mc.move(W*(i % 15), H*(i // 15 + 1), 0, targent, r=True) #================================================ self.progressBar.setMinimum(0) self.progressBar.setMaximum(1) self.progressLabel.setText('0 / 0') self.progressName.setText('{$targent}') mc.setAttr('%s.en'%blendShape, 1)
def rename(attr, name): """ Rename specified attribute """ # Check attribute if not mc.objExists(attr): raise Exception('Attribute "' + attr + '" does not exist!') # Rename (alias) attribute result = mc.aliasAttr(name, attr) # Return result return result
def getTargetIdx( self, target ): '''given a target name this method will return its index in the weight attribute''' indicies = [] aliasList = cmd.aliasAttr(self.name,query=True) if aliasList == None: raise Exception( "not aliasAttr found on %s"%(self.name,)) for n in range(0,len(aliasList),2): if aliasList[n] == target: idx = aliasList[n+1][7:][:-1] return int(idx) raise AttributeError("target doesn't exist")
def _getTargetNames(rbsNode, idx=-1): if idx == -1: idxList = _getTargetIndices(rbsNode) return [_getTargetNames(rbsNode, i) for i in idxList] alias = cmds.aliasAttr('%s.%s[%d]' % (rbsNode, _rbsAttrs[0], idx), q=True) if not alias: return _unnamed elif alias.endswith(_nameSfx[0]): return alias[:-len(_nameSfx[0])] return alias
def renameTarget(blendShape, target, newName): """ Rename the specified blendShape target @param blendShape: Name of blendShape to rename target from @type blendShape: str @param target: BlendShape target to rename @type target: str @param newName: New name for the blendShape target @type newName: str """ # Check blendShape if not isBlendShape(blendShape): raise Exception('Object "' + blendShape + '" is not a valid blendShape node!') # Check target if not hasTarget(blendShape, target): raise Exception('BlendShape "' + blendShape + '" has no target "' + target + '"!') # Rename target attribute cmds.aliasAttr(newName, blendShape + '.' + target) # Return Result return newName
def addEyeCmd(): """Adds new eyelid inputs.""" geo = _getGeoFromUI() rbsNode = geo and _getRbs(geo) prfx = cmds.layoutDialog(t='Add eye', ui=lambda *x: _addEyeDialog(rbsNode)) if len(prfx) > 1: return # find first available lower lid index miList = _getEyeIdxList(rbsNode) idx = 0 while idx in miList or (idx+1) in miList: idx += 2 lowerAttr = '%s.it[%d]' % (rbsNode, idx) upperAttr = '%s.it[%d]' % (rbsNode, idx+1) lowerName = '%s_lower' % prfx upperName = '%s_upper' % prfx # add lower and upper indices cmds.getAttr('%s.im' % lowerAttr) cmds.getAttr('%s.im' % upperAttr) # set the aliases for the inputTarget attributes (lower and upper) if cmds.aliasAttr(lowerAttr, q=True) != lowerName: _setAlias(lowerAttr, lowerName) if cmds.aliasAttr(upperAttr, q=True) != upperName: _setAlias(upperAttr, upperName) # create and connect locators _createEyeLocators(rbsNode, idx) # update tab ui _updateUI() _selectTab(prfx)
def getTargetName(blendShape, targetGeo): """ Get blendShape target alias for specified target geometry @param blendShape: BlendShape node to get target name from @type blendShape: str @param targetGeo: BlendShape target geometry to get alia name for @type targetGeo: str """ # ========== # - Checks - # ========== # BlendShape if not isBlendShape(blendShape): raise Exception('Object "' + blendShape + '" is not a valid blendShape node!') # Target if not cmds.objExists(targetGeo): raise Exception('Target geometry "' + targetGeo + '" does not exist!') # =================== # - Get Target Name - # =================== # Get Target Shapes targetShape = glTools.utils.shape.getShapes(targetGeo, nonIntermediates=True, intermediates=False) if not targetShape: targetShape = cmds.ls(cmds.listRelatives(targetGeo, ad=True, pa=True), shapes=True, noIntermediate=True) if not targetShape: raise Exception('No shapes found under target geometry "' + targetGeo + '"!') # Find Target Connection targetConn = cmds.listConnections(targetShape, sh=True, d=True, s=False, p=False, c=True) if not targetConn.count(blendShape): raise Exception('Target geometry "' + targetGeo + '" is not connected to blendShape "' + blendShape + '"!') targetConnInd = targetConn.index(blendShape) targetConnAttr = targetConn[targetConnInd - 1] targetConnPlug = cmds.listConnections(targetConnAttr, sh=True, p=True, d=True, s=False)[0] # Get Target Index targetInd = int(targetConnPlug.split('.')[2].split('[')[1].split(']')[0]) # Get Target Alias targetAlias = cmds.aliasAttr(blendShape + '.weight[' + str(targetInd) + ']', q=True) # ================= # - Return Result - # ================= return targetAlias
def on_btn_FixSkinBsStart_clicked(self, clicked=None): if clicked == None:return openCloseDeformer(self.__baseModel, 0, ('skinCluster')) self.duplicateScupModel() openCloseDeformer(self.__baseModel, 1, ('skinCluster')) bs = mc.blendShape(self.__baseModel, self.__sculpmodel)[0] attr = mc.aliasAttr(bs, q=True)[0] mc.setAttr(bs + '.' + attr, 1) mc.delete(self.__sculpmodel, ch=True) openCloseDeformer(self.__baseModel, 0, ('skinCluster')) self.dupliacteTempModel()
def getBlendShapeInfo(blendShape): ''' return blendShape's ID and attributes dict.. ''' attribute_dict = {} if mc.nodeType(blendShape) != 'blendShape': return attribute_dict infomations = mc.aliasAttr(blendShape, q=True) for i in range(len(infomations)): if i % 2 == 1:continue bs_id = infomations[i + 1] bs_attr = infomations[i + 0] bs_id = int(re.search('\d+', bs_id).group()) attribute_dict[bs_id] = bs_attr return attribute_dict
def __getTargetNameandIndicies( self ): '''returns a list of the target names on the blendshape. both the index list and the name list are guaranteed to be in the correct order''' indicies = [] aliasList = cmd.aliasAttr(self.name,query=True) if aliasList == None: return [] for n in range(1,len(aliasList),2): idx = int(aliasList[n][7:][:-1]) indicies.append(idx) indicies.sort() names = [None]*len(indicies) #build the name array of the correct size for n in range(0,len(aliasList),2): curNameIdx = int(aliasList[n+1][7:][:-1]) for i in range(len(indicies)): if curNameIdx == indicies[i]: names[i] = aliasList[n] return names,indicies
def setTargetWeights(blendShape, target, wt, geometry=''): """ Set per vertex target weights for the specified blendShape target @param blendShape: Name of blendShape to set target weights for @type blendShape: str @param target: Name of blendShape target to set weights for @type target: str @param wt: Weight value list to apply to the specified blendShape target @type wt: list @param geometry: Name of blendShape driven geometry to set weights on @type geometry: str """ # Check blendShape if not isBlendShape(blendShape): raise Exception('Object "' + blendShape + '" is not a valid blendShape node!') # Check target if not cmds.objExists(blendShape + '.' + target): raise Exception('blendShape "' + blendShape + '" has no "' + target + '" target attribute!') # Check geometry if geometry and not cmds.objExists(geometry): raise Exception('Object "' + geometry + '" does not exist!') # Get target index aliasList = cmds.aliasAttr(blendShape, q=True) aliasTarget = aliasList[(aliasList.index(target) + 1)] targetIndex = aliasTarget.split('[')[-1] targetIndex = int(targetIndex.split(']')[0]) # Get geometry index into blendShape geomIndex = 0 if geometry: geomIndex = glTools.utils.deformer.getGeomIndex(geometry, blendShape) # Get number of geometry components compCount = glTools.utils.component.getComponentCount(geometry) # Set target weights cmds.setAttr( blendShape + '.it[' + str(geomIndex) + '].itg[' + str(targetIndex) + '].tw[0:' + str(compCount - 1) + ']', *wt)
def LRBlendShapeWeight(self, lipCrv, lipCrvBS): cvs = cmds.ls(lipCrv+'.cv[*]', fl =1) length = len (cvs) increment = 1.0/(length-1) targets = cmds.aliasAttr( lipCrvBS, q=1) tNum = len(targets) for t in range(0, tNum, 2): if targets[t][0] == 'l' : indexL=re.findall('\d+', targets[t+1]) cmds.setAttr(lipCrvBS + '.inputTarget[0].inputTargetGroup[%s].targetWeights[%s]'%(str(indexL[0]), str(length/2)), .5 ) for i in range(0, length/2): cmds.setAttr(lipCrvBS + '.inputTarget[0].inputTargetGroup[%s].targetWeights[%s]'%(str(indexL[0]), str(i)), 0 ) cmds.setAttr(lipCrvBS + '.inputTarget[0].inputTargetGroup[%s].targetWeights[%s]'%(str(indexL[0]), str(length-i-1)), 1 ) if targets[t][0] == 'r' : indexR=re.findall('\d+', targets[t+1]) cmds.setAttr(lipCrvBS + '.inputTarget[0].inputTargetGroup[%s].targetWeights[%s]'%(str(indexR[0]), str(length/2)), .5 ) for i in range(0, length/2): cmds.setAttr(lipCrvBS + '.inputTarget[0].inputTargetGroup[%s].targetWeights[%s]'%(str(indexR[0]), str(i)), 1 ) cmds.setAttr(lipCrvBS + '.inputTarget[0].inputTargetGroup[%s].targetWeights[%s]'%(str(indexR[0]), str(length-i-1)), 0 )
def copyPose(fromNode, toNode, flip=False): attrs = mc.listAttr(fromNode, keyable=True) if not attrs: return #if attributes are aliased, get the real names for mirroring axis aliases = mc.aliasAttr(fromNode, query=True) if aliases: for alias,real in zip(aliases[::2],aliases[1::2]): if alias in attrs: attrs.remove(alias) attrs.append(real) axis = getMirrorAxis(toNode) for attr in attrs: if attr == 'mirrorAxis': continue if not mc.attributeQuery(attr, node=toNode, exists=True): continue fromPlug = '{}.{}'.format(fromNode, attr) toPlug = '{}.{}'.format(toNode, attr) fromValue = mc.getAttr(fromPlug) toValue = mc.getAttr(toPlug) if attr in axis: fromValue *= -1.0 toValue *= -1.0 try: utl.setAnimValue(toPlug, fromValue) except:pass if flip: try: utl.setAnimValue(fromPlug, toValue) except:pass
def loadConnections(self, simp, create=True, multiplier=1): # Build/create any shapes #shapes = set() #for i in [simp.combos, simp.sliders]: #for c in i: #for p in c.prog.pairs: #shapes.add(p.shape) shapes = simp.shapes if not shapes: shapes.append(simp.buildRestShape()) aliases = cmds.aliasAttr(self.shapeNode, query=True) or [] aliasDict = dict(zip(aliases[1::2], aliases[::2])) doFullRename = False for shapeIdx, shape in enumerate(shapes): weightAttr = "{0}.weights[{1}]".format(self.op, shapeIdx) cnxs = cmds.listConnections(weightAttr, plugs=True, source=False) shapeName = "{0}.{1}".format(self.shapeNode, shape.name) if not cnxs: # no current connection exists, check by name s = cmds.ls(shapeName) if not s: # no connection exists, and no destination found, I should create it if not create: raise RuntimeError("Shape {0} not found with creation turned off".format(shape.name)) shp = self.createRawShape(shape.name, shape) cmds.delete(shp) else: # no connection exists, but a destination exists by name # so connect it shape.thing = s[0] if not cmds.isConnected(weightAttr, shape.thing): # at this point, it shouldn't be connected, but check anyway cmds.connectAttr(weightAttr, shape.thing, force=True) else: # a connection already exists, so we'll assume that's correct if len(cnxs) > 1: # Multiple connections to this weight exist ... WTF DUDE?? raise RuntimeError("One Simplex weight is connected to multiple blendshapes: {0}: {1}".format(weightAttr, cnxs)) cnx = cnxs[0] if cnx != shapeName: # doublecheck the aliases as well # here we have a badly named shape # I hope that some other shape doesn't already have this name print "Got Name: {0} But Expected: {1}".format(cnx, shapeName) #weightName = "weight[{0}]".format(shapeIdx) #alias = aliasDict.get(weightName) #aliasName = "{0}.{1}".format(self.shapeNode, alias) #cmds.aliasAttr(shape.name, aliasName) #cnx = shapeName doFullRename = True shape.thing = cnx if doFullRename: # TODO: Maybe put this into its own method print "Bad Shape Names Found, Refreshing Blendshape Aliases" aliasNames = aliasDict.values() remAliases = map('.'.join, zip([self.shapeNode]*len(aliasDict), aliasDict.values())) cmds.aliasAttr(remAliases, remove=True) for shapeIdx, shape in enumerate(shapes): weightAttr = "{0}.weights[{1}]".format(self.op, shapeIdx) cnxs = cmds.listConnections(weightAttr, plugs=True, source=False) cmds.aliasAttr(shape.name, cnxs[0]) # Build/connect any sliders for slider in simp.sliders: things = cmds.ls("{0}.{1}".format(self.ctrl, slider.name)) if not things: if not create: raise RuntimeError("Slider {0} not found with creation turned off".format(slider.name)) self.createSlider(slider.name, slider, multiplier) else: slider.thing = things[0]
def renameShape(self, shape, name): """ Change the name of the shape """ cmds.aliasAttr(name, shape.thing) shape.thing = "{0}.{1}".format(self.shapeNode, name)
def createCorrective(self, mode, *args): '''# remove heads up display cmds.headsUpDisplay('sculptModeDisplay', remove = True)''' '''# off the isolate curPanel = cmds.paneLayout('viewPanes', q = True, pane1= True) cmds.isolateSelect(curPanel, state = False)''' # show skin geometry cmds.setAttr('%s.visibility' % self.skinGeo, True) self.vtxDeltaDic = {} sculptVtxFinVecDic = {} sculptVtxPointDic = {} inverseVtxPosDic = {} # get skin cluster cmds.select(self.skinGeo, r=True) mel.eval('string $selList[] = `ls -sl`;') mel.eval('string $source = $selList[0];') self.skinCluster = mel.eval('findRelatedSkinCluster($source);') # get number of vertex vtxNum = cmds.polyEvaluate(self.skinGeo, v=True) # progress window cmds.progressWindow(title='Creating Corrective Shape', maxValue=vtxNum, status='stand by', isInterruptable=True) # get the delta that between sculpted geometry and skin geometry for i in xrange(vtxNum): if cmds.progressWindow(q=True, isCancelled=True): break cmds.progressWindow(e=True, step=1, status='calculating delta...') sculptVtxPos = cmds.pointPosition('%s.vtx[%d]' % (self.sculptGeo, i), world=True) sculptVtxVec = OpenMaya.MVector(*sculptVtxPos) skinVtxPos = cmds.pointPosition('%s.vtx[%d]' % (self.skinGeo, i), world=True) skinVtxVec = OpenMaya.MVector(*skinVtxPos) delta = sculptVtxVec - skinVtxVec # if vertex didn't move, skip if delta.length() < 0.001: continue self.vtxDeltaDic[i] = delta cmds.progressWindow(e=True, progress=0, status='calculating delta...') # set envelop to 0 about all deformers without skin cluster of skin geometry allConnections = cmds.listHistory(self.skinGeo) for item in allConnections: if cmds.objectType(item) in self.deformerList: cmds.setAttr('%s.envelope' % item, 0) # reset progression window maxValue cmds.progressWindow(e=True, maxValue=len(self.vtxDeltaDic)) # get vertex position that skin cluster plus delta for i in self.vtxDeltaDic.keys(): if cmds.progressWindow(q=True, isCancelled=True): break cmds.progressWindow( e=True, step=1, status='calculating final sculpt vtx position...') skinVtxPos = cmds.pointPosition('%s.vtx[%d]' % (self.skinGeo, i), world=True) skinVtxVec = OpenMaya.MVector(*skinVtxPos) sculptVtxFinVecDic[i] = skinVtxVec + self.vtxDeltaDic[i] sculptVtxPointDic[i] = OpenMaya.MPoint(sculptVtxFinVecDic[i].x, sculptVtxFinVecDic[i].y, sculptVtxFinVecDic[i].z) cmds.progressWindow(e=True, progress=0, status='calculating final sculpt vtx position...') # get inversed vertex position for i in self.vtxDeltaDic.keys(): if cmds.progressWindow(q=True, isCancelled=True): break cmds.progressWindow(e=True, step=1, status='calculating inverse matrix...') # set matrix pallete matrixPallete = OpenMaya.MMatrix() matrixPalletInitList = [ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ] OpenMaya.MScriptUtil.createMatrixFromList(matrixPalletInitList, matrixPallete) # get influences influenceList = cmds.skinCluster('%s.vtx[%d]' % (self.skinGeo, i), q=True, wi=True) # for each influence get the matrix and multiply inverse matrix for influence in influenceList: infBindMatrixList = cmds.getAttr('%s.bindPose' % influence) infWorldMatrixList = cmds.getAttr('%s.worldMatrix' % influence) infWeight = cmds.skinPercent(self.skinCluster, '%s.vtx[%d]' % (self.skinGeo, i), q=True, transform=influence, v=True) if infWeight == 0.0: continue infBindMatrix = OpenMaya.MMatrix() OpenMaya.MScriptUtil.createMatrixFromList( infBindMatrixList, infBindMatrix) infWorldMatrix = OpenMaya.MMatrix() OpenMaya.MScriptUtil.createMatrixFromList( infWorldMatrixList, infWorldMatrix) matrixPallete += (infBindMatrix.inverse() * infWorldMatrix) * infWeight inverseVtxPosDic[i] = sculptVtxPointDic[i] * matrixPallete.inverse( ) cmds.progressWindow(e=True, progress=0, status='calculating inverse matrix...') # on eidt mode, replace poseName to selTrg if mode == 'editMode': self.poseName = cmds.textScrollList('r_poseTexScrList', q=True, selectItem=True)[0] if mode != 'editMode': # get corrective geometry by duplicating skin geometry with skinCluster envelope 0 cmds.setAttr('%s.envelope' % self.skinCluster, 0) cmds.duplicate(self.skinGeo, n=self.poseName) # delete intermediate shape shapList = cmds.ls(self.poseName, dag=True, s=True) for shap in shapList: if cmds.getAttr('%s.intermediateObject' % (shap)): cmds.delete(shap) # set corrective shape's vertex position if mode != 'editMode': for i in self.vtxDeltaDic.keys(): if cmds.progressWindow(q=True, isCancelled=True): break cmds.progressWindow( e=True, step=1, status='calculating corrective vtx position...') cmds.xform('%s.vtx[%d]' % (self.poseName, i), ws=True, t=(inverseVtxPosDic[i].x, inverseVtxPosDic[i].y, inverseVtxPosDic[i].z)) elif mode == 'editMode': for i in self.vtxDeltaDic.keys(): if cmds.progressWindow(q=True, isCancelled=True): break cmds.progressWindow( e=True, step=1, status='calculating facial target vtx position...') # get vertex position that no assigned deformer cmds.setAttr('%s.envelope' % self.skinCluster, 0) skinVtxPos = cmds.pointPosition('%s.vtx[%d]' % (self.skinGeo, i), world=True) # get modified vertex vector modifiedVtxPos = [(inverseVtxPosDic[i].x - skinVtxPos[0]), (inverseVtxPosDic[i].y - skinVtxPos[1]), (inverseVtxPosDic[i].z - skinVtxPos[2])] # add modified vertex vector to original target vertex vector facialTrgVtxPos = cmds.pointPosition('%s.vtx[%d]' % (self.poseName, i), world=True) finalVtxPos = [(facialTrgVtxPos[0] + modifiedVtxPos[0]), (facialTrgVtxPos[1] + modifiedVtxPos[1]), (facialTrgVtxPos[2] + modifiedVtxPos[2])] # set final vertex position cmds.xform('%s.vtx[%d]' % (self.poseName, i), ws=True, t=finalVtxPos) cmds.progressWindow(endProgress=True) # all deformer's envelope set to 1 of skin geometry cmds.setAttr('%s.envelope' % self.skinCluster, 1) allConnections = cmds.listHistory(self.skinGeo) for item in allConnections: if cmds.objectType(item) in self.deformerList: cmds.setAttr('%s.envelope' % item, 1) # add corrective geometry to geo_grp if mode != 'editMode': corGeoGrpName = self.skinGeo + '_corrective_geo_grp' if cmds.objExists(corGeoGrpName): cmds.parent(self.poseName, corGeoGrpName) cmds.setAttr('%s.visibility' % self.poseName, False) else: cmds.createNode('transform', n=corGeoGrpName) cmds.parent(self.poseName, corGeoGrpName) cmds.setAttr('%s.visibility' % self.poseName, False) # delete sculpt geometry cmds.delete(self.sculptGeo) if mode != 'editMode': # add corrective to blend shape node if cmds.objExists(self.bsName): bsAttrList = cmds.aliasAttr(self.bsName, q=True) weightNumList = [] for bsAttr in bsAttrList: if 'weight' in bsAttr: reObj = re.search(r'\d+', bsAttr) weightNum = reObj.group() weightNumList.append(int(weightNum)) bsIndex = max(weightNumList) + 1 cmds.blendShape(self.bsName, edit=True, target=(self.skinGeo, bsIndex, self.poseName, 1.0)) cmds.setAttr('%s.%s' % (self.bsName, self.poseName), 1) # refresh pose list self.populatePoseList() else: cmds.blendShape(self.poseName, self.skinGeo, n=self.bsName, frontOfChain=True)[0] cmds.setAttr('%s.%s' % (self.bsName, self.poseName), 1) # refresh pose list self.populatePoseList() # get data for pose reader driverJoint = cmds.textFieldButtonGrp('jntTexButGrp', q=True, text=True) parentJoint = cmds.textFieldButtonGrp('prntJointTexBtnGrp', q=True, text=True) locatorJoint = cmds.textFieldButtonGrp('locJointTexBtnGrp', q=True, text=True) # pose reader self.poseReader(driverJoint, parentJoint, locatorJoint, self.poseName) # mirror mirOpt = cmds.checkBox('mirChkBox', q=True, v=True) if mirOpt: # create fliped opposite side geometry flipGeo = self.flipGeo() # add opposite corrective to the blend shape node bsAttrList = cmds.aliasAttr(self.bsName, q=True) weightNumList = [] for bsAttr in bsAttrList: if 'weight' in bsAttr: reObj = re.search(r'\d+', bsAttr) weightNum = reObj.group() weightNumList.append(int(weightNum)) bsIndex = max(weightNumList) + 1 cmds.blendShape(self.bsName, edit=True, target=(self.skinGeo, bsIndex, flipGeo, 1.0)) cmds.setAttr('%s.%s' % (self.bsName, flipGeo), 1) # refresh pose list self.populatePoseList() # get data for opposite side pose reader jntSearchTex = cmds.textFieldGrp('jntSrchTexFld', q=True, text=True) jntReplaceTex = cmds.textFieldGrp('jntRplcTexFld', q=True, text=True) oppoDriverJnt = re.sub(jntSearchTex, jntReplaceTex, driverJoint, 1) oppoParentJnt = re.sub(jntSearchTex, jntReplaceTex, parentJoint) oppolocatorJnt = re.sub(jntSearchTex, jntReplaceTex, locatorJoint, 1) # set opposite side pose srcRo = cmds.getAttr('%s.rotate' % (driverJoint))[0] srcRo = (srcRo[0], -srcRo[1], srcRo[2]) cmds.setAttr('%s.rotate' % (oppoDriverJnt), *srcRo) # create opposite side pose reader self.poseReader(oppoDriverJnt, oppoParentJnt, oppolocatorJnt, flipGeo) self.populatePoseList()
def genMatrix(blendShapeNode, deformedGeometry=None, resultPos=None, resultInd=None, targetName=None): """ This procedure is meant to return transform matrices which describe how a 1-unit offset in each X, Y, Z direction actually transforms to an offset at the end of the subsequent deformer stack. :param str blendShapeNode: the blendShape node whose offsets are in question :param str deformedGeometry: the name of the mesh that's deformed by blendShapeNode :param str targetName: the name of the blendShape target :param list resultPos: the default positions of the points in resultCmp :param list resultInd: the indices of the points in resultCmp. For resultCmp element "<mesh>.vtx[5]", its resultInd element would be 5, for example. """ removeTarget = False if not targetName: targetName = 'CORRECTIVE_DUMMY_TARGET' removeTarget = True # initialize empty shape data shapeData = bs.getEmptyShapeData() shape = bs.getEmptyShape() shapeData['shapes'][targetName] = shape shape['offsets'] = {} if not mc.objExists('%s.%s' % (blendShapeNode, targetName)): shapeIndex = 0 weightIndices = mc.getAttr(blendShapeNode + ".weight", multiIndices=True) if weightIndices: shapeIndex = weightIndices[-1] + 1 attr = '%s.weight[%i]' % (blendShapeNode, shapeIndex) mc.getAttr(attr) mc.aliasAttr(targetName, attr) mc.setAttr(attr, 1.0) # get the x, y and z basis vectors for each point perAxisUnitOffsetVectors = [(1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 1.0)] # X, Y, Z. axes = [] for ii in range(3): for ind in resultInd: shape['offsets'][ind] = perAxisUnitOffsetVectors[ii] bs.setBlendShapeData(blendShapeNode, shapeData) currentAxisOffsetPos = getPositions(deformedGeometry) newCurrentAxisOffsetPos = [currentAxisOffsetPos[j] for j in resultInd] currentAxes = [ e[0] - e[1] for e in zip(newCurrentAxisOffsetPos, resultPos) ] axes.append(currentAxes) if removeTarget: mc.aliasAttr(blendShapeNode + '.' + targetName, remove=True) mc.removeMultiInstance(blendShapeNode + '.weight[' + str(shapeIndex) + ']', b=True) mc.removeMultiInstance(blendShapeNode + '.inputTarget[0].inputTargetGroup[' + str(shapeIndex) + '].inputTargetItem[6000]') mc.removeMultiInstance(blendShapeNode + '.inputTarget[0].inputTargetGroup[' + str(shapeIndex) + ']') xAxes = axes[0] yAxes = axes[1] zAxes = axes[2] nonInvertablePoints = [] nonInvertablePointsSet = set() # use the basis vectors to compute the final position # calculate the shapeMatrix first: matrices = {} for index, xAxis, yAxis, zAxis in itertools.izip(resultInd, xAxes, yAxes, zAxes): shapeMatrix = numpy.array([[xAxis[0], xAxis[1], xAxis[2], 0], [yAxis[0], yAxis[1], yAxis[2], 0], [zAxis[0], zAxis[1], zAxis[2], 0], [0, 0, 0, 1]]) matrices[index] = shapeMatrix result = {} result['matrices'] = matrices invShapeMatrices = {} # calculate the invShapeMatrix first: invShapeMatrices, nonInvertablePointsSet, nonInvertablePoints = invertMatrices( matrices) result['invShapeMatrices'] = invShapeMatrices result['nonInvertablePoints'] = nonInvertablePoints result['nonInvertablePointsSet'] = nonInvertablePointsSet return result
def copy_blendshape_node(node, target): """ Copies the given blendshape node into the given target shape :param node: blendshape node :type node: str :param target: target shape node :type target: str :return: copied blenshape node :rtype: str """ logger.debug("Copying blendshape node {} to {}".format(node, target)) # get blendshape targets indices targets_idx = cmds.getAttr("{}.weight".format(node), multiIndices=True) # skip node if no targets where found if not targets_idx: return # list for ignored targets (when they are live connected) ignore = [] # creates blendshape deformer node on target node_copy = cmds.deformer(target, type="blendShape", name="flex_copy_{}".format(node))[0] # loop on blendshape targets indices for idx in targets_idx: # input target group attribute attr_name = (BLENDSHAPE_TARGET.format(node, idx)) # blendshape target name target_name = cmds.aliasAttr("{}.weight[{}]".format(node, idx), query=True) # checks for empty target if not cmds.getAttr(attr_name, multiIndices=True): continue # loop on actual targets and in-between targets for target in cmds.getAttr(attr_name, multiIndices=True): # target attribute name target_attr = "{}[{}]".format(attr_name, target) # checks for incoming connections on the geometry target if cmds.listConnections("{}.inputGeomTarget".format(target_attr), destination=False): logger.warning("{} can't be updated because it is a live " "target".format(target_name)) ignore.append(idx) continue # updates node copy target destination = target_attr.replace( target_attr.split(".")[0], node_copy) cmds.connectAttr(target_attr, destination, force=True) cmds.disconnectAttr(target_attr, destination) # skips updating target name if this was a life target if idx in ignore: continue # forces the weight attribute to be shown on the blendshape node cmds.setAttr("{}.weight[{}]".format(node_copy, idx), 0) # updates blendshape node attribute name if target_name: cmds.aliasAttr(target_name, "{}.weight[{}]".format(node_copy, idx)) # gets targets on copied node to see if there is any node with zero target idx = cmds.getAttr("{}.weight".format(node_copy), multiIndices=True) if not idx: cmds.delete(node_copy) return return node_copy
def ribbonize(surf_tr, equal=1, num_of_ctrls=5, num_of_jnts=29, prefix="", constrain=1, add_fk=0, wire=0): attrs = [ ".tx", ".ty", ".tz", ".rx", ".ry", ".rz", ".sx", ".sy", ".sz", ".v" ] if prefix == "": mc.warning("care to name it?") return else: prefix = prefix + "_" ##################################################### surf_tr = mc.rename(surf_tr, prefix + "ribbon_surface") surf = mc.listRelatives(surf_tr, shapes=True)[0] # freeze transformations and delete the surface history mc.makeIdentity(surf_tr, t=True, r=True, s=True, apply=True) mc.delete(surf_tr, ch=True) # duplicate surface curves to determine the direction u_curve = mc.duplicateCurve(surf_tr + ".v[.5]", local=True, ch=0) v_curve = mc.duplicateCurve(surf_tr + ".u[.5]", local=True, ch=0) # delete the history just in case mc.delete(surf_tr, ch=True) u_length = mc.arclen(u_curve) v_length = mc.arclen(v_curve) if u_length < v_length: mc.reverseSurface(surf_tr, d=3, ch=False, rpo=True) mc.reverseSurface(surf_tr, d=0, ch=False, rpo=True) parameter = ".parameterU" other_param = ".parameterV" # correct u_curve after reversing to calculate the length u_curve_corr = mc.duplicateCurve(surf_tr + ".v[.5]", local=True, ch=0)[0] ############################################################################# # selected surface is periodic or open? (cylinder or a plane) if mc.getAttr(surf + ".formU") == 2 or mc.getAttr(surf + ".formV") == 2: curve_type = "periodic" divider_for_ctrls = num_of_ctrls elif mc.getAttr(surf + ".formU") == 0 or mc.getAttr(surf + ".formV") == 0: curve_type = "open" divider_for_ctrls = num_of_ctrls - 1 ############################################################################# param_ctrls = param_from_length(u_curve_corr, num_of_ctrls, curve_type, "uv") param_joints = param_from_length(u_curve_corr, num_of_jnts, curve_type, "uv") length = mc.arclen(u_curve_corr) mc.delete(u_curve, v_curve, u_curve_corr) ############################################################################ # create groups, main control and main control offset final_group = mc.group(n=prefix + "ribbon_grp", em=True) ctrl_joints_grp = mc.group(n=prefix + "ctrl_joints_grp", em=True) ctrl_grp = mc.group(n=prefix + "ctrls_grp", em=True) follicles_grp = mc.group(n=prefix + "follicles_grp", em=True) rig_grp = mc.group(n=prefix + "rig_grp", em=True) main_ctrl = mc.circle(n=prefix + "ctrl_main", nr=(0, 1, 0), r=length / 5, ch=0)[0] main_ctrl_offset = mc.group(n=prefix + "ctrl_main_offset", em=True) mc.parent(main_ctrl, main_ctrl_offset) mc.parent(ctrl_grp, main_ctrl) mc.parent(main_ctrl_offset, rig_grp, final_group) mc.parent(surf_tr, ctrl_joints_grp, follicles_grp, rig_grp) # move main_ctrl_offset to the center of the surfaces bbox (in case its pivot is somewhere else) mid_point = get_bbox_center(surf_tr) for attr, mid_pnt_el in izip(attrs[:3], mid_point): mc.setAttr(main_ctrl_offset + attr, mid_pnt_el) ############################################################################ fols = [] fols_tr = [] bind_jnts = [] bnd_joints_rad = (length / 60) / (float(num_of_jnts) / 40) for x in range(num_of_jnts): fol = mc.createNode("follicle") mc.setAttr(fol + ".visibility", 0) temp_fol = mc.listRelatives(fol, p=True)[0] fols_tr.append( mc.rename(temp_fol, "{}follicle_{:02d}".format(prefix, x + 1))) fols.append(mc.listRelatives(fols_tr[-1], s=True)[0]) # connect follicle shapes to their transforms mc.connectAttr(fols[-1] + ".outTranslate", fols_tr[-1] + ".translate", f=True) mc.connectAttr(fols[-1] + ".outRotate", fols_tr[-1] + ".rotate", f=True) # attach follicle shapes to the surface mc.connectAttr(surf + ".worldMatrix[0]", fols[-1] + ".inputWorldMatrix") mc.connectAttr(surf + ".local", fols[-1] + ".inputSurface") mc.setAttr(fols[-1] + parameter, param_joints[x]) mc.setAttr(fols[-1] + other_param, 0.5) mc.parent(fols_tr[-1], follicles_grp) # create final bind joints on the surface bind_jnts.append( mc.createNode("joint", n="{}bnd_jnt_{:02d}".format(prefix, x + 1))) mc.parent(bind_jnts[-1], fols_tr[-1], r=True) mc.setAttr(bind_jnts[-1] + ".radius", bnd_joints_rad) set_color(bind_jnts, "mid_blue") #create temp follicles for control offset groups to align temp_fols = [] temp_fols_tr = [] for x in range(num_of_ctrls): temp_fols.append(mc.createNode("follicle")) temp_fols_tr.append(mc.listRelatives(temp_fols[-1], p=True)[0]) mc.connectAttr(temp_fols[-1] + ".outTranslate", temp_fols_tr[-1] + ".translate", f=True) mc.connectAttr(temp_fols[-1] + ".outRotate", temp_fols_tr[-1] + ".rotate", f=True) mc.connectAttr(surf + ".worldMatrix[0]", temp_fols[-1] + ".inputWorldMatrix") mc.connectAttr(surf + ".local", temp_fols[-1] + ".inputSurface") #################################################### if equal == 1: for x, temp_fol in enumerate(temp_fols): mc.setAttr(temp_fol + parameter, param_ctrls[x]) mc.setAttr(temp_fol + other_param, 0.5) if equal == 0: v = 0 for temp_fol in temp_fols: mc.setAttr(temp_fol + parameter, v) mc.setAttr(temp_fol + other_param, 0.5) v = v + (1.0 / divider_for_ctrls) #################################################### #create controls and control joints controls = ctrl_maker(prefix, ctrl_type="cube", count=num_of_ctrls, deg=3, sp=8) ctrl_ofs_grps = [] ctrl_joints = [] ctrl_jnt_ofs_grps = [] ctrl_joints_rad = bnd_joints_rad * 2 ik_ctrl_scale = (length / 35) / (float(num_of_ctrls) / 5) for x, ctrl in enumerate(controls): ctrl_ofs_grp = mc.group(ctrl, n="{}_offset".format(ctrl)) mc.delete(mc.parentConstraint(temp_fols_tr[x], ctrl_ofs_grp)) ctrl_ofs_grps.append(ctrl_ofs_grp) #scale ik controls ctrl_shapes = mc.listRelatives(ctrl, s=True) for ctrl_shape in ctrl_shapes: ctrl_cvs_count = mc.getAttr(ctrl_shape + ".controlPoints", size=True) mc.scale(ik_ctrl_scale, ik_ctrl_scale, ik_ctrl_scale, "{}.cv[0:{}]".format(ctrl_shape, ctrl_cvs_count - 1), r=True, ocp=True) #create the control joints ctrl_joints.append( mc.createNode("joint", n="{}ctrl_jnt_{:02d}".format(prefix, x + 1))) #set the radius of controls joints to 2 times that of the surface joints mc.setAttr(ctrl_joints[x] + ".radius", ctrl_joints_rad) #create offset groups for ctrl joints ctrl_jnt_ofs_grp = mc.group(ctrl_joints[-1], n="{}_offset".format(ctrl_joints[-1])) mc.delete(mc.parentConstraint(temp_fols_tr[x], ctrl_jnt_ofs_grp)) ctrl_jnt_ofs_grps.append(ctrl_jnt_ofs_grp) ### set_color(controls, "green") set_color(ctrl_joints, "red") mc.parent(ctrl_ofs_grps, ctrl_grp) mc.parent(ctrl_jnt_ofs_grps, ctrl_joints_grp) lock_hide(ctrl_ofs_grps, attrs[:9]) lock_hide(ctrl_jnt_ofs_grps, attrs[:9]) mc.delete(temp_fols_tr) #################################################### #determine if constraint or connection method is chosen if constrain == 0: for (c, j) in izip(controls, ctrl_joints): for attr in attrs[:7]: #skip scale attributes mc.connectAttr(c + attr, j + attr) mc.parentConstraint(main_ctrl, ctrl_joints_grp, mo=True) mc.scaleConstraint(main_ctrl, ctrl_joints_grp) #scale the follicles with the main control for flt in fols_tr: mc.connectAttr(main_ctrl + ".sx", flt + ".sx") mc.connectAttr(main_ctrl + ".sx", flt + ".sy") mc.connectAttr(main_ctrl + ".sx", flt + ".sz") elif constrain == 1: for (c, j) in izip(controls, ctrl_joints): mc.parentConstraint(c, j) mc.scaleConstraint(c, j) #scale the follicles with the main control for flt in fols_tr: mc.scaleConstraint(main_ctrl, flt) ####################################################################### if wire == True and num_of_ctrls > 1: temp_crv = mc.duplicateCurve(surf_tr + ".v[.5]", n=prefix + "wire_crv", local=False, ch=0)[0] if num_of_ctrls == 2: degree = 1 else: degree = 3 wire_crv = mc.curve(p=param_from_length( temp_crv, num_of_ctrls + (num_of_ctrls - 1), "open", "world"), d=degree) mc.delete(temp_crv) wire_crv = mc.rename( wire_crv, prefix + "wire_crv" ) # if name at the creation time, the shape doesn't get renamed mc.delete(wire_crv, ch=True) wire = mc.wire(surf_tr, gw=False, en=1.0, ce=0.0, li=0.0, dds=(0, 50), w=wire_crv, n=prefix + "wire")[0] mc.connectAttr(main_ctrl + ".sx", wire + ".scale[0]") cps = param_from_length(wire_crv, num_of_ctrls, "open", "uv", normalized=False) for cp in cps: mc.select("{}.u[{}]".format(wire_crv, cp), r=True) mc.dropoffLocator(1.0, 1.0, wire) mc.select(cl=True) for x, ctrl in enumerate(controls): mc.connectAttr(ctrl + ".rx", "{}.wireLocatorTwist[{}]".format(wire, x)) wire_grp = mc.group(wire_crv, wire_crv + "BaseWire", n=prefix + "wire_crv_grp") mc.parent(wire_grp, rig_grp) lock_hide([wire_grp], attrs[:9]) wire_skin_cluster = mc.skinCluster(ctrl_joints, wire_crv, dr=2, mi=2, bm=0)[0] else: #bind the surface to the joints nurbs_skin_cluster = mc.skinCluster(ctrl_joints, surf_tr, dr=2, mi=num_of_ctrls - 1, ns=num_of_ctrls * 5, bm=0, n=prefix + "skinCluster")[0] mc.skinPercent(nurbs_skin_cluster, surf_tr, pruneWeights=0.2) if wire == True and num_of_ctrls == 1: mc.warning("wire skipped. at least 2 controls needed") ########################################################################################## mc.setAttr(surf_tr + ".v", 0) mc.setAttr(rig_grp + ".v", 0) mc.connectAttr(main_ctrl + ".sx", main_ctrl + ".sy") mc.connectAttr(main_ctrl + ".sx", main_ctrl + ".sz") mc.aliasAttr("Scale", main_ctrl + ".sx") set_color(main_ctrl, "yellow") mc.connectAttr(main_ctrl_offset + ".sx", main_ctrl_offset + ".sy") mc.connectAttr(main_ctrl_offset + ".sx", main_ctrl_offset + ".sz") mc.aliasAttr("Scale", main_ctrl_offset + ".sx") #lock and hide attributes lock_hide([ final_group, follicles_grp, ctrl_joints_grp, surf_tr, ctrl_grp, rig_grp ], attrs[:9]) lock_hide([ctrl_grp, main_ctrl, main_ctrl_offset], attrs[7:]) lock_hide(controls, attrs[7:]) #clear selection mc.select( cl=True ) #if selection isn't cleared a control joint gets added to the bind joints set #create a set with bind joints bind_jnts_set = mc.sets(n=prefix + "bind_jnts_set") mc.sets(bind_jnts, add=bind_jnts_set) mc.select(cl=True) ik_ctrls_set = mc.sets(n=prefix + "ik_ctrls_set") mc.sets(controls, add=ik_ctrls_set) mc.select(cl=True) controls_set = mc.sets(n=prefix + "controls_set") mc.sets(main_ctrl, ik_ctrls_set, add=controls_set) ########################################################################################## if add_fk == 1 and mc.getAttr(surf + ".formU") != 2 and mc.getAttr( surf + ".formV") != 2: fk_ctrls, fk_ctrl_off_grps = make_fk_ctrls(prefix, num_of_ctrls) mc.parent(fk_ctrl_off_grps[0], ctrl_grp) #scale fk controls fk_ctrl_scale = ik_ctrl_scale * 2 for fk_ctrl in fk_ctrls: fk_ctrl_shapes = mc.listRelatives(fk_ctrl, s=True) for fk_ctrl_shape in fk_ctrl_shapes: fk_ctrl_cvs_count = mc.getAttr(fk_ctrl_shape + ".controlPoints", size=True) mc.scale(fk_ctrl_scale, fk_ctrl_scale, fk_ctrl_scale, "{}.cv[0:{}]".format(fk_ctrl_shape, fk_ctrl_cvs_count - 1), r=True, ocp=True) #add fk controls to a set mc.select(cl=True) fk_ctrls_set = mc.sets(n=prefix + "fk_ctrls_set") mc.sets(fk_ctrls, add=fk_ctrls_set) ######## ik_ctrl_constr_grps = [ mc.group(ctrl, n=ctrl + "_constr_grp") for ctrl in controls ] [ mc.xform(ik_ctrl_constr_grp, piv=(0, 0, 0), os=True) for ik_ctrl_constr_grp in ik_ctrl_constr_grps ] for ik, fk in izip(controls[:-1], fk_ctrl_off_grps): mc.delete(mc.parentConstraint(ik, fk)) for fk, ik in izip(fk_ctrls, ik_ctrl_constr_grps[:-1]): mc.parentConstraint(fk, ik) #constrain last ik ctrl mc.parentConstraint(fk_ctrls[-1], ik_ctrl_constr_grps[-1], mo=True) lock_hide(ik_ctrl_constr_grps, attrs[:9]) ######## set_color(fk_ctrls, "blue") lock_hide(fk_ctrl_off_grps, attrs[:9]) mc.sets(fk_ctrls_set, add=controls_set) mc.select(cl=True) elif add_fk == 1 and (mc.getAttr(surf + ".formU") == 2 or mc.getAttr(surf + ".formV") == 2): mc.warning("surface is periodic. fk controls skipped") ################ADD MESSAGE ATTRS################ mc.addAttr(main_ctrl, ln="joints", at="message") mc.addAttr(main_ctrl, ln="follicles", at="message") mc.addAttr(main_ctrl, ln="surface", at="message") if mc.attributeQuery("i_am_the_surface", node=surf, exists=True) == False: mc.addAttr(surf, ln="i_am_the_surface", at="message") mc.connectAttr(main_ctrl + ".surface", surf + ".i_am_the_surface") for j, f in izip(bind_jnts, fols): mc.addAttr(j, ln="i_am_a_joint", at="message") mc.addAttr(f, ln="i_am_a_follicle", at="message") mc.connectAttr(main_ctrl + ".joints", j + ".i_am_a_joint") mc.connectAttr(main_ctrl + ".follicles", f + ".i_am_a_follicle")
def edo_addBlendShapeAndExpressionsByFacialCtrl(ctrlName): #ctrlName='test_CTRL' endstr = ctrlName.split('_')[-1] allMeshes = [] if endstr == 'CTRL': upmeshes = cmds.listRelatives(ctrlName + '_up', c=1, type='transform', pa=1) dnmeshes = cmds.listRelatives(ctrlName + '_dn', c=1, type='transform', pa=1) lfmeshes = cmds.listRelatives(ctrlName + '_lf', c=1, type='transform', pa=1) lfupmeshes = cmds.listRelatives(ctrlName + '_lfup', c=1, type='transform', pa=1) lfdnmeshes = cmds.listRelatives(ctrlName + '_lfdn', c=1, type='transform', pa=1) rtmeshes = cmds.listRelatives(ctrlName + '_rt', c=1, type='transform', pa=1) rtupmeshes = cmds.listRelatives(ctrlName + '_rtup', c=1, type='transform', pa=1) rtdnmeshes = cmds.listRelatives(ctrlName + '_rtdn', c=1, type='transform', pa=1) fourAxisupmeshes = cmds.listRelatives(ctrlName + '_fourAxisup', c=1, type='transform', pa=1) fourAxisdnmeshes = cmds.listRelatives(ctrlName + '_fourAxisdn', c=1, type='transform', pa=1) fourAxislfmeshes = cmds.listRelatives(ctrlName + '_fourAxislf', c=1, type='transform', pa=1) fourAxisrtmeshes = cmds.listRelatives(ctrlName + '_fourAxisrt', c=1, type='transform', pa=1) edo_combineAllList(allMeshes, upmeshes) edo_combineAllList(allMeshes, dnmeshes) edo_combineAllList(allMeshes, lfmeshes) edo_combineAllList(allMeshes, rtmeshes) edo_combineAllList(allMeshes, lfupmeshes) edo_combineAllList(allMeshes, rtupmeshes) edo_combineAllList(allMeshes, lfdnmeshes) edo_combineAllList(allMeshes, rtdnmeshes) edo_combineAllList(allMeshes, fourAxisupmeshes) edo_combineAllList(allMeshes, fourAxisdnmeshes) edo_combineAllList(allMeshes, fourAxislfmeshes) edo_combineAllList(allMeshes, fourAxisrtmeshes) if allMeshes == [] or allMeshes == None: return False else: allMeshes = cmds.listRelatives(ctrlName, c=1, type='transform', pa=1) bsnodes = [] targetMesh = '' for m in allMeshes: #m=allMeshes[0] print m if 'connectCurve' in m: continue targetMesh = m.split('__')[1] + '_' if cmds.objExists(targetMesh): BSname = targetMesh + '_BLENDSHAPE' if not BSname in bsnodes: bsnodes.append(BSname) if not cmds.objExists(BSname): bsnode = cmds.blendShape(targetMesh, frontOfChain=1, n=BSname) #wc=cmds.blendShape(BSname,q=1,wc=1) wc = edo_getMaxLocalIndexFromPhysicalCount(BSname + '.weight') + 1 output = cmds.listConnections(m + '.worldMesh[0]', s=0, d=1, type='blendShape') if not output == None: if not BSname in cmds.listConnections( m + '.worldMesh[0]', s=0, d=1, type='blendShape'): cmds.blendShape(BSname, e=1, t=[targetMesh, wc, m, 1.0]) else: id = edo_targetIsInBlendShapeWeightId(m, BSname) if id == -1: cmds.blendShape(BSname, e=1, t=[targetMesh, wc, m, 1.0]) else: cmds.blendShape(BSname, e=1, ib=True, t=[targetMesh, id, m, 1.0]) print 'get expression...' for bsnode in bsnodes: #bsnode=bsnodes[0] exname = ctrlName + '__' + bsnode.replace('_BLENDSHAPE', '_EXPRESSION') extext = '//' + exname + '\n' extext += '//don\'t write custom expression in here!,the script will delete this scirpt first before create a new expression\n\n' if cmds.objExists(exname): cmds.delete(exname) #bsattrlen=cmds.blendShape(bsnode,q=1,wc=1) bsattrlen = edo_getMaxLocalIndexFromPhysicalCount(bsnode + '.weight') + 1 for i in range(0, bsattrlen): #i=1 print i ctrlattrname = '' if endstr == 'CTRL': bsattr = cmds.aliasAttr(bsnode + '.weight[' + str(i) + ']', q=1) m = bsattr bsattrname = bsnode + '.' + m print m if not ctrlName in m or '___' in m: print m + ' ... pass' continue else: print m + ' ... addex' ctrlattrname = m.split('__')[len(m.split('__')) - 1] ctrlattrname = ctrlattrname.replace('CTRL_', 'FRAME.') ctrlattrname = ctrlattrname.replace( 'fourAxis', 'fourAxis_') extext += bsattrname + '=' + ctrlattrname + ';\n' else: bsattr = cmds.aliasAttr(bsnode + '.weight[' + str(i) + ']', q=1) m = bsattr bsattrname = bsnode + '.' + m print m if not ctrlName in m: print m + ' ... pass' continue else: print m + ' ... addex' tmp = m.split('___') st = tmp[0].split('__')[-1] tmp.remove(tmp[0]) ctrlattrname = st for t in tmp: ctrlattrname += ('___' + t) ctrlattrname = ctrlattrname + '.multiplyValue' extext += bsattrname + '=' + ctrlattrname + ';\n' print 'add expression' print exname + ' : \n' + extext + '\n' cmds.expression(n=exname, s=extext)
def createCorrectiveTarget(cls, *args): # Check working uint curUnit = cmds.currentUnit(q=True, linear=True) if curUnit != 'cm': cmds.currentUnit(linear='cm') # Remove HUD cmds.headsUpDisplay('sclptHUD', remove=True) # Refresh new corrective name text field cmds.textField(UI.widgets['correctiveTrgNameTxtFld'], e=True, text='') # Show cache geometry and inverse geometry shape. cls.shpVisOnOff(cls.geo, 'on') cls.shpVisOnOff(cls.invGeo, 'on') # Add invGeo and sculptGeo to blendshape node for cls.correctiveTrgName in [cls.sculptGeo, cls.invGeo]: if cls.bsNodeName != 'None': bsAttrList = cmds.aliasAttr(cls.bsNodeName, q=True) if not bsAttrList: cmds.blendShape(cls.bsNodeName, edit=True, target=(cls.geo, 0, cls.correctiveTrgName, 1.0)) cmds.setAttr( '%s.%s' % (cls.bsNodeName, cls.correctiveTrgName), 1) else: weightNumList = [] for bsAttr in bsAttrList: if 'weight' in bsAttr: reObj = re.search(r'\d+', bsAttr) weightNum = reObj.group() weightNumList.append(int(weightNum)) bsIndex = max(weightNumList) + 1 cmds.blendShape(cls.bsNodeName, edit=True, target=(cls.geo, bsIndex, cls.correctiveTrgName, 1.0)) cmds.setAttr( '%s.%s' % (cls.bsNodeName, cls.correctiveTrgName), 1) elif cls.bsNodeName == 'None': cls.bsNodeName = '{0}_correctiveBS'.format(cls.geo) cmds.blendShape(cls.correctiveTrgName, cls.geo, n=cls.bsNodeName, frontOfChain=True)[0] cmds.setAttr('%s.%s' % (cls.bsNodeName, cls.correctiveTrgName), 1) # Fill blend shape node option menu # Load BS nodes cls.bsList = [] allConnections = cmds.listHistory(cls.geo) for item in allConnections: if cmds.objectType(item) == 'blendShape': cls.bsList.append(item) # If already exists menu item in the bsOptMenu, delete menu items before populate bsOptItems = cmds.optionMenu(UI.widgets['bsNodeOptMenu'], q=True, itemListLong=True) if bsOptItems != None: for bsOptItem in bsOptItems: cmds.deleteUI(bsOptItem) if cls.bsList: for bsNode in cls.bsList: cmds.menuItem(label=bsNode, p=UI.widgets['bsNodeOptMenu']) # Build node network for inverse target mulNode = cmds.shadingNode('multiplyDivide', n=cls.sculptGeo + '_mul', asUtility=True) cmds.setAttr('%s.input2X' % mulNode, -1) cmds.connectAttr('%s.%s' % (cls.bsNodeName, cls.sculptGeo), '%s.input1X' % mulNode) cmds.connectAttr('%s.outputX' % mulNode, '%s.%s' % (cls.bsNodeName, cls.invGeo)) # Add corrective and inverse target geometry to geo_grp correctiveTrgGeoGrpName = cls.geo + '_correctiveTrg_geo_grp' if cmds.objExists(correctiveTrgGeoGrpName): cmds.parent(cls.sculptGeo, correctiveTrgGeoGrpName) cmds.parent(cls.invGeo, correctiveTrgGeoGrpName) else: cmds.createNode('transform', n=correctiveTrgGeoGrpName) cmds.parent(cls.sculptGeo, correctiveTrgGeoGrpName) cmds.parent(cls.invGeo, correctiveTrgGeoGrpName) # Visibility off for sculpt and inverse geo shapes. cls.shpVisOnOff(cls.sculptGeo, 'off') cls.shpVisOnOff(cls.invGeo, 'off') # Refresh corrective target list cls.populateCorrectiveTrgList() # Return working unit cmds.currentUnit(linear=curUnit) # Button enable control cmds.button(UI.widgets['sculptBtn'], e=True, enable=True) cmds.button(UI.widgets['cancelBtn'], e=True, enable=False) cmds.button(UI.widgets['createBtn'], e=True, enable=False)
def addTarget(blendShape, target, base='', targetIndex=-1, targetAlias='', targetWeight=0.0, topologyCheck=False): ''' Add a new target to the specified blendShape @param blendShape: Name of blendShape to remove target from @type blendShape: str @param target: New blendShape target geometry @type target: str @param base: BlendShape base geometry. If empty, use first connected base geomtry @type base: str @param targetIndex: Specify the target index. If less than 0, use next available index. @type targetIndex: str @param targetAlias: Override the default blendShape target alias with this string @type targetAlias: str @param targetWeight: Set the target weight value @type targetWeight: float ''' # ========== # - Checks - # ========== # BlendShape if not isBlendShape(blendShape): raise Exception('Object "' + blendShape + '" is not a valid blendShape node!') # Target if not mc.objExists(target): raise Exception('Target geometry "' + target + '" does not exist!') # Base if base and not mc.objExists(base): raise Exception('Base geometry "' + base + '" does not exist!') # ============== # - Add Target - # ============== # Get Base Geometry if not base: base = getBaseGeo(blendShape)[0] # Get Target Index if targetIndex < 0: targetIndex = nextAvailableTargetIndex(blendShape) # Add Target mc.blendShape(blendShape, e=True, t=(base, targetIndex, target, 1.0), topologyCheck=topologyCheck) # Get Target Name targetName = getTargetName(blendShape, target) # Override Target Alias if targetAlias: targetIndex = getTargetIndex(blendShape, targetName) mc.aliasAttr(targetAlias, blendShape + '.weight[' + str(targetIndex) + ']') targetName = targetAlias # ===================== # - Set Target Weight - # ===================== if targetWeight: mc.setAttr(blendShape + '.' + targetName, targetWeight) # ================= # - Return Result - # ================= return (blendShape + '.' + targetName)
def setBlendShapeData(node, shapeData, inputIndex=0, shapes=None): """ sets the shape data onto a blendShape node. :param str node: the blendShape to add the shapes to. :param dict shapeData: the shape data to apply to the node. :param list shapes: if given, only modify given target names """ nodeType = mc.nodeType(node) inputShape = mc.deformer(node, g=True, q=True) shapeAliasLookup = getShapeAliasLookup(node) if not 'shapes' in shapeData: print("procedureName" + ': shapeData does not have a "shapes" key. Returning now...') return for shapeAlias in shapeData['shapes']: if shapes and shapeAlias not in shapes: continue # read the information stored for this shape targetData = shapeData['shapes'][shapeAlias] targetOffsets = targetData["offsets"] targetWeights = targetData["weights"] shapeIndex = shapeAliasLookup.get(shapeAlias, None) # if the shape doesn't already exist, create it at the end of the list newShape = False if shapeIndex is None: newShape = True weightIndices = mc.getAttr(node + ".weight", mi=True) if weightIndices is None: shapeIndex = 0 else: shapeIndex = weightIndices[-1] + 1 mc.addMultiInstance(node + '.weight[' + str(shapeIndex) + ']') if shapeAlias[0] != '[': mc.aliasAttr(shapeAlias.strip(), node + ".weight[" + str(shapeIndex) + "]") # iterate through the offset dictionary pointList = [] componentList = [] #speed optimization shapeComponentsToUse = {} for pointIndex in targetOffsets: pointData = targetOffsets[pointIndex] pointList.append((pointData[0], pointData[1], pointData[2], 1.0)) componentList.append('vtx[' + str(pointIndex) + ']') # create the element by calling getAttr try: mc.getAttr(node + '.inputTarget[' + str(inputIndex) + ']') except: pass try: mc.getAttr(node + '.inputTarget[' + str(inputIndex) + '].inputTargetGroup[' + str(shapeIndex) + ']') except: pass shapeAttr = node + ".inputTarget[" + str( inputIndex) + "].inputTargetGroup[" + str(shapeIndex) + "]" mc.setAttr(shapeAttr + ".inputTargetItem[6000].inputPointsTarget", len(componentList), type="pointArray", *pointList) mc.setAttr(shapeAttr + ".inputTargetItem[6000].inputComponentsTarget", len(componentList), type="componentList", *componentList) tAttrs = mc.listAttr(shapeAttr, m=True, string='targetWeights') if tAttrs != None: for a in tAttrs: mc.removeMultiInstance((node + '.' + a), b=True) # set the weights for weight in targetWeights: mc.setAttr(shapeAttr + ".targetWeights[" + str(weight) + "]", targetWeights[weight])
def cmd_editorSetDrivenKey(): ses = mm.eval('getShapeEditorTreeviewSelection(24)') bs = ses[0].split('.')[0] id = int(ses[0].split('.')[1]) idS = 'weight[' + str(id) + ']' aList = cmds.aliasAttr(bs, query=1) ses = '' for i in range(0, len(aList), 2): if aList[i + 1] == idS: ses = aList[i] attrRule = '.+_[x|X|y|Y|z|Z][0-9]+' if (len(re.findall(attrRule, ses)) == 0): cmds.warning('Attribute name incorrect.') return 0 rule = 'j[clr][A-Z]\d+_[a-zA-Z0-9]+' djo = '' # drive joint for x in cmds.ls(type='joint'): xp = x.split('_') if len(xp) > 1: if xp[1] == ses.split('_')[0]: if len(re.findall(rule, x)) > 0: djo = x if djo == '': sl = cmds.ls(selection=1) if len(sl) > 0: djo = sl[-1] ax = ses.split('_')[1][0] da = '' # drive attribute if ax in ['X', 'x']: da = 'quatX' if ax in ['Y', 'y']: da = 'quatY' if ax in ['Z', 'z']: da = 'quatZ' if (cmds.objExists(djo + '.' + da) == 0): cmd_editorSetDrivenKey_quatAttr(djo, ax) pm = 1 # plus or minus if ax in ['x', 'y', 'z']: pm = -1 ag = float(ses.split('_')[1][1:]) ga = cmds.getAttr(djo + '.' + da) print djo + '.' + ax cmds.setDrivenKeyframe(bs + '.' + ses, currentDriver=djo + '.' + da, inTangentType='flat', value=0, outTangentType='flat') cmds.setDrivenKeyframe(bs + '.' + ses, currentDriver=djo + '.' + da, driverValue=ag * pm, value=1, inTangentType='spline', outTangentType='spline') cmds.setDrivenKeyframe(bs + '.' + ses, currentDriver=djo + '.' + da, driverValue=(((ag * pm) - ga) * 1.15) + ga, value=1.1, inTangentType='flat', outTangentType='flat') cmds.setDrivenKeyframe(bs + '.' + ses, currentDriver=djo + '.' + da, driverValue=(((ag * pm) - ga) * 0.5) + ga, value=0.3, inTangentType='spline', outTangentType='spline')
def create_blendshapes_backup(source, target, nodes): """ Creates an updated backup for the given blendshapes nodes on source .. important:: This method does not work as the other source/target type of methods in flex. The source is the current geometry before topology update containing the blendshape nodes. We use it in order to create a wrap to the newer target geometry topology. :param source: current shape node :type source: str :param target: new shape node :type target: str :return: backup blendshape nodes :rtype: list """ logger.debug("Creating blendshapes backup") # gets simpler shape name shape_name = get_prefix_less_name(target) # get attributes types attrs = get_shape_type_attributes(target) # creates source duplicate intermediate = get_shape_orig(source)[0] source_duplicate = create_duplicate( intermediate, "{}_flex_bs_sourceShape".format(shape_name)) # first loops to create a clean copy of the blendshape nodes nodes_copy = [] for node in nodes: duplicate = copy_blendshape_node(node, source_duplicate) if duplicate: nodes_copy.append(duplicate) # creates wrapped target shape warp_target = create_duplicate(target, "{}_flex_bs_warpShape".format(shape_name)) # wraps the duplicate to the source create_wrap(source_duplicate, warp_target) # creates blendshape target shape target_duplicate = create_duplicate( target, "{}_flex_bs_targetShape".format(shape_name)) return_nodes = [] # loops on the blendshape nodes for node in nodes_copy: # creates transfer blendshape transfer_node = cmds.deformer(target_duplicate, type="blendShape", name="flex_transfer_{}".format(node))[0] # get blendshape targets indices. We skip verification because at this # stage the copied blendshapes nodes will always have targets targets_idx = cmds.getAttr("{}.weight".format(node), multiIndices=True) # loop on blendshape targets indices for idx in targets_idx or []: # input target group attribute attr_name = (BLENDSHAPE_TARGET.format(node, idx)) # blendshape target name target_name = cmds.aliasAttr("{}.weight[{}]".format(node, idx), query=True) # loop on actual targets and in-between targets for target in cmds.getAttr(attr_name, multiIndices=True): # gets and sets the blendshape weight value weight = float((target - 5000) / 1000.0) cmds.setAttr("{}.weight[{}]".format(node, idx), weight) # geometry target attribute geometry_target_attr = "{}[{}].inputGeomTarget".format( attr_name, target) shape_target = geometry_target_attr.replace( geometry_target_attr.split(".")[0], transfer_node) # updates the target cmds.connectAttr("{}.{}".format(warp_target, attrs["output"]), shape_target, force=True) cmds.disconnectAttr( "{}.{}".format(warp_target, attrs["output"]), shape_target) cmds.setAttr("{}.weight[{}]".format(node, idx), 0) cmds.setAttr("{}.weight[{}]".format(transfer_node, idx), 0) if target_name: cmds.aliasAttr(target_name, "{}.weight[{}]".format(transfer_node, idx)) # adds blendshape node to nodes to return return_nodes.append("{}".format(transfer_node)) # deletes backup process shapes cmds.delete(cmds.listRelatives(source_duplicate, parent=True), cmds.listRelatives(warp_target, parent=True)) # forces refresh cmds.refresh() return return_nodes
def ribbonize(surf_tr, equal=1, num_of_ctrls=5, num_of_jnts=29, prefix="", constrain=1, add_fk=0, wire=0): attrs = [ ".tx", ".ty", ".tz", ".rx", ".ry", ".rz", ".sx", ".sy", ".sz", ".v" ] if prefix == "": mc.warning("te importa nombrarlo?") return else: prefix = prefix + "_" ##################################################### surf_tr = mc.rename(surf_tr, prefix + "ribbon_surface") surf = mc.listRelatives(surf_tr, shapes=True)[0] # Congelar transformaciones y borrar el historial de superficies. mc.makeIdentity(surf_tr, t=True, r=True, s=True, apply=True) mc.delete(surf_tr, ch=True) # duplicar la superficie curvas para determinar la direccion. u_curve = mc.duplicateCurve(surf_tr + ".v[.5]", local=True, ch=0) v_curve = mc.duplicateCurve(surf_tr + ".u[.5]", local=True, ch=0) # borro historial solo porsiaca. mc.delete(surf_tr, ch=True) u_length = mc.arclen(u_curve) v_length = mc.arclen(v_curve) if u_length < v_length: mc.reverseSurface(surf_tr, d=3, ch=False, rpo=True) mc.reverseSurface(surf_tr, d=0, ch=False, rpo=True) parameter = ".parameterU" other_param = ".parameterV" # corrija u_curve despues de invertir para calcular la longitud. u_curve_corr = mc.duplicateCurve(surf_tr + ".v[.5]", local=True, ch=0)[0] ############################################################################# # La superficie seleccionada es periodica o abierta? (cilindro o plano) if mc.getAttr(surf + ".formU") == 2 or mc.getAttr(surf + ".formV") == 2: curve_type = "periodic" divider_for_ctrls = num_of_ctrls elif mc.getAttr(surf + ".formU") == 0 or mc.getAttr(surf + ".formV") == 0: curve_type = "open" divider_for_ctrls = num_of_ctrls - 1 ############################################################################# param_ctrls = param_from_length(u_curve_corr, num_of_ctrls, curve_type, "uv") param_joints = param_from_length(u_curve_corr, num_of_jnts, curve_type, "uv") length = mc.arclen(u_curve_corr) mc.delete(u_curve, v_curve, u_curve_corr) ############################################################################ # Creo grupos, Control General y control general de offset final_group = mc.group(n=prefix + "ribbon_grp", em=True) ctrl_joints_grp = mc.group(n=prefix + "ctrl_joints_grp", em=True) ctrl_grp = mc.group(n=prefix + "ctrls_grp", em=True) follicles_grp = mc.group(n=prefix + "follicles_grp", em=True) rig_grp = mc.group(n=prefix + "rig_grp", em=True) main_ctrl = mc.circle(n=prefix + "ctrl_main", nr=(0, 1, 0), r=length / 5, ch=0)[0] main_ctrl_offset = mc.group(n=prefix + "ctrl_main_offset", em=True) mc.parent(main_ctrl, main_ctrl_offset) mc.parent(ctrl_grp, main_ctrl) mc.parent(main_ctrl_offset, rig_grp, final_group) mc.parent(surf_tr, ctrl_joints_grp, follicles_grp, rig_grp) # Muevo main_ctrl_offset al centro de la geometria bbox (en caso de que el pivote este en otro lugar) mid_point = get_bbox_center(surf_tr) for attr, mid_pnt_el in izip(attrs[:3], mid_point): mc.setAttr(main_ctrl_offset + attr, mid_pnt_el) ############################################################################ fols = [] fols_tr = [] bind_jnts = [] bnd_joints_rad = (length / 60) / (float(num_of_jnts) / 40) for x in range(num_of_jnts): fol = mc.createNode("follicle") mc.setAttr(fol + ".visibility", 0) temp_fol = mc.listRelatives(fol, p=True)[0] fols_tr.append( mc.rename(temp_fol, "{}follicle_{:02d}".format(prefix, x + 1))) fols.append(mc.listRelatives(fols_tr[-1], s=True)[0]) # conecto follicle shapes al transform mc.connectAttr(fols[-1] + ".outTranslate", fols_tr[-1] + ".translate", f=True) mc.connectAttr(fols[-1] + ".outRotate", fols_tr[-1] + ".rotate", f=True) # atacho follicle shapes a la superficie mc.connectAttr(surf + ".worldMatrix[0]", fols[-1] + ".inputWorldMatrix") mc.connectAttr(surf + ".local", fols[-1] + ".inputSurface") mc.setAttr(fols[-1] + parameter, param_joints[x]) mc.setAttr(fols[-1] + other_param, 0.5) mc.parent(fols_tr[-1], follicles_grp) # creo el bind final y joints en la superficie bind_jnts.append( mc.createNode("joint", n="{}bnd_jnt_{:02d}".format(prefix, x + 1))) mc.parent(bind_jnts[-1], fols_tr[-1], r=True) mc.setAttr(bind_jnts[-1] + ".radius", bnd_joints_rad) set_color(bind_jnts, "mid_blue") #creo un temporal follicles para controles offset groups para alinear temp_fols = [] temp_fols_tr = [] for x in range(num_of_ctrls): temp_fols.append(mc.createNode("follicle")) temp_fols_tr.append(mc.listRelatives(temp_fols[-1], p=True)[0]) mc.connectAttr(temp_fols[-1] + ".outTranslate", temp_fols_tr[-1] + ".translate", f=True) mc.connectAttr(temp_fols[-1] + ".outRotate", temp_fols_tr[-1] + ".rotate", f=True) mc.connectAttr(surf + ".worldMatrix[0]", temp_fols[-1] + ".inputWorldMatrix") mc.connectAttr(surf + ".local", temp_fols[-1] + ".inputSurface") #################################################### if equal == 1: for x, temp_fol in enumerate(temp_fols): mc.setAttr(temp_fol + parameter, param_ctrls[x]) mc.setAttr(temp_fol + other_param, 0.5) if equal == 0: v = 0 for temp_fol in temp_fols: mc.setAttr(temp_fol + parameter, v) mc.setAttr(temp_fol + other_param, 0.5) v = v + (1.0 / divider_for_ctrls) #################################################### #creo controles y controle para joints controls = ctrl_maker(prefix, ctrl_type="cube", count=num_of_ctrls, deg=3, sp=8) ctrl_ofs_grps = [] ctrl_joints = [] ctrl_jnt_ofs_grps = [] ctrl_joints_rad = bnd_joints_rad * 2 ik_ctrl_scale = (length / 35) / (float(num_of_ctrls) / 5) for x, ctrl in enumerate(controls): ctrl_ofs_grp = mc.group(ctrl, n="{}_offset".format(ctrl)) mc.delete(mc.parentConstraint(temp_fols_tr[x], ctrl_ofs_grp)) ctrl_ofs_grps.append(ctrl_ofs_grp) #escala ik controls ctrl_shapes = mc.listRelatives(ctrl, s=True) for ctrl_shape in ctrl_shapes: ctrl_cvs_count = mc.getAttr(ctrl_shape + ".controlPoints", size=True) mc.scale(ik_ctrl_scale, ik_ctrl_scale, ik_ctrl_scale, "{}.cv[0:{}]".format(ctrl_shape, ctrl_cvs_count - 1), r=True, ocp=True) #creo los controles de joints ctrl_joints.append( mc.createNode("joint", n="{}ctrl_jnt_{:02d}".format(prefix, x + 1))) #seteo el radio de controles para joints de 2 tiepos. de el surface y joints mc.setAttr(ctrl_joints[x] + ".radius", ctrl_joints_rad) #creo offset groups para cotroles de joints ctrl_jnt_ofs_grp = mc.group(ctrl_joints[-1], n="{}_offset".format(ctrl_joints[-1])) mc.delete(mc.parentConstraint(temp_fols_tr[x], ctrl_jnt_ofs_grp)) ctrl_jnt_ofs_grps.append(ctrl_jnt_ofs_grp) ### set_color(controls, "green") set_color(ctrl_joints, "red") mc.parent(ctrl_ofs_grps, ctrl_grp) mc.parent(ctrl_jnt_ofs_grps, ctrl_joints_grp) lock_hide(ctrl_ofs_grps, attrs[:9]) lock_hide(ctrl_jnt_ofs_grps, attrs[:9]) mc.delete(temp_fols_tr) #################################################### #determino que constraint o coneccion o metodo es elegido# que formalidad if constrain == 0: for (c, j) in izip(controls, ctrl_joints): for attr in attrs[:7]: #skip de la escala de atributos mc.connectAttr(c + attr, j + attr) mc.parentConstraint(main_ctrl, ctrl_joints_grp, mo=True) mc.scaleConstraint(main_ctrl, ctrl_joints_grp) #escala del foliculo con el main // por coneccion del editor for flt in fols_tr: mc.connectAttr(main_ctrl + ".sx", flt + ".sx") mc.connectAttr(main_ctrl + ".sx", flt + ".sy") mc.connectAttr(main_ctrl + ".sx", flt + ".sz") elif constrain == 1: for (c, j) in izip(controls, ctrl_joints): mc.parentConstraint(c, j) mc.scaleConstraint(c, j) #scala del folliculos con el main control for flt in fols_tr: mc.scaleConstraint(main_ctrl, flt) ####################################################################### if wire == True and num_of_ctrls > 1: temp_crv = mc.duplicateCurve(surf_tr + ".v[.5]", n=prefix + "wire_crv", local=False, ch=0)[0] if num_of_ctrls == 2: degree = 1 else: degree = 3 wire_crv = mc.curve(p=param_from_length( temp_crv, num_of_ctrls + (num_of_ctrls - 1), "open", "world"), d=degree) mc.delete(temp_crv) wire_crv = mc.rename( wire_crv, prefix + "wire_crv" ) # Si el nombre va en el momento de la creacion, la forma no se renombra mc.delete(wire_crv, ch=True) wire = mc.wire(surf_tr, gw=False, en=1.0, ce=0.0, li=0.0, dds=(0, 50), w=wire_crv, n=prefix + "wire")[0] mc.connectAttr(main_ctrl + ".sx", wire + ".scale[0]") cps = param_from_length(wire_crv, num_of_ctrls, "open", "uv", normalized=False) for cp in cps: mc.select("{}.u[{}]".format(wire_crv, cp), r=True) mc.dropoffLocator(1.0, 1.0, wire) mc.select(cl=True) for x, ctrl in enumerate(controls): mc.connectAttr(ctrl + ".rx", "{}.wireLocatorTwist[{}]".format(wire, x)) wire_grp = mc.group(wire_crv, wire_crv + "BaseWire", n=prefix + "wire_crv_grp") mc.parent(wire_grp, rig_grp) lock_hide([wire_grp], attrs[:9]) wire_skin_cluster = mc.skinCluster(ctrl_joints, wire_crv, dr=2, mi=2, bm=0)[0] else: #bind de la superficie a los joints nurbs_skin_cluster = mc.skinCluster(ctrl_joints, surf_tr, dr=2, mi=num_of_ctrls - 1, ns=num_of_ctrls * 5, bm=0, n=prefix + "skinCluster")[0] mc.skinPercent(nurbs_skin_cluster, surf_tr, pruneWeights=0.2) if wire == True and num_of_ctrls == 1: mc.warning("wire skipped. at least 2 controls needed") ########################################################################################## mc.setAttr(surf_tr + ".v", 0) mc.setAttr(rig_grp + ".v", 0) mc.connectAttr(main_ctrl + ".sx", main_ctrl + ".sy") mc.connectAttr(main_ctrl + ".sx", main_ctrl + ".sz") mc.aliasAttr("Scale", main_ctrl + ".sx") set_color(main_ctrl, "yellow") mc.connectAttr(main_ctrl_offset + ".sx", main_ctrl_offset + ".sy") mc.connectAttr(main_ctrl_offset + ".sx", main_ctrl_offset + ".sz") mc.aliasAttr("Scale", main_ctrl_offset + ".sx") #lock and hide atributos lock_hide([ final_group, follicles_grp, ctrl_joints_grp, surf_tr, ctrl_grp, rig_grp ], attrs[:9]) lock_hide([ctrl_grp, main_ctrl, main_ctrl_offset], attrs[7:]) lock_hide(controls, attrs[7:]) #limpiamos seleccion (clear selection) mc.select( cl=True ) #Si la seleccion no se borra, se agrega un bind de control al conjunto de bind de enlace #crea a set con bind joints bind_jnts_set = mc.sets(n=prefix + "bind_jnts_set") mc.sets(bind_jnts, add=bind_jnts_set) mc.select(cl=True) ik_ctrls_set = mc.sets(n=prefix + "ik_ctrls_set") mc.sets(controls, add=ik_ctrls_set) mc.select(cl=True) controls_set = mc.sets(n=prefix + "controls_set") mc.sets(main_ctrl, ik_ctrls_set, add=controls_set) ########################################################################################## if add_fk == 1 and mc.getAttr(surf + ".formU") != 2 and mc.getAttr( surf + ".formV") != 2: fk_ctrls, fk_ctrl_off_grps = make_fk_ctrls(prefix, num_of_ctrls) mc.parent(fk_ctrl_off_grps[0], ctrl_grp) #scala fk controls fk_ctrl_scale = ik_ctrl_scale * 2 for fk_ctrl in fk_ctrls: fk_ctrl_shapes = mc.listRelatives(fk_ctrl, s=True) for fk_ctrl_shape in fk_ctrl_shapes: fk_ctrl_cvs_count = mc.getAttr(fk_ctrl_shape + ".controlPoints", size=True) mc.scale(fk_ctrl_scale, fk_ctrl_scale, fk_ctrl_scale, "{}.cv[0:{}]".format(fk_ctrl_shape, fk_ctrl_cvs_count - 1), r=True, ocp=True) #add fk controls al set mc.select(cl=True) fk_ctrls_set = mc.sets(n=prefix + "fk_ctrls_set") mc.sets(fk_ctrls, add=fk_ctrls_set) ######## ik_ctrl_constr_grps = [ mc.group(ctrl, n=ctrl + "_constr_grp") for ctrl in controls ] [ mc.xform(ik_ctrl_constr_grp, piv=(0, 0, 0), os=True) for ik_ctrl_constr_grp in ik_ctrl_constr_grps ] for ik, fk in izip(controls[:-1], fk_ctrl_off_grps): mc.delete(mc.parentConstraint(ik, fk)) for fk, ik in izip(fk_ctrls, ik_ctrl_constr_grps[:-1]): mc.parentConstraint(fk, ik) #constrain ultimo ik ctrl mc.parentConstraint(fk_ctrls[-1], ik_ctrl_constr_grps[-1], mo=True) lock_hide(ik_ctrl_constr_grps, attrs[:9]) ######## set_color(fk_ctrls, "blue") lock_hide(fk_ctrl_off_grps, attrs[:9]) mc.sets(fk_ctrls_set, add=controls_set) mc.select(cl=True) elif add_fk == 1 and (mc.getAttr(surf + ".formU") == 2 or mc.getAttr(surf + ".formV") == 2): mc.warning("surface is periodic. fk controls skipped") ################ ADD mensaje de atributo ################ mc.addAttr(main_ctrl, ln="joints", at="message") mc.addAttr(main_ctrl, ln="follicles", at="message") mc.addAttr(main_ctrl, ln="surface", at="message") if mc.attributeQuery("i_am_the_surface", node=surf, exists=True) == False: mc.addAttr(surf, ln="i_am_the_surface", at="message") mc.connectAttr(main_ctrl + ".surface", surf + ".i_am_the_surface") for j, f in izip(bind_jnts, fols): mc.addAttr(j, ln="i_am_a_joint", at="message") mc.addAttr(f, ln="i_am_a_follicle", at="message") mc.connectAttr(main_ctrl + ".joints", j + ".i_am_a_joint") mc.connectAttr(main_ctrl + ".follicles", f + ".i_am_a_follicle")
def updateData(self, *a, **kw): """ Get's attr updated data """ assert mc.objExists( '%s.%s' % (self.obj.nameShort, self.attr) ) is True, "'%s.%s' doesn't exist" % (self.obj.nameShort, self.attr) # Default attrs self.nameCombined = '%s.%s' % (self.obj.nameShort, self.attr) self.minValue = False self.maxValue = False self.defaultValue = False self.nameNice = mc.attributeQuery(self.attr, node=self.obj.nameShort, niceName=True) self.nameLong = mc.attributeQuery(self.attr, node=self.obj.nameShort, longName=True) self.nameAlias = False if mc.aliasAttr(self.nameCombined, q=True): self.nameAlias = mc.aliasAttr(self.nameCombined, q=True) self.get(*a, **kw) #>>> Parent Stuff pBuffer = mc.attributeQuery(self.attr, node=self.obj.nameShort, listParent=True) if pBuffer is None: self.parent = False else: self.parent = pBuffer[0] self.children = mc.attributeQuery(self.attr, node=self.obj.nameShort, listChildren=True) if self.children is None: self.children = False self.siblings = mc.attributeQuery(self.attr, node=self.obj.nameShort, listSiblings=True) if self.siblings is None: self.siblings = False self.enum = False self.userAttrs = mc.listAttr(self.obj.nameShort, userDefined=True) or [] standardFlagsBuffer = attributes.returnStandardAttrFlags( self.obj.nameShort, self.nameLong) standardDataBuffer = attributes.returnAttributeDataDict( self.obj.nameShort, self.nameLong) #Check connections self.driver = attributes.returnDriverAttribute(self.nameCombined, False) self.driven = attributes.returnDrivenAttribute(self.nameCombined, False) self.numeric = standardFlagsBuffer.get('numeric') self.dynamic = standardFlagsBuffer.get('dynamic') self.locked = standardFlagsBuffer.get('locked') self.keyable = standardFlagsBuffer.get('keyable') self.hidden = standardFlagsBuffer.get('hidden') if self.dynamic: self.readable = standardFlagsBuffer.get('readable') self.writable = standardFlagsBuffer.get('writable') self.storable = standardFlagsBuffer.get('storable') self.usedAsColor = standardFlagsBuffer.get('usedAsColor') #>>> Numeric if self.numeric: bufferDict = attributes.returnNumericAttrSettingsDict( self.obj.nameShort, self.nameLong) if bufferDict: self.maxValue = bufferDict.get('max') self.minValue = bufferDict.get('min') self.defaultValue = bufferDict.get('default') self.softMaxValue = bufferDict.get('softMax') self.softMinValue = bufferDict.get('softMin') self.rangeValue = bufferDict.get('range') self.softRangeValue = bufferDict.get('softRange') else: self.maxValue = False self.minValue = False self.defaultValue = False self.softMaxValue = False self.softMinValue = False self.rangeValue = False self.softRangeValue = False if self.form == 'enum': self.enum = standardFlagsBuffer.get('enum')
def jsBlendDeltas(): bs = mc.textField(jsBD_bs_TF, q=1, tx=True) offset = 10 addToBs = mc.checkBox(addToBs_CB, q=True, v=True) name = mc.textField(jsBD_name_TF, q=1, tx=True) name = name.replace(' ', '_') name = name.replace('.', '_') # List meshes selMeshes = mc.ls(sl=True) # Duplicate corrective mesh and posed mesh corr = mc.duplicate(selMeshes[0], n="jsEBD_corrective") posed = mc.duplicate(selMeshes[1], n="jsEBD_posed") mc.setAttr("jsEBD_posed.tx", l=False) mc.setAttr("jsEBD_posed.ty", l=False) mc.setAttr("jsEBD_posed.tz", l=False) # Set envelopes to 0 hist = mc.listHistory(selMeshes[1], pdo=True) skin = mc.ls(hist, type='skinCluster') skinLen = len(skin) blends = mc.ls(hist, type='blendShape') print blends blendsLen = len(blends) if blendsLen != 0: for node in blends: mc.setAttr(node + ".envelope", 0) if skinLen == 1: mc.setAttr(skin[0] + ".envelope", 0) # Duplicate default mesh default = mc.duplicate(selMeshes[1], n="jsEBD_default") mc.setAttr("jsEBD_default.tx", l=False) mc.setAttr("jsEBD_default.ty", l=False) mc.setAttr("jsEBD_default.tz", l=False) # Extract deltas bsn = mc.blendShape(corr, posed, default, n="jsBD_BS") mc.setAttr(bsn[0] + '.' + corr[0], 1) mc.setAttr(bsn[0] + '.' + posed[0], -1) newMesh = mc.duplicate(default, n=name) mc.delete(corr, posed, default) # Move result getTX = mc.getAttr(selMeshes[0] + ".tx") mc.setAttr(newMesh[0] + ".tx", getTX - offset) getTY = mc.getAttr(selMeshes[0] + ".ty") mc.setAttr(newMesh[0] + ".ty", getTY) # Set envelopes to 1 if blendsLen != 0: for node in blends: mc.setAttr(node + ".envelope", 1) if skinLen == 1: mc.setAttr(skin[0] + ".envelope", 1) if addToBs == 1: # Create blend shape targetIndex = mc.aliasAttr(bs, q=True) indexLen = len(targetIndex) mc.blendShape(bs, e=True, t=(selMeshes[1], indexLen / 2, newMesh[0], 1.0))
def edo_addBlendShapeAndExpressionsByFacialCtrlInbetween(ctrlName): #ctrlName=sels[0] #ctrlName='bbb_CONNECT_lfup___aaa_CONNECT_fourAxis_up' sfix = '' if '_CTRL' in ctrlName: sfix = '_CTRL' if '_CONNECT' in ctrlName: sfix = '_CONNECT' if sfix == '': #cmds.confirmDialog( title='Confirm', message='this node is not created by autoBlendShapeManagerTools', button=['got it'] ) raise Exception('this node [' + ctrlName + '] is not created by autoBlendShapeManagerTools') return False endstr = ctrlName.split('_')[-1] allMeshes = [] if endstr == 'CTRL' or endstr == 'CONNECT': upmeshes = cmds.listRelatives(ctrlName + '_up', c=1, type='transform', pa=1) dnmeshes = cmds.listRelatives(ctrlName + '_dn', c=1, type='transform', pa=1) lfmeshes = cmds.listRelatives(ctrlName + '_lf', c=1, type='transform', pa=1) lfupmeshes = cmds.listRelatives(ctrlName + '_lfup', c=1, type='transform', pa=1) lfdnmeshes = cmds.listRelatives(ctrlName + '_lfdn', c=1, type='transform', pa=1) rtmeshes = cmds.listRelatives(ctrlName + '_rt', c=1, type='transform', pa=1) rtupmeshes = cmds.listRelatives(ctrlName + '_rtup', c=1, type='transform', pa=1) rtdnmeshes = cmds.listRelatives(ctrlName + '_rtdn', c=1, type='transform', pa=1) fourAxisupmeshes = cmds.listRelatives(ctrlName + '_fourAxisup', c=1, type='transform', pa=1) fourAxisdnmeshes = cmds.listRelatives(ctrlName + '_fourAxisdn', c=1, type='transform', pa=1) fourAxislfmeshes = cmds.listRelatives(ctrlName + '_fourAxislf', c=1, type='transform', pa=1) fourAxisrtmeshes = cmds.listRelatives(ctrlName + '_fourAxisrt', c=1, type='transform', pa=1) edo_combineAllList(allMeshes, upmeshes) edo_combineAllList(allMeshes, dnmeshes) edo_combineAllList(allMeshes, lfmeshes) edo_combineAllList(allMeshes, rtmeshes) edo_combineAllList(allMeshes, lfupmeshes) edo_combineAllList(allMeshes, rtupmeshes) edo_combineAllList(allMeshes, lfdnmeshes) edo_combineAllList(allMeshes, rtdnmeshes) edo_combineAllList(allMeshes, fourAxisupmeshes) edo_combineAllList(allMeshes, fourAxisdnmeshes) edo_combineAllList(allMeshes, fourAxislfmeshes) edo_combineAllList(allMeshes, fourAxisrtmeshes) if allMeshes == [] or allMeshes == None: return False else: allMeshes = cmds.listRelatives(ctrlName, c=1, type='transform', pa=1) bsnodes = [] targetMesh = '' for mm in allMeshes: #mm=allMeshes[2] print mm if 'connectCurve' in mm: continue targetMesh = mm.split('__')[1] + '_' targetCtrl = mm.split('__')[-1] ##if selected object is a ctrl if cmds.objExists(targetMesh) and cmds.objExists(targetCtrl): BSname = targetMesh + '_BLENDSHAPE' m = cmds.rename(mm, edo_splitBlendshapeWeightStr(mm, '6000')) print m if m[-1].lower() == m[-1].upper(): print m + '... is a wrong named target,passed...' continue if len(m.split('__')) == 4 and m.split('__')[2].upper() == m.split( '__')[2].lower(): print 'add inbetween...' if not BSname in bsnodes: bsnodes.append(BSname) if not cmds.objExists(BSname): bsnode = cmds.blendShape(targetMesh, frontOfChain=1, n=BSname) #wc=cmds.blendShape(BSname,q=1,wc=1) wc = edo_getMaxLocalIndexFromPhysicalCount(BSname + '.weight') + 1 attrname = edo_splitBlendshapeWeightStr(m, m.split('__')[2]) id = edo_targetIsInBlendShapeWeightId(attrname, BSname) wv = (float(m.split('__')[2]) - 5000) / 1000 output = cmds.listConnections(m + '.worldMesh[0]', s=0, d=1, type='blendShape') if not output == None: if not BSname in cmds.listConnections( m + '.worldMesh[0]', s=0, d=1, type='blendShape'): if id == -1: cmds.blendShape(BSname, e=1, t=[targetMesh, wc, m, wv]) else: cmds.blendShape(BSname, e=1, ib=True, t=[targetMesh, id, m, mv]) try: cmds.aliasAttr(attrname, BSname + '.weight[' + str(wc) + ']') except: print 'pass aliasAttr...' else: if id == -1: cmds.blendShape(BSname, e=1, t=[targetMesh, wc, m, wv]) else: cmds.blendShape(BSname, e=1, ib=True, t=[targetMesh, id, m, wv]) try: cmds.aliasAttr(attrname, BSname + '.weight[' + str(wc) + ']') except: print 'pass aliasAttr...' else: if not BSname in bsnodes: bsnodes.append(BSname) if not cmds.objExists(BSname): bsnode = cmds.blendShape(targetMesh, frontOfChain=1, n=BSname) #attrname=edo_splitBlendshapeWeightStr(m,m.split('__')[2]) id = edo_targetIsInBlendShapeWeightId(m, BSname) #wc=cmds.blendShape(BSname,q=1,wc=1) wc = edo_getMaxLocalIndexFromPhysicalCount(BSname + '.weight') + 1 output = cmds.listConnections(m + '.worldMesh[0]', s=0, d=1, type='blendShape') if not output == None: if not BSname in cmds.listConnections( m + '.worldMesh[0]', s=0, d=1, type='blendShape'): cmds.blendShape(BSname, e=1, t=[targetMesh, wc, m, 1.0]) else: if id == -1: cmds.blendShape(BSname, e=1, t=[targetMesh, wc, m, 1.0]) else: cmds.blendShape(BSname, e=1, ib=True, t=[targetMesh, id, m, 1.0]) else: ##if selected object is a complexed frame if cmds.objExists(mm[(len(ctrlName) * -1):]): print 'selected object is a complexed frame' BSname = targetMesh + '_BLENDSHAPE' #mm='BS__pSphere1__5500__aaa_CTRL_rtdn___bbb_CTRL_lfdn' m = cmds.rename(mm, edo_splitBlendshapeWeightStr(mm, '6000')) print m if m[-1].lower() == m[-1].upper(): print m + '... is a wrong named target,passed...' continue if len(m.split('__')) == 5 and m.split( '__')[2].upper() == m.split('__')[2].lower(): print 'add inbetween...' if not BSname in bsnodes: bsnodes.append(BSname) if not cmds.objExists(BSname): bsnode = cmds.blendShape(targetMesh, frontOfChain=1, n=BSname) #wc=cmds.blendShape(BSname,q=1,wc=1) wc = edo_getMaxLocalIndexFromPhysicalCount(BSname + '.weight') + 1 attrname = edo_splitBlendshapeWeightStr( m, m.split('__')[2]) id = edo_targetIsInBlendShapeWeightId(attrname, BSname) wv = (float(m.split('__')[2]) - 5000) / 1000 output = cmds.listConnections(m + '.worldMesh[0]', s=0, d=1, type='blendShape') if not output == None: if not BSname in cmds.listConnections( m + '.worldMesh[0]', s=0, d=1, type='blendShape'): if id == -1: cmds.blendShape(BSname, e=1, t=[targetMesh, wc, m, wv]) else: cmds.blendShape(BSname, e=1, ib=True, t=[targetMesh, id, m, mv]) try: cmds.aliasAttr( attrname, BSname + '.weight[' + str(wc) + ']') except: print 'pass aliasAttr...' else: if id == -1: cmds.blendShape(BSname, e=1, t=[targetMesh, wc, m, wv]) else: cmds.blendShape(BSname, e=1, ib=True, t=[targetMesh, id, m, wv]) try: cmds.aliasAttr(attrname, BSname + '.weight[' + str(wc) + ']') except: print 'pass aliasAttr...' else: if not BSname in bsnodes: bsnodes.append(BSname) if not cmds.objExists(BSname): bsnode = cmds.blendShape(targetMesh, frontOfChain=1, n=BSname) #attrname=edo_splitBlendshapeWeightStr(m,m.split('__')[2]) id = edo_targetIsInBlendShapeWeightId(m, BSname) #wc=cmds.blendShape(BSname,q=1,wc=1) wc = edo_getMaxLocalIndexFromPhysicalCount(BSname + '.weight') + 1 output = cmds.listConnections(m + '.worldMesh[0]', s=0, d=1, type='blendShape') if not output == None: if not BSname in cmds.listConnections( m + '.worldMesh[0]', s=0, d=1, type='blendShape'): cmds.blendShape(BSname, e=1, t=[targetMesh, wc, m, 1.0]) else: if id == -1: cmds.blendShape(BSname, e=1, t=[targetMesh, wc, m, 1.0]) else: cmds.blendShape(BSname, e=1, ib=True, t=[targetMesh, id, m, 1.0]) #add expression.... print 'get expression...' for bsnode in bsnodes: #bsnode=bsnodes[0] exname = ctrlName + '__' + bsnode.replace('_BLENDSHAPE', '_EXPRESSION') extext = '//' + exname + '\n' extext += '//don\'t write custom expression in here!,the script will delete this scirpt first before create a new expression\n\n' if cmds.objExists(exname): cmds.delete(exname) #bsattrlen=cmds.blendShape(bsnode,q=1,wc=1) bsattrlen = edo_getMaxLocalIndexFromPhysicalCount(bsnode + '.weight') + 1 for i in range(0, bsattrlen): #i=0 print i ctrlattrname = '' if endstr == 'CTRL' or endstr == 'CONNECT': bsattr = cmds.aliasAttr(bsnode + '.weight[' + str(i) + ']', q=1) m = bsattr bsattrname = bsnode + '.' + m print m if not ctrlName in m or '___' in m: print m + ' ... pass' continue else: print m + ' ... addex' ctrlattrname = m.split('__')[len(m.split('__')) - 1] ctrlattrname = ctrlattrname.replace(sfix + '_', '_FRAME.') ctrlattrname = ctrlattrname.replace( 'fourAxis', 'fourAxis_') extext += bsattrname + '=' + ctrlattrname + ';\n' else: bsattr = cmds.aliasAttr(bsnode + '.weight[' + str(i) + ']', q=1) m = bsattr bsattrname = bsnode + '.' + m print m if not ctrlName in m: print m + ' ... pass' continue else: print m + ' ... addex' tmp = m.split('___') st = tmp[0].split('__')[-1] tmp.remove(tmp[0]) ctrlattrname = st for t in tmp: ctrlattrname += ('___' + t) ctrlattrname = ctrlattrname + '.multiplyValue' extext += bsattrname + '=' + ctrlattrname + ';\n' print 'add expression' print exname + ' : \n' + extext + '\n' try: cmds.expression(n=exname, s=extext) except: print 'you probably connect some attribute to this blendshape attribute, the script can not create expression on it'
def setShapeData(node, shapeData, inputIndex=0, shapes=None): """ sets the shape data onto a blendShape node. :param str node: the blendShape to add the shapes to. :param dict shapeData: the shape data to apply to the node. :param list shapes: if given, only modify given target names """ targetName = None if shapes: targetName = shapes[0] if not mc.objExists('%s.%s' % (node, targetName)): shapeIndex = 0 weightIndices = mc.getAttr(node + ".weight", multiIndices=True) if weightIndices: shapeIndex = weightIndices[-1] + 1 attr = '%s.weight[%i]' % (node, shapeIndex) mc.getAttr(attr) mc.aliasAttr(targetName, attr) mc.setAttr(attr, 1.0) nodeType = mc.nodeType(node) inputShape = mc.deformer(node, g=True, q=True) shapeAliasLookup = getShapeAliasLookup(node) print(shapeAliasLookup) if not 'shapes' in shapeData: print("procedureName" + ': shapeData does not have a "shapes" key. Returning now...') return for shapeAlias in shapeData['shapes']: if shapes and shapeAlias not in shapes: continue print(shapeAlias) # read the information stored for this shape targetData = shapeData['shapes'][shapeAlias] targetOffsets = targetData["offsets"] targetWeights = targetData["weights"] shapeIndex = shapeAliasLookup.get(shapeAlias, None) print('shapeIndex: ' + str(shapeIndex)) # iterate through the offset dictionary pointList = [] componentList = [] for pointIndex in targetOffsets: pointData = targetOffsets[pointIndex] pointList.append((pointData[0], pointData[1], pointData[2], 1.0)) componentList.append('vtx[' + str(pointIndex) + ']') # create the element by calling getAttr try: mc.getAttr(node + '.inputTarget[' + str(inputIndex) + ']') except: pass try: mc.getAttr(node + '.inputTarget[' + str(inputIndex) + '].inputTargetGroup[' + str(shapeIndex) + ']') except: pass shapeAttr = node + ".inputTarget[" + str( inputIndex) + "].inputTargetGroup[" + str(shapeIndex) + "]" mc.setAttr(shapeAttr + ".inputTargetItem[6000].inputPointsTarget", len(componentList), type="pointArray", *pointList) mc.setAttr(shapeAttr + ".inputTargetItem[6000].inputComponentsTarget", len(componentList), type="componentList", *componentList) tAttrs = mc.listAttr(shapeAttr, m=True, string='targetWeights') if tAttrs != None: for a in tAttrs: mc.removeMultiInstance((node + '.' + a), b=True) # set the weights for weight in targetWeights: mc.setAttr(shapeAttr + ".targetWeights[" + str(weight) + "]", targetWeights[weight])
def alias(self, newName): """alias the current attribute with a new name :param newName: alias name for the attribute :type newName: str""" mc.aliasAttr(newName, self.fullname)
def setDefaultAttrState(objList, attrList, valueList=[]): ''' Set default attribute state values for a specified list of object attributes. @param objList: List of objects to store default attribute state values for. @type objList: list @param attrList: List of attributes to store default attribute state values for. @type attrList: list @param valueList: List of attributes values to assign to the default attribute states. If empty, use current object attribute values. @type valueList: list ''' # Check Object List if not objList: return if not attrList: return if len(attrList) != len(valueList): print( 'Attribute and value list mis-match! Recording existing attribute values.' ) valueList = [] # Define defaultAttrState attribute name defAttr = 'defaultAttrState' aliasSuffix = 'defaultState' # For each object in list for obj in objList: # Check Object if not mc.objExists(obj): raise Exception('Object "' + obj + '" does not exist!') if not mc.attributeQuery(defAttr, n=obj, ex=True): addDefaultAttrState([obj]) # For each attribute in list for i in range(len(attrList)): # Get current attribute attr = attrList[i] attrAlias = attr + '_' + aliasSuffix # Check attribute if not mc.attributeQuery(attr, n=obj, ex=True): raise Exception('Object "' + obj + '" has no attribute "' + attr + '"!') # Get attribute value if valueList: value = valueList[i] else: value = mc.getAttr(obj + '.' + attr) # Add default attribute state if not mc.attributeQuery(attrAlias, n=obj, ex=True): try: index = mc.getAttr(obj + '.' + defAttr, s=True) except: print('Error getting multi length from "' + obj + '.' + defAttr + '"') mc.setAttr(obj + '.' + defAttr + '[' + str(index) + ']', 0) try: mc.aliasAttr(attrAlias, obj + '.' + defAttr + '[' + str(index) + ']') except: print('Error setting attribute alias ("' + attrAlias + '") for node attr "' + obj + '.' + defAttr + '[' + str(index) + ']"') # Set default attribute state try: mc.setAttr(obj + '.' + attrAlias, value) except: print('Unable to set default attr state ("' + attrAlias + '") for object "' + obj + '" to value (' + str(value) + ')!')