Using Python Scripting to set animation timecode zero in motionbuilder

901 Views Asked by At

Everyone.

I have some animation file that the start time is not zero. I am trying to create a script that will set the animation timecode to zero. For example, the picture shows the timecode is not from zero. Thank you very much for your help。 enter image description here

1

There are 1 best solutions below

0
On

I'm a bit late but this is probably still interesting to share!

You can set your current take's timespan easily using an FBTimeSpan() instance like this, by specifying a start and end frame as FBTime() objects:

lStartFrame = 0
lEndFrame = 100
FBSystem().CurrentTake.LocalTimeSpan = FBTimeSpan(FBTime(0, 0, 0, lStartFrame, 0), FBTime(0, 0, 0, lEndFrame, 0))

But I guess that what you are looking for is a way to offset your animation and make it start at 0, isn't it?

Here are two functions from my own library, using the Story mode to offset your current animation at a given frame. The first one works on the current or all characters of your scene (character animation track). The second one on selected conponents (generic animation track). For each one you can pass as argument the frame it should start from and if you want to frame the new timespan at the end (replace your old first/last frames with the new ones).

from pyfbsdk import *


def offset_character_animation_at_frame(frame = 0, all_chars = True, frame_anim=True):
    ''' Offset current/all(default) characters animation to a given frame, 0 by default '''

    # get list of current/all characters
    if all_chars:
        char_list = FBSystem().Scene.Characters
    else:
        char_list = [FBApplication().CurrentCharacter]

    # get initial timespan
    lStartFrame = FBSystem().CurrentTake.LocalTimeSpan.GetStart().GetFrame()
    lEndFrame = FBSystem().CurrentTake.LocalTimeSpan.GetStop().GetFrame()

    # turn on Story mode
    FBStory().Mute = False

    # process character list
    for char in char_list:
        # set timespan
        FBSystem().CurrentTake.LocalTimeSpan = FBTimeSpan(FBTime(0, 0, 0, lStartFrame, 0), FBTime(0, 0, 0, lEndFrame, 0))
        # set current character
        FBApplication().CurrentCharacter = char
        # insert character animation track
        track = FBStoryTrack(FBStoryTrackType.kFBStoryTrackCharacter, FBStory().RootFolder)
        track.Name = '{}_charAnimTrack'.format(FBApplication().CurrentCharacter.Name)
        track.Details.append(FBApplication().CurrentCharacter)
        # insert take in story mode
        take = FBSystem().CurrentTake
        inserted_clip = track.CopyTakeIntoTrack(take.LocalTimeSpan, take)
        # move inserted clip to given frame
        inserted_clip.Start = FBTime(0,0,0,frame)
        # frame new timespan
        FBSystem().CurrentTake.LocalTimeSpan = FBTimeSpan(FBTime(0, 0, 0, inserted_clip.Start.GetFrame(), 0), FBTime(0, 0, 0, inserted_clip.Stop.GetFrame(), 0))
        # defining plot options and plot to current take
        PlotOptions = FBPlotOptions()
        PlotOptions.ConstantKeyReducerKeepOneKey = True
        PlotOptions.PlotAllTakes = False
        PlotOptions.PlotOnFrame = True
        PlotOptions.PlotPeriod = FBTime( 0, 0, 0, 1 )
        PlotOptions.PlotTranslationOnRootOnly = True
        PlotOptions.PreciseTimeDiscontinuities = True
        PlotOptions.RotationFilterToApply = FBRotationFilter.kFBRotationFilterGimbleKiller
        PlotOptions.UseConstantKeyReducer = True
        char.PlotAnimation(FBCharacterPlotWhere.kFBCharacterPlotOnSkeleton, PlotOptions)
        # empty Story mode
        for track in FBStory().RootFolder.Tracks:
            for clip in track.Clips:
                clip.FBDelete()
            track.FBDelete()

    # set back original timespan if specified
    if not frame_anim:
        FBSystem().CurrentTake.LocalTimeSpan = FBTimeSpan(FBTime(0, 0, 0, lStartFrame, 0), FBTime(0, 0, 0, lEndFrame, 0))

    # turn off Story mode
    FBStory().Mute = True


def offset_generic_animation_at_frame(frame = 0, frame_anim = True):
    ''' Offset selected components animation to a given frame, 0 by default '''

    # get selected components
    lModelList = FBModelList()
    FBGetSelectedModels(lModelList)
    if not lModelList:
        raise ValueError("Select at least one component")

    # get initial timespan
    lStartFrame = FBSystem().CurrentTake.LocalTimeSpan.GetStart().GetFrame()
    lEndFrame = FBSystem().CurrentTake.LocalTimeSpan.GetStop().GetFrame()

    # turn on Story mode
    FBStory().Mute = False

    # set timespan        
    FBSystem().CurrentTake.LocalTimeSpan = FBTimeSpan(FBTime(0, 0, 0, lStartFrame, 0), FBTime(0, 0, 0, lEndFrame, 0))
    # insert generic animation track and add selected components to it
    track = FBStoryTrack(FBStoryTrackType.kFBStoryTrackAnimation, FBStory().RootFolder)
    track.Name = 'genericAnimTrack'
    for comp in lModelList:
        track.Details.append(comp)
    # insert take in story mode
    take = FBSystem().CurrentTake
    inserted_clip = track.CopyTakeIntoTrack(take.LocalTimeSpan, take)
    # move inserted clip to given frame
    inserted_clip.Start = FBTime(0,0,0,frame)
    # frame new timespan
    FBSystem().CurrentTake.LocalTimeSpan = FBTimeSpan(FBTime(0, 0, 0, inserted_clip.Start.GetFrame(), 0), FBTime(0, 0, 0, inserted_clip.Stop.GetFrame(), 0))
    # plot selected take
    lOptions = FBPlotOptions()   
    lOptions.ConstantKeyReducerKeepOneKey = False
    lOptions.PlotAllTakes = False
    lOptions.PlotOnFrame = True
    lOptions.PlotPeriod = FBTime( 0, 0, 0, 1 )
    lOptions.PlotTranslationOnRootOnly = False
    lOptions.PreciseTimeDiscontinuities = True
    lOptions.RotationFilterToApply = FBRotationFilter.kFBRotationFilterGimbleKiller
    lOptions.UseConstantKeyReducer = False
    FBSystem().CurrentTake.PlotTakeOnSelected(lOptions)

    # empty Story mode
    for track in FBStory().RootFolder.Tracks:
        for clip in track.Clips:
            clip.FBDelete()
        track.FBDelete()

    # set back original timespan if specified
    if not frame_anim:
        FBSystem().CurrentTake.LocalTimeSpan = FBTimeSpan(FBTime(0, 0, 0, lStartFrame, 0), FBTime(0, 0, 0, lEndFrame, 0))

    # turn off Story mode
    FBStory().Mute = True


# MAIN
offset_generic_animation_at_frame(frame = 0, frame_anim = False)
offset_character_animation_at_frame(frame = 0, all_chars = True, frame_anim=True)