def createPathFromSel(): """Create a path curve object from selected transforms. SELECT THEM IN A PROPER ORDER. EPS ARE MADE IN ORDER OF SELETION.""" trans = pmc.ls(sl=True, transforms=True) c = pmc.curve(d=3, ep=(s.getTranslation(ws=True) for s in trans)) pmc.closeCurve(c, ch=0, rpo=True) return c
def add_curve_shape(shape_choice, transform_node=None, color=''): # curve library calling if not transform_node: transform_node = pm.ls(selection=True)[0] curve_transform = curve_library[shape_choice]() curve_shape = pm.listRelatives(curve_transform, shapes=True)[0] if curve_library_bool[shape_choice]: pm.closeCurve(curve_shape, ch=0, replaceOriginal=1) if color: set_color(color, input_shape=curve_shape) pm.parent(curve_shape, transform_node, shape=True, r=True) pm.rename(curve_shape, transform_node + '_Shape') pm.delete(curve_transform)
def RoundSquare(self): crv = create_shape(self.name, 'square_rounded', length=self.length, height=self.height, width=self.radius, offset=self.offset) crv = pm.closeCurve(crv, replaceOriginal=True)[0] crv.setRotation((0, -90, 0)) # pm.makeIdentity(crv, apply=True) return crv
def create_ctr_shape(self, shape): """ Creates curve shape and parents it under ctr transform """ #Loads shapes dictionary shape_file_read = open(g_data.ctrls_shapes_file,'r') shapes_dictionary = json.load(shape_file_read) #Args validation if not shape in shapes_dictionary.keys(): raise Exception('%s is not a registered shape') #Extracts data shapes_data = shapes_dictionary[shape] for curve_data in shapes_data.keys(): curve_degree = shapes_data[curve_data]['degree'] curve_form = shapes_data[curve_data]['form'] #Points are multiplied by size point_data = shapes_data[curve_data]['points'] curve_points = [] for each_point in point_data: sized_p = [p*self.size for p in each_point] curve_points.append(sized_p) # curve_points = [p*self.size for p in point_data] #Create curve in maya temp_curve = pm.curve(name = self.full_name, degree = curve_degree, point = curve_points) if curve_form == 2: #2 is closed pm.closeCurve(temp_curve, preserveShape = False, replaceOriginal = True) curve_shape = temp_curve.getShape() #Parent curve shape under control and delete temp transform pm.parent(curve_shape, self.pm_node, r = 1, s = 1) pm.delete(temp_curve) #Store shape in object attribute self.shapes.append(curve_shape)
# coding:utf-8 __author__ = 'timmyliang' __email__ = '*****@*****.**' __date__ = '2019-11-25 15:42:22' """ 选顶点生成曲线 """ import pymel.core as pm # NOTE 开启顺序获取 if not pm.selectPref(q=1, tso=1): pm.selectPref(tso=1) vtx_list = [] for vtx in pm.ls(sl=1, fl=1, os=1): if type(vtx) == pm.general.MeshVertex: vtx_list.append(vtx) # NOTE 生成曲线 curve = pm.curve(d=1, p=[vtx.getPosition(space="world") for vtx in vtx_list]) # NOTE 闭合曲线 pm.closeCurve(curve, ch=0, rpo=1)
def create_control_icon(iconType, iconName, iconScale, joint=False, offset=False): ### Read from a dictionary or JSON or Alembic file that stores point information iconLib = icon_library(iconType) pPoints = iconLib['points'] pD = iconLib['degree'] controlCurve = pm.curve(name=iconName, d=pD, p=pPoints) controlCurve.s.set(iconScale) pm.makeIdentity(controlCurve, apply=True) if iconLib['closed'] == True: oName = controlCurve.name() pm.closeCurve(controlCurve, ch=False, ps=True, rpo=True) controlCurve = pm.PyNode(oName) # A hack to make sure the arrows on arrowBox are uniformly scaled, relative to the width:height ratio. if iconType == 'arrowBox': axes = [iconScale[0], iconScale[2]] scaleFactor = min(axes) / max(axes) if iconScale[0] > iconScale[2]: oPivot = (pnt_ws(controlCurve.cv[21]) + pnt_ws(controlCurve.cv[27])) * 0.5 pm.scale(controlCurve.cv[21:27], scaleFactor, 1, 1, r=True, p=oPivot) oPivot = (pnt_ws(controlCurve.cv[11]) + pnt_ws(controlCurve.cv[5])) * 0.5 pm.scale(controlCurve.cv[5:11], scaleFactor, 1, 1, r=True, p=oPivot) oPivot = (pnt_ws(controlCurve.cv[3]) + pnt_ws(controlCurve.cv[29])) * 0.5 pm.scale(controlCurve.cv[29:32], scaleFactor, 1, 1, r=True, p=oPivot) pm.scale(controlCurve.cv[0:3], scaleFactor, 1, 1, r=True, p=oPivot) oPivot = (pnt_ws(controlCurve.cv[13]) + pnt_ws(controlCurve.cv[19])) * 0.5 pm.scale(controlCurve.cv[13:19], scaleFactor, 1, 1, r=True, p=oPivot) else: oPivot = (pnt_ws(controlCurve.cv[21]) + pnt_ws(controlCurve.cv[27])) * 0.5 pm.scale(controlCurve.cv[21:27], 1, 1, scaleFactor, r=True, p=oPivot) oPivot = (pnt_ws(controlCurve.cv[11]) + pnt_ws(controlCurve.cv[5])) * 0.5 pm.scale(controlCurve.cv[5:11], 1, 1, scaleFactor, r=True, p=oPivot) oPivot = (pnt_ws(controlCurve.cv[3]) + pnt_ws(controlCurve.cv[29])) * 0.5 pm.scale(controlCurve.cv[29:32], 1, 1, scaleFactor, r=True, p=oPivot) pm.scale(controlCurve.cv[0:3], 1, 1, scaleFactor, r=True, p=oPivot) oPivot = (pnt_ws(controlCurve.cv[13]) + pnt_ws(controlCurve.cv[19])) * 0.5 pm.scale(controlCurve.cv[13:19], 1, 1, scaleFactor, r=True, p=oPivot) if offset: pm.move(controlCurve.cv, offset, relative=True) ### Pick a particular default if not defined (circle?) ### scale, rotate and transform appropriately (using placing functions) ### color and style the curve ### set the icon in proper layers ### shape parent as necessary if joint: controlCurve.rename(controlCurve.name() + 'Shape') pm.select(None) oJoint = pm.joint(n=iconName, r=0.5) pm.select(None) pm.parent(controlCurve.getShapes(), oJoint, shape=True, relative=True) pm.delete(controlCurve) return oJoint return controlCurve
def create(self): self.transformNode = pm.curve(p=self.style['p'], k= self.style['k'], d = self.style['d']) if self.style['closeCurve']: pm.closeCurve(self.transformNode, ch = False, replaceOriginal=True, object=True, preserveShape=False, blendKnotInsertion=True) pm.rename(self.transformNode, self.name)
# coding:utf-8 __author__ = 'timmyliang' __email__ = '*****@*****.**' __date__ = '2019-11-20 10:08:56' """ 获取曲线 ControlPoint 的位置 """ import pymel.core as pm if __name__ == "__main__": jnt_list = pm.ls(sl=1, type="joint") crv = pm.curve(p=[jnt.getTranslation() for jnt in jnt_list]) pm.closeCurve(crv, ch=0, rpo=1) info = pm.createNode("curveInfo") crv.worldSpace[0].connect(info.inputCurve) for i, jnt in enumerate(jnt_list): loc = pm.spaceLocator(n="%s_loc" % jnt) loc.setParent(crv) loc.v.set(0) info.controlPoints[i].connect(loc.t) grp = pm.group(jnt, n="%s_crv_loc" % jnt) pm.parentConstraint(loc, grp, mo=1)
def banker(joint, ik_control, pivot_track=None, side='', use_track_shape=True): """ Creates a reverse foot control that changes pivot based on curve shape and control rotation input. Useful for banking. Args: joint (pm.nodetypes.Joint): Joint that will be driven by the reverse module and IK handle. ik_control (pm.nodetypes.Transform): Control that drives the IK Handle. pivot_track (pm.nodetypes.Transform): With a NurbsCurve shape as child that will act as the track for the pivot. side (string or None): Side to generate cross section use_track_shape (boolean): If True, will use the pivot track shape as the control shape Returns: (pm.nodetypes.Transform): Control that moves the reverse foot pivot. """ joint_name = joint.name() prefix = joint_name + '_' axis = pipermath.getOrientAxis(joint.getParent(), joint) axes = convert.axisToTriAxis(axis) if not side: side = pcu.getSide(joint_name) # get the IK handle and validate there is only one ik_handle = list(set(ik_control.connections(skipConversionNodes=True, type='ikHandle'))) if len(ik_handle) != 1: pm.error('Needed only ONE ik_handle. {} found.'.format(str(len(ik_handle)))) ik_handle = ik_handle[0] # create a pivot track (cross section curve) if no pivot track (curve) is given if not pivot_track: # if IK joint given, get the name of the regular joint by stripping the ik prefix if joint_name.startswith(pcfg.ik_prefix): stripped_name = pcu.removePrefixes(joint_name, pcfg.ik_prefix) namespace_name = pcfg.skeleton_namespace + ':' + stripped_name search_joint = pm.PyNode(stripped_name) if pm.objExists(stripped_name) else pm.PyNode(namespace_name) else: search_joint = joint # tries to get the meshes influenced by the skin cluster connected to the joint skins = search_joint.future(type='skinCluster') meshes = {mesh for skin in skins for mesh in pm.skinCluster(skin, q=True, g=True)} if skins else None # create the pivot track curve pm.select(cl=True) pivot_track = curve.originCrossSection(meshes, side=side, name=prefix + 'pivotTrack') # validate that only one is made if len(pivot_track) != 1: pm.error('Needed only ONE curve! {} curves made. Try to specify a side.'.format(str(len(pivot_track)))) pivot_track = pivot_track[0] # create the pivot and the normalized pivot, move the norm pivot to joint and then to floor pivot = pm.group(em=True, name=prefix + 'Pivot') normalized_pivot = pm.group(em=True, name=prefix + 'normalizedPivot') pm.matchTransform(normalized_pivot, joint, pos=True, rot=False, scale=False) normalized_pivot.ty.set(0) xform.toOffsetMatrix(normalized_pivot) # figure out control size, create control, lock and hide axis, translate, and scale if ik_control.hasAttr(pcfg.proxy_fk_ik): switcher_control = switcher.get(ik_control) transforms = switcher.getData(switcher_control.attr(pcfg.switcher_transforms), cast=True) size = control.calculateSize(transforms[-1]) else: size = None if use_track_shape: ctrl = pm.duplicate(pivot_track, n=prefix + 'bank')[0] curve.color(ctrl, 'burnt orange') else: ctrl = control.create(joint, shape=curve.plus, name=prefix + 'bank', axis=axes[0], color='burnt orange', matrix_offset=True, size=size, inner=.125, outer=1.25) attribute.lockAndHide(ctrl.attr('r' + axes[0])) attribute.lockAndHideCompound(ctrl, ['t', 's']) # node to add small number small_add = pm.createNode('plusMinusAverage', n=prefix + 'plusSmallNumber') small_add.input1D[0].set(0.001) normalize_node = pm.createNode('vectorProduct', n=prefix + 'pivotNormal') normalize_node.operation.set(0) normalize_node.normalizeOutput.set(True) # adding a small amount to avoid division by zero ctrl.attr('r' + axes[1]) >> small_add.input1D[1] small_add.output1D >> normalize_node.attr('input1' + axes[2].upper()) # need to multiply the rotation by -1 negative_mult = pm.createNode('multDoubleLinear', n=prefix + 'negative') ctrl.attr('r' + axes[2]) >> negative_mult.input1 negative_mult.input2.set(-1) normalize_input_attribute = negative_mult.output normalize_input_attribute >> normalize_node.attr('input1' + axes[1].upper()) normalize_node.output >> normalized_pivot.translate # creating the normalized (circle) version of the cross section positions = [] duplicate_curve = pm.duplicate(pivot_track)[0] pm.move(0, 0, 0, duplicate_curve, rpr=True) cvs = duplicate_curve.numCVs() for cv in range(0, cvs): position = duplicate_curve.cv[cv].getPosition(space='world') position.normalize() positions.append(position) # delete the duplicate and finally make the normalize track. Make sure to close the curve and center pivots pm.delete(duplicate_curve) normalized_track = pm.curve(d=1, p=positions, k=range(len(positions)), ws=True, n=prefix + 'normalizedTrack') normalized_track = pm.closeCurve(normalized_track, replaceOriginal=True)[0] pm.xform(normalized_track, centerPivots=True) # move normalized track to joint, then to floor, and freeze transforms pm.matchTransform(normalized_track, joint, pos=True, rot=False, scale=False) normalized_track.ty.set(0) myu.freezeTransformations(normalized_track) decomposed_matrix = pm.createNode('decomposeMatrix', n=normalize_node + '_decompose') normalized_pivot.worldMatrix >> decomposed_matrix.inputMatrix nearest_point = pm.createNode('nearestPointOnCurve', n=prefix + 'nearestPoint') decomposed_matrix.outputTranslate >> nearest_point.inPosition normalized_track.getShape().worldSpace >> nearest_point.inputCurve curve_info = pm.createNode('pointOnCurveInfo', n=prefix + 'curveInfo') nearest_point.parameter >> curve_info.parameter pivot_track.getShape().worldSpace >> curve_info.inputCurve reverse_group = pm.group(em=True, n=prefix + 'reverse_grp') xform.parentMatrixConstraint(ik_control, reverse_group, offset=True) pm.parent([pivot, ctrl], reverse_group) # curve_info position is where the pivot goes! Connect something to it if you want to visualize it ctrl.r >> pivot.r curve_info.result.position >> pivot.rotatePivot # connect ik handle by letting the pivot drive it pm.parent(ik_handle, pivot) # make the pivot drive the joint's rotations joint.r.disconnect() xform.parentMatrixConstraint(pivot, joint, t=False, r=True, s=False, offset=True) # clean up by hiding curves pivot_track.visibility.set(False) normalized_track.visibility.set(False) ik_control.addAttr(pcfg.banker_attribute, dt='string', k=False, h=True, s=True) ik_control.attr(pcfg.banker_attribute).set(ctrl.name()) # hook up pivot control with fk_ik attribute if ik has an fk-ik proxy if ik_control.hasAttr(pcfg.proxy_fk_ik): switcher_control = switcher.get(ik_control) switcher_attribute = switcher_control.attr(pcfg.fk_ik_attribute) switcher_attribute >> ctrl.lodVisibility attribute.addSeparator(ctrl) ctrl.addAttr(pcfg.proxy_fk_ik, proxy=switcher_attribute, k=True, dv=0, hsx=True, hsn=True, smn=0, smx=1) return ctrl