def LoadAndRetAnim (FileLoc,pOptions): manager = FBFbxManager() Char = FBSystem().Scene.Characters[0] manager.LoadAnimationOnCharacter(FileLoc,Char,0,0,1,1,FBFbxManagerLoadAnimationMethod.kFBFbxManagerLoadConnect,pOptions,0,0,0) Char.PlotAnimation(FBCharacterPlotWhere.kFBCharacterPlotOnControlRig,pOptions) Char.PlotAnimation(FBCharacterPlotWhere.kFBCharacterPlotOnSkeleton,pOptions) del (manager, Char)
def AdjustmentBlendObject(obj): take = FBSystem().CurrentTake if take.GetLayerCount() > 1: poseLayerFCurves = GetObjectFCurvesForLayer(obj, take.GetLayerCount() - 1) baseLayerFCurves = GetObjectFCurvesForLayer(obj, 0) for i in range(len(poseLayerFCurves)): poseFCurve = poseLayerFCurves[i] keys = poseFCurve.Keys if len(keys) > 1: keyPairsList = GetKeyPairsFromFCurve(keys) for keyPair in keyPairsList: startTime = keyPair[0] stopTime = keyPair[1] startValue = keyPair[2] stopValue = keyPair[3] spanValues = EvaluateFCurveForKeyPairTimespan( baseLayerFCurves[i], startTime, stopTime) percentageValues, totalBaseLayerChange = GetPercentageOfChangeValues( spanValues) totalPoseLayerChange = abs(stopValue - startValue) previousValue = startValue for value in percentageValues: valueDelta = (totalPoseLayerChange / 100.0) * value[1] if stopValue > startValue: currentValue = previousValue + valueDelta else: currentValue = previousValue - valueDelta poseLayerFCurves[i].KeyAdd(value[0], currentValue) previousValue = currentValue
def JiggleTimeline(): currentTime = FBPlayerControl().GetEditCurrentTime() FBPlayerControl().GotoStart() FBSystem().Scene.Evaluate() FBPlayerControl().GotoEnd() FBSystem().Scene.Evaluate() FBPlayerControl().Goto(currentTime) FBSystem().Scene.Evaluate()
def get_frames(): # Get the start and end frames of the time slider start_frame = float( FBSystem().CurrentTake.LocalTimeSpan.GetStart().GetFrame()) end_frame = float( FBSystem().CurrentTake.LocalTimeSpan.GetStop().GetFrame()) return end_frame - start_frame
def SetLayerWeight(weight=100.0, layerName=None): take = FBSystem().CurrentTake layer = None if layerName: layer = take.GetLayerByName(layerName) if not layer: layer = take.GetLayer(take.GetCurrentLayer()) if layer: if layer.Name != "BaseAnimation": layer.Weight = weight
def CreateNewLayer(layerName=None): take = FBSystem().CurrentTake oldLayersList = GetLayers() take.CreateNewLayer() newLayersList = GetLayers() for layer in newLayersList: if layer not in oldLayersList: newLayer = layer if layerName: newLayer.Name = layerName return newLayer
def AdjustmentBlendCharacter(character = None): if not character: character = FBApplication().CurrentCharacter if character: take = FBSystem().CurrentTake if take.GetLayerCount() > 1: characterObjs = GetCharacterEffectorsAndExtensions(character) for obj in characterObjs: if obj: AdjustmentBlendObject(obj) else: FBMessageBox("Error...", "No additive layer found. Adjustment blending affects interpolation between keys on the the top most additive layer.", "OK") else: FBMessageBox("Error...", "No additive layer found. Adjustment blending affects interpolation between keys on the top most additive layer.", "OK")
def KeyCharacter(character=None, layerName=None, includeScale=False): if not character: character = FBApplication().CurrentCharacter if character: if layerName: take = FBSystem().CurrentTake layer = take.GetLayerByName(layerName) if layer: take.SetCurrentLayer(layer.GetLayerIndex()) characterModels = GetCharacterEffectorsAndExtensions(character) if characterModels: for obj in characterModels: FBSystem().Scene.Evaluate KeyObject(obj, includeScale)
def FastPlotList(objectsToPlot, allTakes=False): if isinstance(objectsToPlot, list): if len(objectsToPlot) > 0: objList = GetSelected() DeselectAll() take = FBSystem().CurrentTake take.PlotTakeOnObjects(PlotOptions(allTakes), objectsToPlot) SelectList(objList) else: print("Plot failed: List of objects to plot is empty.") else: print( "Plot failed: List of objects not found. Fast Plot List needs to be provided with a list of objects to plot." )
def host_info(self): """ :returns: A dictionary with information about the application hosting this engine. The returned dictionary is of the following form on success: { "name": "Motionbuilder", "version": "18000.0", } and of following form on an error preventing the version identification. { "name": "Motionbuilder", "version: "unknown" } """ host_info = {"name": "Motionbuilder", "version": "unknown"} try: # NOTE: The 'Version' returns a double value # we really need the conversion to string. host_info["version"] = str(FBSystem().Version) except: # Fallback to initialized values above pass return host_info
def DeselectAll(): FBBeginChangeAllModels() for obj in FBSystem().Scene.Components: try: obj.Selected = False except: pass FBEndChangeAllModels()
def DeleteTakeByName(name, wildcardSearch=False): for take in FBSystem().Scene.Takes: if wildcardSearch: if name in take.Name: take.FBDelete() else: if take.Name == name: take.FBDelete()
def GetConstraintByName(name, includeNamespace=True): '''Returns a constraint that matches it's long name''' for const in FBSystem().Scene.Constraints: if includeNamespace: constraintName = const.LongName else: constraintName = const.Name if name == constraintName: return ConvertToPMBConstraint(const)
def PastePose(pose, character=None, pivot=None, match=True): if not character: character = FBApplication().CurrentCharacter if character: poseOptions = PoseOptions(pivot, match) FBBeginChangeAllModels() pose.PastePose(character, options) FBEndChangeAllModels() FBSystem().Scene.Evaluate()
def post_app_init(self): """ Executes once all apps have been initialized """ MOTIONBUILDER_2018_VERSION = 18000.0 if FBSystem().Version < MOTIONBUILDER_2018_VERSION: # older versions are missing image plugins, hotpatch them in. self._add_qt470_image_format_plugins_to_library_path() self._initialize_menu()
def AddObjectsToExtension(objList, extension=None, character=None): if not character: character = FBApplication().CurrentCharacter if not extension: if character: extension = FBCharacterExtension(character.LongName + "_Extension") else: extension = FBCharacterExtension("Character_Extension") if not isinstance(objList, list) and not isinstance( objList, FBPropertyListComponent): objList = [objList] for obj in objList: FBConnect(obj, extension) extension.AddObjectProperties(obj) extension.UpdateStancePose() if character: FBSystem().SuspendMessageBoxes = True character.AddCharacterExtension(extension) FBSystem().SuspendMessageBoxes = False return extension
def __init__(self, engine, menu_name): self._engine = engine self._menu_name = menu_name self.__menu_index = 1 self._callbacks = {} # Currently, root-level menu items seem to cause Motionbuilder 2011 & 2012 to # crash (2013+ works fine though). sub-menus work correctly so for <=2012 we # force everything to be at least one level deep so at least it's stable! fb_sys = FBSystem() self.__all_menus_nested = (fb_sys.Version < 13000.0)
def ReplaceNamespace(oldNamespace, newNamespace, objList=None): if not objList: objList = FBSystem().Scene.Components if not isinstance(objList, list) and not isinstance( objList, FBPropertyListComponent): objList = [objList] for obj in objList: obj.ProcessObjectNamespace(FBNamespaceAction.kFBReplaceNamespace, oldNamespace, newNamespace) objs = FindByNamespace(oldNamespace) if not objs: DeleteObjectsByNamespace(oldNamespace)
def FindByNamespace(namespace): if namespace[-1] != ":": namespace = namespace + ":" foundObjects = [] for obj in FBSystem().Scene.Components: if not isinstance(obj, FBNamespace): if obj.LongName.replace(obj.Name, "") == namespace: foundObjects.append(obj) if len(foundObjects) == 1: foundObjects = foundObjects[0] elif foundObjects == []: foundObjects = None return foundObjects
def GetConstraintsByType(_type): '''Returns a list of constraints that are of a given type (Aim, Position, etc)''' ret = [] for constraint in FBSystem().Scene.Constraints: if not isinstance(constraint, PMBConstraint): classType = getattr( kConstraintClassDict.get(constraint.Description), 'constraintType') else: classType = getattr(constraint, 'constraintType') if classType == _type: ret.append(ConvertToPMBConstraint(constraint)) return ret
def GetPoseByName(name, wildcardSearch=True): poseList = [] for pose in FBSystem().Scene.CharacterPoses: if wildcardSearch: if name in pose.Name: poseList.append(pose) else: if name == pose.Name: poseList.append(pose) if len(poseList) == 1: poseList = poseList[0] elif poseList == []: poseList = None return poseList
def CopyTakeByName(name, wildcardSearch=False): newTakeList = [] for take in FBSystem().Scene.Takes: if wildcardSearch: if name in take.Name: newTake = take.CopyTake(take.Name) newTakeList.append(newTake) else: if take.Name == name: newTake = take.CopyTake(take.Name) newTakeList.append(newTake) if len(newTakeList) == 1: newTakeList = newTakeList[0] elif newTakeList == []: newTakeList = None return newTakeList
def _check_for_mobu(self): ''' try to determine if current application is motionbuilder related ''' found = False try: import re from pyfbsdk import FBSystem mobu_patt = re.compile("motionbuilder", re.IGNORECASE) if mobu_patt.search(FBSystem().ApplicationPath): self._application = "mobu" found = True except: pass return found
def SetupLibPath(lib_filename=None): common_script_file = inspect.getfile( inspect.currentframe()) if lib_filename is None else lib_filename common_script_file = os.path.basename(common_script_file) paths = FBSystem().GetPythonStartupPath() for path in paths: if os.path.isfile(os.path.join(path, common_script_file)): # check if that path is inside sys.path if not path in sys.path: sys.path.append(path) break else: raise Exception('Script File Is Not Found In Any Python StartUp Path!')
def GetSelected(sceneObjectsOnly=True): foundObjects = [] for obj in FBSystem().Scene.Components: if not isinstance(obj, FBMesh) and obj.Selected: if sceneObjectsOnly: if isinstance(obj, FBModel) or isinstance( obj, FBModelMarker) or isinstance( obj, FBModelSkeleton) or isinstance( obj, FBModelNull) or isinstance(obj, FBCamera): foundObjects.append(obj) else: foundObjects.append(obj) if len(foundObjects) == 0: print 'No objects selected' elif len(foundObjects) == 1: foundObjects = foundObjects[0] return foundObjects
def GetCharacterExtensionObjects(character=None): if not character: character = FBApplication().CurrentCharacter if character: characterExtentionObjects = [] for ext in FBSystem().Scene.CharacterExtensions: attachedChar = ext.PropertyList.Find("AttachedCharacter") if len(attachedChar) > 0: if attachedChar[0] == character: extObjList = GetObjectsFromExtension(ext) characterExtentionObjects = characterExtentionObjects + extObjList if characterExtentionObjects == []: characterExtentionObjects = None else: characterExtentionObjects = list( dict.fromkeys(characterExtentionObjects)) return characterExtentionObjects
def CreateConstraint(_type, name=None): ''' Create a constraint with the given type and optionally with a name @param _type: name of constraint type found in kConstraintTypes @param name: name to give constraint. Default is used if None ''' try: constraint = FBConstraintManager().TypeCreateConstraint( kConstraintTypes[_type]) except KeyError: raise Exception("Invalid constraint type '%s'" % _type) FBSystem().Scene.Constraints.append(constraint) if name: constraint.Name = name return ConvertToPMBConstraint(constraint)
def __get_pyside_folder(self): """ Get the correct pyside folder name according to the correct Motionbuilder version. :returns: String of the correct pyside distribution folder name (not the entire path) """ version = FBSystem().Version folder = '' # MotionBuilder 2012 and 2013 use a qt compiled with vs2008 (even though mobu 2013 itself is compiled with 2010). # Use a dumpbin /headers on MoBu's qtcore4.dll to see which linker version was used, since versioning can # easily get confusing. if version < 14000: folder = "pyside112_py26_qt470_win64_vs2008" else: folder = "pyside112_py26_qt470_win64_vs2010" return folder
def FindByName(name, includeWildcards=False, includeNamespace=True, sceneObjectsOnly=False): foundObjects = [] for obj in FBSystem().Scene.Components: if not isinstance(obj, FBMesh): if sceneObjectsOnly: if isinstance(obj, FBModel) or isinstance( obj, FBModelMarker) or isinstance( obj, FBModelSkeleton) or isinstance( obj, FBModelNull) or isinstance(obj, FBCamera): SearchFiltering(obj, name, includeNamespace, includeWildcards, foundObjects) else: SearchFiltering(obj, name, includeNamespace, includeWildcards, foundObjects) if len(foundObjects) == 0: print 'Search for "%s" found nothing' % (name) elif len(foundObjects) == 1: foundObjects = foundObjects[0] return foundObjects
def CopySelectedStoryClipsToTakes(centerClips=True): clipsList = GetSelectedStoryClips(True) trackMuteStatus = [] for track in FBStory().RootFolder.Tracks: trackMuteStatus.append([track, track.Mute]) track.Mute = True for clipInfo in clipsList: newTrack, newClip = CopyClipToNewTrack(clipInfo) if centerClips: newClip.Translation = FBVector3d(0, 0, 0) newClip.Rotation = FBVector3d(0, -90, 0) newTake = CreateNewTake(newClip.Name) FBSystem().CurrentTake = newTake span = newTake.LocalTimeSpan span.Set(newClip.Start, newClip.Stop) newTake.LocalTimeSpan = span character = newTrack.Character if not character: character = FBApplication().CurrentCharacter PlotToCharacter(character) newTrack.FBDelete() for trackInfo in trackMuteStatus: trackInfo[0].Mute = trackInfo[1] FBStory().Mute = True
import sys import xml.etree.ElementTree as ET #@UnresolvedImport import inspect #@UnresolvedImport from pyfbsdk import FBMessageBox, FBSystem #@UnresolvedImport # assumes system/user PYTHONPATH contains path to ./PipelineConstructionSet/python try: import common.core.globalVariables as gv except: FBMessageBox("PYTHONPATH setup", "Please add system variable PYTHONPATH to\nlocation of ./PipelineConstructionSet/python", "OK", None, None, 1) _MAINTENANCE = False # find app version version = None appPath = FBSystem().ApplicationPath if len(appPath) > 2: appName = appPath.split('\\')[3] if len(appName) > 0: version = int(appName.split(' ')[1]) if not version: FBMessageBox("Version failure", "Failed to find MoBu version.\n\nSkipping ArtMonkey boot.", "OK", None, None, 1, False) else: if _MAINTENANCE: FBMessageBox("Performing Maintenance", "Sorry, ArtMonkey is temporarily down for maintenance.\n\nShould be back up within the hour.", "OK", "Darn", "That Sucks", 1, False) else: #-------------------------------------------- # read from schema pcsXML = ET.parse('%s/schemas/pcsSchema.xml' % gv.toolsLocation) pcsXMLcore = pcsXML.getiterator('Core')[0]