Using MotionBulider and Python to create a Take Renaming Tool

I’ve used Take Renaming tools in the past and I’ve always found them to be an amazing time saver, so when I sat down to think about what I would like to learn next in my Motionbuilder Python Scripting adventure I knew that writing my own Take Naming Tool would be a lot of fun.
This experiment lead me to do a lot of google searching, thankfully I was able to sift through a ton of links and forums to find what I needed and along the way learned a lot through trial and error.
Here is a quick demo of the TakeReName_v1.0 tool.
Below I will spot light what was new to me, going quickly over searching for a string and dealing with letter case as well as replacing strings.
The entire Take Renaming (TakeReName_v1.0) script will be posted at the very end, or if you would just like to skip all that and down load the script than you can find it here. 🙂
I used the Regular expression operations to do the brunt of the work and you can read more about the re module here. For this post we will simply import the re module and move onto the functions “findall”, “IGNORECASE” and how we will swap words/characters within strings.
Importing the re module is easy enough:
from re import *
Below we have two example of the “findall” function that only have 1 small difference – “IGNORECASE”. You can find more information on “findall” here.
##this line is used only for this example
eFind.Text = "Take 001"
## Findall Example that is case sensitive
## On every Take in our scene
for take in FBSystem().Scene.Takes:
## search the take name for our desired string and if found make have that take become selected
if findall(eFind.Text,take.Name):
## Select the take
take.Selected=True
else:
## have the take become deselected if the desired string is not found make within the take's name
take.Selected=False
## Findall regardless of letter case using IGNORECASE
## On every Take in our scene
for take in FBSystem().Scene.Takes:
## search the take name for our desired string and if found make have that take become selected
if findall(eFind.Text,take.Name, IGNORECASE): ##IGNORECASE
## Select the take
take.Selected=True
else:
## have the take become deselected if the desired string is not found make within the take's name
take.Selected=False
Below here is an example of replacing the original text with our newly desired text. I tried a number of methods (starting with this one), but they would fall short when it came time to test with using my TakeReNamer tool’s “Ignore Case” option. After many searches and reading many forums I stumbled upon this link.
## If selected rename that takes to the desired string within the "Replace" field
for take in FBSystem().Scene.Takes:
if take.Selected == True:
## Deal with the "Find" field so that the string is not case sensitive
lProcessFields = compile(escape(eFind.Text), IGNORECASE)
## Witihin our Current Takes Name - Substitute our "Find" field string with our "Replace" Field string
lReName = lProcessFields.sub(eReplace.Text, take.Name)
## Rename the take to the new Take name
take.Name = lReName
del lReName
Here is the full script:
from pyfbsdk import *
from pyfbsdk_additions import *
from re import *
##labels
lFind = FBLabel()
lReplace = FBLabel()
##editable fields
eFind = FBEdit()
eReplace = FBEdit()
##buttons
bKeepOrg = FBButton()
bAsPrefix = FBButton()
bAsSuffix = FBButton()
bIgnoreCase = FBButton()
bAffectSelTakesOnly = FBButton()
bSelTakes = FBButton()
bRename = FBButton()
##Determine if "Ignore Case" is selected and then search all takes for the desired input string
def SearchAndSelctTakes():
##Make Sure no takes are already selected
for take in FBSystem().Scene.Takes:
if take.Selected == True:
take.Selected=False
else:
pass
##Ignore Case
if bIgnoreCase.State == 1:
##Find all takes that match the text inputed in to the "Find" field of our tool window
for take in FBSystem().Scene.Takes:
if findall(eFind.Text,take.Name, IGNORECASE):
take.Selected=True
else:
False
##Case Sensitive
else:
##Find all takes that match the text inputed in to the "Find" field of our tool window
for take in FBSystem().Scene.Takes:
if findall(eFind.Text,take.Name):
take.Selected=True
else:
False
## Select Takes Button - Search All Takes for the desired string and if found select those takes
def BtnCallbSelTakes(control, event):
## fail safe if the "FIND:" field is left blank - without this you run the risk of causing every character within the takes name to be replaced by the word/phrase that is in the "Replace:" field
if eFind.Text == "":
pass
else:
SearchAndSelctTakes()
def BtnCallbRename(control, event):
## Perform the Rename on only the Take the User has selected
if bAffectSelTakesOnly.State == 1:
pass
## Perform ReName on all Valid Takes
else:
## Perform the search on our takes and select the correct ones
SearchAndSelctTakes()
## fail safe if the "FIND:" field is left blank - without this you run the risk of causing every character within the takes name to be replaced by the word/phrase that is in the "Replace:" field
if eFind.Text == "":
pass
## If selected rename that takes to the desired string within the "Replace" field
else:
for take in FBSystem().Scene.Takes:
if take.Selected == True:
## Deal with the "Find" field so that its desired string is not case sensitive
lProcessFields = compile(escape(eFind.Text), IGNORECASE)
## Witihin our Current Takes Name - Substitute our "Find" field string with our "Replace" Field string
lReName = lProcessFields.sub(eReplace.Text, take.Name)
if bKeepOrg.State == 0:
## Rename our Current Take to Match our New Name
take.Name = lReName
del lReName
## Deal with the Options of maintaining the Original Takes name as a Prefix or a Suffix
if bKeepOrg.State == 1:
## Keep Original Takes name as a Prefix (ie. "Original Take Name_What Is Typed In The Replaced Field")
if bAsPrefix.State == 1:
lNewName = take.Name + "_" + eReplace.Text
take.Name = lNewName
del lNewName
## Keep Original Takes name as a Suffix (ie. "What Is Typed In The Replaced Field_Original Take Name")
if bAsSuffix.State == 1:
lNewName = eReplace.Text + "_" + take.Name
take.Name = lNewName
del lNewName
##If neither the "As Prefix" or "As Suffix" option is sleected
else:
pass
## If no Takes are selected
else:
pass
##Fail safe for the check box "Keep Origianl Take Name"
def BtnCallbKeepOrg(control, event):
if bKeepOrg.State == 1:
bAsPrefix.Enabled = bAsSuffix.Enabled = True
else:
bAsPrefix.Enabled = bAsSuffix.Enabled = False
bAsPrefix.State = bAsSuffix.State = 0
##Fail safe for "As Prefix" Check Box
def BtnCallbAsPrefix(control, event):
if bAsPrefix.State == 1:
bAsSuffix.State = 0
else:
bAsPrefix.State = bAsSuffix.State = 0
##Fail safe for "As Suffix" Check box
def BtnCallbAsSuffix(control, event):
if bAsSuffix.State == 1:
bAsPrefix.State = 0
else:
bAsPrefix.State = bAsSuffix.State = 0
## UI Layout
def PopulateTool(t):
#populate regions here
x = FBAddRegionParam(20,FBAttachType.kFBAttachNone,"")
y = FBAddRegionParam(35,FBAttachType.kFBAttachNone,"")
w = FBAddRegionParam(50,FBAttachType.kFBAttachNone,"")
h = FBAddRegionParam(20,FBAttachType.kFBAttachNone,"")
t.AddRegion("lFind","lFind", x, y, w, h)
t.SetControl("lFind", lFind)
lFind.Visible = True
lFind.ReadOnly = False
lFind.Enabled = True
lFind.Hint = ""
lFind.Caption = "Find:"
lFind.Style = FBTextStyle.kFBTextStyleNone
lFind.Justify = FBTextJustify.kFBTextJustifyLeft
lFind.WordWrap = True
x = FBAddRegionParam(80,FBAttachType.kFBAttachNone,"")
y = FBAddRegionParam(30,FBAttachType.kFBAttachNone,"")
w = FBAddRegionParam(500,FBAttachType.kFBAttachNone,"")
h = FBAddRegionParam(20,FBAttachType.kFBAttachNone,"")
t.AddRegion("eFind","eFind", x, y, w, h)
t.SetControl("eFind", eFind)
eFind.Visible = True
eFind.ReadOnly = False
eFind.Enabled = True
eFind.Hint = ""
eFind.Text = ""
eFind.PasswordMode = False
x = FBAddRegionParam(20,FBAttachType.kFBAttachNone,"")
y = FBAddRegionParam(75,FBAttachType.kFBAttachNone,"")
w = FBAddRegionParam(50,FBAttachType.kFBAttachNone,"")
h = FBAddRegionParam(20,FBAttachType.kFBAttachNone,"")
t.AddRegion("lReplace","lReplace", x, y, w, h)
t.SetControl("lReplace", lReplace)
lReplace.Visible = True
lReplace.ReadOnly = False
lReplace.Enabled = True
lReplace.Hint = ""
lReplace.Caption = "Replace:"
lReplace.Style = FBTextStyle.kFBTextStyleNone
lReplace.Justify = FBTextJustify.kFBTextJustifyLeft
lReplace.WordWrap = True
x = FBAddRegionParam(80,FBAttachType.kFBAttachNone,"")
y = FBAddRegionParam(70,FBAttachType.kFBAttachNone,"")
w = FBAddRegionParam(500,FBAttachType.kFBAttachNone,"")
h = FBAddRegionParam(20,FBAttachType.kFBAttachNone,"")
t.AddRegion("eReplace","eReplace", x, y, w, h)
t.SetControl("eReplace", eReplace)
eReplace.Visible = True
eReplace.ReadOnly = False
eReplace.Enabled = True
eReplace.Hint = ""
eReplace.Text = ""
eReplace.PasswordMode = False
x = FBAddRegionParam(20,FBAttachType.kFBAttachNone,"")
y = FBAddRegionParam(110,FBAttachType.kFBAttachNone,"")
w = FBAddRegionParam(150,FBAttachType.kFBAttachNone,"")
h = FBAddRegionParam(20,FBAttachType.kFBAttachNone,"")
t.AddRegion("bKeepOrg","bKeepOrg", x, y, w, h)
t.SetControl("bKeepOrg", bKeepOrg)
bKeepOrg.Visible = True
bKeepOrg.ReadOnly = False
bKeepOrg.Enabled = True
bKeepOrg.Hint = ""
bKeepOrg.Caption = "Keep Original Take Name"
bKeepOrg.State = 0
bKeepOrg.Style = FBButtonStyle.kFBCheckbox
bKeepOrg.Justify = FBTextJustify.kFBTextJustifyLeft
bKeepOrg.Look = FBButtonLook.kFBLookNormal
bKeepOrg.OnClick.Add(BtnCallbKeepOrg)
x = FBAddRegionParam(175,FBAttachType.kFBAttachNone,"")
y = FBAddRegionParam(110,FBAttachType.kFBAttachNone,"")
w = FBAddRegionParam(75,FBAttachType.kFBAttachNone,"")
h = FBAddRegionParam(20,FBAttachType.kFBAttachNone,"")
t.AddRegion("bAsPrefix","bAsPrefix", x, y, w, h)
t.SetControl("bAsPrefix", bAsPrefix)
bAsPrefix.Visible = True
bAsPrefix.ReadOnly = False
bAsPrefix.Enabled = False
bAsPrefix.Hint = ""
bAsPrefix.Caption = "As Prefix"
bAsPrefix.State = 0
bAsPrefix.Style = FBButtonStyle.kFBCheckbox
bAsPrefix.Justify = FBTextJustify.kFBTextJustifyLeft
bAsPrefix.Look = FBButtonLook.kFBLookNormal
bAsPrefix.OnClick.Add(BtnCallbAsPrefix)
x = FBAddRegionParam(255,FBAttachType.kFBAttachNone,"")
y = FBAddRegionParam(110,FBAttachType.kFBAttachNone,"")
w = FBAddRegionParam(90,FBAttachType.kFBAttachNone,"")
h = FBAddRegionParam(20,FBAttachType.kFBAttachNone,"")
t.AddRegion("bAsSuffix","bAsSuffix", x, y, w, h)
t.SetControl("bAsSuffix", bAsSuffix)
bAsSuffix.Visible = True
bAsSuffix.ReadOnly = False
bAsSuffix.Enabled = False
bAsSuffix.Hint = ""
bAsSuffix.Caption = "As Suffix"
bAsSuffix.State = 0
bAsSuffix.Style = FBButtonStyle.kFBCheckbox
bAsSuffix.Justify = FBTextJustify.kFBTextJustifyLeft
bAsSuffix.Look = FBButtonLook.kFBLookNormal
bAsSuffix.OnClick.Add(BtnCallbAsSuffix)
x = FBAddRegionParam(20,FBAttachType.kFBAttachNone,"")
y = FBAddRegionParam(130,FBAttachType.kFBAttachNone,"")
w = FBAddRegionParam(100,FBAttachType.kFBAttachNone,"")
h = FBAddRegionParam(30,FBAttachType.kFBAttachNone,"")
t.AddRegion("bIgnoreCase","bIgnoreCase", x, y, w, h)
t.SetControl("bIgnoreCase", bIgnoreCase)
bIgnoreCase.Visible = True
bIgnoreCase.ReadOnly = False
bIgnoreCase.Enabled = True
bIgnoreCase.Hint = ""
bIgnoreCase.Caption = "Ignore Case"
bIgnoreCase.State = 0
bIgnoreCase.Style = FBButtonStyle.kFBCheckbox
bIgnoreCase.Justify = FBTextJustify.kFBTextJustifyLeft
bIgnoreCase.Look = FBButtonLook.kFBLookNormal
x = FBAddRegionParam(160,FBAttachType.kFBAttachNone,"")
y = FBAddRegionParam(130,FBAttachType.kFBAttachNone,"")
w = FBAddRegionParam(170,FBAttachType.kFBAttachNone,"")
h = FBAddRegionParam(30,FBAttachType.kFBAttachNone,"")
t.AddRegion("bAffectSelTakesOnly","bAffectSelTakesOnly", x, y, w, h)
t.SetControl("bAffectSelTakesOnly", bAffectSelTakesOnly)
bAffectSelTakesOnly.Visible = True
bAffectSelTakesOnly.ReadOnly = False
bAffectSelTakesOnly.Enabled = True
bAffectSelTakesOnly.Hint = ""
bAffectSelTakesOnly.Caption = "Rename Only Selected Takes"
bAffectSelTakesOnly.State = 0
bAffectSelTakesOnly.Style = FBButtonStyle.kFBCheckbox
bAffectSelTakesOnly.Justify = FBTextJustify.kFBTextJustifyLeft
bAffectSelTakesOnly.Look = FBButtonLook.kFBLookNormal
x = FBAddRegionParam(355,FBAttachType.kFBAttachNone,"")
y = FBAddRegionParam(110,FBAttachType.kFBAttachNone,"")
w = FBAddRegionParam(100,FBAttachType.kFBAttachNone,"")
h = FBAddRegionParam(50,FBAttachType.kFBAttachNone,"")
t.AddRegion("bSelTakes","bSelTakes", x, y, w, h)
t.SetControl("bSelTakes", bSelTakes)
bSelTakes.Visible = True
bSelTakes.ReadOnly = False
bSelTakes.Enabled = True
bSelTakes.Hint = ""
bSelTakes.Caption = "Select Takes"
bSelTakes.State = 0
bSelTakes.Style = FBButtonStyle.kFBPushButton
bSelTakes.Justify = FBTextJustify.kFBTextJustifyCenter
bSelTakes.Look = FBButtonLook.kFBLookNormal
bSelTakes.OnClick.Add(BtnCallbSelTakes)
x = FBAddRegionParam(470,FBAttachType.kFBAttachNone,"")
y = FBAddRegionParam(110,FBAttachType.kFBAttachNone,"")
w = FBAddRegionParam(100,FBAttachType.kFBAttachNone,"")
h = FBAddRegionParam(50,FBAttachType.kFBAttachNone,"")
t.AddRegion("bRename","bRename", x, y, w, h)
t.SetControl("bRename", bRename)
bRename.Visible = True
bRename.ReadOnly = False
bRename.Enabled = True
bRename.Hint = ""
bRename.Caption = "Rename"
bRename.State = 0
bRename.Style = FBButtonStyle.kFBPushButton
bRename.Justify = FBTextJustify.kFBTextJustifyCenter
bRename.Look = FBButtonLook.kFBLookNormal
bRename.OnClick.Add(BtnCallbRename)
## Tool Window
def CreateTool():
t = FBCreateUniqueTool("TakeReNamer_v1.0")
t.StartSizeX = 610
t.StartSizeY = 220
PopulateTool(t)
ShowTool(t)
CreateTool()
Overall the tool was a lot of fun to write. I wish the input fields were a little more forgiving to use, sometimes I would have to hit the ReName button twice – first time deselected the field I was last typing in and the second click would actually run the renaming script it self. this is more of a MotionBuilder python UI thing.