70 lines
3.5 KiB
Python
Executable File
70 lines
3.5 KiB
Python
Executable File
# This script will create an analysis actor that outputs curves
|
|
# for speech targets with a "Cartoon Coarticulation" model.
|
|
# There is no blending between targets, just an immediate ramp
|
|
# to the phoneme's mapped value. To use the script, set up your
|
|
# mapping from the Mapping tab how you want it, then run this
|
|
# script. Save the resulting actor in the "Analysis Actors"
|
|
# folder so you can use it as an analysis actor. If you do use
|
|
# the resulting analysis actor, make sure the actor you are using
|
|
# it on has a blank mapping, otherwise curves will be overdriven
|
|
# or overwritten with the default coarticulation results.
|
|
|
|
from FxStudio import *
|
|
import copy
|
|
|
|
phonemeMap = FxPhonemes.PhonemeMap()
|
|
|
|
class MappingPhoneme:
|
|
def __init__(self, name, visemeTable):
|
|
self.visemeTable = copy.deepcopy(visemeTable)
|
|
self.name = name
|
|
class MappingTable:
|
|
def __init__(self):
|
|
self.phonemes = []
|
|
phonemeMap = FxPhonemes.PhonemeMap()
|
|
visemeTable = {}
|
|
for entry in phonemeMap.entries:
|
|
visemeTable[entry.targetName] = 0
|
|
for entry in FxPhonemes.PHONEME_REGISTRY.entries:
|
|
self.phonemes.append(MappingPhoneme(entry.facefxCoding, visemeTable))
|
|
def addEntry(self, phonemeId, weight, target):
|
|
self.phonemes[phonemeId].visemeTable[target] = weight
|
|
|
|
|
|
|
|
# Create combiner nodes for all targets in mapping
|
|
visemeTable = {}
|
|
for entry in phonemeMap.entries:
|
|
visemeTable[entry.targetName] = 0
|
|
for key in visemeTable.keys():
|
|
# Below we assume that no targets are driven below -1000 or above 1000
|
|
FxStudio.issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "%s" -max "1000" -min "-1000";'%(key))
|
|
|
|
# The amount to shoft phonemes by.
|
|
timeshift = -.05
|
|
|
|
issueCommand('animGroup -create -group "_PhonemeEventGroup";');
|
|
issueCommand('animGroup -create -group "_NoScalePhonemeEventGroup";');
|
|
issueCommand('animGroup -create -group "_ShiftedPhonemeEventGroup";');
|
|
for entry in FxPhonemes.PHONEME_REGISTRY.entries:
|
|
issueCommand('anim -add -group "_PhonemeEventGroup" -name "%s";'%(entry.facefxCoding))
|
|
issueCommand('anim -add -group "_NoScalePhonemeEventGroup" -name "%s";'%(entry.facefxCoding))
|
|
issueCommand('anim -add -group "_ShiftedPhonemeEventGroup" -name "%s";'%(entry.facefxCoding))
|
|
# Remove Duration Scale
|
|
issueCommand('event -group "_PhonemeEventGroup" -anim "%s" -add -eventgroup "_NoScalePhonemeEventGroup" -eventanim "%s" -inheritdur "false";' % (entry.facefxCoding, entry.facefxCoding));
|
|
# Shift by timeshift. Use a very small duration so the phoneme transitions are instantaneous.
|
|
issueCommand('event -group "_NoScalePhonemeEventGroup" -anim "%s" -add -eventgroup "_ShiftedPhonemeEventGroup" -persist "true" -eventanim "%s" -duration ".001" -start %f' % (entry.facefxCoding, entry.facefxCoding, timeshift));
|
|
|
|
|
|
mapping = MappingTable()
|
|
for entry in phonemeMap.entries:
|
|
mapping.addEntry(entry.phonemeId, entry.mappingAmount, entry.targetName)
|
|
|
|
for phoneme in mapping.phonemes:
|
|
for key in phoneme.visemeTable.keys():
|
|
selectAnimation("_ShiftedPhonemeEventGroup", phoneme.name);
|
|
issueCommand('curve -group "_ShiftedPhonemeEventGroup" -anim "%s" -add -name "%s" -owner "user";'%(phoneme.name, key))
|
|
issueCommand('select -type "curve" -names "%s";'%(key))
|
|
issueCommand('key -insert -default -time "0" -value "%f";'%(phoneme.visemeTable[key]))
|
|
issueCommand('key -insert -default -time "1" -value "%f";'%(phoneme.visemeTable[key]))
|