My goal is to set a shader to each parts of a geo. The parts of the geo are typically a group of attached faces. I do this to bake an ID map and then use it in Substance Painter.
So far, I separate the parts, then assign a shader to each and unite them back. I eventually delete the history to clean the outliner and the mesh itself.
import maya.cmds as mc
import random
selection = mc.ls(sl=True)[0]
parent = mc.listRelatives( selection, ap = True)[0]
mc.polySeparate(selection)
parts = mc.ls(sl=True)
for p in parts:
sha = mc.shadingNode('lambert', asShader=True, name=p+"_lambert")
sg = mc.sets(empty=True, renderable=True, noSurfaceShader=True, name=p+"_SG")
mc.setAttr(sha+".color", random.uniform(0.0, 1.0), random.uniform(0.0, 1.0), random.uniform(0.0, 1.0))
mc.connectAttr( sha+".outColor", sg+".surfaceShader", f=True)
mc.sets(p, e=True, forceElement=sg)
result = mc.select( selection, r = True )
sel = mc.ls( sl=True )
parts = mc.listRelatives( sel[0], c = True )
mc.polyUnite(parts, muv = True, name = selection)
mc.DeleteHistory()
I've got my shaders on parts but lose my original group under which the mesh was parented, and it doesn't feel right to do it this way.
Is there a way to create sets of parts without using 'separate' and assign a shader to each set?
I am assuming that you are assigning shaders on a combined object but my script should give you the idea : (run it and it will assign random shader on the combined sphere)
Just to resume Im listing the faces of the object selected. I take one face, grow the selection until it cant anymore Assign a shader on them, removing the selection of faces from the main list and do it again in a loop at the end im producing some kind of history by creating a set per object and sub set per lambert assigned
import maya.cmds as cmds
import random
def growComponent(component):
# component = vertices[0]
check = component.split('.')
if len(check) != 2:
cmds.error('please select one component in order to grow the selection')
mySel = [component]
counterSel = len(cmds.ls(component, fl = True))
myFinalSel = 0
while myFinalSel != counterSel:
mySel = component
counterSel = len(mySel)
vert = cmds.polyListComponentConversion(mySel, tv = True)
component = cmds.polyListComponentConversion(vert, tf = True)
component = cmds.ls(component, fl = True)
myFinalSel = len(component)
component = cmds.polyListComponentConversion(component, tv = True)
return component
# =========================
#just to illustrate an exemple selection of 10 sphere combined
psph = [cmds.polySphere()[0] for i in range(10)]
for i in psph:
cmds.setAttr(i+'.t', random.uniform(0.0, 3.0), random.uniform(0.0, 3.0), random.uniform(0.0, 3.0))
sph_comb = cmds.polyUnite(psph)
cmds.delete(sph_comb, ch=True)
# ===============================
selection = cmds.ls(sph_comb)[0]
faceSet = cmds.sets(em = True, name = '{}_sg_faceset'.format(selection))
combinedFaceGrp = cmds.ls(selection + '.f[:]', fl = True)
partsFace = []
x = 0
while combinedFaceGrp or x>10000:
len(combinedFaceGrp)
component = growComponent(combinedFaceGrp[0])
faces = cmds.polyListComponentConversion(component, tf = True)
partset = cmds.sets(faces, name='part{}_{}_set'.format(x, selection))
cmds.sets(partset, edit = True, fe = faceSet)
x+=1
# remove face selected
faces_fl = cmds.ls(faces, fl=True)
combinedFaceGrp = list(set(combinedFaceGrp)-set(faces_fl))
# assign shader
sha = cmds.shadingNode('lambert', asShader=True, name="{}_{}_lambert".format(selection, x))
sg = cmds.sets(empty=True, renderable=True, noSurfaceShader=True, name="{}_{}_sg".format(selection, x))
cmds.setAttr(sha+".color", random.uniform(0.0, 1.0), random.uniform(0.0, 1.0), random.uniform(0.0, 1.0))
cmds.connectAttr( sha+".outColor", sg+".surfaceShader", f=True)
cmds.sets(faces, e=True, forceElement=sg)