Looks like a bug. I took the code from the final post in that cgsociety post. I commented everything from the InvertSelection onward and everything looks correct at this point. The second you uncomment InvertSelection, you’ll find that Inverting the selection of the selected faces on the duplicate object results in the selection pointing back to the original objects as though the InvertSelection is based on the selection prior to your script running.
A workaround to this would be to write your own explicit InvertSelection. I’ve written a short Python script that works in 2018. It’s limited to detaching mesh faces.
import maya.cmds as cmds
import maya.mel as mel
import maya.api.OpenMaya as om
def get_selection():
sel_list = om.MGlobal.getActiveSelectionList()
sel = []
for i in range(sel_list.length()):
(path,comp) = sel_list.getComponent(i)
shape_path = path
shape_path.extendToShape()
# Only support meshes and face component selection
if not shape_path.apiType() == om.MFn.kMesh:
continue
if not comp.apiType() == om.MFn.kMeshPolygonComponent:
continue
sel.append( (path,comp) )
return sel
def inverse_comp(path, comp):
# Return the inverse of this component selection
mesh_fn = om.MFnMesh(path)
comp_fn = om.MFnSingleIndexedComponent(comp)
num_faces = mesh_fn.numPolygons
comp_ids = comp_fn.getElements()
inv_comp_ids = [i for i in range(mesh_fn.numPolygons) if i not in comp_ids]
inv_comp_fn = om.MFnSingleIndexedComponent()
inv_comp = inv_comp_fn.create(om.MFn.kMeshPolygonComponent)
inv_comp_fn.addElements(inv_comp_ids)
return inv_comp
def convert_str_to_path(strpath):
sel = om.MSelectionList()
sel.add(strpath)
return sel.getDagPath(0)
def extract_faces(path, comp):
dup_path_str = maya.cmds.duplicate(path.fullPathName(), rr=True)
assert(len(dup_path_str) == 1)
dup_path = convert_str_to_path(dup_path_str[0])
inv_comp = inverse_comp(path, comp)
comp_ids = om.MFnSingleIndexedComponent(comp).getElements()
inv_comp_ids = om.MFnSingleIndexedComponent(inv_comp).getElements()
# Delete comp from path
path_str = path.partialPathName()
comp_str = [ path_str + '.f[' + str(i) + ']' for i in comp_ids]
del_cmd = r'delete ' + ' '.join(comp_str)
print del_cmd
mel.eval(del_cmd)
# Delete inv_comp from dup_path
dup_path_str = dup_path.partialPathName()
inv_comp_str = [ dup_path_str + '.f[' + str(i) + ']' for i in inv_comp_ids]
inv_del_cmd = r'delete ' + ' '.join(inv_comp_str)
print inv_del_cmd
mel.eval(inv_del_cmd)
return (dup_path,comp)
def main():
sel = get_selection()
dups = []
for (path, comp) in sel:
dup_path = extract_faces(path, comp)
dups.append(dup_path)
dup_sel = om.MSelectionList()
for (path,_) in dups:
dup_sel.add( path )
om.MGlobal.setActiveSelectionList(dup_sel)
main()
Hope this helps. It’s probably still worth reporting that InvertSelection fails in script usage.