"""Utility methods used to sort nodes and graphs.
:created: 20/11/2020
:author: Benoit GIELLY <benoit.gielly@gmail.com>
"""
from __future__ import absolute_import
import logging
from maya import cmds, mel
LOG = logging.getLogger(__name__)
[docs]class Symmetry(object):
"""Generates a symmetry table for selected mesh."""
[docs] def __init__(self):
self.table = {}
self.edge = None
self.mesh = None
self.update()
@property
def center(self):
"""Get center vertices."""
return self.get_side_vertices("center")
@property
def left(self):
"""Get left side vertices."""
return self.get_side_vertices("left")
@property
def right(self):
"""Get right side vertices."""
return self.get_side_vertices("right")
[docs] @staticmethod
def get_vertex_id(vertex):
"""Get vertex index from name."""
return int(vertex.rsplit("[")[-1].rsplit("]")[0])
[docs] def get_vertex_name(self, index):
"""Get vertex name from index."""
return "{}.vtx[{}]".format(self.mesh, index)
[docs] def get_side_vertices(self, side):
"""Get all components of given side."""
return [self.get_vertex_name(i) for i in self.table.get(side)]
[docs] def mirror_selection(self, add=False):
"""Mirror selected vertices.
Args:
add (bool): Add to existing selection when True.
"""
selection = cmds.ls(selection=True, flatten=True)
vertices = self.mirror(selection)
cmds.select(vertices, add=add)
[docs] def mirror(self, vertices):
"""Mirror vertices.
Args:
vertices (list): List of vertices to mirror.
Yields:
str: The next vertex full name in the given list.
"""
for each in vertices:
index = self.get_vertex_id(each)
yield self.get_vertex_name(self.table[index])
[docs] def update(self):
"""Generate a symmetry table."""
# get selected edge, mesh name and all vertices
self.edge = (cmds.ls(selection=True) or [None])[0]
self.mesh = self.edge.rpartition(".")[0]
# populate the table using maya topology symmetry (ergh...)
try:
cmds.symmetricModelling(self.edge, topoSymmetry=True)
self.populate_table()
except Exception:
raise
else:
mel.eval("reflectionSetMode none;")
[docs] def populate_table(self):
"""Populate the symmetry table with vertices.
Notes:
Maya topology symmetry must be already activated.
"""
self.table.clear()
vertices = cmds.ls(self.mesh + ".vtx[*]", flatten=True)
for i, vtx in enumerate(vertices):
if i in self.table:
continue
# select and find symmetrical vertices
cmds.select(vtx, symmetry=True)
selected = cmds.ls(selection=True, flatten=True)
# if selection length is one, its a center vertex
if len(selected) == 1:
self.table[i] = i
self.table.setdefault("center", []).append(i)
continue
# find opposite vertex index and add them to table
opposite = [x for x in selected if x != vtx][0]
j = self.get_vertex_id(opposite)
self.table[i], self.table[j] = j, i
# find which are left and right
xpos = cmds.xform(
selected,
query=True,
translation=True,
worldSpace=True,
)[0::3]
min_id = xpos.index(min(xpos))
left = i if vtx != selected[min_id] else j
self.table.setdefault("left", []).append(left)
right = i if vtx == selected[min_id] else j
self.table.setdefault("right", []).append(right)