import os import sys import time import subprocess import crapQueueTools import crapLogger # Import FileTools and XmlTools from the MB folder drivePath = os.path.splitdrive(os.getcwd())[0] + os.path.sep mbframeCapPath = os.path.join(drivePath, "wildwest", "dcc", "motionbuilder2014", "python", "RS", "Core", "Automation", "FrameCapture") sys.path.append(mbframeCapPath) import CaptureModel as CaptureModel import FileTools import XmlTools # Set Constants NETWORKROOT = "N:" + os.path.sep PROJECTNAME = os.environ.get('RS_PROJECT').upper() CAPTUREROOT = os.path.join(NETWORKROOT, "RSGNYC", "Production", "CaptureRenders") REFRESHTIME = 10 JOBTIMEOUT = 3600 def SyncPathFromP4(p4Path): # Detect Folders and Update Path Accordingly if p4Path.endswith("/"): p4Path = p4Path[:-1] if "." not in p4Path.split("/")[-1]: p4Path += "/..." # Run Terminal Sync Command commandText = "p4 sync -f " + p4Path proc = subprocess.Popen(commandText, stdout=subprocess.PIPE) output, error = proc.communicate() def ProcessExportJob(jobXmlPath): # Create capObj Instance capObj = CaptureModel.MobuCaptureModel(jobXmlPath) capObj.UpdateTag("queueStartTime", str(os.path.getctime(jobXmlPath))) capObj.UpdateTime("prepStartTime") # Create Log logPath = os.path.split(jobXmlPath)[0] + os.path.sep + "exportJob.ulog" jobLog = crapLogger.Clog(capObj.projectName, logPath, appendToFile=False) jobLog.LogMessage("Capture initialized and log created.") # Set Standard Paths capObj.UpdateTag("fbxPath", os.path.normpath(capObj.perforceFbxPath)) capObj.UpdateTag("fbxName", os.path.splitext(os.path.split(capObj.fbxPath)[1])[0].upper()) capObj.UpdateTag("p4FbxPath", ("/" + capObj.fbxPath.replace("\\", "/")[2:]).replace("//gta5/", "//depot/gta5/")) capObj.UpdateTag("projectRoot", capObj.fbxPath.split("{0}{1}{0}".format(os.path.sep, "art"))[0]) capObj.UpdateTag("localCutsPath", os.path.join(capObj.projectRoot, "assets", "cuts", capObj.fbxName)) capObj.UpdateTag("perforceCutsPath", "/".join([capObj.p4FbxPath.split("/art/")[0], "assets", "cuts", capObj.fbxName])) capObj.UpdateTag("networkCutsPath", os.path.join(CAPTUREROOT, "ExportQueue", capObj.projectName, "cuts", capObj.fbxName)) # Old Tags - need to get removed/updated (along with fixing perforceFbxPath) capObj.UpdateTag("baseFolder", CAPTUREROOT + os.path.sep) capObj.UpdateTag("exportDataFolder", os.path.join(capObj.projectRoot, "build", "dev", "preview") + os.path.sep) capObj.UpdateTag("exportType", "Script Export") capObj.UpdateTag("cutFolder", capObj.localCutsPath + os.path.sep) # Sync / Setup Fbx and Cut Folders jobLog.LogMessage("Capture Type: " + capObj.captureType) if capObj.captureType != "FAST": jobLog.LogMessage("Syncing FBX from perforce.") SyncPathFromP4(capObj.p4FbxPath) # SyncPathFromP4(capObj.perforceCutsPath) else: jobLog.LogMessage("Verifying FBX folder for fast cap.") FileTools.CreateParentFolders(capObj.fbxPath) # Sync Latest Plugins jobLog.LogMessage("Syncing latest plugins from perforce.") perforceProjectRoot = capObj.p4FbxPath.split("/art/")[0] pluginsRoot = "/".join([perforceProjectRoot, "tools", "dcc", "current", "motionbuilder2014", "plugins", "x64"]) SyncPathFromP4("/".join([pluginsRoot, "3rdParty"])) SyncPathFromP4("/".join([pluginsRoot, "expressions"])) # Update mbStartTime and Status jobLog.LogMessage("Opening Motionbuilder and launching MB script.") capObj.UpdateTime("mbStartTime") capObj.UpdateTag("status", "LOAD FBX") # Open Up Motionbuilder and Run MB Script mobuExePath = r'C:\Program Files\Autodesk\MotionBuilder 2014\bin\x64\motionbuilder.exe' crapMbScriptPath = "X:\\wildwest\\script\\python\\standalone\\CaptureRender\\crapMBScript.py" mbAppFolder = "C:\\Program Files\\Autodesk\\MotionBuilder 2014\\" proc = subprocess.Popen('{0} -suspendMessages {1}'.format(mobuExePath, crapMbScriptPath), cwd=mbAppFolder) # Read Status / Wait for Timeout previousStatus = "" while True: status = XmlTools.ReadTagValueFromXmlPath(jobXmlPath, "status") if status != previousStatus: jobLog.LogMessage("MB Script Status: " + str(status)) previousStatus = status if status == "EXPORT SUCCESS" or status.startswith("EXPORT ERROR"): break if (time.time() - os.path.getmtime(jobXmlPath)) > JOBTIMEOUT: status = "EXPORT ERROR: Timeout during " + status.lower() jobLog.LogMessage("MB Script Status: " + str(status)) break time.sleep(5) # Detect Export Data Actually Built if (not os.path.exists(capObj.exportDataFolder)) or ( os.path.getmtime(capObj.exportDataFolder) < float(capObj.mbStartTime)): status = "EXPORT ERROR: No export data built." # Notify 'Operator' of Errors if status.startswith("EXPORT ERROR"): print "\n\n**** {} ****".format(status) issueMessage = "Fix the issue, rebuild, and press enter to continue. Otherwise close this window to exit." issuePause = raw_input(issueMessage + "\n") jobLog.LogMessage("Continuing after build issue pause.") # Create New capObj and Add exportFinishTime capObj = CaptureModel.MobuCaptureModel(jobXmlPath) capObj.UpdateTime("exportFinishTime") # More Old Tags - can't wait to get rid of these capObj.UpdateTag("exportStartRange", "0") capObj.UpdateTag("exportEndRange", capObj.endFrame) # Close Motionbuilder and Logs jobLog.LogMessage("Closing MB, Logs, and Build Monitor.") processList = ["motionbuilder.exe", "UniversalLogViewer.exe", "BuildMonitor.exe"] for eachProcess in processList: commandText = "taskkill /f /im " + eachProcess proc = subprocess.Popen(commandText, shell=True, stdout=subprocess.PIPE) time.sleep(5) # Delete Previous Capture Jobs jobLog.LogMessage("Deleting any matched capture job files.") capQueueFolder = os.path.join(CAPTUREROOT, "CaptureQueue", capObj.projectName) capJobXml = os.path.join(capQueueFolder, capObj.fbxName + ".xml") capJobData = os.path.join(capQueueFolder, capObj.fbxName) capCutData = os.path.join(capJobData, "cutData") FileTools.DeletePath(capJobXml) FileTools.DeletePath(capJobData) # Copy Export Data Folder jobLog.LogMessage("Copying export data to captureQueue.") FileTools.CopyFolderContents(capObj.exportDataFolder, capJobData) # Move TempCuts to Regular Cuts for Fast Caps if capObj.captureType == "FAST": cutsRoot = os.path.split(capObj.localCutsPath)[0] tempCutFolder = os.path.join(cutsRoot, "tempCuts", capObj.fbxName) FileTools.DeletePath(capObj.localCutsPath) FileTools.CopyPath(tempCutFolder, cutsRoot) # Copy Cut Folder jobLog.LogMessage("Copying cut data to captureQueue.") FileTools.CopyFolderContents(capObj.localCutsPath, capCutData) # Copy Log File jobLog.LogMessage("Copying log and xml file - job finished.") FileTools.CopyPath(logPath, capJobData) # Copy Xml File FileTools.CopyPath(jobXmlPath, capQueueFolder) def MonitorQueue(): queueFolder = os.path.join(CAPTUREROOT, "ExportQueue", PROJECTNAME) QueueManager = crapQueueTools.QueueManager(queueFolder) while True: jobXmlPath = QueueManager.SearchForJobs() # No Valid Jobs Found if jobXmlPath is None: print "\nNO QUEUE FILES FOUND" print "WAITING {} SECONDS".format(str(REFRESHTIME)) time.sleep(REFRESHTIME) continue # Valid Job Found print "\n\n===================================================" print "NOW Exporting: " + os.path.split(jobXmlPath)[1] print "===================================================" ProcessExportJob(jobXmlPath) MonitorQueue()