2 minutes
Save/Load hard edges in Maya
A friend of mine ran into some trouble where he kept losing edge information on his models. He asked me if I could make something to save out the hard edges to a file so they could be loaded back on if he lost them.
Way quicker version
To save:
import maya.api.OpenMaya as om
selection_list = om.MSelectionList()
dag_path = selection_list.getDagPath(0)
edge_it = om.MItMeshEdge(dag_path)
hard_edge_info = []
while not edge_it.isDone():
# save a list of the edge number and a bool whether it's a soft edge
hard_edge_info.append([int(edge_it.index()), edge_it.isSmooth])
edge_it.next()
To load:
selection_list = om.MSelectionList()
dag_path = selection_list.getDagPath(0)
mfn_mesh = om.MFnMesh(dag_path)
# zip over the small 2 member lists to end up with 2 big lists.
edge_numbers, edge_hardness = zip(*hard_edge_info)
mfn_mesh.setEdgeSmoothings(edge_numbers, edge_hardness)
mfn_mesh.cleanupEdgeSmoothing()
mfn_mesh.updateSurface()
Old version
import pymel.core as pm
import os
import re
from PySide2.QtCore import *
from PySide2.QtUiTools import *
from PySide2.QtGui import *
from PySide2.QtWidgets import *
import nv_utils.qt_utils as qt_utils
import nv_utils.io_utils as io_utils
import nv_maya_utils.general as general
import nv_maya_utils.decorators as maya_decorators
class HardEdgeSaverWindow(QMainWindow):
def __init__(self, parent=general.get_maya_main_window()):
qt_utils.delete_window(self)
super(HardEdgeSaverWindow, self).__init__(parent)
widget = QWidget()
layout = QVBoxLayout()
btn_save = QPushButton("Save hard edges")
btn_load = QPushButton("Load hard edges")
btn_save.clicked.connect(self.save)
btn_load.clicked.connect(self.load_edges_from_file)
layout.addWidget(btn_save)
layout.addWidget(btn_load)
widget.setLayout(layout)
self.setWindowTitle("Hard Edge Saver")
self.setWindowFlags(Qt.Dialog)
self.setCentralWidget(widget)
self.scene_dict = self.get_scene_dict()
@maya_decorators.progress_window(status="Saving hard edges...")
def save(self):
if pm.sceneName() == "":
general.show_viewport_message("Save the scene first", color="red")
return
meshes = self.get_all_or_selected_meshes()
for mesh in meshes:
self.save.update_progress(100/len(meshes),"Saving %s..." % mesh.name())
self.scene_dict[mesh.name()] = self.get_hard_edges(mesh)
io_utils.write_json(self.scene_dict, self.get_file_path())
general.show_viewport_message("Saved to %s" % self.get_file_path(), color="green")
def get_hard_edges(self, mesh):
edge = 0x8000
off = 0
hard = 1
smooth = 2
all_and_next = 3
pm.select(mesh)
pm.polySelectConstraint(mode=all_and_next, type=edge, smoothness=hard)
hard_edges = [re.search(r"\[(.*?)\]", edge.name()).group(0) for edge in pm.selected()]
pm.polySelectConstraint(mode=off, type=0x8000, smoothness=hard)
pm.select(None)
return hard_edges
@general.progress_window_decorator(status="Loading hard edges...")
def load_edges_from_file(self):
with pm.UndoChunk():
meshes = self.get_all_or_selected_meshes()
for mesh in meshes:
hard_edges = io_utils.read_json(self.get_file_path()).get(mesh.name())
if hard_edges is not None:
self.load_edges_from_file.update_progress(100/len(meshes), "Loading %s..." % mesh.name())
selection_list = ["%s.e%s" % (mesh.name(), edge_number) for edge_number in hard_edges]
pm.select(selection_list)
pm.polySoftEdge(angle=0, constructionHistory=1)
pm.bakePartialHistory(prePostDeformers=True)
pm.select(None)
def get_file_path(self):
scene_name = os.path.basename(pm.sceneName())
scene_name_no_ext = scene_name.split(".")[0]
scene_folder = os.path.dirname(pm.sceneName())
file_path = os.path.join(scene_folder, "%s_hard_edges.json" % scene_name_no_ext)
return file_path
def get_scene_dict(self):
if os.path.isfile(self.get_file_path()):
return io_utils.read_json(self.get_file_path())
else:
return {}
def get_all_or_selected_meshes(self):
meshes = []
for node in pm.ls(selection=True, type="transform", long=True):
try:
if node.getShape().type() == "mesh":
meshes.append(node)
except:
pass
if not meshes:
for node in pm.ls(type="transform", long=True):
try:
if node.getShape().type() == "mesh":
meshes.append(node)
except:
pass
return meshes
Read other posts