import os import subprocess import sys import time import telnetlib import socket from pyfbsdk import * from _winreg import * HOST = "localhost" PORT = 50000 DEVICENAME = "Faceware Retargeter" STANDALONGEXEPATH = "C:/Program Files/Faceware/Retargeter 4.0/MotionBuilder/2012(64)/FacewareRetargeter_GUI.exe" tn = telnetlib.Telnet() class RetargeterCommands: def __init__(self, standalongexepath = STANDALONGEXEPATH): # the GUID below is retrieved from the Application ID in InstallJammer aKey = OpenKey( HKEY_LOCAL_MACHINE, r"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\B9DABB7D-3E38-4320-AAE6-F3F277003AC6", 0, KEY_READ | KEY_WOW64_32KEY ) standalongexepath, type = QueryValueEx( aKey, "InstallLocation" ) standalongexepath = os.path.join( standalongexepath, 'FacewareRetargeter_GUI.exe' ) self._runstandalong(standalongexepath) self._adddevice() self._connect() # Run standalong is it hasn't run def _runstandalong(self, standalongexepath): processliststring = subprocess.Popen(["wmic", "process", "get", "executablepath"], stdout=subprocess.PIPE).stdout.read() processlist = [ x.strip().lower().replace("\\", "/") for x in processliststring.split("\n") ] if(standalongexepath.lower() not in processlist): subprocess.Popen(standalongexepath) # Add retarget device if not found def _adddevice(self): device = self._finddevice(DEVICENAME) if not device: device = FBCreateObject("Browsing/Templates/Devices", DEVICENAME, DEVICENAME) device.Online = True FBSystem().Scene.Devices.append(device) print DEVICENAME + " device added." else: print DEVICENAME + " device found." # Find retarget device def _finddevice(self, name): result = None devicelist = FBSystem().Scene.Devices if devicelist: for device in devicelist: if device.Name == name: result = device break return result # Connect to Mobu retarget GUI def _connect(self): global tn try: tn.open(HOST, PORT) except socket.error as detail: print detail # Send the command across the connection def _send(self, command, retry = 3): global tn if not (command.endswith("\n")): command = command + "\n" sent = False while (not sent) and (retry > 0): try: tn.read_very_eager() tn.write(command) sent = True except AttributeError as detail: self._connect() retry = retry - 1 if(retry == 0): print detail return sent # Receive response def _receive(self): try: result = tn.read_until("\n", 1) newline = False while(len(result) == 0): sys.stdout.write('.') newline = True time.sleep(1) result = tn.read_until("\n", 1) if newline: print "" result = result.strip() return result except Exception as detail: print detail return "0 " + str(detail) # Execute Mobu command in string def execute(self, command): global tn if not (command.endswith("\n")): command = command + "\n" if(self._send(command)): result = self._receive() #print result if(not bool(int(result[0]))): raise Exception(result[2:]) else: return result[2:] # addpose("Brows", 10, "PoseName") def addpose(self, posegroupname, sceneframenumber, posename): self.execute("ImAddPose " + "\"" + posegroupname + "\" " + "\"" + str(sceneframenumber) + "\" " + "\"" + posename + "\"") # addretargetrange("Brows", "Not All", "1-10") def addretargetrange(self, posegroupname, rangename, range): self.execute("ImAddRetargetRange " + "\"" + posegroupname + "\" " + "\"" + rangename + "\" " + "\"" + range + "\"") # addsharedpose("Brows", 0") def addsharedpose(self, posegroupname, sceneframenumber): self.execute("ImAddSharedPose " + "\"" + posegroupname + "\" " + "\"" + str(sceneframenumber)) # applysharedposetoscene("Brows", "Male2_Sports_Instructor_Line002_Andre_IM", 0) def applysharedposetoscene(self, posegroupname, jobname, framenumber): self.execute("ImApplySharedPoseToScene " + "\"" + posegroupname + "\" " + "\"" + jobname + "\" " + "\"" + str(framenumber) + "\"") # backup("FolderName") def backup(self, foldername): self.execute("ImBackup " + "\"" + foldername + "\"") # clearallkeys("Brows", "All Frames") def clearallkeys(self, posegroupname, rangename): self.execute("ImClearAllKeys " + "\"" + posegroupname + "\" " + "\"" + rangename + "\"") # compareimatoscene("Brows", "Brows_All Frames.ima") def compareimatoscene(self, posegroupname, filename): self.execute("ImCompareImaToScene " + "\"" + posegroupname + "\" " + "\"" + filename + "\"") # compareposestoposegroupfile("Brows", "Brows_All Frames.impd") def compareposestoposegroupfile(self, posegroupname, filename): self.execute("ImComparePosesToPoseGroupFile " + "\"" + posegroupname + "\" " + "\"" + filename + "\"") # compareposestoscene("Brows") def compareposestoscene(self, posegroupname): self.execute("ImComparePosesToScene " + "\"" + posegroupname + "\"") # copypose("Brows", 0, 10, "CopiedPose") def copypose(self, posegroupname, sceneframenumber, newframenumber, newposename): self.execute("ImCopyPose " + "\"" + posegroupname + "\" " + "\"" + str(sceneframenumber) + "\" " + "\"" + str(newframenumber) + "\" " + "\"" + newposename + "\"") # createnetworkdatabase("c:/test.db") def createnetworkdatabase(self, databasepath): self.execute("ImCreateNetworkDatabase " + "\"" + databasepath + "\"") # defaultcurrentframe("Brows") def defaultcurrentframe(self, posegroupname): self.execute("ImDefaultCurrentFrame " + "\"" + posegroupname + "\"") # deletepose("Brows", 10, False) def deletepose(self, posegroupname, sceneframenumber, deleteKeys = False): self.execute("ImDeletePose " + "\"" + posegroupname + "\" " + "\"" + str(sceneframenumber) + "\" " + "\"" + str(int(deleteKeys)) + "\"") # deleteretargetingrange def deleteretargetingrange(self, posegroupname, rangename): self.execute("ImDeleteRetargetingRange " + "\"" + posegroupname + "\" " + "\"" + rangename + "\"") # deletesharedpose def deletesharedpose(self, posegroupname, jobname, framenumber): self.execute("ImDeleteSharedPose " + "\"" + posegroupname + "\" " + "\"" + jobname + "\" " + "\"" + str(framenumber) + "\"") # editretargetingrange("Brows", "All Frames", "Not All", 0, 0, 0, "", "1-10", False, 1) def editretargetingrange(self, posegroupname, rangename, newrangename, pruning, prunebuffer, smoothing, mastercontrol, rangestr, useautosolve, poseweight): self.execute("ImEditRetargetingRange " + "\"" + posegroupname + "\" " + "\"" + rangename + "\" " + "\"" + newrangename + "\" " + "\"" + str(pruning) + "\" " + "\"" + str(prunebuffer) + "\" " + "\"" + str(smoothing) + "\" " + "\"" + mastercontrol + "\" " + "\"" + rangestr + "\" " + "\"" + str(int(useautosolve)) + "\" " + "\"" + str(poseweight) + "\"") # exportposegroupkeys("Brows", "c:/test.txt") def exportposegroupkeys(self, posegroupname, exportfileName): self.execute("ImExportPoseGroupKeys " + "\"" + posegroupname + "\" " + "\"" + exportfileName + "\"") # getautoposes("Brows", "All Frames", 3) def getautoposes(self, posegroupname, rangename, numposes): self.execute("ImGetAutoPoses " + "\"" + posegroupname + "\" " + "\"" + rangename + "\" " "\"" + str(numposes) + "\"") # getvalueorkeyvalue("testing", 0, False) def getvalueorkeyvalue(self, controlname, framenumber, iskeyvalue): self.execute("ImGetValueOrKeyValue " + "\"" + controlname + "\" " + "\"" + str(framenumber) + "\" " "\"" + str(int(iskeyvalue)) + "\"") # loadperformance(performanceFile, characterFile) def loadperformance(self, performanceFile, characterFile, setFrameRate = False, setPlaybackRange = False, importVideo = False, importAudio = False, generateAutoSolve = False): self.execute("ftiOpenPerformance " + "\"" + performanceFile + "\" " + "\"" + characterFile + "\" " + ("-SetFrameRate " if bool(setFrameRate) else "") + ("-SetPlaybackRange " if bool(setPlaybackRange) else "") + ("-ImportVideo " if bool(importVideo) else "") + ("-ImportAudio " if bool(importAudio) else "") + ("-GenerateAutoSolve " if bool(generateAutoSolve) else "")) # movepose("Brows", 0, 10, "CopiedPose") def movepose(self, posegroupname, sceneframenumber, newframenumber, newposename): self.execute("ImMovePose " + "\"" + posegroupname + "\" " + "\"" + str(sceneframenumber) + "\" " + "\"" + str(newframenumber) + "\" " + "\"" + newposename + "\"") # reloadretargetingresults("Brows", "All Frames") def reloadretargetingresults(self, posegroupname, rangename): self.execute("ImReloadRetargetingResults " + "\"" + posegroupname + "\" " + "\"" + rangename + "\"") # restore("Foldername") def restore(self, foldername): self.execute("ImRestore " + "\"" + foldername + "\"") # reverttoposes("Brows", "All Frames") def reverttoposes(self, posegroupname, rangename): self.execute("ImRevertToPoses " + "\"" + posegroupname + "\" " + "\"" + rangename + "\"") # rundiagnostics("c:/log.log", "1-10") def rundiagnostics(self, logfile, rangestr): self.execute("ImRunDiagnostics " + "\"" + logfile + "\" " + "\"" + rangestr + "\"") # runretargeting("Brows", "All Frames", 0, False) def runretargeting(self, posegroupname, rangename, selectedtype = 0, generateautosolve = False): print str(selectedtype) self.execute("ftiRetarget " + "\"" + posegroupname + "\" " + "\"" + rangename + "\" " + ("-UseSelectedControls " if (selectedtype != 0) else "") + "\"" + str(selectedtype) + "\" " + ("-GenerateAutoSolve " if bool(generateautosolve) else "")) # setnetworkdatabase("d:/Shared_Poses.imdb") def setnetworkdatabase(self, filename): self.execute("ImSetNetworkDatabase " + "\"" + filename + "\"") # setplaybackrange() def setplaybackrange(self): self.execute("ImSetPlaybackRange") # setposename("Brows", 1, "SetName") def setposename(self, posegroupname, sceneframenumber, newposename): self.execute("ImSetPoseName " + "\"" + posegroupname + "\" " + "\"" + str(sceneframenumber) + "\" " + "\"" + newposename + "\"") # setsceneframeoffset(1) def setsceneframeoffset(self, offset): self.execute("ImSetSceneFrameOffset " + "\"" + str(offset) + "\"") # setservices() def setservices(self): self.execute("ImSetServices " + "\"" + posegroupname + "\"") # updatepose("Brows", 0) def updatepose(self, posegroupname, sceneframenumber): self.execute("ImUpdatePose " + "\"" + posegroupname + "\" " + "\"" + str(sceneframenumber) + "\"") # updateposeselected("Brows", "All Frames", 0, True) def updateposeselected(self, posegroupname, rangename, sceneframenumber, isselected): self.execute("ImUpdatePoseSelected " + "\"" + posegroupname + "\" " + "\"" + rangename + "\" " + "\"" + str(sceneframenumber) + "\" " + "\"" + str(int(isselected)) + "\"") # updatesharedposes("Brows", "Eyes", "Mouth") def updatesharedposes(self, *poses): self.execute("ImUpdateSharedPoses " + "\"" + "\" \"".join(poses) + "\"") # updatesharedposeselected("Brows", "All Fraames", "Male2_Sports_Instructor_Line002_Andre_IM", 10, 0) def updatesharedposeselected(self, posegroupname, rangename, jobname, framenumber, isselected): self.execute("ImUpdateSharedPoseSelected " + "\"" + posegroupname + "\" " + "\"" + rangename + "\" " + "\"" + jobname + "\" " + "\"" + str(framenumber) + "\" " + "\"" + str(int(isselected)) + "\"")