835 lines
36 KiB
Python
Executable File
835 lines
36 KiB
Python
Executable File
#-------------------------------------------------------------------------------
|
|
# Create an analysis actor for generating events.
|
|
#
|
|
#
|
|
# Owner: Doug Perkowski
|
|
#
|
|
# Copyright (c) 2002-2011 OC3 Entertainment, Inc.
|
|
#-------------------------------------------------------------------------------
|
|
from FxStudio import *
|
|
from FxGestureShared import *
|
|
|
|
|
|
# The equals operator doesn't actually copy objects unless you use x = copy.deepcopy(y)
|
|
import copy
|
|
|
|
|
|
|
|
# An overall parameter to increase or decrease the speed of emphasis gestures
|
|
gcSpeed = 1.0
|
|
# An overall parameter to increase or decrease the intensity of emphasis gestures
|
|
gcMagnitude = 1.0
|
|
|
|
# In version 1.7, Emphasis and Orientation curves are spit out, and Eye output
|
|
# does not contain counter-movement for head rotations. It requires setup in the
|
|
# in-game actor, as opposed to putting that setup (and overhead) into the analysis
|
|
# actor where it won't impact performance or cause headaches when setting up.
|
|
version_17X_Compatible = getScriptSetting("gesturelib_version_17X_Compatible", "false")
|
|
|
|
# If you don't want gestures to insert keys at negative time,
|
|
# set noNegativeKeys to "true". The downside is that early
|
|
# gestures will not look as good if they are expressed at all.
|
|
# Also, early gestures may have a faster onset as suppression
|
|
# wears off, so you can't end the suppression too abruptly.
|
|
# Coarticulation curves from mapping may still create negative keys.
|
|
noNegativeKeys = getScriptSetting("gesturelib_noNegativeKeys", "false")
|
|
|
|
# The Normalized Power curve can be useful for opening the mouth wider
|
|
# on stresses syllables.
|
|
generateNormalizedPowerCurve = getScriptSetting("gesturelib_generateNormalizedPowerCurve", "false")
|
|
|
|
|
|
gestureLibName = "_HeadGestureLib"
|
|
issueCommand('animGroup -create -group "%s";'%(gestureLibName));
|
|
|
|
# Because this event group doesn't have an underscore, events from this group
|
|
# will be passed on from the analysis actor
|
|
#outputEventsGroup = "FxAnalysisEvents"
|
|
#issueCommand('animGroup -create -group "%s";'%(outputEventsGroup));
|
|
|
|
|
|
|
|
# A blank animation
|
|
EmptyAnim = Anim("Empty", gestureLibName);
|
|
|
|
AnimEventGroup = "_AnimEventGroup"
|
|
PhonemeEventGroup = "_PhonemeEventGroup"
|
|
StressEventGroup = "_StressEventGroup"
|
|
SilenceEventGroup = "_SilenceEventGroup"
|
|
# This group is for events we recognize in text tags.
|
|
TextEventGroup = "_TextEvents"
|
|
EmoticonEventGroup = "EmoticonEvents"
|
|
InternalEmoticonEventGroup = "_EmoticonEvents"
|
|
|
|
EmphasisHeadPitchName = "_Emphasis Head Pitch"
|
|
EmphasisHeadYawName = "_Emphasis Head Yaw"
|
|
EmphasisHeadRollName = "_Emphasis Head Roll"
|
|
OrientationHeadPitchName = "_Orientation Head Pitch"
|
|
OrientationHeadYawName = "_Orientation Head Yaw"
|
|
OrientationHeadRollName = "_Orientation Head Roll"
|
|
HeadPitchName = "Head Pitch"
|
|
HeadYawName = "Head Yaw"
|
|
HeadRollName = "Head Roll"
|
|
NeckPitchName = "Neck Pitch"
|
|
NeckYawName = "Neck Yaw"
|
|
NeckRollName = "Neck Roll"
|
|
EyeYawName = "_Eye Yaw"
|
|
EyePitchName = "_Eye Pitch"
|
|
EyeYawCombinedName = "Eye Yaw"
|
|
EyePitchCombinedName = "Eye Pitch"
|
|
SquintName = "Squint"
|
|
EyebrowRaiseName = "Eyebrow Raise"
|
|
BlinkName = "Blink"
|
|
# By changing the names, we can change what curves are output.
|
|
if version_17X_Compatible == "true":
|
|
EmphasisHeadPitchName = "Emphasis Head Pitch"
|
|
EmphasisHeadYawName = "Emphasis Head Yaw"
|
|
EmphasisHeadRollName = "Emphasis Head Roll"
|
|
OrientationHeadPitchName = "Orientation Head Pitch"
|
|
OrientationHeadYawName = "Orientation Head Yaw"
|
|
OrientationHeadRollName = "Orientation Head Roll"
|
|
HeadPitchName = "_Head Pitch"
|
|
HeadYawName = "_Head Yaw"
|
|
HeadRollName = "_Head Roll"
|
|
EyeYawName = "Gaze Eye Yaw"
|
|
EyePitchName = "Gaze Eye Pitch"
|
|
EyeYawCombinedName = "_IGNORE_Eye Yaw"
|
|
EyePitchCombinedName = "_IGNORE_Eye Pitch"
|
|
SquintName = "_IGNORE_Squint"
|
|
|
|
|
|
|
|
animGroups = [AnimEventGroup, PhonemeEventGroup, StressEventGroup, SilenceEventGroup, TextEventGroup, EmoticonEventGroup, InternalEmoticonEventGroup]
|
|
for group in animGroups:
|
|
issueCommand('animGroup -create -group "%s";'%(group));
|
|
|
|
|
|
AnimBegin = Anim("Anim_Begin", AnimEventGroup);
|
|
AnimEnd = Anim("Anim_End", AnimEventGroup);
|
|
|
|
headPitch = Anim(OrientationHeadPitchName, gestureLibName);
|
|
headYaw = Anim(OrientationHeadYawName, gestureLibName);
|
|
headRoll = Anim(OrientationHeadRollName, gestureLibName);
|
|
OrientationAnimations = [headPitch, headYaw, headRoll];
|
|
|
|
RandomOrientation = Anim("Random Orientation", gestureLibName);
|
|
|
|
|
|
OrientBlendin = .5
|
|
ZeroOrientation = Anim("Zero Orientation", gestureLibName);
|
|
ZeroOrientation.curves.append(OneSecondCurve("_Orientation_Correction",1));
|
|
ZeroOrientation.buildAnim()
|
|
ZeroOrientationEvent = Event(ZeroOrientation.name, ZeroOrientation.group)
|
|
ZeroOrientationEvent.persist = "true"
|
|
ZeroOrientationEvent.inheritdur = "false"
|
|
ZeroOrientationEvent.inheritmag = "false"
|
|
ZeroOrientationEvent.set_blendin(OrientBlendin)
|
|
ZeroOrientationEvent.set_blendout(OrientBlendin)
|
|
|
|
for anim in OrientationAnimations:
|
|
anim.curves.append(OneSecondCurve(anim.name,1));
|
|
anim.buildAnim()
|
|
|
|
# Head Pitch events are small and less likely because
|
|
# We move the head quite a bit in the pitch direction
|
|
# with emphasis events.
|
|
headPitchEvent = Event(headPitch.name, headPitch.group)
|
|
headPitchEvent.persist = "true"
|
|
headPitchEvent.minmagnitude = -1.5
|
|
headPitchEvent.maxmagnitude = 1.5
|
|
headPitchEvent.set_blendin(OrientBlendin)
|
|
headPitchEvent.set_blendout(OrientBlendin)
|
|
headPitchEvent.probability = .33
|
|
RandomOrientation.events.append(headPitchEvent)
|
|
|
|
headYawEvent = Event(headYaw.name, headYaw.group)
|
|
headYawEvent.persist = "true"
|
|
headYawEvent.minmagnitude = -2.5
|
|
headYawEvent.maxmagnitude = 2.5
|
|
headYawEvent.set_blendin(OrientBlendin)
|
|
headYawEvent.set_blendout(OrientBlendin)
|
|
headYawEvent.probability = .66
|
|
RandomOrientation.events.append(headYawEvent)
|
|
|
|
headRollEvent = Event(headRoll.name, headRoll.group)
|
|
headRollEvent.persist = "true"
|
|
headRollEvent.minmagnitude = -2.25
|
|
headRollEvent.maxmagnitude = 2.25
|
|
headRollEvent.set_blendin(OrientBlendin)
|
|
headRollEvent.set_blendout(OrientBlendin)
|
|
headRollEvent.probability = .66
|
|
RandomOrientation.events.append(headRollEvent)
|
|
|
|
RandomOrientation.buildAnim()
|
|
|
|
|
|
gazePitch = Anim(EyePitchName, gestureLibName);
|
|
gazeYaw = Anim(EyeYawName, gestureLibName);
|
|
RandomGaze = Anim("Random Gaze", gestureLibName)
|
|
GazeAnimations = [gazePitch, gazeYaw];
|
|
GazeMin = -1
|
|
GazeMax = 1
|
|
GazeProb = 1
|
|
GazeBlendin = .5
|
|
GazeDuration = .4
|
|
for anim in GazeAnimations:
|
|
anim.curves.append(OneSecondCurve(anim.name,1));
|
|
anim.buildAnim()
|
|
event = Event(anim.name, anim.group)
|
|
event.persist = "true"
|
|
event.inheritdur = "false"
|
|
event.inheritmag = "false"
|
|
event.minmagnitude = GazeMin
|
|
event.maxmagnitude = GazeMax
|
|
event.set_blendin(GazeBlendin)
|
|
event.set_blendout(GazeBlendin)
|
|
event.set_duration(GazeDuration)
|
|
event.probability = GazeProb
|
|
RandomGaze.events.append(event)
|
|
RandomGaze.buildAnim()
|
|
|
|
|
|
ZeroGaze = Anim("Zero Gaze", gestureLibName)
|
|
ZeroGaze.curves.append(OneSecondCurve("_Gaze_Correction",1));
|
|
ZeroGazeEvent = Event(ZeroGaze.name, ZeroGaze.group)
|
|
ZeroGazeEvent.persist = "true"
|
|
ZeroGazeEvent.inheritdur = "false"
|
|
ZeroGazeEvent.inheritmag = "false"
|
|
ZeroGazeEvent.set_blendin(GazeBlendin)
|
|
ZeroGazeEvent.set_blendout(GazeBlendin)
|
|
ZeroGaze.buildAnim()
|
|
|
|
# make sure very short files don't have blink that forces the animation to be longer.
|
|
ZeroBlink = Anim("Zero Blink", gestureLibName)
|
|
ZeroBlink.curves.append(OneSecondCurve("_Blink_Correction",1));
|
|
ZeroBlinkEvent = Event(ZeroBlink.name, ZeroBlink.group)
|
|
ZeroBlinkEvent.persist = "true"
|
|
ZeroBlinkEvent.set_blendin(.5)
|
|
ZeroBlinkEvent.set_blendout(.5)
|
|
ZeroBlinkEvent.inheritdur = "false"
|
|
ZeroBlinkEvent.inheritmag = "false"
|
|
ZeroBlinkEvent.set_duration(.4)
|
|
ZeroBlink.buildAnim()
|
|
|
|
# In most cases the final stress will close out the orientation shifts, but animations with
|
|
# only one stress will not have a final stress, so close out orientation shifts at AnimEnd.
|
|
AnimEnd.events.append(ZeroOrientationEvent)
|
|
AnimEnd.events.append(ZeroGazeEvent)
|
|
AnimEnd.events.append(ZeroBlinkEvent)
|
|
AnimEnd.buildAnim()
|
|
|
|
|
|
Squint = Anim("_Squint", gestureLibName);
|
|
SquintCurve = Curve("_Squint")
|
|
SquintCurve.keys.append(Key(gcSpeed *-.2867, 0));
|
|
SquintCurve.keys.append(Key(0, 1));
|
|
SquintCurve.keys.append(Key(gcSpeed *.5017, 0));
|
|
Squint.curves.append(SquintCurve);
|
|
|
|
|
|
EyebrowRaise = Anim("_Eyebrow Raise", gestureLibName);
|
|
EyebrowRaiseCurve = Curve("_Eyebrow Raise")
|
|
EyebrowRaiseCurve.keys.append(Key(gcSpeed *-.2867, 0));
|
|
EyebrowRaiseCurve.keys.append(Key(0, 1));
|
|
EyebrowRaiseCurve.keys.append(Key(gcSpeed *.5017, 0));
|
|
EyebrowRaise.curves.append(EyebrowRaiseCurve);
|
|
|
|
Blink = Anim("_Blink", gestureLibName);
|
|
BlinkCurve = Curve("_Blink");
|
|
BlinkCurve.keys.append(Key(-.125, 0));
|
|
BlinkCurve.keys.append(Key(0, 1));
|
|
BlinkCurve.keys.append(Key(.083, 0));
|
|
Blink.curves.append(BlinkCurve);
|
|
|
|
HeadNod = Anim(EmphasisHeadPitchName, gestureLibName);
|
|
HeadNodCurve = Curve(EmphasisHeadPitchName);
|
|
HeadNodCurve.keys.append(Key(gcSpeed * -.325, 0));
|
|
HeadNodCurve.keys.append(Key(0, 1));
|
|
HeadNodCurve.keys.append(Key(gcSpeed * .645, 0));
|
|
HeadNod.curves.append(HeadNodCurve);
|
|
|
|
HeadTilt = Anim(EmphasisHeadRollName, gestureLibName);
|
|
HeadTiltCurve = Curve(EmphasisHeadRollName);
|
|
HeadTiltCurve.keys.append(Key(gcSpeed * -.2867, 0));
|
|
HeadTiltCurve.keys.append(Key(0, 1));
|
|
HeadTiltCurve.keys.append(Key(gcSpeed * .645, 0));
|
|
HeadTilt.curves.append(HeadTiltCurve);
|
|
|
|
HeadTurn = Anim(EmphasisHeadYawName, gestureLibName);
|
|
HeadTurnCurve = Curve(EmphasisHeadYawName);
|
|
HeadTurnCurve.keys.append(Key(gcSpeed * -.2867, 0));
|
|
HeadTurnCurve.keys.append(Key(0, 1));
|
|
HeadTurnCurve.keys.append(Key(gcSpeed * .645, 0));
|
|
HeadTurn.curves.append(HeadTurnCurve);
|
|
|
|
EmphasisAnimations = [Squint, EyebrowRaise, Blink, HeadNod, HeadTilt, HeadTurn]
|
|
|
|
for anim in EmphasisAnimations:
|
|
anim.buildAnim()
|
|
|
|
# The end of a silence is a good place for an orientation shift as it
|
|
# can signify a change in thought. Long silences deliminate utterances
|
|
# and trigger Stress_Initial and Stress_Final stresses which are also
|
|
# good places for orientation shifts.
|
|
Silence_Medium = Anim("Silence_Medium", SilenceEventGroup);
|
|
|
|
orientationEvent = Event(RandomOrientation.name, RandomOrientation.group)
|
|
orientationEvent.probability = .8
|
|
orientationEvent.minstart = -.3
|
|
orientationEvent.maxstart = .3
|
|
orientationEvent.inheritdur = "false";
|
|
orientationEvent.inheritmag = "false";
|
|
orientationEvent.minduration = 1.5
|
|
orientationEvent.maxduration = 2
|
|
Silence_Medium.events.append(orientationEvent)
|
|
|
|
gazeEvent = Event(RandomGaze.name, RandomGaze.group)
|
|
gazeEvent.probability = .8
|
|
gazeEvent.minstart = .5
|
|
gazeEvent.maxstart = .9
|
|
gazeEvent.inheritdur = "false";
|
|
gazeEvent.inheritmag = "false";
|
|
Silence_Medium.events.append(gazeEvent)
|
|
|
|
Silence_Medium.buildAnim()
|
|
|
|
Silence_Short = Anim("Silence_Short", SilenceEventGroup);
|
|
Silence_Short.events.append(gazeEvent)
|
|
Silence_Short.buildAnim()
|
|
|
|
# We'll use a recursive anim to sprinkle blinks randomly throughout the
|
|
# animation. Blinks can also occur during a stress.
|
|
recursiveAnim = Anim("recursive", gestureLibName)
|
|
blinkEvent = Event(Blink.name, Blink.group)
|
|
blinkEvent.probability = .8
|
|
recursiveAnim.events.append(blinkEvent)
|
|
recursiveEvent = Event(recursiveAnim.name, recursiveAnim.group)
|
|
recursiveEvent.minstart = 4
|
|
recursiveEvent.maxstart = 6
|
|
recursiveAnim.events.append(recursiveEvent)
|
|
recursiveAnim.buildAnim();
|
|
|
|
|
|
# Don't start our recursive blinks until we are well into the audio..
|
|
recursiveEvent.minstart = 1
|
|
recursiveEvent.maxstart = 3
|
|
AnimBegin.events.append(recursiveEvent)
|
|
|
|
if noNegativeKeys == "true":
|
|
GestureSuppressionCurve = Curve("_Emphasis_Correction")
|
|
# Don't set the first key unreasonably far back...it will increase baking times.
|
|
GestureSuppressionCurve.keys.append(Key(-2, 1));
|
|
GestureSuppressionCurve.keys.append(Key(0, 1));
|
|
GestureSuppressionCurve.keys.append(Key(0.4, 0));
|
|
AnimBegin.curves.append(GestureSuppressionCurve);
|
|
AnimBegin.buildAnim();
|
|
|
|
# make sure very short files don't have blink that forces the animation to be longer.
|
|
BlinkCorrection = Anim("_Blink_Correction", gestureLibName)
|
|
BlinkCorrection.curves.append(OneSecondCurve("_Blink_Correction",1));
|
|
BlinkCorrection.buildAnim()
|
|
|
|
|
|
|
|
EmphasisBlinkProbability = .2;
|
|
|
|
SCMinStart = 0
|
|
SCMaxStart = 0
|
|
SCMinDur = 1 * gcSpeed
|
|
SCMaxDur = 1 * gcSpeed
|
|
SCMinMag = 1 * gcMagnitude
|
|
SCMaxMag = 1 * gcMagnitude
|
|
|
|
|
|
# To compliment head movements, we can either squint or raise eyebrows, but not both.
|
|
EyebrowSquintPick1 = Anim("EyebrowSquintPick1", gestureLibName)
|
|
EyebrowSquintPick1.groupChildEvents = "true"
|
|
eyebrowEvent = Event(EyebrowRaise.name, EyebrowRaise.group )
|
|
eyebrowEvent.probability = .7
|
|
eyebrowEvent.minstart = SCMinStart
|
|
eyebrowEvent.maxstart = SCMaxStart
|
|
eyebrowEvent.minduration = SCMinDur
|
|
eyebrowEvent.maxduration = SCMaxDur
|
|
eyebrowEvent.minmagnitude = SCMinMag *.3
|
|
eyebrowEvent.maxmagnitude = SCMaxMag *.6
|
|
eyebrowEvent.weight = 2
|
|
EyebrowSquintPick1.events.append(eyebrowEvent)
|
|
squintEvent = copy.deepcopy(eyebrowEvent)
|
|
squintEvent.name = Squint.name
|
|
squintEvent.minmagnitude = SCMinMag * .3
|
|
squintEvent.maxmagnitude = SCMaxMag * .5
|
|
squintEvent.probability = .5
|
|
squintEvent.weight = 1
|
|
EyebrowSquintPick1.events.append(squintEvent)
|
|
EyebrowSquintPick1.buildAnim()
|
|
|
|
EyebrowSquintPick1Event = Event(EyebrowSquintPick1.name, EyebrowSquintPick1.group)
|
|
BlinkEvent = Event(Blink.name, Blink.group)
|
|
BlinkEvent.probability = .05
|
|
|
|
|
|
SC_Initial = Anim("Stress_Initial", StressEventGroup)
|
|
SC_Quick = Anim("Stress_Quick", StressEventGroup)
|
|
SC_Normal = Anim("Stress_Normal", StressEventGroup)
|
|
SC_Isolated = Anim("Stress_Isolated", StressEventGroup)
|
|
SC_Final = Anim("Stress_Final", StressEventGroup)
|
|
|
|
|
|
#Close out the Orientation and Gaze at the final stress.
|
|
SC_Final.events.append(ZeroOrientationEvent);
|
|
SC_Final.events.append(ZeroGazeEvent)
|
|
|
|
# Start our gestures off with an orientation shift, but a smaller one than
|
|
# usual as we are also going to have Emphasis movement.
|
|
orientationEvent.set_magnitude(.7)
|
|
orientationEvent.minstart = 0
|
|
orientationEvent.maxstart = 0
|
|
SC_Initial.events.append(orientationEvent);
|
|
|
|
ActivateOrientation =copy.deepcopy(ZeroOrientationEvent);
|
|
ActivateOrientation.set_magnitude(0)
|
|
ActivateOrientation.set_start(-ActivateOrientation.maxblendin)
|
|
ActivateGaze =copy.deepcopy(ZeroGazeEvent);
|
|
ActivateGaze.set_magnitude(0)
|
|
ActivateGaze.set_start(-ActivateGaze.maxblendin)
|
|
SC_Initial.events.append(ActivateOrientation);
|
|
SC_Initial.events.append(ActivateGaze);
|
|
|
|
StrongHeadNodEvent = Event(HeadNod.name, HeadNod.group)
|
|
StrongHeadNodEvent.minstart = SCMinStart
|
|
StrongHeadNodEvent.maxstart = SCMaxStart
|
|
StrongHeadNodEvent.minduration = SCMinDur
|
|
StrongHeadNodEvent.maxduration = SCMaxDur
|
|
StrongHeadNodEvent.minmagnitude = 4 * SCMinMag
|
|
StrongHeadNodEvent.maxmagnitude = 4 * SCMaxMag
|
|
|
|
InvertedHeadNodEvent = Event(HeadNod.name, HeadNod.group)
|
|
InvertedHeadNodEvent.minstart = SCMinStart
|
|
InvertedHeadNodEvent.maxstart = SCMaxStart
|
|
InvertedHeadNodEvent.minduration = 1.2 * SCMinDur
|
|
InvertedHeadNodEvent.maxduration = 1.2 * SCMaxDur
|
|
InvertedHeadNodEvent.minmagnitude = -2.4 * SCMinMag
|
|
InvertedHeadNodEvent.maxmagnitude = -2.4 * SCMaxMag
|
|
|
|
NormalHeadNodEvent = Event(HeadNod.name, HeadNod.group)
|
|
NormalHeadNodEvent.minstart = SCMinStart
|
|
NormalHeadNodEvent.maxstart = SCMaxStart
|
|
NormalHeadNodEvent.minduration = 1.2 * SCMinDur
|
|
NormalHeadNodEvent.maxduration = 1.2 * SCMaxDur
|
|
NormalHeadNodEvent.minmagnitude = 2.4 * SCMinMag
|
|
NormalHeadNodEvent.maxmagnitude = 2.4 * SCMaxMag
|
|
|
|
QuickHeadNodEvent = Event(HeadNod.name, HeadNod.group)
|
|
QuickHeadNodEvent.minstart = SCMinStart
|
|
QuickHeadNodEvent.maxstart = SCMaxStart
|
|
QuickHeadNodEvent.minduration = .8 * SCMinDur
|
|
QuickHeadNodEvent.maxduration = .8 * SCMaxDur
|
|
QuickHeadNodEvent.minmagnitude = 1.6 * SCMinMag
|
|
QuickHeadNodEvent.maxmagnitude = 1.6 * SCMaxMag
|
|
|
|
QuickInvertedNodEvent = Event(HeadNod.name, HeadNod.group)
|
|
QuickInvertedNodEvent.minstart = SCMinStart
|
|
QuickInvertedNodEvent.maxstart = SCMaxStart
|
|
QuickInvertedNodEvent.minduration = .8 * SCMinDur
|
|
QuickInvertedNodEvent.maxduration = .8 * SCMaxDur
|
|
QuickInvertedNodEvent.minmagnitude = -1.6 * SCMinMag
|
|
QuickInvertedNodEvent.maxmagnitude = -1.6 * SCMaxMag
|
|
|
|
|
|
EmptyEvent = Event(EmptyAnim.name, EmptyAnim.group)
|
|
|
|
HeadTiltEvent = Event(HeadTilt.name, HeadTilt.group)
|
|
HeadTiltEvent.minstart = SCMinStart
|
|
HeadTiltEvent.maxstart = SCMaxStart
|
|
HeadTiltEvent.minduration = SCMinDur
|
|
HeadTiltEvent.maxduration = SCMaxDur
|
|
HeadTiltEvent.minmagnitude = 1.6 * SCMinMag
|
|
HeadTiltEvent.maxmagnitude = 1.6 * SCMaxMag
|
|
|
|
NegHeadTiltEvent = Event(HeadTilt.name, HeadTilt.group)
|
|
NegHeadTiltEvent.minstart = SCMinStart
|
|
NegHeadTiltEvent.maxstart = SCMaxStart
|
|
NegHeadTiltEvent.minduration = SCMinDur
|
|
NegHeadTiltEvent.maxduration = SCMaxDur
|
|
NegHeadTiltEvent.minmagnitude = -1.6 * SCMinMag
|
|
NegHeadTiltEvent.maxmagnitude = -1.6 * SCMaxMag
|
|
|
|
HeadTurnEvent = Event(HeadTurn.name, HeadTurn.group)
|
|
HeadTurnEvent.minstart = SCMinStart
|
|
HeadTurnEvent.maxstart = SCMaxStart
|
|
HeadTurnEvent.minduration = SCMinDur
|
|
HeadTurnEvent.maxduration = SCMaxDur
|
|
HeadTurnEvent.minmagnitude = 1.6 * SCMinMag
|
|
HeadTurnEvent.maxmagnitude = 1.6 * SCMaxMag
|
|
|
|
NegHeadTurnEvent = Event(HeadTurn.name, HeadTurn.group)
|
|
NegHeadTurnEvent.minstart = SCMinStart
|
|
NegHeadTurnEvent.maxstart = SCMaxStart
|
|
NegHeadTurnEvent.minduration = SCMinDur
|
|
NegHeadTurnEvent.maxduration = SCMaxDur
|
|
NegHeadTurnEvent.minmagnitude = -1.6 * SCMinMag
|
|
NegHeadTurnEvent.maxmagnitude = -1.6 * SCMaxMag
|
|
|
|
# An convenient event for any stress
|
|
SC_ALL = Anim("Stress_All", StressEventGroup)
|
|
SC_ALL.events.append(EyebrowSquintPick1Event)
|
|
SC_ALL.events.append(BlinkEvent)
|
|
SC_ALL.buildAnim()
|
|
SC_ALL_Event = Event(SC_ALL.name, SC_ALL.group)
|
|
|
|
StressCtgries = [SC_Initial, SC_Quick, SC_Normal, SC_Isolated, SC_Final]
|
|
|
|
pick1Anims = []
|
|
for sc in StressCtgries:
|
|
pick1Anim = Anim(sc.name + "_Pick1", gestureLibName)
|
|
pick1Anim.groupChildEvents = "true"
|
|
pick1AnimEvent = Event(pick1Anim.name, pick1Anim.group)
|
|
pick1Anim.group = gestureLibName
|
|
pick1Anims.append(pick1Anim)
|
|
sc.events.append(pick1AnimEvent)
|
|
sc.events.append(SC_ALL_Event)
|
|
sc.buildAnim()
|
|
|
|
|
|
EAs = [StrongHeadNodEvent, InvertedHeadNodEvent, QuickHeadNodEvent, NormalHeadNodEvent, EmptyEvent, HeadTiltEvent, NegHeadTiltEvent, HeadTurnEvent, NegHeadTurnEvent]
|
|
|
|
# SC_Initial
|
|
weights = [.33,.17,.03,.13,.1,.05,.05,.06,.06]
|
|
i = 0
|
|
for EA in EAs:
|
|
EA.weight = weights[i]
|
|
pick1Anims[0].events.append(EA)
|
|
i += 1
|
|
pick1Anims[0].buildAnim()
|
|
|
|
# SC_Quick
|
|
weights = [0,.1,.3,.09,.2,.1,.1,.1,.1]
|
|
i = 0
|
|
for EA in EAs:
|
|
EA.weight = weights[i]
|
|
pick1Anims[1].events.append(EA)
|
|
i += 1
|
|
pick1Anims[1].buildAnim()
|
|
|
|
# SC_Normal
|
|
weights = [.04,.14,.1,.36,.1,.075,.075,.075,.075]
|
|
i = 0
|
|
for EA in EAs:
|
|
EA.weight = weights[i]
|
|
pick1Anims[2].events.append(EA)
|
|
i += 1
|
|
pick1Anims[2].buildAnim()
|
|
|
|
# SC_Isolated
|
|
weights = [.23,.20,.1,.17,.1,.05,.05,.05,.05]
|
|
i = 0
|
|
for EA in EAs:
|
|
EA.weight = weights[i]
|
|
pick1Anims[3].events.append(EA)
|
|
i += 1
|
|
pick1Anims[3].buildAnim()
|
|
|
|
# SC_Final
|
|
weights = [.33,.10,.07,.24,.15,.015,.015,.035,.035]
|
|
i = 0
|
|
for EA in EAs:
|
|
EA.weight = weights[i]
|
|
pick1Anims[4].events.append(EA)
|
|
i += 1
|
|
pick1Anims[4].buildAnim()
|
|
|
|
emoticonSupport = "true"
|
|
EmoticonNodePrefix = "_Emoticon "
|
|
# Emoticons
|
|
# The emoticon system allows the artist to use combinations of punctuation markers
|
|
# to trigger animations. The below emoticons
|
|
if emoticonSupport == "true" and version_17X_Compatible == "false":
|
|
emotions = [["happy", ":)"], ["sad", ":("], ["angry", ";("], ["surprised", ":@"]]
|
|
for emotion in emotions:
|
|
emotionAnim = Anim(emotion[0], InternalEmoticonEventGroup)
|
|
emoticonAnim = Anim(emotion[1], EmoticonEventGroup)
|
|
emotionAnim.curves.append(OneSecondCurve(emotion[0],1))
|
|
emotionAnimEvent = Event(emotion[0], InternalEmoticonEventGroup);
|
|
emotionAnimEvent.set_blendin(.2)
|
|
emotionAnimEvent.set_blendout(.2)
|
|
emotionAnimEvent.blendunscaled = "true"
|
|
emoticonAnim.events.append(emotionAnimEvent)
|
|
emoticonAnim.buildAnim()
|
|
emotionAnim.buildAnim()
|
|
|
|
# __ emoticon turns off speech gestures
|
|
emphasisCorrectionAnim = Anim("_Emphasis_Correction", InternalEmoticonEventGroup)
|
|
emphasisCorrectionAnim.curves.append(OneSecondCurve("_Emphasis_Correction", 1))
|
|
emphasisCorrectionAnim.buildAnim()
|
|
emphasisCorrectionEvent = Event(emphasisCorrectionAnim.name, emphasisCorrectionAnim.group)
|
|
# This needs to be very slow, otherwise if can cause jerkey animation
|
|
emphasisCorrectionEvent.set_blendin(1)
|
|
emphasisCorrectionEvent.set_blendin(1)
|
|
emphasisCorrectionEvent.blendunscaled = "true"
|
|
emoticonAnim = Anim("__", EmoticonEventGroup)
|
|
emoticonAnim.events.append(emphasisCorrectionEvent)
|
|
emoticonAnim.buildAnim()
|
|
|
|
oneSecondEmoticonAnimNames = [HeadPitchName, HeadYawName, HeadRollName, EyePitchCombinedName, EyeYawCombinedName, SquintName, EyebrowRaiseName, BlinkName, "_Emphasis_Correction"]
|
|
for oneSecondEmoticonAnimName in oneSecondEmoticonAnimNames:
|
|
oneSecondEmoticonAnim = Anim(EmoticonNodePrefix + oneSecondEmoticonAnimName, InternalEmoticonEventGroup)
|
|
oneSecondEmoticonAnim.curves.append(OneSecondCurve(EmoticonNodePrefix + oneSecondEmoticonAnimName, 1))
|
|
oneSecondEmoticonAnim.buildAnim()
|
|
|
|
# %^ look away up
|
|
# %- look away right
|
|
# -% look away left
|
|
# %_ look away down
|
|
# emoticon name, eye-yaw magnitude, eye-pitch magnitude
|
|
lookaways = [["%^",0,-20], ["%-",20,0], ["-%",-20, 0], ["%_", 0, 20]];
|
|
for lookaway in lookaways:
|
|
emoticonAnim = Anim(lookaway[0], EmoticonEventGroup)
|
|
EmoticonEyePitchEvent = Event( EmoticonNodePrefix + EyePitchCombinedName ,InternalEmoticonEventGroup)
|
|
EmoticonEyePitchEvent.set_magnitude(lookaway[2])
|
|
EmoticonEyePitchEvent.set_blendin(.2)
|
|
EmoticonEyePitchEvent.set_blendout(.2)
|
|
EmoticonEyePitchEvent.blendunscaled = "true"
|
|
emoticonAnim.events.append(EmoticonEyePitchEvent)
|
|
EmoticonEyeYawEvent = Event( EmoticonNodePrefix + EyeYawCombinedName ,InternalEmoticonEventGroup)
|
|
EmoticonEyeYawEvent.set_magnitude(lookaway[1])
|
|
EmoticonEyeYawEvent.set_blendin(.2)
|
|
EmoticonEyeYawEvent.set_blendout(.2)
|
|
EmoticonEyeYawEvent.blendunscaled = "true"
|
|
emoticonAnim.events.append(EmoticonEyeYawEvent)
|
|
emoticonAnim.buildAnim()
|
|
|
|
|
|
# #- head turn right
|
|
# -# head turn left
|
|
# #^ head turn up
|
|
# #_ head turn down
|
|
# =# head roll right
|
|
# #= head roll left
|
|
|
|
headturns = [["#^",0,-10, 0], ["#-",10,0, 0], ["-#",-10, 0, 0], ["#_", 0, 10, 0], ["#=", 0, 0, 10], ["=#", 0, 0, -10]];
|
|
for headturn in headturns:
|
|
emoticonAnim = Anim(headturn[0], EmoticonEventGroup)
|
|
EmoticonHeadPitchEvent = Event( EmoticonNodePrefix + HeadPitchName ,InternalEmoticonEventGroup)
|
|
EmoticonHeadPitchEvent.set_magnitude(headturn[2])
|
|
EmoticonHeadPitchEvent.set_blendin(.5)
|
|
EmoticonHeadPitchEvent.set_blendout(.5)
|
|
EmoticonHeadPitchEvent.blendunscaled = "true"
|
|
emoticonAnim.events.append(EmoticonHeadPitchEvent)
|
|
|
|
EmoticonHeadYawEvent = Event( EmoticonNodePrefix + HeadYawName,InternalEmoticonEventGroup)
|
|
EmoticonHeadYawEvent.set_magnitude(headturn[1])
|
|
EmoticonHeadYawEvent.set_blendin(.5)
|
|
EmoticonHeadYawEvent.set_blendout(.5)
|
|
EmoticonHeadYawEvent.blendunscaled = "true"
|
|
emoticonAnim.events.append(EmoticonHeadYawEvent)
|
|
|
|
EmoticonHeadRollEvent = Event( EmoticonNodePrefix + HeadRollName ,InternalEmoticonEventGroup)
|
|
EmoticonHeadRollEvent.set_magnitude(headturn[3])
|
|
EmoticonHeadRollEvent.set_blendin(.5)
|
|
EmoticonHeadRollEvent.set_blendout(.5)
|
|
EmoticonHeadRollEvent.blendunscaled = "true"
|
|
emoticonAnim.events.append(EmoticonHeadRollEvent)
|
|
|
|
emoticonAnim.buildAnim()
|
|
# emoticon, eyebrow, squint
|
|
# @@ wide eyes
|
|
# -- squint
|
|
# (& eyebrows up
|
|
# )& eyebrows down
|
|
eyeAnims = [["(&", .8, 0], [")&", -.8, 0], ["@@", .5, -.5], ["--", -.2, .5] ]
|
|
for eyeAnim in eyeAnims:
|
|
emoticonAnim = Anim(eyeAnim[0], EmoticonEventGroup)
|
|
EmoticonEyebrowEvent = Event( EmoticonNodePrefix + EyebrowRaiseName ,InternalEmoticonEventGroup)
|
|
EmoticonEyebrowEvent.set_magnitude(eyeAnim[1])
|
|
EmoticonEyebrowEvent.set_blendin(.3)
|
|
EmoticonEyebrowEvent.set_blendout(.3)
|
|
EmoticonEyebrowEvent.blendunscaled = "true"
|
|
emoticonAnim.events.append(EmoticonEyebrowEvent)
|
|
|
|
EmoticonSquintEvent = Event( EmoticonNodePrefix + SquintName ,InternalEmoticonEventGroup)
|
|
EmoticonSquintEvent.set_magnitude(eyeAnim[2])
|
|
EmoticonSquintEvent.set_blendin(.3)
|
|
EmoticonSquintEvent.set_blendout(.3)
|
|
EmoticonSquintEvent.blendunscaled = "true"
|
|
emoticonAnim.events.append(EmoticonSquintEvent)
|
|
emoticonAnim.buildAnim()
|
|
# FaceFX Studio can insert text tags when certain words are spoken. Inserting a
|
|
# "Negative" event when a negative word is spoken looks good if the negative word
|
|
# triggers a head shake. We supress normal based gestures when we do this.
|
|
# You need to set up a analysis text preprocessor python callback to make use of
|
|
# this. Also, it requires modifications to work with 1.7.X compatible setups,
|
|
# becuase it keys the "Head Yaw" curve directly.
|
|
textTagEvents = "true"
|
|
if textTagEvents == "true" and version_17X_Compatible == "false":
|
|
# We don't want the head shake geting suppressed along with the normal gestures,
|
|
# So key the output curve directly.
|
|
headShakeAnim = Anim(HeadYawName, TextEventGroup)
|
|
headShakeCurve = Curve(HeadYawName)
|
|
# Don't set the first key unreasonably far back...it will increase baking times.
|
|
headShakeCurve.keys.append(Key(-.2, 0));
|
|
headShakeCurve.keys.append(Key(0, 2.5));
|
|
headShakeCurve.keys.append(Key(.2, 0));
|
|
headShakeAnim.curves.append(headShakeCurve);
|
|
orientationEvent.set_start(-.15)
|
|
headShakeAnim.events.append( orientationEvent )
|
|
headShakeAnim.buildAnim()
|
|
|
|
emphasisCorrectionAnim = Anim("_Emphasis_Correction", TextEventGroup)
|
|
emphasisCorrectionCurve = Curve("_Emphasis_Correction")
|
|
# Don't set the first key unreasonably far back...it will increase baking times.
|
|
emphasisCorrectionCurve.keys.append(Key(-.5, 0));
|
|
emphasisCorrectionCurve.keys.append(Key(-.15, 1));
|
|
emphasisCorrectionCurve.keys.append(Key(.15, 1));
|
|
emphasisCorrectionCurve.keys.append(Key(.5, 0));
|
|
emphasisCorrectionAnim.curves.append(emphasisCorrectionCurve);
|
|
emphasisCorrectionAnim.buildAnim()
|
|
emphasisCorrectionEvent = Event(emphasisCorrectionAnim.name, emphasisCorrectionAnim.group)
|
|
emphasisCorrectionEvent.inheritmag = "false"
|
|
|
|
headShakeEvent = Event(headShakeAnim.name, headShakeAnim.group)
|
|
headShakePosNegAnim = Anim("Head Yaw PosNeg", TextEventGroup)
|
|
headShakePosNegAnim.groupChildEvents = "true"
|
|
headShakePosNegAnim.events.append(headShakeEvent);
|
|
inverseHeadShakeEvent = copy.deepcopy(headShakeEvent);
|
|
inverseHeadShakeEvent.set_magnitude(-1);
|
|
headShakePosNegAnim.events.append(inverseHeadShakeEvent);
|
|
headShakePosNegAnim.buildAnim()
|
|
headShakePosNegAnimEvent = Event(headShakePosNegAnim.name, headShakePosNegAnim.group)
|
|
|
|
negativeHeadShakeAnim = Anim("Negative Head Shake", TextEventGroup);
|
|
negativeHeadShakeAnim.events.append(emphasisCorrectionEvent);
|
|
negativeHeadShakeAnim.events.append(Event(headShakePosNegAnimEvent.name, headShakePosNegAnimEvent.group));
|
|
negativeHeadShakeAnim.buildAnim()
|
|
negativeHeadShakeEvent = Event(negativeHeadShakeAnim.name, negativeHeadShakeAnim.group)
|
|
|
|
# Make a copy of some other events, but make them act on the output nodes, not
|
|
# on the ones that are supressed with _Emphasis_Correction
|
|
EyebrowSquintPick1_noCorrection = copy.deepcopy(EyebrowSquintPick1)
|
|
EyebrowRaise_noCorrection = copy.deepcopy(EyebrowRaise)
|
|
Squint_noCorrection = copy.deepcopy(Squint)
|
|
copyanims = [EyebrowRaise_noCorrection, Squint_noCorrection, EyebrowSquintPick1_noCorrection]
|
|
for anim in copyanims:
|
|
anim.name = anim.name.lstrip('_')
|
|
anim.group = TextEventGroup
|
|
issueCommand('anim -add -group "%s" -name "%s";'%(anim.group, anim.name))
|
|
for curve in anim.curves:
|
|
curve.name = curve.name.lstrip('_')
|
|
for event in anim.events:
|
|
event.name = event.name.lstrip('_')
|
|
event.group = TextEventGroup
|
|
anim.buildAnim()
|
|
|
|
# Add some variability
|
|
negativeHeadShakeEvent.minstart = -.1
|
|
negativeHeadShakeEvent.maxstart = .1
|
|
negativeHeadShakeEvent.minduration = .9
|
|
negativeHeadShakeEvent.maxduration = 1.1
|
|
negativeHeadShakeEvent.minmagnitude = .9
|
|
negativeHeadShakeEvent.maxmagnitude = 1.1
|
|
EyebrowSquintPick1_noCorrectionEvent = Event(EyebrowSquintPick1_noCorrection.name, EyebrowSquintPick1_noCorrection.group)
|
|
EyebrowSquintPick1_noCorrectionEvent.minstart = -.1
|
|
EyebrowSquintPick1_noCorrectionEvent.maxstart = .1
|
|
EyebrowSquintPick1_noCorrectionEvent.minduration = .9
|
|
EyebrowSquintPick1_noCorrectionEvent.maxduration = 1.1
|
|
EyebrowSquintPick1_noCorrectionEvent.minmagnitude = .9
|
|
EyebrowSquintPick1_noCorrectionEvent.maxmagnitude = 1.1
|
|
negativeAnim = Anim("Negative", TextEventGroup)
|
|
negativeAnim.events.append(EyebrowSquintPick1_noCorrectionEvent);
|
|
negativeAnim.events.append(negativeHeadShakeEvent);
|
|
negativeAnim.buildAnim()
|
|
|
|
|
|
issueCommand('batch;')
|
|
|
|
rotationOutputCurves = [HeadPitchName, HeadRollName, HeadYawName, NeckPitchName, NeckRollName, NeckYawName, EyePitchCombinedName, EyeYawCombinedName]
|
|
eyeOutputCurves = [EyebrowRaiseName, BlinkName, SquintName]
|
|
emotionOutputCurves = ["happy", "sad", "angry", "surprised"]
|
|
|
|
|
|
# We can run this script on an existing actor to use it in conjunction with the <Events Only> analysis actor.
|
|
# In this scenario, we'll skip the creation of the output combiner nodes because we assume they exist in the actor
|
|
# If they don't exist in the actor, this script will output errors at the very end.
|
|
if getNumFaceGraphNodes() == 0:
|
|
for curve in rotationOutputCurves:
|
|
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "%s" -min -30 -max 30;'%(curve))
|
|
for curve in eyeOutputCurves:
|
|
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "%s" -min -1 -max 1;'%(curve))
|
|
for curve in emotionOutputCurves:
|
|
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "%s" -min 0 -max 1;'%(curve))
|
|
|
|
if generateNormalizedPowerCurve == "true":
|
|
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "_Analysis_Normalized_Power"')
|
|
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "Normalized Power"')
|
|
# FaceFX does a poor job baking the Normalized power curve (or any jittery curve), so create
|
|
# create a small face graph setup to remove useless keys by ensuring that all values below .01 are
|
|
# forced to 0.
|
|
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "_reduce0keysAdd"')
|
|
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "_reduce0keys"')
|
|
issueCommand('graph -link -from "_Analysis_Normalized_Power" -to "_reduce0keysAdd" -linkfn "clamped linear" -linkfnparams "m=1000|clampx=0.010000|clampy=0.010000|clampdir=-1.000000"')
|
|
issueCommand('graph -link -from "_Analysis_Normalized_Power" -to "_reduce0keys" -linkfn "linear" -linkfnparams "m=1.000000|b=-0.010000"')
|
|
issueCommand('graph -link -from "_reduce0keys" -to "Normalized Power" -linkfn "linear"')
|
|
issueCommand('graph -link -from "_reduce0keysAdd" -to "Normalized Power" -linkfn "linear"')
|
|
|
|
|
|
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "%s" -min -10 -max 10;'%(OrientationHeadPitchName))
|
|
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "%s" -min -10 -max 10;'%(OrientationHeadRollName))
|
|
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "%s" -min -10 -max 10;'%(OrientationHeadYawName))
|
|
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "%s" -min -10 -max 10;'%(EmphasisHeadPitchName))
|
|
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "%s" -min -10 -max 10;'%(EmphasisHeadRollName))
|
|
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "%s" -min -10 -max 10;'%(EmphasisHeadYawName))
|
|
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "%s" -min -10 -max 10;'%(EyePitchName))
|
|
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "%s" -min -10 -max 10;'%(EyeYawName))
|
|
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "_Eyebrow Raise";')
|
|
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "_Blink";')
|
|
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "_Squint";')
|
|
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "_All_Correction";')
|
|
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "_Emphasis_Correction";')
|
|
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "_Blink_Correction";')
|
|
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "_Orientation_Correction";')
|
|
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "_Gaze_Correction";')
|
|
|
|
|
|
for curve in rotationOutputCurves:
|
|
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "%s" -min -30 -max 30;'%(EmoticonNodePrefix + curve))
|
|
issueCommand('graph -link -from "%s" -to "%s" -linkfn "linear";'%(EmoticonNodePrefix+ curve, curve))
|
|
|
|
for curve in eyeOutputCurves:
|
|
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "%s" -min -1 -max 1;'%(EmoticonNodePrefix + curve))
|
|
issueCommand('graph -link -from "%s" -to "%s" -linkfn "linear";'%(EmoticonNodePrefix + curve, curve))
|
|
|
|
|
|
|
|
issueCommand('graph -link -from "_All_Correction" -to "_Emphasis_Correction" -linkfn "linear";')
|
|
issueCommand('graph -link -from "_All_Correction" -to "_Blink_Correction" -linkfn "linear";')
|
|
issueCommand('graph -link -from "_All_Correction" -to "_Orientation_Correction" -linkfn "linear";')
|
|
issueCommand('graph -link -from "_All_Correction" -to "_Gaze_Correction" -linkfn "linear";')
|
|
issueCommand('graph -link -from "%s" -to "%s" -linkfn "linear";'%(EmphasisHeadPitchName, HeadPitchName))
|
|
issueCommand('graph -link -from "%s" -to "%s" -linkfn "linear";'%(EmphasisHeadYawName, HeadYawName))
|
|
issueCommand('graph -link -from "%s" -to "%s" -linkfn "linear";'%(EmphasisHeadRollName, HeadRollName))
|
|
issueCommand('graph -link -from "_Blink" -to "%s" -linkfn "linear";'%(BlinkName))
|
|
issueCommand('graph -link -from "_Eyebrow Raise" -to "%s" -linkfn "linear";'%(EyebrowRaiseName))
|
|
issueCommand('graph -link -from "_Squint" -to "%s" -linkfn "linear";'%(SquintName))
|
|
issueCommand('graph -link -from "_Emphasis_Correction" -to "%s" -linkfn "corrective";'%(EmphasisHeadPitchName))
|
|
issueCommand('graph -link -from "_Emphasis_Correction" -to "%s" -linkfn "corrective";'%(EmphasisHeadYawName))
|
|
issueCommand('graph -link -from "_Emphasis_Correction" -to "%s" -linkfn "corrective";'%(EmphasisHeadRollName))
|
|
issueCommand('graph -link -from "_Emphasis_Correction" -to "_Squint" -linkfn "corrective";')
|
|
issueCommand('graph -link -from "_Emphasis_Correction" -to "_Eyebrow Raise" -linkfn "corrective";')
|
|
issueCommand('graph -link -from "_Emphasis_Correction" -to "_Blink_Correction" -linkfn "linear";')
|
|
issueCommand('graph -link -from "_Blink_Correction" -to "_Blink" -linkfn "corrective";')
|
|
issueCommand('graph -link -from "_Orientation_Correction" -to "%s" -linkfn "corrective";'%(OrientationHeadPitchName))
|
|
issueCommand('graph -link -from "_Orientation_Correction" -to "%s" -linkfn "corrective";'%(OrientationHeadYawName))
|
|
issueCommand('graph -link -from "_Orientation_Correction" -to "%s" -linkfn "corrective";'%(OrientationHeadRollName))
|
|
issueCommand('graph -link -from "%s" -to "%s" -linkfn "linear";'%(OrientationHeadPitchName,HeadPitchName))
|
|
issueCommand('graph -link -from "%s" -to "%s" -linkfn "linear";'%(OrientationHeadYawName,HeadYawName))
|
|
issueCommand('graph -link -from "%s" -to "%s" -linkfn "linear";'%(OrientationHeadRollName,HeadRollName))
|
|
issueCommand('graph -link -from "%s" -to "%s" -linkfn "negate";'%(HeadPitchName,EyePitchCombinedName))
|
|
issueCommand('graph -link -from "%s" -to "%s" -linkfn "negate";'%(HeadYawName,EyeYawCombinedName))
|
|
|
|
issueCommand('graph -link -from "_Gaze_Correction" -to "%s" -linkfn "corrective";'%(EyePitchName))
|
|
issueCommand('graph -link -from "_Gaze_Correction" -to "%s" -linkfn "corrective";'%(EyeYawName))
|
|
issueCommand('graph -link -from "%s" -to "%s" -linkfn "linear";'%(EyePitchName,EyePitchCombinedName))
|
|
issueCommand('graph -link -from "%s" -to "%s" -linkfn "linear";'%(EyeYawName,EyeYawCombinedName))
|
|
issueCommand('execBatch -editednodes;')
|
|
|
|
|