def detach(extract=False): """ Extracts or duplicate selected polygon faces. """ selected = mampy.complist() if not selected: raise InvalidSelection('Detach only works on edge and polygon components.') else: control = selected[0] if control.type not in [MFn.kMeshPolygonComponent, MFn.kMeshEdgeComponent]: raise InvalidSelection('Detach only works on edges and polygons.') new = ComponentList() for comp in selected: node = Node(comp.dagpath) name = '{}_{}'.format(node.transform.short_name, 'ext' if extract else 'dup') cmds.duplicate(str(comp.dagpath), n=name) # Delete unwanted children from duplicate hierarchy dupdag = Node(name) for child in dupdag.iterchildren(): if child.type == MFn.kTransform: cmds.delete(str(child)) if extract: cmds.polyDelFacet(comp.cmdslist()) dupcomp = MeshPolygon.create(dupdag.dagpath).add(comp.indices) cmds.polyDelFacet(dupcomp.toggle().cmdslist()) cmds.hilite(str(dupdag)) new.append(dupcomp.get_complete()) cmds.select(new.cmdslist(), r=True)
def unbevel(): """ Unbevel beveled edges. Select Edges along a bevel you want to unbevel. Make sure the edge is not connected to another edge from another bevel. This will cause the script to get confused. """ selected = mampy.complist() for edge in selected: # cmds.select(edge.cmdslist(), r=True) merge_list = ComponentList() for each in edge.get_connected_components(): outer_edges, inner_verts = get_outer_and_inner_edges_from_edge_loop(each) edge1, edge2 = outer_edges line1 = Line3D(edge1[0].bbox.center, edge1[1].bbox.center) line2 = Line3D(edge2[0].bbox.center, edge2[1].bbox.center) intersection = line1.shortest_line_to_other(line2) inner_verts.translate(t=intersection.sum() * 0.5, ws=True) merge_list.append(inner_verts) # Merge components on object after all operation are done. Mergin # before will change vert ids and make people sad. cmds.polyMergeVertex(merge_list.cmdslist(), distance=0.001)
def flood(): """Get contiguous components from current selection.""" selected = mampy.complist() if not selected: raise NothingSelected() flood = ComponentList() for comp in selected: if comp.type == MFn.kMeshMapComponent: iter_ = comp.map_shells else: iter_ = comp.mesh_shells flood.extend(iter_.itervalues()) cmds.select(flood.cmdslist())
def adjacent(): """Grow and remove previous selection to get adjacent selection. .. todo:: make contractable """ selected = mampy.complist() if not selected: raise NothingSelected() toggle_components = ComponentList() for each in selected: try: adjacent_selection = { MFn.kMeshPolygonComponent: each.to_edge().to_face(), MFn.kMeshEdgeComponent: each.to_vert().to_edge(), MFn.kMeshVertComponent: each.to_edge().to_vert(), MFn.kMeshMapComponent: each.to_edge().to_map(), }[each.type] toggle_components.append(adjacent_selection) except KeyError: raise InvalidSelection('Selection must be mesh component.') cmds.select(toggle_components.cmdslist(), toggle=True)
def poly_invert(shell=False): """ Invert selection. If shell is active but there are no selections, script assumes we want a full invert. .. note:: If current selection mask is *object* and there are no selections there is no way that I know of to find out the active component type. """ # To find out how we want to operate on the objects we walk through # the possible outcomes leaving the object list at last. modes = [mampy.complist(), mampy.daglist(hl=True), mampy.daglist()] for mode, selected in enumerate(modes): if not selected: continue break if mode == 2: if not selected: cmds.select(mampy.daglist(visible=True, assemblies=True).cmdslist()) else: cmds.select(selected.cmdslist(), toggle=True) if mode == 1: for mask in get_active_flags_in_mask(object=False): try: active_mask = { 'facet': MFn.kMeshPolygonComponent, 'edge': MFn.kMeshEdgeComponent, 'vertex': MFn.kMeshVertComponent, 'polymeshUV': MFn.kMeshMapComponent, }[mask]; break except KeyError: continue for dag in selected: component = SingleIndexComponent.create(dag.dagpath, active_mask) cmds.select(component.get_complete().cmdslist(), toggle=True) if mode == 0: selection_list = ComponentList() for comp in selected: if shell: for mesh in comp.mesh_shells.itervalues(): selection_list.append(mesh) else: selection_list.append(comp.get_complete()) cmds.select(selection_list.cmdslist(), toggle=True)
def merge_faces(): """Removes edges inside of face selection.""" selected = mampy.complist() if not selected: raise NothingSelected() control_object = next(iter(selected)) if not control_object.type == MFn.kMeshPolygonComponent or not len(control_object) > 1: raise InvalidSelection("Must have at least two connected faces selected.") new_faces = ComponentList() for face in selected: # We must first collect all necessary elements before we operate on them. # This is to avoid getting uncertain information due to indices changing # when performing the delete function. border_vertices = ComponentList() internal_edges = ComponentList() for connected_face in face.get_connected_components(): border_vertices.append(connected_face.to_vert(border=True)) internal_edges.append(connected_face.to_edge(internal=True)) # We only delete once per object to perserve as much information as # possible. cmds.polyDelEdge(internal_edges.cmdslist()) # Collect the most shared face on the border vertices to get new faces # from the delete operation. for border_vert in border_vertices: counter = collections.Counter() for idx in border_vert.indices: f = border_vert.new().add(idx).to_face() counter.update(f.indices) new_faces.append(face.new().add(counter.most_common(1).pop()[0])) # Select and be happy! cmds.select(new_faces.cmdslist())