Save All Story Clips To New Takes with MotionBuilder Python Script

UPDATED: A quick update that will now allow the script to maintain all of the original tracks within the story. The story will look exactly as it was pre-processing. Thanks Simon Kay

Below is a script that I wrote, It goes through all you Story tracks and clips and then processes them into new Scene Takes. Each clip will reside on its own take and it will be shift along the time line to start at frame zero.

I would use this tool for any long mocap shots that needed to be cut up into a number of smaller moves.

The Script was a very quick development on my part and will only be effective for Character Tracks. It is not going to provide you with any proper processing for clips that are blending into one and other. The number of clips you have sliced up within your Character Tracks will equal the number of new takes the script will create.

import pyfbsdk as fb

##Update Bug Work Around
def JiggleTimeline(): 
    fb.FBPlayerControl().GotoNextKey()
    fb.FBSystem().Scene.Evaluate()
    fb.FBPlayerControl().GotoPreviousKey()
    fb.FBSystem().Scene.Evaluate()

##Get All Story Track
def GetTracks():
    trackList = []
    for track in fb.FBStory().RootFolder.Tracks:
        trackList.extend([track])
    return trackList

##Plot The Story Clip
def PlotStoryClip(char):
    ##Plot Options
    lPlotClipOptions = fb.FBPlotOptions()
    lPlotClipOptions.ConstantKeyReducerKeepOneKey = False
    lPlotClipOptions.PlotAllTakes = False
    lPlotClipOptions.PlotOnFrame = True
    lPlotClipOptions.PlotPeriod = fb.FBTime( 0, 0, 0, 1 )
    lPlotClipOptions.PlotTranslationOnRootOnly = False
    lPlotClipOptions.PreciseTimeDiscontinuities = False
    lPlotClipOptions.RotationFilterToApply = fb.FBRotationFilter.kFBRotationFilterUnroll
    lPlotClipOptions.UseConstantKeyReducer = False
    char = fb.FBApplication().CurrentCharacter
    char.PlotAnimation (fb.FBCharacterPlotWhere.kFBCharacterPlotOnSkeleton,lPlotClipOptions )               
    char.PlotAnimation(fb.FBCharacterPlotWhere.kFBCharacterPlotOnControlRig,lPlotClipOptions ) 

##Process Evey Clip OF Every Character Story Track On To A New Take
def ProcessStory():
    ##Make A Track List
    trackList = GetTracks()
    ##Go Through Every Track In The List
    for track in trackList:
        track.Mute = True
        ##Get The Number Of Clips On The Track
        for n in range(track.GetSrcCount()):
            ##Update The Time Line To Prevent Unwanted Results
            JiggleTimeline()
            
            ##Create A "Temp Track" In The Story
            lTrack = fb.FBStoryTrack(fb.FBStoryTrackType.kFBStoryTrackCharacter, fb.FBStory().RootFolder)
            ##Set The Temp Track Character To Match Our Clips Character
            lTrack.Details.append(track.Character)
            ##Clone The Clip We Want To Process
            newClip = track.GetSrc(n).Clone()
            ##Set The Clone Clip To Be On The New Track We Created
            lTrack.Clips.append(newClip)
            ##Move The Cloned Clip To Start At Frame Zero
            newClip.Start = fb.FBTime(0,0,0,0)
            
            ##Create A New Take
            fb.FBSystem().Scene.Takes.append( fb.FBTake(track.GetSrc(n).Name+"-Processed") )
            ##Make The Newest Take To Be The Current Take
            fb.FBSystem().CurrentTake = fb.FBSystem().Scene.Takes[-1]
            ##Set The Current Take's Lenght To Match The Length Of The Clip
            fb.FBSystem().CurrentTake.LocalTimeSpan = fb.FBTimeSpan(fb.FBTime(0, 0, 0, 0, 0), fb.FBTime(0, 0, 0, lTrack.GetSrc(0).Stop.GetFrame(), 0))
            
            ##Update The Time Line To Prevent Unwanted Results
            JiggleTimeline()
            
            ##Plot The Clip To Our Desired Character
            PlotStoryClip(track.Character)
            
            ##Clean Out Temp Track
            lTrack.FBDelete()
        
ProcessStory()

del GetTracks, JiggleTimeline, PlotStoryClip, ProcessStory

This was a very quick test that I did over a lunch one day, there are a number of features that I would like to someday implement as well as making the script none destructive to takes/clips. I hope this helps speed up your work flow.

I hope this helps.

Add a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.