SCRIPT: Auto generate Universal mat from image maps

Forums: SCRIPT: Auto generate Universal mat from image maps
Sub forum for help and tutorials.

Moderator: JimStar

SCRIPT: Auto generate Universal mat from image maps

Postby pixerati2 » Mon Jun 03, 2019 4:24 pm

pixerati2 Mon Jun 03, 2019 4:24 pm
Got tired of endlessly hooking up all the image map texture nodes to a universal material.

This script asks for the location of a single image texture (can be diffuse/albedo, specular, or metallic) and will then proceed to automatically find and connect other image maps in the same directory to the appropriate connections on the universal material. (Will automatically invert gloss maps for roughness).

Requires that the image textures have the same naming prefix. Should work with most standard namings (e.g. you can call the albedo pass either albedo or diffuse and it'll pick it up), but you can include additional alternate namings just by adding them to the dictionary list ("listOfMaps") in the script--just don't override the very first item in the list: it's the official Octane texture name the script uses to connect the nodes.

The top button will automatically create the material and apply it to a selected object. Alternately, you can perform the steps manually using the buttons below it.

Only tested on Windows.


Code: Select all
import maya.cmds as cmds
import maya.mel as mel
import pymel.core as pm
#import ntpath
from os import listdir
from os.path import isfile, join


imageFilePath = None
prefix = ''
pathText = None
prefixText = None
currentMaterial = None

def SetFilePath():
    # Sets the file path to the images
    basicFilter = "*.*"
    global imageFilePath
    global prefix
    global prefixText
    global pathText
    fileNames = None
    #fileNames = pm.fileDialog2(fileFilter=basicFilter, dialogStyle=1)
    fileNames = cmds.fileDialog2(fileFilter=basicFilter, dialogStyle=2, caption='Locate albedo, specular, or metallic file',
                                         fileMode=1, returnFilter=False)   
    if (fileNames == None): return False
    if (len(fileNames)==0): return False
    fileName = fileNames[0]   
    imageFilePath = os.path.dirname(fileName)
    prefix = os.path.basename(fileName)
    lowercasePrefix = prefix.lower()
    if "diffuse" in lowercasePrefix:
        indexOfDiffuseKeyword = lowercasePrefix.find('diffuse')
    elif "diff" in lowercasePrefix:
        indexOfDiffuseKeyword = lowercasePrefix.find('diff')   
    elif "albedo" in lowercasePrefix:
        indexOfDiffuseKeyword = lowercasePrefix.find('albedo')
    elif "specular" in lowercasePrefix:
        indexOfDiffuseKeyword = lowercasePrefix.find('specular') 
    elif "spec" in lowercasePrefix:
        indexOfDiffuseKeyword = lowercasePrefix.find('spec')   
    elif "metalness" in lowercasePrefix:
        indexOfDiffuseKeyword = lowercasePrefix.find('metalness')
    elif "metallic" in lowercasePrefix:
        indexOfDiffuseKeyword = lowercasePrefix.find('metallic')   
    elif "metal" in lowercasePrefix:
        indexOfDiffuseKeyword = lowercasePrefix.find('metal')   
    prefix = prefix[:indexOfDiffuseKeyword]
    cmds.text(prefixText, edit=True, label=prefix)
    cmds.text(pathText, edit=True, label=imageFilePath)
    return True

def SetPrefix():
    global prefix
    result = pm.promptDialog(
                title='Enter image texture prefix',
                message='Enter prefix:',
                tx=prefix,
                button=['OK', 'Cancel'],
                defaultButton='OK',
                cancelButton='Cancel',
                dismissString='Cancel')
   
    if result == 'OK':
        prefix = pm.promptDialog(query=True, text=True)   
        cmds.text(prefixText, edit=True, label=prefix)

def CreateMat():
    global currentMaterial
    global prefix
    global imageFilePath
    initialSelection = cmds.ls( sl=True)
    transmissionMap = None
    diffuseMap = None
    metallicMap = None
    specularMap = None
    roughnessMap = None
    anisotropyMap = None
    rotationMap = None
    dielectricMap = None
    coatingMap = None
    coatingRoughnessMap = None
    sheenMap = None
    sheenRoughnessMap = None
    mediumMap = None
    indexMap = None
    bumpMap = None
    normalMap = None
    displacementMap = None
    opacityMap = None
    edgeRoundingMap = None
    emissionMap = None
    invertRoughness = False
    filmWidthMap = None
    listOfMaps = {"Transmission,transmission":transmissionMap,
                  "Albedo,diffuse,albedo":diffuseMap,
                  "Metallic,metal":metallicMap,
                  "Specular,specular":specularMap,
                  "Roughness,rough,gloss":roughnessMap,
                  "Rotation,rotation":rotationMap,
                  "DielectricIorMap,dielec,ior":dielectricMap,
                  "Coating, coat":coatingMap,
                  "CoatingRoughness, ctrough":coatingRoughnessMap,
                  "FilmWidth,film":filmWidthMap,
                  "Sheen,sheen":sheenMap,
                  "SheenRoughness,shnRough":sheenRoughnessMap,
                  "Medium,medium":mediumMap,
                  "Index,index,ior,refractiveindex,refractive_index":indexMap,
                  "Bump,bump":bumpMap,
                  "Normal,normal":normalMap,
                  "Displacement,displac":displacementMap,
                  "Opacity,opacity":opacityMap,
                  "Emission,emiss,lumin":emissionMap}
       
    filesInDir = [f for f in listdir(imageFilePath) if isfile(join(imageFilePath, f))]
    for currentFile in filesInDir:
        if (prefix in currentFile):
            currentFileLC = currentFile.lower()
            for currentMap in listOfMaps:
                #pm.confirmDialog( title='Current map: ', message=listOfMaps[currentMap], button=['OK'], dismissString='OK' )                                                   
                searchTerms = currentMap.split(",")
                for searchTerm in searchTerms:
                    #pm.confirmDialog( title='Current search term: ', message=searchTerm, button=['OK'], dismissString='OK' )                                   
                    if (searchTerm in currentFileLC):
                        listOfMaps[currentMap] = imageFilePath + "/" + currentFile
                        if searchTerm == "gloss": # gloss maps are the inverse of roughness maps
                            #pm.confirmDialog( title='Found gloss1', message="Inverting", button=['OK'], dismissString='OK' )                                                               
                            invertRoughness = True
     
   
    # Time to build the network
    #commandText = 'shadingNode -asShader octaneGlossyMaterial -name "' + prefix + '_octUnivMat";'
    #mel.eval(commandText)
    materialName = prefix + '_octUnivMat'
    SGName = prefix + '_SG'
    currentMaterial = cmds.shadingNode('octaneUniversalMaterial', name=materialName, asShader=True) 
    shading_group= cmds.sets(name=SGName, renderable=True, noSurfaceShader=True, empty=True)
    cmds.connectAttr('%s.outColor' % currentMaterial, '%s.surfaceShader' % shading_group)

    for currentMap in listOfMaps:
        if listOfMaps[currentMap] is not None:
            keyWordTerms = currentMap.split(",")
            userMessage = keyWordTerms[0] + " set to: " + listOfMaps[currentMap]
            #pm.confirmDialog( title='Setting map', message=userMessage, button=['OK'], dismissString='OK' )     
   
    for currentMap in listOfMaps:
        if listOfMaps[currentMap] is not None:
            #pm.confirmDialog( title='Map present: ', message=listOfMaps[currentMap], button=['OK'], dismissString='OK' )           
            keyWordTerms = currentMap.split(",")
            currentImageType = keyWordTerms[0]
            nameOfImageNode = os.path.basename(listOfMaps[currentMap])
            nameOfImageNode = os.path.splitext(nameOfImageNode)[0]
            currentImageNode = cmds.shadingNode('octaneImageTexture', name=nameOfImageNode, asShader=True)
            commandTex = 'connectAttr -f ' + currentImageNode + '.outTex ' + currentMaterial + '.' + currentImageType + ';'
            mel.eval(commandTex)
            commandTex = 'setAttr -type "string" ' + currentImageNode + '.File "' + listOfMaps[currentMap] + '";'
            mel.eval(commandTex)
            # Check for gloss map requiring invert
            if ( (currentMap == "Roughness,rough,gloss") and (invertRoughness == True) ):
                # Invert the roughness map
                #pm.confirmDialog( title='Found gloss', message="Inverting", button=['OK'], dismissString='OK' )                                                                               
                commandTex = 'setAttr "' + currentImageNode + '.Invert" 1;'
                mel.eval(commandTex)
    cmds.select(initialSelection)  # reselect the original objects

def getSGfromShader(shader=None):
    if shader:
        if cmds.objExists(shader):
            sgq = cmds.listConnections(shader, d=True, et=True, t='shadingEngine')
            if sgq:
                return sgq[0]
    return None

def assignObjectListToShader(objList=None, shader=None):
    """
    Assign the shader to the object list
    arguments:
        objList: list of objects or faces
    """
    # assign selection to the shader
    shaderSG = getSGfromShader(shader)
    if objList:
        if shaderSG:
            cmds.sets(objList, e=True, forceElement=shaderSG)
        else:
            print 'The provided shader didn\'t returned a shaderSG'
           
    else:
        print 'Please select one or more objects'
       
def assignSelectionToShader(shader=None):
    sel = cmds.ls(sl=True, l=True)
    if sel:
        assignObjectListToShader(sel, shader)

def AssignMat():
    assignSelectionToShader(currentMaterial)

def DoItAll():
    #get initial selection
    initialSelection = cmds.ls( sl=True)     
    dirFound = SetFilePath()
    if dirFound:
        CreateMat()
        cmds.select(initialSelection)  # reselect the original objects
        AssignMat()



# Make a new window
#
window = pm.window( title="Octane Material Builder", iconName='Short Name', widthHeight=(500, 200) )
pm.columnLayout( adjustableColumn=True )
# Result: ui.ColumnLayout('window1|columnLayout98') #
prefixText = pm.text("Image prefix", align='left', font='boldLabelFont')
pathText = pm.text("Image path", align='left', font='boldLabelFont')
pm.button( label='LOCATE, CREATE, AND ASSIGN', command=lambda *args:DoItAll() )
pm.button( label='Locate diffuse texture', command=lambda *args:SetFilePath() )
pm.button( label='Set common image prefix (optional)', command=lambda *args:SetPrefix() )
pm.button( label='Create material', command=lambda *args:CreateMat() )
pm.button( label='Assign current mat to selected', command=lambda *args:AssignMat() )
# Result: ui.Button('window1|columnLayout98|button111') #
pm.button( label='Close', command=('pm.deleteUI(\"' + window + '\", window=True)') )
# Result: ui.Button('window1|columnLayout98|button112') #
pm.setParent( '..' )
# Result: u'' #
pm.showWindow( window )
Attachments
ConvertOctaneMaterials_v04.zip
(2.81 KiB) Downloaded 344 times
pixerati2
Licensed Customer
Licensed Customer
 
Posts: 42
Joined: Sun Jul 06, 2014 4:06 pm

Re: SCRIPT: Auto generate Universal mat from image maps

Postby kommando_2k » Fri Jul 31, 2020 5:40 am

kommando_2k Fri Jul 31, 2020 5:40 am
Script seem broken. :? Attempt import quixel megascan texture files but only created Universal Material but nothing else include texture nodes when execute script.
kommando_2k
Licensed Customer
Licensed Customer
 
Posts: 35
Joined: Mon Sep 02, 2013 5:47 am

Return to Help / Tutorials


Who is online

Users browsing this forum: No registered users and 2 guests

Thu Mar 28, 2024 8:35 am [ UTC ]