Switch fileTex to psdFileTex


#1

Hi, I’m trying to write an script that switches textures (fileTex) to psdFileTex nodes and activate it’s alpha, and change it back if the file is in a different format.

I created the psdFileTex, copied the fileTex attributes to it and activated the first alpha channel, but I don’t know how to connect this new node to the material fileTex is using. I don’t know how to get the materials the fileTex is using.

Since I don’t know how to access the materials through the texture nodes, I did a loop through the materials, and got the texFiles the materials are using with listConnections, but I don’t know from where to where they are connected.

Any help where should I looking for?


#2

Normally the best way to go through this is to look at the Node Editor to help visualize what you need to do in script. So suppose we create a simple scene:

  1. Create a polySphere.
  2. Assign a new blinn material to the sphere.
  3. Assign a file texture node onto the color channel of the blinn material.
  4. (Optional) Add a file with transparency to the file texture node.

If you did each of those steps, you’ll note that there are two connections going out from the file node and into the material:

file1.outColor > blinn1.color
file1.outTransparency > blinn1.transparency

If you run the same steps with a PSDFileTex node, you’ll see the same connections.

So now we just need a script to do this and you were on the right track with listConnections. I’ve done a sample in Python.


 import maya.cmds as cmds
 def findMaterialConnections( texNode ):
 	matConnections = cmds.listConnections(texNode, destination=True, connections=True, plugs=True, type='lambert')
 	print matConnections
 	
 findMaterialConnections( 'psdFileTex1' )
 # Result:
 # [u'psdFileTex1.outColor', u'blinn1.color', u'psdFileTex1.outTransparency', u'blinn1.transparency']
 

You can see from the result that for each pair every even index, you get the source plug, and odd index represents the destination plug that the source plugs into. So let’s break down what my command call does:

[ul]
[li]It specifies the node I want to browse connections for as texNode.[/li][/ul]
[ul]
[li]It specifies destination=True to force it to return the attributes/nodes that are on the destination side of the connection. If the connection was driving the texture node, then you’d want to set this to false. But since we’re looking for outColor and outTransparency connections, the Node Editor shows that these drive the material.[/li][/ul]
[ul]
[li]It specifies connections=True, to make sure that we get the both the node and attribute of the texNode that is driving the connetion.[/li][/ul]
[ul]
[li]It specifies plug=True to make sure that we get both the node and the attribute of the material side.[/li][/ul]
[ul]
[li]Lastly, it specifies type=‘lambert’. This filters all connections to only look at connections at nodes of these types. Lambert is a base class for all software shader nodes so this will pickup other nodes like blinn, phong etc. If you want to capture other material nodes like dx11Shader or other plug-in nodes, you would need to run the command again with a different type and accumulate the results into a list.[/li][/ul]

From there, you should have all the info you need to do an in place change between file and psdFile nodes.

Hope this helps.


#3

Thanks! listConnections seems to do the job and the pm version looks easier to deal with.


#4

This is what I got and it seems to be working fine. I’m posting it just in case it helps someone in the future.

from maya import cmds
import pymel.core as pm

#---------------------------------------------------------------
# Replace File Texture Nodes by a PSD File Texture Nodes
# if their extension is PSD
#
# main() to keep the same name
# main(True) to rename the node to match it's texture file name
#---------------------------------------------------------------

def findMaterialConnections( texNode ):
    allMats = pm.ls(materials=True)

    #Gather All Material Types    
    matTypes =[]
    for mat in allMats:
        matTypes.append(pm.objectType(mat))
    matTypes =list(set(matTypes))
    
    #Gather All the connections in all materials
    connections =[]
    for matType in matTypes:
        connectionsList = pm.listConnections(texNode, destination=True, connections=True, plugs=True, type=matType)
        for connectionListItem in connectionsList:
            connections.append(connectionListItem)

    return connections

def main (matchFileName = False):
    texs = pm.ls(textures=True)
    
    for tex in texs:
        texName = tex.shortName()
        texFile = tex.fileTextureName.get().replace("\\","/")
        filewithoutExt = texFile[texFile.rfind("/")+1:texFile.find(".")]
        fileExt = texFile[texFile.find(".")+1:].lower()   #ex : psd
        
        if fileExt.upper() == "PSD":
            #Set Texture Path
            texturePath = tex.fileTextureName.get()
            psdFile = pm.shadingNode('psdFileTex', asTexture=True)
            psdFile.fileTextureName.set( texturePath )
            
            #Set Attributes
            attrs = pm.listAttr(tex, hd=True)
            for attr in attrs:
                try:
                    cmds.setAttr(psdFile +"."+ attr, cmds.getAttr(tex+"."+attr) )
                except:
                    pass
                    
            #Set Connections
            connections = findMaterialConnections( tex )
            for conn in connections:
                c_out = str(conn[0])
                pm.connectAttr(str(psdFile)+c_out[c_out.find("."):], conn[1], force=True)
                
                #Set Alpha
                if c_out.find(".outTransparency") != -1:
                    alphaList = psdFile.alphaList.get()
                    if (len(alphaList) > 0):
                        psdFile.alpha.set(alphaList[0])
                        
            pm.delete(tex)
            if matchFileName == True:
                pm.rename(psdFile, filewithoutExt)
            else:
                pm.rename(psdFile, texName)