349 lines
12 KiB
Python
Executable File
349 lines
12 KiB
Python
Executable File
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)) + "\"")
|
|
|