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.

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.