#####################3
## Author: Jan Pijpers
## Date: 30-01-2013
## Shader information Script
## This script outputs an xml file of the shaders and its textures that are being used by the fist object of a selection.
## Usage: Select an object inside of autodesk maya and run the script
import pymel.core as pm
import xml.dom.minidom as xml
class shaderInfo():
'''
class that gathers information about the shader
and stores them into an xml file
'''
def __init__(self, geo = None):
'''
argument geo = pm.PyNode()
'''
## Check if user is providing his own list of objects
if not geo:
self.selectedObjects = pm.selected()
else:
if type(geo) != type([]):
geo = [geo]
self.selectedObjects = geo
## safety checks
if not self.selectedObjects:
pm.informBox("Please select an object", "Please select an object for the script to work")
return
if self.selectedObjects[0].type() != 'transform':
pm.informBox("Please select a transform", "Please select a geometrical object in the viewport. Selecting a shape directly from the outliner will not work.")
return
## get all the shaders of the selected object. If wrapped in a for loop this can work for N number of objects.
shaders = self.getShaders(self.selectedObjects[0])
xmlShaderData = self.sortShaderData(shaders)
self.writeFile(xmlShaderData)
def getShaders(self, object):
## Get the shape of the object. as that is connected to the shading engine
self.shapes = object.getShapes()
if not self.shapes:
# user selected something other than geo, maybe locator etc
return
## Get the shading enginetextures
shadingEngine = pm.listConnections(self.shapes,type='shadingEngine')
shadingEngineConnections = pm.listConnections(shadingEngine)
## Get the shaders (materials) AND remove dupplicates. as one shader can be used several times on a mesh/ shapes
shaders = list(set(pm.ls(shadingEngineConnections, materials=1)))
return shaders
## Here we sort our shader data. We can check for anything we like here.
## We could even add the shader type so we can rebuild it.
## we could even make it recursive so it check for shaders within shaders etc
def sortShaderData(self, shaders):
shaderData = {}
## Create XML document
xml_doc = xml.Document()
xml_root = xml_doc.createElement("ShaderInfo")
xml_doc.appendChild(xml_root)
## Run through all our shaders we receeive
for shader in shaders:
shaderXML = xml_doc.createElement("Shader")
shaderXML.setAttribute('name', shader.name())
## get all our connections
shaderConnections = pm.listConnections(shader, connections = True)
## Run through our connections so we can be more picky about whats we get returned
for shaderConnection, sourceConnection in shaderConnections:
if sourceConnection.type() == 'file':
filePath = sourceConnection.fileTextureName.get()
fileXML = xml_doc.createElement('file')
fileXML.setAttribute('shaderInput', shaderConnection.split('.')[-1]) ## only get the info on which channel it is put into.
fileXML.setAttribute('filePath', filePath)
shaderXML.appendChild(fileXML)
xml_root.appendChild(shaderXML)
return xml_doc
## Write our data
def writeFile(self, xmlData, filePath = None):
## Ask for file path if we dint get any.
if not filePath:
filePath = pm.fileDialog2(caption = 'Select a location to save your shader data', fileFilter = '.shaderInfo', fileMode = 0)[0]
## Standard open close write etc.
f = open(filePath, 'w')
f.write(xmlData.toprettyxml())
f.close()
## Usage: Select an object in the scene and run this script.
## It will ask for a file location on where to save the shader data.
shaderInfo()