Esempio n. 1
1
def select_deselect_edge_lists(root_edge, loop=True):
    kw = {'edgeLoop' if loop else 'edgeRing': root_edge.index}
    if root_edge in mampy.complist():
        kw.update({'deselect': True})
    else:
        kw.update({'add': True})
    cmds.polySelect(root_edge.dagpath, **kw)
Esempio n. 2
0
def get_face_weighted_sets():
    sets = cmds.ls('{}*'.format(_face_weighted_name))
    selected, to_weight = mampy.daglist(), ComponentList()
    if selected:
        for each in selected:
            set_name = get_face_weighted_set_name(each.transform.short_name)
            if set_name in sets:
                to_weight.extend(mampy.complist(cmds.sets(set_name, q=True)))
    else:
        for set_name in sets:
            try:
                to_weight.extend(mampy.complist(cmds.sets(set_name, q=True)))
            except ValueError:
                continue
    return to_weight
Esempio n. 3
0
def vertex_normals_from_selection_center():
    bbox = BoundingBox()
    for component in mampy.complist():
        if not component.is_vert():
            component = component.to_vert()
        bbox.expand(component.bbox)
    set_vertex_normals_on_selected_from_vector(bbox.center)
Esempio n. 4
0
def set_vertex_normals_on_selected_from_vector(vector):
    for component in mampy.complist():
        if not component.is_vert():
            component = component.to_vert()
        for index in component:
            normal = (component.points[index] - vector).normalize()
            component.mesh.setVertexNormal(normal, index, space=api.MSpace.kWorld)
Esempio n. 5
0
def select_deselect_border_edge(root_edge, tolerance):

    def get_vector_from_edge(edge, index):
        p1, p2 = [edge.points[i] for i in edge.vertices[index]]
        return p2 - p1

    root_edge_vector = get_vector_from_edge(root_edge, root_edge.index)
    edge_border_indices = cmds.polySelect(
        root_edge.dagpath,
        edgeBorder=root_edge.index,
        noSelection=True
    )
    border_edge = root_edge.new().add(edge_border_indices)
    edges_to_select = root_edge.new()
    for idx in border_edge:
        border_edge_vector = get_vector_from_edge(border_edge, idx)
        if root_edge_vector.isParallel(border_edge_vector, tolerance):
            edges_to_select.add(idx)

    connected = edges_to_select.get_connected_components()
    for e in connected:
        if root_edge.index in e:
            if root_edge in mampy.complist():
                cmds.select(e.cmdslist(), d=True)
            else:
                cmds.select(e.cmdslist(), add=True)
Esempio n. 6
0
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)
Esempio n. 7
0
def flatten(averaged=True):
    """
    Flattens selection by averaged normal.
    """
    def flatten(component, script_job=False):

        if script_job:
            cmds.select(selected.cmdslist())
        else:
            cmds.select(component.cmdslist())

        center = list(component.bbox.center)[:3]
        origin = get_average_vert_normal(component.normals, component.indices)

        # Perform scale
        cmds.manipScaleContext('Scale', e=True, mode=6, alignAlong=origin)
        radians = cmds.manipScaleContext('Scale', q=True, orientAxes=True)
        t = [math.degrees(r) for r in radians]
        cmds.scale(0, 1, 1, r=True, oa=t, p=center)

    def script_job():
        """
        Get normal from script job selection and pass it to flatten.
        """
        flatten(next(iter(mampy.complist())).to_vert(), True)

    selected = mampy.complist()
    if averaged:
        for comp in selected:
            flatten(comp.to_vert())
        cmds.select(selected.cmdslist(), r=True)
    else:
        # Scale selection to given selection.
        cmds.scriptJob(event=['SelectionChanged', script_job], runOnce=True)
Esempio n. 8
0
def select_deselect_surrounded(root_comp):
    selected = mampy.complist()
    if not selected:
        cmds.selecet(root_comp.get_complete().cmdslist(), add=True)
    else:
        for comp in selected:
            # Find correct dagpath to work on
            if not root_comp.dagpath == comp.dagpath:
                continue

            if comp.is_complete():
                cmds.select(comp.cmdslist(), d=True)
            else:
                connected = list(comp.get_connected_components())
                connected_unselected = list(comp.toggle().get_connected_components())

                if any(root_comp.index in c for c in connected):
                    kw = {'deselect': True}
                    iterable = connected
                elif any(root_comp.index in c for c in connected_unselected):
                    kw = {'add': True}
                    iterable = connected_unselected

                for c in iterable:
                    if root_comp.index in c:
                        cmds.select(c.cmdslist(), **kw)
Esempio n. 9
0
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())
def bevel():
    """
    Bevel is a collection of functions usually performed when certain states
    are fulfilled, such as: selection, border edge etc.
    """
    selected = mampy.complist()
    if not selected:
        raise NothingSelected()

    component = selected[0]
    # Eearly return in case of map components
    if component.type == MFn.kMeshMapComponent:
        raise InvalidComponentSelection()

    if component.type == api.MFn.kMeshEdgeComponent:
        # Check if we can extrude edge borders or bevel internal edges.
        if all(component.is_border(i) for i in component.indices):
            # When extruding border edges we don't want the context tool to handle
            # the manipulation. Just restore old tool right away.
            with restore_context():
                dragger_contexts.Extrude().execute()
        elif not any(component.is_border(i) for i in component.indices):
            dragger_contexts.Bevel().set_context()
        else:
            raise InvalidSelection('Mixed selections, cant mix edge borders with '
                                   'non borders when beveling.')
    else:
        # Else perform an extrude on polygon or vertex.
        if cmds.currentCtx() == dragger_contexts.Extrude.NAME:
            dragger_contexts.Extrude().execute()
        else:
            dragger_contexts.Extrude().set_context()
def bridge():
    selected = mampy.complist()
    if not selected:
        raise NothingSelected()

    # Quit early if face selections.
    if selected[0].type == api.MFn.kMeshPolygonComponent:
        bridge_face()

    # Only work on border components
    for component in get_borders_from_complist(selected):
        component = component.to_edge(internal=True)
        connected = list(component.get_connected_components())
        # If border is closed or edges are next to each others
        if len(connected) == 1:
            border_edge = get_border_loop_indices_from_edge_index(component.index)
            if border_edge == set(component.indices):
                cmds.polyCloseBorder(component.cmdslist())
            else:
                cmds.polyAppend(
                    str(component.dagpath),
                    s=1,
                    a=(component.index, component.indices[-1])
                )
        else:
            cmds.polyBridgeEdge(divisions=0)
Esempio n. 12
0
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 bridge_face():
    faces = mampy.complist()
    # Get edge border before deleting face.
    mamselect.mesh.convert('edge')
    # Now safe to delete face and perform bridge.
    cmds.delete(faces.cmdslist())
    cmds.polyBridgeEdge(divisions=0)
Esempio n. 14
0
def inbetween():
    """Select components between the last two selections."""
    # TODO: refactor and finish.
    ordered_selection = mampy.complist(os=True)

    if not len(ordered_selection) % 2 == 0:
        comp1, comp2 = ordered_selection[-2:]
    else:
        for comp in ordered_selection:
            cmds.polySelect(comp.cmdslist(), q=True, loop=True)
Esempio n. 15
0
def deselect_all_but():
    preselect = mampy.complist(preSelectHilite=True)
    obj = get_object_under_cursor()
    if not obj:
        return

    cmds.select(obj, r=True)
    if not preselect:
        return
    else:
        cmds.hilite(obj, toggle=True)
Esempio n. 16
0
def spin_edge(offset=1):
    """
    Spin all selected edges.

    Allows us to spin edges within a face selection.
    """
    selected = mampy.complist()
    for comp in selected:
        if not comp.is_edge():
            comp = comp.to_edge(internal=True)
        cmds.polySpinEdge(comp.cmdslist(), offset=offset, ch=False)
    cmds.select(cl=True); cmds.select(selected.cmdslist(), r=True)
def connect():
    """
    Control flow for connected component tools.
    """
    selected = mampy.complist()
    if selected:
        object_type = selected.pop().type
        if object_type in [MFn.kMeshMapComponent]:
            raise InvalidComponentSelection()
        elif object_type == MFn.kMeshVertComponent:
            mamtools.mel('ConnectComponents')
        else:
            mamtools.mel('connectTool')
Esempio n. 18
0
def merge_verts(move):
    """Merges verts to first selection."""
    ordered_selection = mampy.complist(os=True)
    if move or len(ordered_selection) == 2:
        if len(next(iter(ordered_selection))) > 1:
            pass
        else:
            if not move:
                v1, v2 = ordered_selection
                pos = v1.bbox.expand(v2.bbox).center
            else:
                pos = ordered_selection.pop().bbox.center
            cmds.xform(ordered_selection.cmdslist(), t=list(pos)[:3], ws=True)
    cmds.polyMergeVertex(ordered_selection.cmdslist(), distance=0.001, ch=True)
def detach(extract=False):
    """
    Dispatches function call depening on selection type or type of panel
    under cursor.
    """
    selected = mampy.complist() or mampy.daglist()
    if not selected:
        raise NothingSelected()

    object_type = selected.pop().type
    if object_type == MFn.kMeshPolygonComponent:
        mamtools.mesh.detach(extract)
    elif object_type in [api.MFn.kTransform]:
        cmds.duplicate(rr=True)
Esempio n. 20
0
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())
Esempio n. 21
0
def collapse():
    selected = mampy.complist()
    if not selected:
        return logger.warn("Invalid component selection.")

    for comp in selected:
        if comp.type == MFn.kMeshEdgeComponent:
            for comp in comp.get_connected_components():
                for edge in comp.indices:
                    vert = MeshVert.create(comp.dagpath).add(comp.vertices[edge])
                    vert.translate(t=list(comp.bbox.center)[:3], ws=True)
        else:
            vert = comp.to_vert()
            vert.translate(t=list(vert.bbox.center)[:3], ws=True)
        cmds.polyMergeVertex(comp.cmdslist(), distance=0.001)
    cmds.select(cl=True)
Esempio n. 22
0
def select_deselect_isolated_components(loop=True, tolerance=0.35):
    """Clear mesh or loop under mouse."""
    preselect = mampy.complist(preSelectHilite=True)
    if not preselect:
        raise NothingSelected()

    preselect_component = preselect.pop()
    if preselect_component.type == api.MFn.kMeshEdgeComponent:
        if not loop:
            select_deselect_edge_lists(preselect_component, loop)
        elif preselect_component.is_border(preselect_component.index):
            select_deselect_border_edge(preselect_component, tolerance)
        else:
            select_deselect_edge_lists(preselect_component, loop)
    else:
        select_deselect_surrounded(preselect_component)
Esempio n. 23
0
def toggle_mesh_under_cursor():
    """Toggle mesh object under cursor."""
    preselect = mampy.complist(preSelectHilite=True)
    if not preselect:
        under_cursor_mesh = get_object_under_cursor()
        if under_cursor_mesh is None:
            return
        node = Node(under_cursor_mesh)
        if cmds.selectMode(q=True, component=True):
            cmds.hilite(str(node.transform))
        else:
            cmds.select(str(node), toggle=True)
    else:
        node = preselect.pop().mdag
        if node.transform in mampy.daglist(hl=True):
            cmds.hilite(str(node.transform), unHilite=True)
Esempio n. 24
0
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)
Esempio n. 25
0
def set_face_weighted_normals_sets(add=True):
    faces = mampy.complist()
    for face in faces:
        name = face.mdag.transform.short_name
        set_name = get_face_weighted_set_name(name)

        try:
            result = bool(cmds.sets(set_name, q=True))
        except ValueError:
            result = False

        if result:
            if add:
                cmds.sets(face.cmdslist(), addElement=set_name)
            else:
                cmds.sets(face.cmdslist(), remove=set_name)
        else:
            cmds.sets(name=set_name)
Esempio n. 26
0
def delete(cv=False):
    """Custom delete using 'right' delete function depending on selection."""
    selected = mampy.complist() or mampy.daglist()
    if not selected:
        return logger.warn("Nothing to delete.")

    for each in selected:
        if isinstance(each, SingleIndexComponent):
            # Try to delete supported types if that fails uss default delete in
            # maya
            try:
                {
                    MFn.kMeshEdgeComponent: partial(cmds.polyDelEdge, each.cmdslist(), cv=cv),
                    MFn.kMeshVertComponent: partial(cmds.polyDelVertex, each.cmdslist()),
                    MFn.kMeshPolygonComponent: partial(cmds.polyDelFacet, each.cmdslist()),
                }[each.type]()
            except KeyError:
                cmds.delete(each.cmdslist())
        else:
            cmds.delete(str(each))
    cmds.select(cl=True)
Esempio n. 27
0
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)
Esempio n. 28
0
def convert(comptype, **convert_arguments):
    """
    Convert current selection to given comptype.
    """
    ComponentType = collections.namedtuple('ComponentType', ('type', 'function'))
    convert_mode = {
        'vert': ComponentType(api.MFn.kMeshVertComponent, 'to_vert'),
        'edge': ComponentType(api.MFn.kMeshEdgeComponent, 'to_edge'),
        'face': ComponentType(api.MFn.kMeshPolygonComponent, 'to_face'),
        'map': ComponentType(api.MFn.kMeshMapComponent, 'to_map'),
    }[comptype]

    selected, converted = mampy.complist(), ComponentList()
    if not selected:
        raise NothingSelected()

    for comp in selected:
        if comp.type == convert_mode:
            continue
        converted.append(getattr(comp, convert_mode.function)(**convert_arguments))

    set_selection_mask(comptype)
    cmds.select(converted.cmdslist())
def merge():
    """
    Dispatches function call depending on selection type
    """
    selected = mampy.complist() or mampy.daglist()
    if not selected:
        raise NothingSelected()

    control_object = selected.pop()
    if control_object.type in [MFn.kTransform]:
        object_type = control_object.shape.type
    else:
        object_type = control_object.type

    try:
        {
            MFn.kMeshVertComponent: functools.partial(mamtools.delete.merge_verts,
                                                      False),
            MFn.kMeshPolygonComponent: mamtools.delete.merge_faces,
            MFn.kMeshEdgeComponent: mamtools.delete.collapse,
            MFn.kMesh: mamtools.mesh.combine_separate,
        }[object_type]()
    except KeyError:
        logger.warn('{} is not a valid type'.format(object_type))
Esempio n. 30
0
 def script_job():
     """
     Get normal from script job selection and pass it to flatten.
     """
     flatten(next(iter(mampy.complist())).to_vert(), True)