""" 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')