def doCheckNames(arg=None): '''Button: Check Names. ''' sys.stdout.write("Checking names... \n") cmds.undoInfo(openChunk=True) currentAssetCategory = getAssetCategory() nodes = getSelectionList() if nodes: invalidNodes = ddCheckNames.do(nodes=nodes, currentAssetCategory=currentAssetCategory) if invalidNodes: cmds.warning("%s%s names are not valid." % (currentAssetCategory[0].upper(), currentAssetCategory[1:-1])) else: sys.stdout.write("%s%s names are valid.\n" % (currentAssetCategory[0].upper(), currentAssetCategory[1:-1])) cmds.undoInfo(closeChunk=True)
def do(nodes=None, replaceWithReference=True, export=True, currentAssetCategory="environments", notify=True): # double check if necessary environment variables exist before continuing print "should we notify? %s" % str(notify) vpe.VP_Environment().test() currentAssetLibrary = ddConstants.ASSET_DIRECTORIES[currentAssetCategory] # Check if assetLibrary folder exists if not os.path.isdir(currentAssetLibrary): confirm = cmds.confirmDialog( title="Warning", messageAlign="center", message="AssetLibrary path does not exist: %s" % currentAssetLibrary, button=["Ok"], defaultButton="Ok", cancelButton="Ok", dismissString="Ok", ) return # Get selection if not nodes: nodes = cmds.ls(selection=True, objectsOnly=True, long=True) if len(nodes) == 0: confirm = cmds.confirmDialog( title="Warning", messageAlign="center", message="Select at least one group object.", button=["Ok"], defaultButton="Ok", cancelButton="Ok", dismissString="Ok", ) return if not isinstance(nodes, list): nodes = [nodes] invalidNodes = list() invalid_textured_nodes = list() override = False resultTopNodes = list() # Clean and export for sel in nodes: sys.stdout.write("\n--> %s\n" % sel.rpartition("|")[2]) currentNode = sel nodeParent = cmds.listRelatives(sel, parent=True, path=True) if cmds.referenceQuery(currentNode, isNodeReferenced=True): currentNode = ddImportFromReference.do(currentNode)[0] invalidNode = ddCheckNames.do(nodes=currentNode, currentAssetCategory=currentAssetCategory) valid_textures = ddCheckTextures.do(node=currentNode)[0] if not invalidNode and valid_textures: publish_details = {} # no need to grab notes from user if not sending email if notify: publish_details["Notes"] = publish_notes.PublishNotes().notes validNode = ddRemoveNamespaces.doRemoveNamespaces(node=currentNode) topGrpLayer = ddRemoveFromLayers.do(nodes=validNode)[0] pos = cmds.xform(validNode, query=True, worldSpace=True, absolute=True, rotatePivot=True) rot = cmds.getAttr("%s.r" % validNode)[0] scl = cmds.getAttr("%s.s" % validNode)[0] ddUnlockGeoTransforms.do(nodes=validNode) returnedNodes = ddRemovePivotOffsets.do( nodes=validNode, returnToPos=False, currentAssetCategory=currentAssetCategory ) if returnedNodes: validNode = returnedNodes[0] ddAddGeoMetadata.do(nodes=validNode) ddLockGeoTransforms.do(nodes=validNode) advancedAssets = cmds.ls(type="container", long=True) if advancedAssets: sys.stdout.write("Deleting advanced assets...\n") cmds.delete(advancedAssets) unknownNodes = cmds.ls(type="unknown", long=True) if unknownNodes: try: sys.stdout.write("Deleting unknown nodes...\n") cmds.delete(unknownNodes) except: cmds.warning("Unable to delete unknown nodes.") if not export: continue if currentAssetLibrary == ddConstants.CHAR_ASSETLIBRARY: exportedNode, exportedPath = exportCharacterAsset(sel) # attempt to collect publish details for character piece charType = {"hero": "hero", "bg": "background", "sec": "secondary"} scene_patt = re.compile("char_(%s)_[A-Z]{3}_[a-z]+" % "|".join(charType.values())) char_patt = re.compile("[A-Z]{3}_[a-zA-Z]+") if scene_patt.search(exportedNode): publish_details["Character"] = char_patt.search(exportedNode).group() publish_details["Template_Category"] = "vad_chesspiece" else: exportedNode, exportedPath, override = exportAsset( node=validNode, override=False, currentAssetCategory=currentAssetCategory ) env_patt = re.compile("[a-z]{3,4}(_[a-z]{3})*(_[a-z]+)*_([a-zA-Z]+[0-9]*[A-Z]v[A-Z])_*") if env_patt.search(exportedNode): publish_details["Enviro_Asset"] = env_patt.search(exportedNode).groups()[-1] publish_details["Template_Category"] = "vad_enviro_asset" if exportedPath: ddScreenBoardGrab.do_boards( nodes=exportedNode.rpartition("|")[2], current_asset_category=currentAssetCategory ) # ddScreenGrab.do(nodes=exportedNode.rpartition("|")[2], currentAssetCategory=currentAssetCategory) else: if currentNode != sel: cmds.delete(currentNode) sys.stdout.write("Export of %s was Canceled..." % exportedNode) return # update publish details with version, file # and file path information version_patt = re.compile("_v([0-9]{2,4})_*") if version_patt.search(exportedNode): publish_details["Version"] = version_patt.search(exportedNode).groups()[0] publish_details["FILEPATH"] = "%s.ma" % exportedPath publish_details["FILE"] = os.path.basename(publish_details["FILEPATH"]) if replaceWithReference and exportedPath: currentSceneFile = cmds.file(query=True, sceneName=True).replace("/", os.sep) exportedFile = "%s.ma" % exportedPath if currentSceneFile == exportedFile: confirm = cmds.confirmDialog( title="Warning", messageAlign="center", message="Scene file is already open. Cannot reference a file into itself.", button=["Ok"], defaultButton="Ok", cancelButton="Ok", dismissString="Ok", ) if confirm == "Ok": continue # Delete original GRP confirm = cmds.confirmDialog( title="Warning", messageAlign="center", message="Delete original GRP?", button=["Ok", "Keep Original"], defaultButton="Ok", cancelButton="Keep Original", dismissString="Keep Original", ) if confirm == "Ok": cmds.delete(exportedNode) else: # Move group back. cmds.xform(exportedNode, worldSpace=True, absolute=True, translation=pos) cmds.setAttr("%s.r" % exportedNode, rot[0], rot[1], rot[2]) cmds.setAttr("%s.s" % exportedNode, scl[0], scl[1], scl[2]) # Reference a copy of the exported file namespace = os.path.split(exportedPath)[1].partition(".")[0] newReferencedNodes = cmds.file( "%s.ma" % exportedPath, reference=True, namespace=namespace, returnNewNodes=True ) referencedTopGrp = "" refTransforms = [x for x in newReferencedNodes if cmds.nodeType(x) == "transform"] for refTransform in refTransforms: refParent = cmds.listRelatives(refTransform, parent=True, fullPath=True) if not refParent or not refParent[0] in refTransforms: referencedTopGrp = refTransform cmds.xform(referencedTopGrp, worldSpace=True, absolute=True, translation=pos) cmds.setAttr("%s.r" % referencedTopGrp, rot[0], rot[1], rot[2]) cmds.setAttr("%s.s" % referencedTopGrp, scl[0], scl[1], scl[2]) if topGrpLayer: cmds.editDisplayLayerMembers(topGrpLayer, referencedTopGrp, noRecurse=True) if nodeParent: referencedTopGrp = cmds.parent(referencedTopGrp, nodeParent[0])[0] resultTopNodes.append(referencedTopGrp.rpartition("|")[2]) else: # Move group back. cmds.xform(exportedNode, worldSpace=True, absolute=True, translation=pos) cmds.setAttr("%s.r" % exportedNode, rot[0], rot[1], rot[2]) cmds.setAttr("%s.s" % exportedNode, scl[0], scl[1], scl[2]) resultTopNodes.append(exportedNode.rpartition("|")[2]) if topGrpLayer: cmds.editDisplayLayerMembers(topGrpLayer, exportedNode, noRecurse=True) if nodeParent: exportedNode = cmds.parent(exportedNode, nodeParent[0])[0] # prep and send publish email publish_details["SHOW"] = os.getenv("SHOW") publish_details["ARTIST"] = os.getenv("ARTIST") if os.getenv("ARTIST") else "Some Artist" # send publish email if user specified notification if notify: sys.stdout.write("Sending email. \n") set_email = pub_mail.PublishEmail(publish_details["Template_Category"]) set_email.publish_details = publish_details set_email.build_email() set_email.send_mail() else: sys.stdout.write("Holding off on sending publish email by request. \n") else: if invalidNode: sys.stdout.write("Invalid name %s. Skipping...\n" % invalidNode[0].rpartition("|")[2]) invalidNodes.append(sel) elif not valid_textures: sys.stdout.write("Invalid texture found on node %s. Skipping...\n" % sel.rpartition("|")[2]) invalid_textured_nodes.append(sel) if invalidNodes: nodeString = "" for invalidNode in invalidNodes: nodeString += "%s, " % invalidNode.rpartition("|")[2] confirm = cmds.confirmDialog( title="Warning", messageAlign="center", message="Please legalize the %s names of the following groups and re-export:\n\n%s" % (currentAssetCategory[:-1], nodeString[:-2]), button=["Ok"], defaultButton="Ok", cancelButton="Ok", dismissString="Ok", ) cmds.select(invalidNodes, replace=True) # report back any nodes found with invalid textures if invalid_textured_nodes: node_string = ", ".join(invalid_textured_nodes) confirm = cmds.confirmDialog( title="Warning", messageAlign="center", message="Please fix the textures of the following groups and re-export:\n\n%s" % (node_string), button=["Ok"], defaultButton="Ok", cancelButton="Ok", dismissString="Ok", ) if invalidNodes: # add to selection of other invalid nodes cmds.select(invalid_textured_nodes, add=True) else: # select only these invalid nodes cmds.select(invalid_textured_nodes, replace=True) if resultTopNodes: try: cmds.select(resultTopNodes, r=1) except: pass
def do(node=None, override=False, publish=False): """Checks if textures files are saved in assetLibrary and file format is ".tif". Names texture files to match GEO. """ if not node: selection = cmds.ls(selection=True, long=True) if selection: node = selection[0] else: return False, override if publish: invalidNode = ddCheckNames.do(node) if invalidNode: sys.stdout.write( "Cannot check textures. Names are not valid for node %s. Skipping... \n" % node.rpartition("|")[2] ) return False, override if cmds.referenceQuery(node, isNodeReferenced=True): sys.stdout.write("--> Unable to check textures of referenced node %s. Skipping... \n" % node.rpartition("|")[2]) return False, override currentNode = node if publish: newNode = ddRemoveNamespaces.do(node) if newNode: currentNode = newNode[0] # Texture file storage location textureDir = os.path.join(ddConstants.ASSETLIBRARY, "tex", "tif") textureDir = os.path.normpath(textureDir) if not os.path.isdir(textureDir): raise Exception("Directory %s does not exist" % textureDir) # Get list of child mesh nodes under GRP node meshList = cmds.listRelatives(currentNode, path=True, allDescendents=True, type="mesh") or [] version = currentNode.partition("_GRP_")[2].partition("_")[0] overwriteOverride = False skipCopy = False skipOverwrite = False publishedOverride = False allShadingEngines = collect_shading_engines(meshList) for shadingEngine in allShadingEngines: cnxList = [x for x in (cmds.listConnections(shadingEngine) or []) if cmds.nodeType(x) == "transform"] cnxList = list(set(cnxList)) cnxList.sort() rootName = cnxList[0].rpartition("|")[2].rpartition("_")[0] currentShadingEngine = shadingEngine connectedMeshes = [ x for x in (cmds.listConnections(currentShadingEngine) or []) if cmds.listRelatives(x, shapes=True) ] connectedMeshes = list(set(connectedMeshes)) if publish: if len(connectedMeshes) > 1: if rootName: rootName = rootName.replace("_GEO", "") while ord(rootName[-1]) in range(49, 58): rootName = rootName[:-1] while ord(rootName[-1]) in range(65, 91): rootName = rootName[:-1] rootName = "%s_GEO" % rootName # Find connected file nodes historyList = cmds.listHistory(currentShadingEngine) or [] fileNodes = [x for x in historyList if cmds.nodeType(x) == "file"] or [] for fileNode in fileNodes: fileTextureName = cmds.getAttr("%s.fileTextureName" % fileNode) newFileName = "" newFilePath = "" # Determine shader attribute file node is connected to surfaceShader = cmds.listConnections("%s.surfaceShader" % currentShadingEngine) if surfaceShader: surfaceShader = surfaceShader[0] cnxList = cmds.listConnections(fileNode, source=False, destination=True, plugs=True) or [] fileNodeCnx = [x for x in cnxList if surfaceShader in x or "bumpValue" in x] if fileNodeCnx: for nodeCnx in fileNodeCnx: attr = nodeCnx.partition(".")[2] if attr in ddConstants.textureTypes.keys(): if not validateTextureFile(fileNode, fileTextureName, publish): return False, override # make sure the color adjustments have not been made # to file node, these should be done to # the file itself # if file_color_changed(fileNode): # return False, override # Create texture name to match GEO newFileName = "%s_%s.tif" % ( rootName.replace("GEO", ddConstants.textureTypes[attr]), version, ) newFilePath = os.path.join(textureDir, newFileName) if publish: fileNode = cmds.rename( fileNode, "%s_FIL" % rootName.replace("GEO", ddConstants.textureTypes[attr]) ) if "bump" in nodeCnx: cmds.rename( nodeCnx.partition(".")[0], "%s_BMP" % rootName.replace("GEO", ddConstants.textureTypes[attr]), ) placeTextureNode = cmds.listConnections(fileNode, source=True, destination=False) if placeTextureNode: cmds.rename( placeTextureNode[0].partition(".")[0], "%s_PTN" % rootName.replace("GEO", ddConstants.textureTypes[attr]), ) else: sys.stdout.write( "--- Skipping %s. Not connected to color, specularColor or normalCamera. \n" % fileTextureName ) if publish: # Rename nodes currentShadingEngine = cmds.rename(currentShadingEngine, rootName.replace("GEO", "SG")) surfaceShader = cmds.rename(surfaceShader, rootName.replace("GEO", "SHD")) # Remove stray namespaces surfaceShaderCnxList = cmds.listConnections(surfaceShader) or [] for shaderCnx in surfaceShaderCnxList: if ":" in shaderCnx: shaderNamespace = shaderCnx.partition(":")[0] try: cmds.select(shaderCnx, replace=True) cmds.namespace(mv=(shaderNamespace, ":"), force=True) except: pass # Check if file saved in assetLibrary if not newFilePath == "" and publish: confirm = "Copy to AssetLibrary" confirmOverwrite = "Overwrite Existing" # New section if fileTextureName.replace("/", os.sep).startswith(ddConstants.ASSETLIBRARY): if not publishedOverride: confirmOverwrite = cmds.confirmDialog( title="Warning", messageAlign="center", message='Texture file "%s" already exists in the assetLibrary. ' % fileTextureName, button=["Ok", "Ok to All", "Cancel"], defaultButton="Skip", cancelButton="Cancel", dismissString="Cancel", ) if confirmOverwrite == "Cancel": return False, override elif confirmOverwrite == "Ok to All": publishedOverride = True skipOverwrite = True continue # End of new section if os.path.isfile(newFilePath): if not overwriteOverride: confirmOverwrite = cmds.confirmDialog( title="Warning", messageAlign="center", message='Texture file "%s" already exists in the assetLibrary. ' % newFileName, button=["Overwrite Existing", "Overwrite All", "Skip", "Skip All", "Cancel"], defaultButton="Overwrite Existing", cancelButton="Cancel", dismissString="Cancel", ) if confirmOverwrite == "Cancel": return False, override elif confirmOverwrite == "Overwrite All": overwriteOverride = True elif confirmOverwrite == "Skip All": overwriteOverride = True skipOverwrite = True elif not override: confirm = cmds.confirmDialog( title="Warning", messageAlign="center", message='Texture file "%s" is not in the assetLibrary. ' % newFileName, button=["Copy to AssetLibrary", "Copy all to AssetLibrary", "Skip", "Skip All", "Cancel"], defaultButton="Copy to assetLibrary", cancelButton="Cancel", dismissString="Cancel", ) if confirm == "Cancel": return False, override # Prevent asset export elif confirm == "Copy all to AssetLibrary": override = True elif confirm == "Skip All": override = True skipCopy = True if not skipOverwrite and not skipCopy: if confirm == "Copy to AssetLibrary" or confirm == "Copy all to AssetLibrary": if os.path.isfile(fileTextureName): if not fileTextureName.replace("/", os.sep) == newFilePath: shutil.copy(fileTextureName, newFilePath) cmds.setAttr("%s.fileTextureName" % fileNode, newFilePath, type="string") else: confirm = cmds.confirmDialog( title="Warning", messageAlign="center", message='Original texture file "%s" does not exist. ' % fileTextureName, button=["Continue", "Cancel"], defaultButton="Continue", cancelButton="Cancel", dismissString="Cancel", ) if confirm == "Cancel": return False, override # Prevent asset export # Allow asset export return True, override
def doScreenGrab(node, currentAssetCategory="environments"): '''Saves out an image of the asset. ''' nodeName = node.rpartition("|")[2] currentAssetLibrary = ddConstants.ASSET_DIRECTORIES[currentAssetCategory] currentImageLibrary = ddConstants.IMAGE_DIRECTORIES[currentAssetCategory] charType = { "hero": "hero", "bg": "background", "sec": "secondary" } chesspieceTypes = ["CPF", "CPO", "CPD", "CPS"] invalidNodes = ddCheckNames.do(nodes=node, currentAssetCategory=currentAssetCategory) if invalidNodes: sys.stdout.write("Legalize names before taking screen grab.\n") return dirs = list() version = "" divider = "" dividerGRP = "" imagePath = currentAssetLibrary smallImagesPath = currentImageLibrary if currentAssetCategory == "environments": dirs = nodeName.rpartition("|")[2].split("_GRP")[0].split("_") version = nodeName.rpartition("|")[2].split("_GRP_")[1].split("_")[0] imagePath = currentAssetLibrary smallImagesPath = currentImageLibrary for i in range(len(dirs)): if not os.path.isdir(smallImagesPath): os.mkdir(smallImagesPath) imagePath = os.path.join(imagePath, dirs[i]) smallImagesPath = os.path.join(smallImagesPath, dirs[i]) imagePath = "%s_%s.jpg" % (imagePath, version) smallImagesPath = "%s_%s.jpg" % (smallImagesPath, version) elif currentAssetCategory == "characters": nodeSplits = nodeName.split("_") for nodeSplit in nodeSplits: if nodeSplit in chesspieceTypes: divider = nodeSplit dirParts = nodeName.split("_%s" % divider)[0].split("_") imagePath = currentAssetLibrary smallImagesPath = currentImageLibrary dividerGRP = "%s_GRP" % divider version = nodeName.split("_%s_" % dividerGRP)[1].split("_")[0] for i in range(2): # eg bg (background) and buffalo if dirParts[i+1] in charType.keys(): dirs.append(charType[dirParts[i+1]]) elif re.search('^[A-Z]+', dirParts[i+1]): print '%s_%s' % (dirParts[i+1], dirParts[i+2]) dirs.append('%s_%s' % (dirParts[i+1], dirParts[i+2])) else: dirs.append(dirParts[i+1]) fileName = nodeName.rpartition("_%s" % dividerGRP)[0].replace("%s_%s_" % (dirParts[0], dirParts[1]), "") fileVersionName = "%s_%s_%s" % (fileName, divider, version) for i in range(len(dirs)): if not os.path.isdir(smallImagesPath): os.mkdir(smallImagesPath) imagePath = os.path.join(imagePath, dirs[i]) smallImagesPath = os.path.join(smallImagesPath, dirs[i]) imagePath = os.path.join(imagePath, "chesspiece", "published") imagePath = os.path.join(imagePath, "%s.jpg" % fileVersionName) smallImagesPath = os.path.join(smallImagesPath.rpartition(os.sep)[0], "%s.jpg" % fileVersionName) cmds.select(node, replace=True) currentPanel = "modelPanel4" if not cmds.modelEditor(currentPanel, exists=True): currentPanel = cmds.getPanel(withFocus=True) mel.eval('enableIsolateSelect %s true;' % currentPanel) cmds.isolateSelect(currentPanel, state=1) mel.eval('lookThroughModelPanel persp %s' % currentPanel) cmds.viewFit() if not currentAssetCategory == "characters": cmds.setAttr("perspShape.preScale", 1.5) nearClipPlane = cmds.getAttr("perspShape.nearClipPlane") farClipPlane = cmds.getAttr("perspShape.farClipPlane") cmds.setAttr("perspShape.nearClipPlane", 0.1) cmds.setAttr("perspShape.farClipPlane", 100000) cmds.select(clear=True) cmds.modelEditor(currentPanel, edit=True, displayAppearance="smoothShaded", displayTextures=True, displayLights="default") cmds.playblast( frame=1, format="image", completeFilename=smallImagesPath, clearCache=True, viewer=False, showOrnaments=False, compression="jpg", quality=40, percent=100, widthHeight=[144,144] ) cmds.playblast( frame=1, format="image", completeFilename=imagePath, clearCache=True, viewer=False, showOrnaments=False, compression="jpg", quality=40, percent=100, widthHeight=[1024,768] ) cmds.isolateSelect(currentPanel, state=0) cmds.setAttr("perspShape.preScale", 1.0) cmds.setAttr("perspShape.nearClipPlane", nearClipPlane) cmds.setAttr("perspShape.farClipPlane", farClipPlane) sys.stdout.write("Screen grab saved to: %s\n" % imagePath)