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.