Files
gtav-src/tools_ng/bin/audio/FaceFx 2012/Scripts/BodyGestures.py
T
2025-09-29 00:52:08 +02:00

243 lines
10 KiB
Python
Executable File

# This script creates an analysis actor that generates curves suitable for body gestures.
# It requires the Rhythm events
# Run the GestureLib.py script first.
from FxStudio import *
from FxGestureShared import *
import copy
# Create the Rhythm event group.
RhythmEventsGroup = "_RhythmEventGroup"
issueCommand('animGroup -create -group "%s";'%(RhythmEventsGroup));
# These are the analysis-generated Rhythm events that are responsible for making the above curves.
# They are guranteed to be at least .4 seconds apart. Meaningful silences (determined by their length
# and how long it's been since another silence) seperate the stresses into Rhythm_Initial, 0 or more
# Rhythm_Middle, then Rhythm_Final. If the stress stands alone in between silences it is a Rhythm_Isolated.
# First is Rhythm_First, last is Rhythm_Last.
Rhythm_First = "Rhythm_First"
Rhythm_Last = "Rhythm_Last"
Rhythm_Middle = "Rhythm_Middle"
Rhythm_Isolated = "Rhythm_Isolated"
Rhythm_Initial = "Rhythm_Initial"
Rhythm_Final = "Rhythm_Final"
# The output curve names aren't specific to the type of movement that they are mapped to
# because they can be used for different purposes. The curves are one of three types:
# 1. Bump - a typical 3-key curve with the first and last keys at 0, and the middle key at 1
# 2. Walk - a persistent curve that does a random walk between 0 and 1
# 3. OnOff - a persistent curve that is either 0 or 1 or blending in between
gestureBump = "gestureBump"
gestureOnOff = "gestureOnOff"
gestureBumpWide = "gestureBumpWide"
gestureWalk1 = "gestureWalk1"
gestureWalk2 = "gestureWalk2"
postureShift = "postureShift"
# altPose is essentially an OnOff curve, but it has a special purpose. It shifts the actor
# from one "phase" to another. The same curves can have different meanings in the different
# phases.
phasePick1 = "phasePick1"
altPose = "altPose"
activateArmGestures = "activateArmGestures"
# Most of the Rhythm events are simply mapped to these "Important" events where most of the actual
# work is done.
Rhythm_Important_All = "Rhythm_Important_All"
Rhythm_Important_Pick1 = "Rhythm_Important_Pick1"
# Create combiner nodes for the output curves.
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "%s";'%(gestureBump))
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "%s";'%(gestureOnOff))
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "%s";'%(gestureBumpWide))
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "%s";'%(altPose))
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "%s";'%(gestureWalk1))
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "%s";'%(gestureWalk2))
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "%s";'%(postureShift))
issueCommand('graph -addnode -nodetype "FxCombinerNode" -name "%s";'%(activateArmGestures))
Rhythm_Important_AllAnim = Anim(Rhythm_Important_All, RhythmEventsGroup);
Rhythm_Important_AllEvent = Event(Rhythm_Important_AllAnim.name, Rhythm_Important_AllAnim.group)
# The animations that create the curves.
gestureBumpAnim = Anim(gestureBump, RhythmEventsGroup)
gestureBumpCurve = Curve(gestureBump)
gestureBumpCurve.keys.append(Key(0, 0));
gestureBumpCurve.keys.append(Key(.3, 1));
gestureBumpCurve.keys.append(Key(.6, 0));
gestureBumpAnim.curves.append(gestureBumpCurve)
gestureBumpAnim.buildAnim()
gestureOnOffPick1 = "gestureOnOffPick1"
gestureOnOffPick1Anim = Anim(gestureOnOffPick1, RhythmEventsGroup)
gestureOnOffAnim = Anim(gestureOnOff, RhythmEventsGroup)
gestureOnOffAnim.curves.append(OneSecondCurve(gestureOnOffAnim.name,1))
gestureOnOffAnim.buildAnim()
gestureOnOffEvent = Event(gestureOnOffAnim.name, gestureOnOffAnim.group)
gestureOnOffEvent.persist = "true"
gestureOnOffEvent.set_blendin(.5)
gestureOnOffEvent.set_blendout(.5)
gestureOnOffEvent.set_magnitude(1)
gestureOnOffEvent.set_duration(.8)
gestureOnOffEvent.weight = .5
gestureOnOffPick1Anim.events.append(gestureOnOffEvent)
gestureOnOffEvent2 = copy.deepcopy(gestureOnOffEvent);
gestureOnOffEvent2 .weight = 1
gestureOnOffEvent2 .set_magnitude(0)
gestureOnOffPick1Anim.events.append(gestureOnOffEvent2)
gestureOnOffPick1Anim.groupChildEvents = "true"
gestureOnOffPick1Anim.buildAnim()
gestureBumpWideAnim = Anim(gestureBumpWide, RhythmEventsGroup)
gestureBumpWideCurve = Curve(gestureBumpWide)
gestureBumpWideCurve.keys.append(Key(-.6, 0));
gestureBumpWideCurve.keys.append(Key(-.233, 1));
gestureBumpWideCurve.keys.append(Key(.233, 1));
gestureBumpWideCurve.keys.append(Key(.6, 0));
gestureBumpWideAnim.curves.append(gestureBumpWideCurve)
gestureBumpWideAnim.buildAnim()
gestureWalk1Anim = Anim(gestureWalk1, RhythmEventsGroup)
gestureWalk1Anim.curves.append(OneSecondCurve(gestureWalk1Anim.name,1))
gestureWalk1Anim.buildAnim()
gestureWalk2Anim = Anim(gestureWalk2, RhythmEventsGroup)
gestureWalk2Anim.curves.append(OneSecondCurve(gestureWalk2Anim.name,1))
gestureWalk2Anim.buildAnim()
postureShiftAnim = Anim(postureShift, RhythmEventsGroup)
postureShiftAnim.curves.append(OneSecondCurve(postureShiftAnim.name,1))
postureShiftAnim.buildAnim()
altPoseAnim = Anim(altPose, RhythmEventsGroup)
altPoseAnim.curves.append(OneSecondCurve(altPoseAnim.name,1))
altPoseAnim.buildAnim()
phasePick1Anim = Anim(phasePick1, RhythmEventsGroup)
altPoseEvent = Event(altPoseAnim.name, altPoseAnim.group)
altPoseEvent.set_blendin(.5)
altPoseEvent.set_blendout(.5)
altPoseEvent.minstart = -.2
altPoseEvent.maxstart = -.1
altPoseEvent.minduration = 1
altPoseEvent.maxduration = 1.4
altPoseEvent.inheritmag = "false"
altPoseEvent.inheritdur = "false"
altPoseEvent.persist = "true"
phasePick1Anim.events.append(altPoseEvent)
altPoseEvent2 = copy.deepcopy(altPoseEvent)
altPoseEvent2.set_magnitude(0)
phasePick1Anim.events.append(altPoseEvent2)
phasePick1Anim.groupChildEvents = "true"
phasePick1Anim.buildAnim()
activateArmGesturesAnim = Anim(activateArmGestures, "_AnimEventGroup")
activateArmGesturesAnim.curves.append(OneSecondCurve(activateArmGesturesAnim.name,1))
activateArmGesturesAnim.buildAnim()
activateArmGesturesEvent = Event(activateArmGesturesAnim.name, activateArmGesturesAnim.group)
activateArmGesturesEvent.blendunscaled = "true"
animEntireAnim = Anim("Anim_Entire", "_AnimEventGroup")
altPoseEvent.set_blendin(.333)
altPoseEvent.set_blendout(.333)
animEntireAnim.events.append(activateArmGesturesEvent)
animEntireAnim.buildAnim()
# Rhythm_Initial setup
# This is probably the most important analysis event. For one thing, we are garunteed to have
# at least .8 seconds before the last Rhythm_Initial event, because by definiition, a Rhythm_Initial
# must at least be followed by a Rhythm_Final and normally one or more Rhythm_Middle too. Each of
# these is guranteed to be .4 seconds apart, so we have at least .8 before Rhythm_Initial
postureShiftEvent = Event(postureShiftAnim.name, postureShiftAnim.group)
postureShiftEvent.persist = "true"
postureShiftEvent.set_blendin(.5)
postureShiftEvent.set_blendout(.5)
postureShiftEvent.set_start(-.4)
postureShiftEvent.probability = .4
postureShiftEvent.minmagnitude = 0
postureShiftEvent.maxmagnitude = 1
phasePick1Event = Event(phasePick1Anim.name, phasePick1Anim.group)
phasePick1Event.set_start(-.3)
phasePick1Event.probability = .6
phasePick1Event.inheritmag = "false"
phasePick1Event.inheritdur = "false"
Rhythm_InitialAnim = Anim(Rhythm_Initial, RhythmEventsGroup);
Rhythm_InitialAnim.events.append(Rhythm_Important_AllEvent)
Rhythm_InitialAnim.events.append(postureShiftEvent)
Rhythm_InitialAnim.events.append(phasePick1Event)
Rhythm_InitialAnim.buildAnim()
# Final, Last, and Isolated just fire an "Important" event
Rhythm_FinalAnim = Anim(Rhythm_Final, RhythmEventsGroup);
Rhythm_LastAnim = Anim(Rhythm_Last, RhythmEventsGroup);
Rhythm_IsolatedAnim = Anim(Rhythm_Isolated, RhythmEventsGroup);
Rhythm_FinalAnim.events.append(Rhythm_Important_AllEvent)
Rhythm_LastAnim.events.append(Rhythm_Important_AllEvent)
Rhythm_IsolatedAnim.events.append(Rhythm_Important_AllEvent)
Rhythm_FinalAnim.buildAnim()
Rhythm_LastAnim.buildAnim()
Rhythm_IsolatedAnim.buildAnim()
# The "Important" events that are fired from most Rhythm events
Rhythm_Important_Pick1Anim = Anim(Rhythm_Important_Pick1, RhythmEventsGroup);
Rhythm_Important_Pick1Event = Event(Rhythm_Important_Pick1Anim.name, Rhythm_Important_Pick1Anim.group)
gestureWalk1Event = Event(gestureWalk1Anim.name, gestureWalk1Anim.group)
gestureWalk1Event.set_start(-.333)
gestureWalk1Event.minmagnitude = 0
gestureWalk1Event.maxmagnitude = 1
gestureWalk1Event.set_blendin(.5)
gestureWalk1Event.set_blendout(.5)
gestureWalk1Event.persist = "true"
gestureWalk1Event.inheritmag = "false"
gestureWalk1Event.inheritdur = "false"
gestureWalk2Event = Event(gestureWalk2Anim.name, gestureWalk2Anim.group)
gestureWalk2Event.set_start(-.333)
gestureWalk2Event.minmagnitude = 0
gestureWalk2Event.maxmagnitude = 1
gestureWalk2Event.set_blendin(.5)
gestureWalk2Event.set_blendout(.5)
gestureWalk2Event.persist = "true"
gestureWalk2Event.inheritmag = "false"
gestureWalk2Event.inheritdur = "false"
gestureBumpWideEvent = Event(gestureBumpWideAnim.name, gestureBumpWideAnim.group)
Rhythm_Important_Pick1Anim.groupChildEvents = "true"
Rhythm_Important_Pick1Anim.events.append(gestureBumpWideEvent)
Rhythm_Important_Pick1Anim.events.append(gestureWalk1Event)
Rhythm_Important_Pick1Anim.events.append(gestureWalk2Event)
Rhythm_Important_Pick1Anim.buildAnim()
gestureBumpEvent = Event(gestureBumpAnim.name, gestureBumpAnim.group)
gestureBumpEvent.minduration = 1
gestureBumpEvent.maxduration = 2
gestureBumpEvent.minmagnitude = .5
gestureBumpEvent.maxmagnitude = 1
gestureBumpEvent.set_start(-.3)
gestureBumpEvent.probability = .5
Rhythm_Important_AllAnim.events.append(gestureBumpEvent)
Rhythm_Important_AllAnim.events.append(Rhythm_Important_Pick1Event)
gestureOnOffPick1Event = Event(gestureOnOffPick1Anim.name, gestureOnOffPick1Anim.group)
gestureOnOffPick1Event.set_start(-.3)
gestureOnOffPick1Event.probability = .5
Rhythm_Important_AllAnim.events.append(gestureOnOffPick1Event)
Rhythm_Important_AllAnim.buildAnim()
# Rhythm_Middle
# This is the most frequent Rhythm event, so be careful what goes in here.
Rhythm_MiddleAnim = Anim(Rhythm_Middle, RhythmEventsGroup);
gestureOnOffPick1Event2 = copy.deepcopy(gestureOnOffPick1Event)
gestureOnOffPick1Event2.probability = .1
Rhythm_MiddleAnim.events.append(gestureOnOffPick1Event2)
gestureBumpEvent2 = copy.deepcopy(gestureBumpEvent)
gestureBumpEvent2.probablility = .3
Rhythm_MiddleAnim.events.append(gestureBumpEvent2)
Rhythm_MiddleAnim.buildAnim()