Lock and Plot selected properties using MotionBuilder’s Python.

 

I ran into a bug in my previous post about Plotting Selected properties – a bug that occurs in MotionBuilder 2015. I got in touch with Discreet and they said it would be easy enough for them to fix the bug in an update/hot fix, but I really wanted to solve this problem myself.

I wanted to reworking my script to allow MotionBuilder to actually plot on selected properties. The solution for decoupling the two Transforms (Translation and Rotation) through Python scripting is to lock the Rotational Properties before plotting – the Scale seems to be working independent from the other two Transforms, so we continue to deal with it through “.SetFocus(False)”.

I will be combining a few of the Python scripts from my previous posts to into a new script that will:

  1. Create a new scene on run time
  2. Create a Marker within that new scene
  3. Animate the marker on its Translation, Rotation and Scaling
  4. Select properties in which we want to Plot and de-select the ones we wished to not plot
  5. Lock the Rotational properties
  6. Plot the Marker

The Resulting code was created in its entirety:

from pyfbsdk import *

# Get the instance of FBApplication, and clear the scene with FileNew().
app = FBApplication()
app.FileNew()

# import time to allow us to access time line controls and play back controls
import time

# ensure new scene is set to 30 fps and that the time line is shown as frames
FBPlayerControl().SetTransportFps(FBTimeMode.kFBTimeMode30Frames)
FBPlayerControl().TransportTimeFormat = FBTransportTimeFormat.kFBTimeFormatFrame

# Set our Timeline to be 200 frames in length
FBSystem().CurrentTake.LocalTimeSpan = FBTimeSpan(
 # set start frame (0, 0, 0, 0, 0) = (hours, minutes, seconds, frames, fields)
 FBTime(0, 0, 0, 0, 0),
 # end frame
 FBTime(0, 0, 0, 200, 0)
 # if you wanted to set the time line to be 3 minutes long you could do some of the following to achieve that:
 #in frames = (0, 0, 0, 5400, 0)
 #in seconds = (0, 0, 180, 0, 0)
 #in minutes = (0, 3, 0, 0, 0) 
 )

# Creat an object that we will animate
lmarker = FBModelMarker('VicMarker')
lmarker.Show = True
lmarker.Size = 1000
lmarker.PropertyList.Find('LookUI').Data=1
lmarker.Color = FBColor(0,1,1)
lmarker.Selected = True

# Define the Transaltion to be represented as lmarker.Translation
xTrans, yTrans, zTrans = lmarker.Translation

# Declare that lmarker.Translation can be animated
lmarker.Translation.SetAnimated(True)

# Position lmarker.Translation to 0 on the x axis, 250 on the y axis and 0 on the z axis [0, 250, 0]
# Set a key at frame 0 (FBTime(0,0,0,0) - the time is the last 0 in the sequence
lmarker.Translation.GetAnimationNode().KeyAdd(FBTime(0,0,0,0), [0, 250, 0])

# Position lmarker.Translation to -200 on the x axis, -150 on the y axis and 200 on the z axis [-200, -150, 200]
# Set a key at frame 25 (FBTime(0,0,0,25)
lmarker.Translation.GetAnimationNode().KeyAdd(FBTime(0,0,0,25), [-200, 150, 200])
# Set a key at frame 50 (FBTime(0,0,0,50) with x,y and z translation values
lmarker.Translation.GetAnimationNode().KeyAdd(FBTime(0,0,0,50), [0, 0, 400])
# Set a key at frame 75......
lmarker.Translation.GetAnimationNode().KeyAdd(FBTime(0,0,0,75), [200, -150, 250])
# etc. for the remaining 5 translation keys that will be set on frames 100, 125, 150, 175 and finally our last frame 200 
lmarker.Translation.GetAnimationNode().KeyAdd(FBTime(0,0,0,100), [0, -250, 0])
lmarker.Translation.GetAnimationNode().KeyAdd(FBTime(0,0,0,125), [-200, -150, -250])
lmarker.Translation.GetAnimationNode().KeyAdd(FBTime(0,0,0,150), [0, 0, -400])
lmarker.Translation.GetAnimationNode().KeyAdd(FBTime(0,0,0,175), [200, 150, -200])
lmarker.Translation.GetAnimationNode().KeyAdd(FBTime(0,0,0,200), [0, 250, 0])

'''
Here is where we will start the attempt to plot on selected properties

First we are going to animate the rotation and the scaling - this will have animation on all 3 transforms
'''

# Define the Transaltion to be represented as lmarker.Translation
xTrans, yTrans, zTrans = lmarker.Translation
# Define the Rotation to be represented as lmarker.Rotation
xRot, yRot, zRot = lmarker.Rotation
# Define the Scale to be represented as lmarker.Rotation
xScl, yScl, zScl = lmarker.Scaling

# Declare that lmarker.Translation, lmarker.Rotation and lmarker.Scale can be animated
lmarker.Translation.SetAnimated(True)
lmarker.Rotation.SetAnimated(True)
lmarker.Scaling.SetAnimated(True)

# Rotate lmarker.Rotation to 0 on the x axis, 0 on the y axis and 0 on the z axis [0, 0, 0]
# Set a key at frame 0 (FBTime(0,0,0,0) - the time is the last 0 in the sequence
lmarker.Rotation.GetAnimationNode().KeyAdd(FBTime(0,0,0,0), [0, 0, 0])

# Rotate lmarker.Rotation to 3600 on the x, y and z axis [3600, 3600, 3600].
# I picked 3600 so that we can really see the result
# Set a key at frame 200 (FBTime(0,0,0,200) - the time is the last 0 in the sequence
lmarker.Rotation.GetAnimationNode().KeyAdd(FBTime(0,0,0,200), [3600, 3600, 3600])

# Scale lmarker.Scaling to 0 on the x axis, 0 on the y axis and 0 on the z axis [0, 0, 0]
lmarker.Scaling.GetAnimationNode().KeyAdd(FBTime(0,0,0,0), [1, 1, 1])

# Scale lmarker.Scaling to 10 on the x, y and z axis [10, 10, 10].
# Set a key at frame 200 (FBTime(0,0,0,200) - the time is the last 0 in the sequence
lmarker.Scaling.GetAnimationNode().KeyAdd(FBTime(0,0,0,100), [5, 5, 5])

# Scale lmarker.Scaling to 0 on the x axis, 0 on the y axis and 0 on the z axis [0, 0, 0]
lmarker.Scaling.GetAnimationNode().KeyAdd(FBTime(0,0,0,200), [1, 1, 1])

''' now let's plot only the translation animations and leave the rotation and scaling untouched '''
# Search the objects PropertyList and find "Lcl Translation, Lcl Rotation and Lcl Scaling"
lTranslation = lmarker.PropertyList.Find( 'Lcl Translation' )
lRotation = lmarker.PropertyList.Find( 'Lcl Rotation' )
lScaling = lmarker.PropertyList.Find( 'Lcl Scaling' )

# Select the marker's Translation fcurves using SetFocus
lTranslation.SetFocus(True)
#Ensure the marker's Rotation and Scaling is not selected
lRotation.SetFocus(False)
lScaling.SetFocus(False)

'''
MotionBuilder 2015 couples the Translation and the Rotation during "PlotTakeOnSelectedProperties", we will 
Lock the Rotation of our object - this should prevent the plotting from occurring on the Marker's Rotational X,Y and Z axis"
'''

# Set all Local Rotational Axis to be locked
lRotation.SetLocked( True )

'''
if we wanted to lock individual axis we would use the ".SetMemberLocked( # , True )"

lRotation.SetMemberLocked( 0 , True ) = Local Rotational X axis
lRotation.SetMemberLocked( 1 , True ) = Local Rotational Y axis
lRotation.SetMemberLocked( 2 , True ) = Local Rotational Z axis
'''

#Plot the Marker's Selected Properties 
FBSystem().CurrentTake.PlotTakeOnSelectedProperties( FBTime(0,0,0,1))

#Unlock the Rotation Properties
lRotation.SetLocked( False )

Viola! It worked! 🙂

The Locking of the Properties can be done easily enough through MotionBuilder’s Python Editor as seen here:

# Search the objects PropertyList and find "Lcl Rotation"
lRotation = lmarker.PropertyList.Find( 'Lcl Rotation' )

#Set the Lock to be True or False
lRotation.SetLocked = True
#This line was added to the end of the script because later on we may want to have access to these properties
lRotation.SetLocked = False

Note the difference between “.SetLocked” and “.SetMemberLocked”:

#SetLocked works on the Local Transform as a whole (X, Y, and Z)
lRotation.SetLocked( True )

#SetLockedMembers works per axis for the Local Transform
#Each axis is represented and a number 0, 1 and 2 = X, Y and Z.
lRotation.SetMemberLocked( 0 , True )
lRotation.SetMemberLocked( 1 , True )
lRotation.SetMemberLocked( 2 , True )

I would rather not do this work around, but it did allow me to explore and learn about locking properties using the “.SetLocked” and “.SetMemeberLocked” within Motionbuilder.

Overall this was great fun and very satisfying.

I hope this helps.

One Comment

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.