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, andbuttoncommands - 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()