# -------------------- # My Batch Export v1.4 # -------------------- # AUTHOR: Zoltan Erdokovy (zoltan.erdokovy@gmail.com) # Blog: www.zspline.net # # This script plots current/all takes, iterates through them, saves # them to a new file, one take per file (geometry and skeleton included) # Then optionally reopens the original, unplotted scene. # Root bones (top level bones not directly linked to a control rig) are # also plotted. # # KNOWN ISSUES: # At this point only the first character gets exported. # # # CHANGELOG: # ---------- # v1.4: # UI for choosing which takes to export: the current one or all of them. # A popup window for choosing weather to reopen the processed scene. # Plots root bone movement. # v1.3: # Fixed exporting single frame poses. # v1.2: # Fixed translations not plotted properly. # v1.1: # Fixed save path. # Now can export scenes without characters. from pyfbsdk import * from pyfbsdk_additions import * import os.path # GET FILE NAME def getFileName(f): #Utility function to get the name of a file without extension import os d, filename = os.path.split(f) if filename: return os.path.splitext(filename)[0] else: return "unknown" # PLOT ROOT BONE def PlotRootBone(mode): for child in FBSystem().Scene.RootModel.Children: if child.ClassName() == 'FBModelSkeleton': child.Selected = True if mode == "AllTakes": FBSystem().CurrentTake.PlotAllTakesOnSelected(FBTime( 0, 0, 0, 1 )) else: FBSystem().CurrentTake.PlotTakeOnSelected(FBTime( 0, 0, 0, 1 )) child.Selected = False # PLOT CHARACTER def PlotCharacter(mode): lScene = FBSystem().Scene lcharactersList = lScene.Characters # Set options for Plot process PlotOptions = FBPlotOptions() PlotOptions.ConstantKeyReducerKeepOneKey = True if mode == "AllTakes": PlotOptions.PlotAllTakes = True else: PlotOptions.PlotAllTakes = False PlotOptions.PlotOnFrame = True PlotOptions.PlotPeriod = FBTime( 0, 0, 0, 1 ) PlotOptions.PlotTranslationOnRootOnly = False PlotOptions.PreciseTimeDiscontinuities = True PlotOptions.RotationFilterToApply = FBRotationFilter.kFBRotationFilterUnroll PlotOptions.UseConstantKeyReducer = False # print len(lcharactersList) if len(lcharactersList)!= 0: lCharacter = lcharactersList[0] lCharacter.PlotAnimation (FBCharacterPlotWhere.kFBCharacterPlotOnSkeleton,PlotOptions ) return # DO EXPORT def DoExport(mode): global lSystem global lApplication global lFileName SaveOptions = FBFbxOptions(False) SaveOptions.UseASCIIFormat = False SaveOptions.BaseCameras = False SaveOptions.CameraSwitcherSettings = False SaveOptions.CurrentCameraSettings = False SaveOptions.GlobalLightingSettings = False SaveOptions.TransportSettings = False LoadOptions = FBFbxOptions(True) lOriginalTake = lSystem.CurrentTake Path = "" PlotRootBone(mode) PlotCharacter(mode) if mode == "AllTakes": # Export all takes. # Iterate the list of takes. # --- START OF FOR LOOP --- # for lTake in lSystem.Scene.Takes: # Switch the current take to the one we want to save. lSystem.CurrentTake = lTake # Build the file name to use. Path = os.path.dirname(lFileName)+'\\' # Original path lTakeFileName = "%s%s.fbx" % (Path,lTake.Name ) # Some feedback for the user... print "Saving Take '%s' to file '%s'" % ( lTake.Name, lTakeFileName ) # Go through the list of takes to export to tag only # the correct take. All the other are disregarded. for index in range(SaveOptions.GetTakeCount()): ## take index if SaveOptions.GetTakeName(index) == lTake.Name: SaveOptions.SetTakeSelect(index, True) else: SaveOptions.SetTakeSelect(index, False) lApplication.FileSave( lTakeFileName, SaveOptions ) # --- END OF FOR LOOP --- # else: # Export current take. # Build the file name to use. # Original path Path = os.path.dirname(lFileName)+'\\' lTakeFileName = "%s%s.fbx" % (Path,lOriginalTake.Name ) # Some feedback for the user... print "Saving Take '%s' to file '%s'" % ( lOriginalTake.Name, lTakeFileName ) # Go through the list of takes to export to tag only # the correct take. All the other are disregarded. for index in range(SaveOptions.GetTakeCount()): ## take index if SaveOptions.GetTakeName(index) == lOriginalTake.Name: SaveOptions.SetTakeSelect(index, True) else: SaveOptions.SetTakeSelect(index, False) lApplication.FileSave( lTakeFileName, SaveOptions ) # Reopen the original scene if the user chooses to. MessageBox = FBMessageBox( "My Batch Exporter", "Reopen scene?", "OK", "Cancel" ) if MessageBox == 1: print "Closing scene." lApplication.FileNew() print "Reopening scene." lApplication.FileOpen(lFileName, False, LoadOptions) del( lOriginalTake, SaveOptions, LoadOptions ) CleanUpAndClose() # CLEAN UP AND CLOSE def CleanUpAndClose(): global lSystem global lApplication global lFileName del( lSystem, lApplication, lFileName ) # FIX: The following symbols are not visible here so I can't delete them. #del( FBSystem, FBApplication, FBFbxManager ) CloseTool(GlobalTool) # --- UI RELATED FUNCTIONS --- # EXPORT CURRENT TAKE CALLBACK def ExportCurrentTakeCallback(control, event): ## print control.Caption, "Exporting current take." print "Exporting current take." DoExport("CurrentTake") # EXPORT ALL TAKES CALLBACK def ExportAllTakesCallback(control, event): print "Exporting all takes." DoExport("AllTakes") # CLOSE CALLBACK def CloseCallback(control, event): CleanUpAndClose() # POPULATE LAYOUT def PopulateLayout(mainLyt): lyt = GridLayout() x = FBAddRegionParam(5,FBAttachType.kFBAttachLeft,"") y = FBAddRegionParam(5,FBAttachType.kFBAttachTop,"") w = FBAddRegionParam(-5,FBAttachType.kFBAttachRight,"") h = FBAddRegionParam(-5,FBAttachType.kFBAttachBottom,"") mainLyt.AddRegion("main","main", x, y, w, h) mainLyt.SetControl("main",lyt) b = FBButton() b.Caption = "Export current take" b.Justify = FBTextJustify.kFBTextJustifyCenter lyt.Add(b,0,0, width = 120, height = 32) b.OnClick.Add(ExportCurrentTakeCallback) b = FBButton() b.Caption = "Export all takes" b.Justify = FBTextJustify.kFBTextJustifyCenter lyt.Add(b,0,1, width = 120, height = 32) b.OnClick.Add(ExportAllTakesCallback) b = FBButton() b.Caption = "Close" b.Justify = FBTextJustify.kFBTextJustifyCenter lyt.Add(b,1,3, width = 60, height = 32) b.OnClick.Add(CloseCallback) # CREATE TOOL def CreateTool(): # Tool creation will serve as the hub for all other controls global GlobalTool GlobalTool = CreateUniqueTool("My Batch Export") GlobalTool.StartSizeX = 400 GlobalTool.StartSizeY = 112 PopulateLayout(GlobalTool) ShowTool(GlobalTool) # ----- MAIN ----- # First get some needed objects. global lSystem lSystem = FBSystem() global lApplication lApplication = FBApplication() global lFileName lFileName = lApplication.FBXFileName if lFileName == "":## If no FBX file has been loaded. FileDlg = FBFilePopup() FileDlg.Style = FBFilePopupStyle.kFBFilePopupSave FileDlg.Caption = "MyBatchExport: Open a file." FileDlg.FileName = "Untitled.fbx" if FileDlg.Execute(): lFileName = FileDlg.FileName # We want to make sure that we have a scene with file name # already, otherwise we might want to open a file popup. # For now we assume that there is already a name to use as a # base name. if lFileName.upper().endswith( '.FBX' ): print "Starting the export tool." CreateTool() else: print 'File name does not end with ".fbx". Unable to proceed!'