Python Tools - Session 14B

Edge Reducer Tool

2020.04.16 - Session 14B

Session Navigation

Overview

The Edge Reducer tool takes a different approach to UI building - instead of Qt/PySide2, it uses Maya's native cmds-style UI commands (pm.window, pm.columnLayout, pm.button). The tool provides controls for selecting edges by ring, loop, or border patterns at regular intervals, then deleting them to reduce mesh density. It also includes a floating vertex cleanup function.

Key Concepts

  • Maya native UI - Build interfaces with pm.window, columnLayout, rowLayout, and button commands
  • pm.Callback - Use PyMEL's Callback wrapper for connecting buttons to methods with arguments
  • Edge selection modes - Select edges by ring, loop, border, or loopOrBorder patterns
  • polySelectEdgesEveryN - MEL command to select every Nth edge in a pattern
  • Component type checking - Use isinstance() to verify selection types (MeshEdge, Transform)
  • Floating vertex cleanup - Select and delete orphan vertices after edge deletion

Source Code - reducer.py

import pymel.core as pm

class EdgeReducerUI():

    def __init__(self):

        self.handle = 'EdgeReducer'

        if pm.window(self.handle, exists=True):
            pm.deleteUI(self.handle)

        with pm.window(self.handle, title='Edge Reducer', width=400, height=100):

            # Start a column layout
            with pm.columnLayout(rowSpacing=10):

                self.ui_select_modes = pm.optionMenu( label='Selection Mode:')
                pm.menuItem( label='edgeRing' )
                pm.menuItem( label='edgeLoop' )
                pm.menuItem( label='edgeBorder' )   
                pm.menuItem( label='edgeLoopOrBorder' )  

                self.ui_every_n = pm.intSliderGrp(label='Select Every', field=True, value=2, min=1, max=10)

                with pm.rowLayout(numberOfColumns=3):
                    pm.button(label='Select Edges', w=100, h=30, command=pm.Callback(self.do_select_edges))
                    pm.button(label='Delete Edges', w=150, h=30, command=pm.Callback(self.do_delete_edges))
                    pm.button(label='Delete Floating Verts', w=150, h=30, command=pm.Callback(self.do_delete_verts))

        # Show the window
        pm.showWindow(self.handle)


    def do_select_edges(self):
        selected_obj = pm.ls(sl=True)
        if len(selected_obj) == 0:
            print 'Warning - Nothing selected'
            return

        if not isinstance(selected_obj[0], pm.MeshEdge):
            print 'Warning - "%s" selected - please select edges' %type(selected_obj[0])
            return

        step = self.ui_every_n.getValue()
        mode = self.ui_select_modes.getValue()
        pm.mel.polySelectEdgesEveryN(mode, step)

    def do_delete_edges(self):
        pm.mel.doDelete()


    def do_delete_verts(self):
        selected_obj = pm.ls(sl=True)
        if len(selected_obj) == 0:
            print 'Warning - Nothing selected'
            return

        if len(selected_obj) == 1 and isinstance(selected_obj[0], pm.nt.Transform):
            transform_node = selected_obj[0]

        else:
            component_name = selected_obj[0].name()
            transform_name = component_name.split('.')[0]
            transform_node = pm.PyNode(transform_name)

        all_vert_string = transform_name + '.vtx[0:' + str(transform_node.numVertices()-1) + ']'
        print all_vert_string
        pm.select(all_vert_string, r=True)
        pm.mel.doDelete()
← Prev Course Overview ->