Getting the material of a face with PyMEL

3,067 views
Skip to first unread message

MaloW

unread,
May 27, 2011, 2:23:39 PM5/27/11
to python_inside_maya
Hi, I'm working on creating an .obj-exporter as a part of a school
project using MEL, Python and PyMEL. I've got it working great, but
right now it can't export several materials for 1 object. My teacher
wasn't quite sure how to do this either but told me that I could ask
here.
How can I from a face, and not from the object, find out which
material is connected to it, so that I can export the materials per-
face and not per-object? I've tried looking at the documentation of
PyMEL as well as using dir() inside maya on a face, but I found
nothing that I thought could be of use.
Any help is appreciated, thanks.

Michiel Duvekot

unread,
May 28, 2011, 1:15:11 PM5/28/11
to python_inside_maya
// assuming you've selected a face
sel = cmds.ls(sl=True)
cmds.hyperShade( shaderNetworksSelectMaterialNodes=True )
print "%s -> %s" % (sel[0], cmds.ls(sl=True)[0])
cmds.select(sel, replace=True)

Martin La Land Romero

unread,
May 28, 2011, 2:08:18 PM5/28/11
to python_in...@googlegroups.com
My tool exports the entire scene with all the textures to a new location, perhaps it has some handy line or lines that can help you out!


import maya.cmds as cmds
import os
import shutil



def AskUserForSaveLocation():
    """
    This function asks the user for the new location of the .mb, .ma file, the user only needs to provide a direction.
    """
    #newLocation ='C:\Users\FFION2\Desktop\GDC_VFX_CLASS' #hardcoded > enter your target directory.
    multipleFilters = "Maya Files (*.ma *.mb);;Maya ASCII (*.ma);;Maya Binary (*.mb);;All Files (*.*)"
    newLocation = cmds.fileDialog2(fileFilter=multipleFilters, fileMode=2, dialogStyle=2) 
   
    print (newLocation, "choosen directory")   
    return newLocation[0]
   
def copyToNewLocation(srcFiles, destDirectory):
    """
    This function checks the for the current location of the file. It also copies each one of the assets to a new directory specified by the user.
    """
   
    #It goes trough each texture as well as the maya file and place them in the new location.
    for i in srcFiles:
        print(i, "Got transferred")
        shutil.copy(i, destDirectory )
  
      
def AskAndCopyCurrentSceneToNewDirectory():
    """
    This function creates a window with a button. It also asks the user to enter a new directory and copies the maya file as well as the teuxtures to the new directory.
    """
   
    #Location of the current maya scene.
    mySceneAssets = cmds.file( q=True, l=True, loc=True )
    newLocation = AskUserForSaveLocation()
   
    #call fucntion copyToNewLocation.
    copyToNewLocation(mySceneAssets, newLocation)
       
mr_copyNewLocUI = ''
if cmds.window(mr_copyNewLocUI, exists= True):
    cmds.deleteUI(mr_copyNewLocUI)
else:
    mr_copyNewLocUI = cmds.window(widthHeight = (357, 139), title = 'mr_CopyAllToNewLocation', mxb = False, mnb = False)
    mainCol = cmds.columnLayout( adj = True)
    cmds.rowColumnLayout( numberOfColumns=2, columnAttach=(1, 'right', 0), columnWidth=[(1, 100), (2, 250)] )

#Create a menuBar with menuItems
cmds.text( label='' )
currDirBtm = cmds.button(label= 'ExportAllTextures/MayaFile', command = 'AskAndCopyCurrentSceneToNewDirectory()' )

#Shows the window.
cmds.showWindow(mr_copyNewLocUI)





--
Martin La Land Romero
www.martinromerovfx.com
http://martinromerovfx.blogspot.com/
martin...@gmail.com
(415)261-2172

John Patrick

unread,
May 28, 2011, 3:23:47 PM5/28/11
to python_in...@googlegroups.com
I think I get what you're after.  shaders are assigned through ShadingEngine nodes, which are sets (the mesh itself does not contain shader assignment data), so you can query the shadingEngine sets for their members like so:

import pymel.core as PM

def getShadingGroupMembership():
    '''
    Get a dictionary of shading group set information
    {'shadingGroup': [assignmnet1, assignment2...]}
    '''
    result = {}
    sgs = PM.ls(type='shadingEngine')
    for sg in sgs:
        result[sg.name()] = sg.members(flatten=True)
    return result

You can go the other way around (finding from the mesh instead of the shading group) by querying the mesh shape for connections to shading engine nodes.

-JP

MaloW

unread,
May 29, 2011, 2:31:41 PM5/29/11
to python_inside_maya
Thanks for the fast answers!
After reading through your answers I manage to solve it using this
code:
To check if the material is applied for the entire object:
sgs = pm.ls(type='shadingEngine');
for sg in sgs:
mems = sg.members(flatten=True);
for mem in mems:
if mem.name() == node.name():
# Material is applied per object

And if that gets false it means materials are applied by face:
sgs = pm.ls(type='shadingEngine');
for sg in sgs:
mems = sg.members(flatten=True);
for mem in mems:
if face in mem:
# if face in mem gets true as long as the
# [] place is correct, so I have to check
# node name as well.
temp = mem.name().split('.')[0];
if node.name() == temp:
# Material is applied by face

Thanks again for your answers!
Reply all
Reply to author
Forward
0 new messages