def create(self, transform=None, as_controller=True): """Create a curve. :param transform: Name of the transform to create the curve shape under. If the transform does not exist, it will be created. :param as_controller: True to mark the curve transform as a controller. :return: The transform of the new curve shapes. """ transform = transform or self.transform if not cmds.objExists(transform): transform = cmds.createNode("transform", name=transform) periodic = self.form == 2 points = self._get_transformed_points() points = points + points[:self.degree] if periodic else points curve = cmds.curve(degree=self.degree, p=points, per=periodic, k=self.knots) shape = shortcuts.get_shape(curve) if self.color is not None: cmds.setAttr("{}.overrideEnabled".format(shape), True) if isinstance(self.color, int): cmds.setAttr("{}.overrideColor".format(shape), self.color) else: cmds.setAttr("{}.overrideRGBColors".format(shape), True) cmds.setAttr("{}.overrideColorRGB".format(shape), *self.color) cmds.parent(shape, transform, r=True, s=True) shape = cmds.rename(shape, "{}Shape".format(transform)) cmds.delete(curve) if as_controller: cmds.controller(transform) logger.info("Created curve {} for transform {}".format( shape, transform)) return transform
def _set_from_curve(self, transform): """Store the parameters from an existing curve in the CurveShape object. :param transform: Transform """ shape = shortcuts.get_shape(transform) if shape and cmds.nodeType(shape) == "nurbsCurve": create_attr = "{}.create".format(shape) connection = cmds.listConnections(create_attr, plugs=True, d=False) if connection: cmds.disconnectAttr(connection[0], create_attr) self.transform = transform self.cvs = cmds.getAttr("{}.cv[*]".format(shape)) self.degree = cmds.getAttr("{}.degree".format(shape)) self.form = cmds.getAttr("{}.form".format(shape)) self.knots = get_knots(shape) if cmds.getAttr("{}.overrideEnabled".format(shape)): if cmds.getAttr("{}.overrideRGBColors".format(shape)): self.color = cmds.getAttr( "{}.overrideColorRGB".format(shape))[0] else: self.color = cmds.getAttr("{}.overrideColor".format(shape)) else: self.color = None if connection: cmds.connectAttr(connection[0], create_attr)
def dump(curves=None, stack=False): """Get a data dictionary representing all the given curves. :param curves: Optional list of curves. :return: A json serializable list of dictionaries containing the data required to recreate the curves. """ if curves is None: curves = cmds.ls(sl=True) or [] data = [] for node in curves: shape = shortcuts.get_shape(node) if cmds.nodeType(shape) == 'nurbsCurve': control = { 'name': node, 'cvs': cmds.getAttr('{0}.cv[*]'.format(node)), 'degree': cmds.getAttr('{0}.degree'.format(node)), 'form': cmds.getAttr('{0}.form'.format(node)), 'xform': cmds.xform(node, q=True, ws=True, matrix=True), 'knots': get_knots(node), 'pivot': cmds.xform(node, q=True, rp=True), 'overrideEnabled': cmds.getAttr('{0}.overrideEnabled'.format(node)), 'overrideRGBColors': cmds.getAttr('{0}.overrideRGBColors'.format(node)), 'overrideColorRGB': cmds.getAttr('{0}.overrideColorRGB'.format(node))[0], 'overrideColor': cmds.getAttr('{0}.overrideColor'.format(node)), } if stack: control['stack'] = get_stack_count(node) control['parent'] = get_stack_parent(node) data.append(control) if curves: cmds.select(curves) return data
def flatten(mesh=None, uvset=None): """Creates a mesh from the UV layout of another mesh. I use this to generate flattened versions of meshes from Marvelous Designer to easily use Quad Draw to create clean meshes and then Transfer Attributes vertex positions through UVs. :param mesh: Mesh to sample. :param uvset: UV set name """ if mesh is None: mesh = cmds.ls(sl=True) if not mesh: raise RuntimeError("No mesh selected.") mesh = mesh[0] o_mesh = shortcuts.get_mobject(shortcuts.get_shape(mesh)) fn_mesh = OpenMaya.MFnMesh(o_mesh) if uvset is None: uvset = fn_mesh.currentUVSetName() vertex_count = fn_mesh.numUVs(uvset) polygon_count = fn_mesh.numPolygons() u_array = OpenMaya.MFloatArray() v_array = OpenMaya.MFloatArray() fn_mesh.getUVs(u_array, v_array, uvset) vertex_array = OpenMaya.MPointArray(u_array.length()) for i in range(u_array.length()): vertex_array.set(i, u_array[i], 0, -v_array[i]) polygon_counts = OpenMaya.MIntArray(polygon_count) it_poly = OpenMaya.MItMeshPolygon(o_mesh) polygon_connects = OpenMaya.MIntArray(fn_mesh.numFaceVertices()) face_vertex_index = 0 while not it_poly.isDone(): face_index = it_poly.index() polygon_counts[face_index] = it_poly.polygonVertexCount() for i in range(polygon_counts[face_index]): int_ptr = shortcuts.get_int_ptr() it_poly.getUVIndex(i, int_ptr) uv_index = shortcuts.ptr_to_int(int_ptr) polygon_connects[face_vertex_index] = uv_index face_vertex_index += 1 it_poly.next() new_mesh = OpenMaya.MFnMesh() new_mesh.create( vertex_count, polygon_count, vertex_array, polygon_counts, polygon_connects, u_array, v_array, ) new_mesh.assignUVs(polygon_counts, polygon_connects)
def get_knots(curve): """Gets the list of knots of a curve so it can be recreated. :param curve: Curve to query. :return: A list of knot values that can be passed into the curve creation command. """ curve = shortcuts.get_shape(curve) info = cmds.createNode('curveInfo') cmds.connectAttr('{0}.worldSpace'.format(curve), '{0}.inputCurve'.format(info)) knots = cmds.getAttr('{0}.knots[*]'.format(info)) cmds.delete(info) return knots
def get_or_create_blendshape_node(geometry): """Get the first blendshape node upstream from the given geometry or create one if one does not exist. :param geometry: Name of the geometry :return: The blendShape node name """ geometry = shortcuts.get_shape(geometry) blendshape = get_blendshape_node(geometry) if blendshape: return blendshape else: return cmds.blendShape(geometry, foc=True)[0]
def set_color(self): """Open a dialog to set the override RGB color of the selected nodes.""" nodes = cmds.ls(sl=True) or [] if nodes: color = cmds.getAttr("{}.overrideColorRGB".format(nodes[0]))[0] color = QColor(color[0] * 255, color[1] * 255, color[2] * 255) color = QColorDialog.getColor(color, self, "Set Curve Color") if color.isValid(): color = [color.redF(), color.greenF(), color.blueF()] for node in nodes: shape = shortcuts.get_shape(node) cmds.setAttr("{}.overrideEnabled".format(shape), True) cmds.setAttr("{}.overrideRGBColors".format(shape), True) cmds.setAttr("{}.overrideColorRGB".format(shape), *color)
def get_blendshape_node(geometry): """Get the first blendshape node upstream from the given geometry. :param geometry: Name of the geometry :return: The blendShape node name """ geometry = shortcuts.get_shape(geometry) history = cmds.listHistory(geometry, il=2, pdo=False) or [] blendshapes = [ x for x in history if cmds.nodeType(x) == "blendShape" and cmds.blendShape(x, q=True, g=True)[0] == geometry ] if blendshapes: return blendshapes[0] else: return None
def get_skin_clusters(nodes): """Get the skinClusters attached to the specified node and all nodes in descendents. :param nodes: List of dag nodes. @return A list of the skinClusters in the hierarchy of the specified root node. """ if isinstance(nodes, basestring): nodes = [nodes, ] all_skins = [] for node in nodes: relatives = cmds.listRelatives(node, ad=True, path=True) or [] relatives.insert(0, node) relatives = [shortcuts.get_shape(node) for node in relatives] for relative in relatives: history = cmds.listHistory(relative, pruneDagObjects=True, il=2) or [] skins = [x for x in history if cmds.nodeType(x) == 'skinCluster'] if skins: all_skins.append(skins[0]) return list(set(all_skins))
def on_file_tree_context_menu(self, pos): index = self.file_tree_view.indexAt(pos) if not index.isValid(): return path = self.file_model.fileInfo(index).absoluteFilePath() if not os.path.isfile(path) or not path.lower().endswith(".obj"): return sel = cmds.ls(sl=True) blendshape = bs.get_blendshape_node(sel[0]) if sel else None menu = QMenu() label = "Import as target" if blendshape else "Import" menu.addAction( QAction(label, self, triggered=self.import_selected_objs)) if sel and shortcuts.get_shape(sel[0]): menu.addAction( QAction("Export selected", self, triggered=partial(export_obj, sel[0], path))) menu.exec_(self.file_tree_view.mapToGlobal(pos))
def get_points(mesh): path = shortcuts.get_dag_path2(shortcuts.get_shape(mesh)) mesh_fn = OpenMaya.MFnMesh(path) return mesh_fn.getPoints()
def set_points(mesh, points): path = shortcuts.get_dag_path2(shortcuts.get_shape(mesh)) mesh_fn = OpenMaya.MFnMesh(path) mesh_fn.setPoints(points)