90 lines
4.7 KiB
Python
Executable File
90 lines
4.7 KiB
Python
Executable File
""" Handles custom payloads in events.
|
|
|
|
Owner: Jamie Redmond
|
|
|
|
Copyright (c) 2002-2011 OC3 Entertainment, Inc.
|
|
|
|
"""
|
|
from FxStudio import *
|
|
from FxAnimation import *
|
|
import string
|
|
import re
|
|
|
|
# This function clears the current skeletal animation tree and builds a new one
|
|
# from the information stored in the take corresponding to the specified
|
|
# animation.
|
|
def buildSkeletalAnimationTree(groupName, animName):
|
|
if len(getRenderAssetName()) > 0 and isRenderAssetValid() and renderAssetHasSkeletalAnimationTree() and len(groupName) > 0 and len(animName) > 0:
|
|
disabledUndo = False
|
|
issuedBatchCommand = False
|
|
try:
|
|
eventTake = EventTake(groupName, animName)
|
|
# Temporarily disable the undo/redo system. This is because this is called inside a Python signal
|
|
# so these commands will be listed in the undo/redo stacks on *top* of the command that triggered
|
|
# the signal. Since we build the tree based on data already present when the signal is fired it is
|
|
# actually an error that these commands end up on the undo/redo stacks anyway.
|
|
issueCommand('undo -disable')
|
|
disabledUndo = True
|
|
issueCommand('animtree -clear')
|
|
for event in eventTake.events:
|
|
payload = string.strip(event.customPayload)
|
|
match = re.match('game:\s+playanim\s+\w+', payload)
|
|
if match != None:
|
|
skeletalAnimationName = re.split(r'\W+', match.group())[2]
|
|
issueCommand('animtree -silent -add -animation %s -starttime %f -blendintime %f -blendouttime %f -durationscale %f -magnitudescale %f' % (skeletalAnimationName, event.startTime, event.blendInTime, event.blendOutTime, event.durationScale, event.magnitudeScale))
|
|
issueCommand('undo -enable')
|
|
except Exception, e:
|
|
if disabledUndo:
|
|
issueCommand('undo -enable')
|
|
raise FaceFXError('{0}'.format(e))
|
|
|
|
|
|
# Checks for animation bounds intersections between the preview animation and the animation tree.
|
|
def checkForPreviewAnimationIntersection():
|
|
previewAnimSettings = PreviewAnimationSettings()
|
|
if previewAnimSettings.animationName != None:
|
|
endTime = previewAnimSettings.startTime + previewAnimSettings.length
|
|
if previewAnimSettings.loop == True:
|
|
# 365.25 days is 31,557,600 seconds which should be for all intents and purposes an infinite end time when looping.
|
|
endTime = 31557600.0
|
|
duplicateInRange = next((anim for anim in getSkeletalAnimationTreeAnimsInTimeRange(previewAnimSettings.startTime, endTime) if anim[0] == previewAnimSettings.animationName), None)
|
|
if duplicateInRange != None:
|
|
# This command should be on the undo/redo stacks just to preserve state but note that when this happens getting
|
|
# back to the previous state will now require two undos instead of one.
|
|
issueCommand('previewanim -animation ""')
|
|
warn('Disabled preview animation %s because it overlaps the same animation with start time %f in the skeletal animation events tree!' %(previewAnimSettings.animationName, duplicateInRange[1]))
|
|
|
|
|
|
# When the animation selection changes we need to build a new skeletal animation tree.
|
|
def EventCustomPayloadManager_onAnimationChanged(groupName, animName):
|
|
buildSkeletalAnimationTree(groupName, animName)
|
|
checkForPreviewAnimationIntersection()
|
|
|
|
|
|
# When a new take is created we need to build a new skeletal animation tree.
|
|
def EventCustomPayloadManager_onPostEventTakeCreation(groupName, animName):
|
|
buildSkeletalAnimationTree(groupName, animName)
|
|
checkForPreviewAnimationIntersection()
|
|
|
|
|
|
# When the preview animation settings change we need to check for preview animation intersections.
|
|
def EventCustomPayloadManager_onPreviewAnimationSettingsChanged():
|
|
checkForPreviewAnimationIntersection()
|
|
|
|
|
|
# When the user changes the render asset we need to build a new skeletal animation tree.
|
|
def EventCustomPayloadManager_onRenderAssetLoaded():
|
|
buildSkeletalAnimationTree(getSelectedAnimGroupName(), getSelectedAnimName())
|
|
checkForPreviewAnimationIntersection()
|
|
|
|
|
|
msg('Initializing and registering the event custom playload manager plugin...')
|
|
|
|
# Hook our functions into their corresponding FaceFX Studio Python signals.
|
|
connectSignal('animationselectionchanged', EventCustomPayloadManager_onAnimationChanged)
|
|
connectSignal('posteventtakecreation', EventCustomPayloadManager_onPostEventTakeCreation)
|
|
connectSignal('previewanimationsettingschanged', EventCustomPayloadManager_onPreviewAnimationSettingsChanged)
|
|
connectSignal('renderassetloaded', EventCustomPayloadManager_onRenderAssetLoaded)
|
|
|
|
msg('Event custom payload manager plugin: ready')
|