def dag_to_geo(dag, geo): position_attr = attribute.add_generic_blend(dag, 'meshPosition') geo_shape = cmds.listRelatives(geo, s=True)[0] sel = om.MSelectionList() sel.add(geo_shape) plane = om.MFnMesh() plane.setObject(sel.getDagPath(0)) foll = cmds.createNode('follicle', name=dag + '_FOLL') foll_grp = cmds.listRelatives(foll, p=True) foll_grp = cmds.rename(foll_grp, foll + '_GRP') pos = cmds.xform(dag, t=True, ws=True, q=True) point = om.MPoint(om.MVector(pos)) parU, parV, face = plane.getUVAtPoint(point, space=4) cmds.connectAttr(foll + '.outTranslate', foll_grp + '.translate') cmds.connectAttr(foll + '.outRotate', foll_grp + '.rotate') cmds.connectAttr(geo_shape + '.outMesh', foll + '.inputMesh') cmds.connectAttr(geo_shape + '.worldMatrix', foll + '.inputWorldMatrix') cmds.setAttr(foll + '.parameterU', parU) cmds.setAttr(position_attr, parV) cmds.connectAttr(position_attr, foll + '.parameterV') constraint.simple_constraint(foll_grp, dag, snap=False)
def create_dag(name, source=None, connect='srt', snap=True, position=None, type='bone', ctrl_type='circle', size=1.0, offset=True): '''Creates a dag object of the given type Args: name (str): base name of node source (str): source dag object for constraining the object to connect (str): connect scale, translation, rotation of new dag to source snap (bool): whether the object will be moved to the source object position (om.MMatrix): matrix for object to be positioned at type (str): type of dag object created size (float): how large the dag will be Returns: (str): dag object created ''' cmds.select(clear=True) # create dag based on the type flag dag = None if type == 'bone': dag = cmds.joint(name=name + '_BONE') cmds.setAttr(dag + '.radius', size) if type == 'control': dag = shape.create_nurbscurve(ctrl_type, name=name + '_CTRL', size=size) dag = cmds.listRelatives(dag, p=True)[0] if type == 'locator': dag = cmds.spaceLocator(name=name + '_CTRL')[0] zero = cmds.createNode('transform', name=dag + '_ZERO') if offset: ofs = cmds.createNode('transform', name=dag + '_OFS') cmds.parent(dag, ofs) cmds.parent(ofs, zero) else: cmds.parent(dag, zero) # position and constrain the dag accordingly if position: cmds.xform(zero, matrix=position, ws=True) if source: if snap: snap_to_dag(source, zero) if connect: constraint.simple_constraint(source, zero, connect=connect) return dag
def section_controls(follow, side, name, default_pos=(0.0, 3.0, 0.0), function_attrs=None, **kwargs): ''' Args: follow (str): control/dag node that the section control follows side (str): C/L/R side control is on, influences color name (str): base name for control default_pos tuple(float, float, float): default position for positioning of control in world space above followed control function_attrs list[(str)]: attributes to create proxy attributes of **kwargs: key is the attribute name, value is a list of the objects whose visibility is being driven. If value is an attribute then the section attribute will be proxy to that attribute. Return: str: node name for section control ''' # get color of control if side == 'L': color = 18 elif side == 'R': color = 13 else: color = 17 zero, ofs, ctrl = cs.gear_ctrl('{}_{}_section_CTRL'.format(side, name)) # set color cmds.setAttr(ctrl + '.overrideEnabled', 1) cmds.setAttr(ctrl + '.overrideColor', color) # visibility attributes attribute.add_headline(ctrl, 'show') for attr, attr_list in kwargs.items(): # make sure item is a list obj_type = type(attr_list) if obj_type != 'list': ValueError('Keyword values must be a list') local_attr.force_visibility_attr(ctrl, attr, items=attr_list) # function attributes if function_attrs: attribute.add_headline(ctrl, 'function') for attr in function_attrs: # create proxy attribute to attribute attr_name = attr.split('.')[1] local_attr.proxy_attribute(ctrl, attr, attr_name) # constrain control to follow control pos = cmds.xform(follow, t=True, ws=True, q=True) cmds.xform(zero, t=pos, ws=True) constraint.simple_constraint(follow, zero, snap=False, connect='t') # set offset from follow control cmds.setAttr(ofs + '.translate', default_pos[0], default_pos[1], default_pos[2])
def attach_to_surface(surface, dag, snap=False, scale=False): # nodes to attach dag to surface POSI = cmds.createNode('pointOnSurfaceInfo', name=dag + '_POSI') matrix_node = cmds.createNode('fourByFourMatrix', name=dag + '_4X4') foll = cmds.createNode('transform', name=dag + '_custom_foll') foll_MSC = cmds.createNode('millSimpleConstraint', name=foll + '_MSC') # find closest point on surface and it's UV values dag_pos = cmds.xform(dag, t=True, ws=True, q=True) pos, parU, parV = closest_point_on_surface(surface, dag_pos) cmds.xform(dag, t=(pos[0], pos[1], pos[2]), ws=True) # attach dag to surface cmds.connectAttr(surface + '.local', POSI + '.inputSurface') cmds.setAttr(POSI + '.parameterU', parU) cmds.setAttr(POSI + '.parameterV', parV) # create matrix from POSI node cmds.connectAttr(POSI + '.normalizedTangentVX', matrix_node + '.in00') cmds.connectAttr(POSI + '.normalizedTangentVY', matrix_node + '.in01') cmds.connectAttr(POSI + '.normalizedTangentVZ', matrix_node + '.in02') cmds.connectAttr(POSI + '.normalizedNormalX', matrix_node + '.in10') cmds.connectAttr(POSI + '.normalizedNormalY', matrix_node + '.in11') cmds.connectAttr(POSI + '.normalizedNormalZ', matrix_node + '.in12') cmds.connectAttr(POSI + '.normalizedTangentUX', matrix_node + '.in20') cmds.connectAttr(POSI + '.normalizedTangentUY', matrix_node + '.in21') cmds.connectAttr(POSI + '.normalizedTangentUZ', matrix_node + '.in22') cmds.connectAttr(POSI + '.positionX', matrix_node + '.in30') cmds.connectAttr(POSI + '.positionY', matrix_node + '.in31') cmds.connectAttr(POSI + '.positionZ', matrix_node + '.in32') cmds.connectAttr(matrix_node + '.output', foll_MSC + '.inMatrix') cmds.connectAttr(foll + '.parentInverseMatrix[0]', foll_MSC + '.parentInverseMatrix') cmds.connectAttr(foll_MSC + '.outTranslate', foll + '.translate') cmds.connectAttr(foll_MSC + '.outRotate', foll + '.rotate') constraint.simple_constraint(foll, dag, snap=snap) if scale: POSI0 = cmds.createNode('pointOnSurfaceInfo', name=dag + '_scale0_POSI') POSI1 = cmds.createNode('pointOnSurfaceInfo', name=dag + '_scale1_POSI') dist = cmds.createNode('math_DistancePoints', name=dag + '_DIST') div = cmds.createNode('math_Divide', name=dag + '_DIV') cmds.connectAttr(surface + '.local', POSI0 + '.inputSurface') cmds.connectAttr(surface + '.local', POSI1 + '.inputSurface') cmds.setAttr(POSI0 + '.parameterU', 0) cmds.setAttr(POSI1 + '.parameterU', 1) cmds.setAttr(POSI0 + '.parameterV', parV) cmds.setAttr(POSI1 + '.parameterV', parV) cmds.connectAttr(POSI0 + '.position', dist + '.input1') cmds.connectAttr(POSI1 + '.position', dist + '.input2') init_distance = cmds.getAttr(dist + '.output') cmds.setAttr(div + '.input2', init_distance) cmds.connectAttr(dist + '.output', div + '.input1') cmds.connectAttr(div + '.output', foll + '.sz') return foll
def attach_to_surface(surface, dag): """Takes a dag node and attaches it to the nearest point on a surface, replacement for a follicle Args: surface (str): name of the transform of the nurbs surface that the dag node will be attached to dag (str): name of the dag node which will be attached Returns: str: Name of transform that follows the surface """ # nodes to attach dag to surface POSI = cmds.createNode('pointOnSurfaceInfo', name=dag + '_POSI') matrix_node = cmds.createNode('fourByFourMatrix', name=dag + '_4X4') foll = cmds.createNode('transform', name=dag + '_custom_foll') foll_MSC = cmds.createNode('millSimpleConstraint', name=foll + '_MSC') MM = cmds.createNode('multMatrix', name=dag + '_MM') # find closest point on surface and it's UV values sel = om.MSelectionList() sel.add(surface) plane = om.MFnNurbsSurface() plane.setObject(sel.getDagPath(0)) point = om.MPoint(om.MVector(cmds.xform(dag, t=True, ws=True, q=True))) pos, parU, parV = plane.closestPoint(point) cmds.xform(dag, t=(pos[0], pos[1], pos[2]), ws=True) # attach dag to surface cmds.connectAttr(surface + '.local', POSI + '.inputSurface') cmds.setAttr(POSI + '.parameterU', parU) cmds.setAttr(POSI + '.parameterV', parV) # create matrix from POSI node cmds.connectAttr(POSI + '.normalizedTangentVX', matrix_node + '.in00') cmds.connectAttr(POSI + '.normalizedTangentVY', matrix_node + '.in01') cmds.connectAttr(POSI + '.normalizedTangentVZ', matrix_node + '.in02') cmds.connectAttr(POSI + '.normalizedNormalX', matrix_node + '.in10') cmds.connectAttr(POSI + '.normalizedNormalY', matrix_node + '.in11') cmds.connectAttr(POSI + '.normalizedNormalZ', matrix_node + '.in12') cmds.connectAttr(POSI + '.normalizedTangentUX', matrix_node + '.in20') cmds.connectAttr(POSI + '.normalizedTangentUY', matrix_node + '.in21') cmds.connectAttr(POSI + '.normalizedTangentUZ', matrix_node + '.in22') cmds.connectAttr(POSI + '.positionX', matrix_node + '.in30') cmds.connectAttr(POSI + '.positionY', matrix_node + '.in31') cmds.connectAttr(POSI + '.positionZ', matrix_node + '.in32') cmds.connectAttr(matrix_node + '.output', MM + '.matrixIn[0]') cmds.connectAttr(surface + '.worldMatrix[0]', MM + '.matrixIn[1]') cmds.connectAttr(MM + '.matrixSum', foll_MSC + '.inMatrix') cmds.connectAttr(foll + '.parentInverseMatrix[0]', foll_MSC + '.parentInverseMatrix') cmds.connectAttr(foll_MSC + '.outTranslate', foll + '.translate') cmds.connectAttr(foll_MSC + '.outRotate', foll + '.rotate') constraint.simple_constraint(foll, dag) return foll
def birail_nurbs_plane(dags, name, side_vector): """ Args: dags[(str)]: dag nodes to control plane name (str): base name of plane side_vector (om.MVector()): side vector to orient/create plane Returns: str: nurbs plane """ mtxs = [] side_vector = side_vector * 2 other_side_vector = side_vector * -1 for each in dags: mtx = cmds.xform(each, matrix=True, ws=True, q=True) mtxs.append(mtx) mtx1 = om.MMatrix() mtx1.setElement(3, 0, side_vector[0]) mtx1.setElement(3, 1, side_vector[1]) mtx1.setElement(3, 2, side_vector[2]) mtx2 = om.MMatrix() mtx2.setElement(3, 0, other_side_vector[0]) mtx2.setElement(3, 1, other_side_vector[1]) mtx2.setElement(3, 2, other_side_vector[2]) prof_crv1 = curves.curve_from_matrices(mtxs, name=name + '_prof1_CRV', degree=2) prof_crv2 = curves.curve_from_matrices(mtxs, name=name + '_prof2_CRV', degree=2) rail_crv1 = curves.curve_from_matrices([mtx1, mtx2], name=name + '_rail1_CRV', degree=1) rail_crv2 = curves.curve_from_matrices([mtx1, mtx2], name=name + '_rail2_CRV', degree=1) cmds.rebuildCurve(prof_crv1, ch=1, rpo=1, kr=0, kcp=1, kt=0, s=30, d=2, tol=0.01) cmds.rebuildCurve(prof_crv2, ch=1, rpo=1, kr=0, kcp=1, kt=0, s=30, d=2, tol=0.01) plane = cmds.doubleProfileBirailSurface(prof_crv1, prof_crv2, rail_crv1, rail_crv2, po=0, name=name) constraint.simple_constraint(dags[0], rail_crv1) constraint.simple_constraint(dags[-1], rail_crv2) for x, each in enumerate(dags): scon1 = cmds.createNode("millSimpleConstraint", name=prof_crv1 + '_MSC') scon2 = cmds.createNode("millSimpleConstraint", name=prof_crv1 + '_MSC') cmds.connectAttr(each + '.worldMatrix[0]', scon1 + '.inMatrix') cmds.connectAttr(prof_crv1 + '.parentInverseMatrix[0]', scon1 + '.parentInverseMatrix') cmds.connectAttr(each + '.worldMatrix[0]', scon2 + '.inMatrix') cmds.connectAttr(prof_crv2 + '.parentInverseMatrix[0]', scon2 + '.parentInverseMatrix') cmds.setAttr(scon1 + '.translateOffset', side_vector[0], side_vector[1], side_vector[2]) cmds.setAttr(scon2 + '.translateOffset', side_vector[0], side_vector[1], side_vector[2]) cmds.connectAttr(scon1 + '.outTranslate', prof_crv1 + '.cv[{}]'.format(x)) cmds.connectAttr(scon2 + '.outTranslate', prof_crv2 + '.cv[{}]'.format(x)) return plane
def create_softmod(name, face): # create plane for follicle plane = cmds.polyPlane(name=name + '_foll_GEO') cmds.setAttr(plane[1] + '.sw', 1) cmds.setAttr(plane[1] + '.sh', 1) cmds.setAttr(plane[0] + '.s', .01, .01, .01) cmds.delete(plane[0], ch=True) cmds.makeIdentity(plane[0], apply=True) # move plane to face vertices = component.face_to_vertex([face]) pos_vtx_list = [] for each in vertices: pos = cmds.xform(each, t=True, ws=True, q=True) pos = (pos[0], pos[1], pos[2]) pos_vtx_list.append(pos) mtx = math.plane_matrix(vertices) cmds.xform(plane[0], matrix=mtx) # create follicle plane_geo = cmds.listRelatives(plane[0], s=True)[0] transform = cmds.createNode('transform', name=name + '_foll') foll = cmds.createNode('follicle', name=name + '_follShape', parent=transform) cmds.connectAttr(foll + ".outTranslate", transform + ".t", force=True) cmds.connectAttr(foll + ".outRotate", transform + ".r", force=True) cmds.setAttr(foll + ".visibility", False) cmds.connectAttr(plane_geo + '.outMesh', foll + '.inputMesh') cmds.connectAttr(plane_geo + '.worldMatrix[0]', foll + '.inputWorldMatrix') cmds.setAttr(foll + '.parameterU', 0.5) cmds.setAttr(foll + '.parameterV', 0.5) # copy skin weights to plane geo = face.split('.')[0] try: skin.copy_skincluster(geo, [plane_geo]) except: constraint.simple_constraint(geo, plane[0], snap=False) # create controls soft_mod_ctrl = ctrls.diamond_shape(name + '_SOFT_CTRL') soft_mod_ctrl_pivot = ctrls.sphere_shape(name + '_SOFT_PIV_CTRL') soft_mod_ctrl_pivot_zero = cmds.createNode('transform', name=soft_mod_ctrl_pivot + '_ZERO') cmds.setAttr(soft_mod_ctrl + '.s', 0.4, 0.4, 0.4) cmds.makeIdentity(soft_mod_ctrl, apply=True) cmds.addAttr(soft_mod_ctrl, ln='falloff', at='double', min=0, keyable=True) cmds.addAttr(soft_mod_ctrl, ln='falloffMode', at='enum', en='volume:surface', keyable=True) cmds.parent(soft_mod_ctrl, soft_mod_ctrl_pivot) cmds.parent(soft_mod_ctrl_pivot, soft_mod_ctrl_pivot_zero) constraint.simple_constraint(transform, soft_mod_ctrl_pivot_zero, snap=True) # create soft mod sm = cluster.create(geo, name + '_softMod', soft=True) constraint.simple_constraint(soft_mod_ctrl_pivot, sm[0], snap=True) constraint.simple_constraint(soft_mod_ctrl, sm[1], snap=True) cmds.connectAttr(soft_mod_ctrl + '.falloff', sm[1] + '.falloff') cmds.connectAttr(soft_mod_ctrl + '.falloffMode', sm[1] + '.falloffMode')