Using MotionBuilder Python To Offset All Animations Within A Scene
Posted On January 7, 2021

Here is a quick script that will allow you to shift/offset all animation keys within a scene. Previously I would do this via story mode or use another technique that would skip over props and/or constraints. This script should shift everything within the scene that is animated.
The script is not good for things like offsetting one character within a scene while leaving other objects/characters alone – this will move everything within the scene.
from pyfbsdk import *
##Get All Animation Nodes Within The Scene
def getAnimatedNodes():
animNodes = []
for i in FBSystem().Scene.Components:
for property in i.PropertyList:
try:
if property.IsAnimated() == True:
animNodes.extend( [property.GetAnimationNode()] )
except: pass
if len(animNodes) != 0:
return animNodes
##OffSet A List Of Animation Node By A Desired Number
def OffSetAnimation( pAnimated = list, pFrameOffSet = int ):
for i in pAnimated:
##Deal With Properties That Have Single FCurve (IK Blends, IK Pull, Ref. Properties, Etc.)
try:
i.FCurve.KeyOffset( FBTime( 0, 0, 0, pFrameOffSet ) )
except: pass
##Deal With Properties That Have Multiple Nodes (X, Y, Z Axis)
try:
for n in range( len(i.Nodes) ):
if i.Nodes[ n ].KeyCount != 0:
i.Nodes[ n ].FCurve.KeyOffset( FBTime( 0, 0, 0, pFrameOffSet ) )
except: pass
##Offset All Animation On A Take So That The Animation Starts At Frame Zero
def StartTakeAnimAtFrameZero():
##Set Scene To 30FPS And Time Line To Show Frames
FBPlayerControl().SetTransportFps(FBTimeMode.kFBTimeMode30Frames)
FBPlayerControl().TransportTimeFormat = FBTransportTimeFormat.kFBTimeFormatFrame
##Get The Takes Original Info
pTakeStart = FBSystem().CurrentTake.LocalTimeSpan.GetStart().GetFrame()
pTakeLength = FBSystem().CurrentTake.LocalTimeSpan.GetDuration().GetFrame()
##Offset Animation
animatedNodes = getAnimatedNodes()
OffSetAnimation( animatedNodes, -pTakeStart )
##Set Time Line To Reflect The New OffSet
FBSystem().CurrentTake.LocalTimeSpan = FBTimeSpan( FBTime(0, 0, 0, 0, 0), FBTime(0, 0, 0, pTakeLength, 0) )
FBPlayerControl().Goto( FBTime(0, 0, 0, 0, 0) )
##Go Through Every Take Within A Scene And Offset The Animation So That They Start On Frame Zero
def OffsetAllTakesToFrameZero():
##Store Current Take
ogTake = FBSystem().CurrentTake
##Go Throuhg Every Take Within The Scene And Offset Keys To Start On Frame Zero
for take in FBSystem().Scene.Takes:
FBSystem().CurrentTake = take
StartTakeAnimAtFrameZero()
##Return To The Take We Were On When We Started The Process
FBSystem().CurrentTake = ogTake
'''
How To Use The Functions
'''
##Example of offsetting an animation by a specific frame amount
##Get the animated nodes within the scene
myAnimatedNodes = getAnimatedNodes()
##Offset the animation nodes to start 100 frames later in the time line
OffSetAnimation( myAnimatedNodes , 100 )
##Offset the animation nodes to start 300 frames earlier in the time line
OffSetAnimation( myAnimatedNodes , -300 )
##Offset all keys to start at frame zero
StartTakeAnimAtFrameZero()
##Offset all takes within the scene so that keys start at frame zero
OffsetAllTakesToFrameZero()
I hope this helps.
5 Comments
Can you help to create python a script: export take list from file with Local Start, Local Stop, Duration, Comments to .txt file?
im not 100% sure what you are asking?
what would be in the .txt file?
file name
take names
export files to cretae (file name, durations)
Take Properties have a:
Local start, Local stop, Duration, Reference start, Reference stop, Comments
It will be good to have all this information for all selected take in the .txt file
Thank you,
here is something i whipped up:
Write Take Info To Text File
I try to do with print, but don’t give me a good result.
for myTake in FBSystem().Scene.Takes:
print ‘ Take: ‘, myTake.Name, myTake.ReferenceTimeSpan, myTake.LocalTimeSpan, FBPropertyString