''' From https://github.com/Danlowlows/MobuCore Adjustment Blending is a method for adjusting additive layer interpolation between keyframes, so that movement on the layer is shifted to areas where there is already movement on the base layer. This helps to maintain the existing energy of the base layer motion, and helps to maintain contact points. For more information, see this talk from GDC 2016: https://youtu.be/eeWBlMJHR14?t=518 MobuCoreLibrary functions are required for this script. ____________________________________________________________________ This script was written by Dan Lowe as part of the MobuCore package. You can reach Dan Lowe on Twitter at https://twitter.com/danlowlows (at time of writing, direct messages are open). MobuCore is made available under the following license terms: Copyright (c) 2019 Dan Lowe This software is provided 'as-is', without any express or implied warranty. In no event will the author be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. 2. If you use this software, in source or binary form, an acknowledgment in the product documentation or credits would be appreciated but is not required. Example: "This product uses MobuCore (c) 2019 Dan Lowe." 3. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 4. This notice may not be removed or altered from any source distribution. ''' from pyfbsdk import * # Gets all referened objects for a given character extension. def GetObjectsFromExtension(ext): extObjList = [] for i in range(ext.GetSrcCount()): extObjList.append(ext.GetSrc(i)) if extObjList == []: extObjList = None return extObjList # Gets all referenced character extension objects for a given character. 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 # Gets the control rig for a given character. def GetControlRigForCharacter(character=None): if not character: character = FBApplication().CurrentCharacter if character: ctrlRig = character.PropertyList.Find("ControlSet") if len(ctrlRig) != 0: ctrlRig = ctrlRig[0] else: ctrlRig = None if ctrlRig: return ctrlRig # Get all character effectors and extensions. def GetCharacterEffectorsAndExtensions(character=None): if not character: character = FBApplication().CurrentCharacter if character: effectors = GetControlRigEffectors(character) extensions = GetCharacterExtensionObjects(character) if not isinstance(effectors, list): effectors = [effectors] if not isinstance(extensions, list): extensions = [extensions] return effectors + extensions # Gets the IK effectors for a given character. def GetControlRigIKEffectors(character=None): if not character: character = FBApplication().CurrentCharacter if character: ctrlRig = GetControlRigForCharacter(character) ikEffectors = [] for nodeId in FBEffectorId.values.itervalues(): if nodeId not in [FBEffectorId.kFBInvalidEffectorId, FBEffectorId.kFBLastEffectorId]: effector = ctrlRig.GetIKEffectorModel(nodeId, 0) if effector: ikEffectors.append(effector) if ikEffectors == []: ikEffectors = None return ikEffectors # Gets the FK effectors for a given character. def GetControlRigFKEffectors(character=None): if not character: character = FBApplication().CurrentCharacter if character: fkEffectors = [] for nodeId in FBBodyNodeId.values.itervalues(): if nodeId not in [FBBodyNodeId.kFBInvalidNodeId, FBBodyNodeId.kFBLastNodeId]: effector = character.GetCtrlRigModel(nodeId) if effector: fkEffectors.append(effector) if fkEffectors == []: fkEffectors = None return fkEffectors # Gets both the FK and IK effectors for a given character. def GetControlRigEffectors(character=None): if not character: character = FBApplication().CurrentCharacter if character: controlRigEffectors = GetControlRigFKEffectors(character) + GetControlRigIKEffectors(character) return controlRigEffectors # Groups pairs of keys from the layer fcurve, between which it will run an independent adjustment blend (allows adjustment blend to work with multiple key poses on the layer). def GetKeyPairsFromFCurve(keys): keyPairsList = [] for i in range(len(keys) - 1): startKeyTime = keys[i].Time startKeyValue = keys[i].Value stopKeyTime = keys[i + 1].Time stopKeyValue = keys[i + 1].Value keyPairsList.append([startKeyTime, stopKeyTime, startKeyValue, stopKeyValue]) return keyPairsList # Gets the transform nodes for an object. def GetObjTransformNodes(obj): transProp = obj.PropertyList.Find("Lcl Translation") rotProp = obj.PropertyList.Find("Lcl Rotation") if not transProp: transProp.SetAnimated(True) transProp = obj.PropertyList.Find("Lcl Translation") if not rotProp: rotProp.SetAnimated(True) rotProp = obj.PropertyList.Find("Lcl Rotation") transNodes = transProp.GetAnimationNode().Nodes rotNodes = rotProp.GetAnimationNode().Nodes nodes = list(transNodes) + list(rotNodes) return nodes # Gets the fcurves for an object from a specified layer. def GetObjectFCurvesForLayer(obj, layerIndex): FBSystem().CurrentTake.SetCurrentLayer(layerIndex) try: return [node.FCurve for node in GetObjTransformNodes(obj)] except: return [] # Reads the per frame values from an fcurve (doesn't require keys to be on those frames). def EvaluateFCurveForKeyPairTimespan(fcurve, startTime, stopTime): keyPairSpanValues = [] current = startTime while not current > stopTime: keyPairSpanValues.append([current, fcurve.Evaluate(current)]) current += FBTime(0, 0, 0, 1) return keyPairSpanValues # Finds the percentage of change that occured on the base layer curve, for the key pair. def GetPercentageOfChangeValues(spanValues): changeValues = [0.0] for i in range(len(spanValues) - 1): frameChangeValue = abs(spanValues[i + 1][1] - spanValues[i][1]) changeValues.append(frameChangeValue) totalBaseLayerChange = sum(changeValues) percentageValues = [] for i in range(len(changeValues)): if totalBaseLayerChange != 0: percentageValues.append([spanValues[i][0], (100.0 / totalBaseLayerChange) * changeValues[i]]) return percentageValues, totalBaseLayerChange # The main adjustment blend function that does everything else. This is what you'd run if you were just adjustment blending a single object. 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 # The main adjustment blending function for running it on an entire character. 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 for %s. Adjustment blending affects interpolation between keys on the the top most additive layer." % take.Name, "OK") else: FBMessageBox("Error...", "No additive layer found for %s. Adjustment blending affects interpolation between keys on the top most additive layer." % take.Name, "OK") def getNumberOfSelectedTakes(): number_of_selected_takes = 0 for take_index in range(len(FBSystem().Scene.Takes)): if FBSystem().Scene.Takes[take_index].Selected == True: number_of_selected_takes += 1 return number_of_selected_takes def run(): # -- Get number of takes selected number_of_selected_takes = getNumberOfSelectedTakes() # if there is one selected take, still ignore it and use the current take # it's a bit annoying when you have one take selected different from the current - chances are the user didn't mean to. if number_of_selected_takes > 1: for take_index in range(len(FBSystem().Scene.Takes)): if FBSystem().Scene.Takes[take_index].Selected == True: # go to take FBSystem().CurrentTake = FBSystem().Scene.Takes[take_index] AdjustmentBlendCharacter() else: AdjustmentBlendCharacter() run() import os from RS import Perforce as P4 from pyfbsdk import * import pythonidelib def popUp(pUpTitle, pUpMessage, btn1="Continue", btn2="Cancel"): input = FBMessageBox(pUpTitle, pUpMessage, btn1, btn2 ) return input def filename(path): withext = str(path.split('\\')[-1]) withoutext = withext.split('.')[0] return withoutext.upper() def fileChecks(fbx): fbxchecks = [False, False, False, False] fbxinfo = P4.GetFileState(fbx) if os.path.exists(fbx): fbxchecks[0] = True else: popUp("Unable to Check Out", "Could not find the file locally") if fbxchecks[0]: if P4.DoesFileExist(fbx): fbxchecks[1] = True else: if popUp("Unable to Check Out", "File does not exist in Perforce. Would you like to add it?") == 1: CL = P4.CreateChangelist("[SOURCE] - " + filename(fbx)) P4.Add(fbx, CL.Number, True) popUp("Checked Out", "FBX Added to CL %s" % CL.Number) if fbxchecks[1]: if not P4.IsOpenForEdit(fbxinfo): fbxchecks[2] = True else: popUp("Unable to Check Out", "File is already Checked out") if P4.IsLatest(fbxinfo): fbxchecks[3] = True else: if popUp("Not Latest Revision", "You do not have the latest revision of this file. Get latest now?") == 1: P4.Sync(fbx) if all(fbxchecks) == True: return True else: return False if fileChecks(FBApplication().FBXFileName): CL = P4.CreateChangelist("[SOURCE] - " + filename(FBApplication().FBXFileName)) P4.Edit(FBApplication().FBXFileName, CL.Number) popUp("Checked Out", "FBX Checked out in CL %s" % CL.Number) else: print "Checks failed" pythonidelib.FlushOutput() ####################################################################### # -- Quickly reduce keys on all animated curves of selected models -- ####################################################################### from pyfbsdk import * def reduceKeysOnSelected(): # Create a Key Reducing filter. cleanFilter = FBFilterManager().CreateFilter('Key Reducing') cleanFilter.PropertyList.Find('Precision').Data = 0.04 # -- Create an empty FBModelList selectedModels = FBModelList() topModel = None # -- Search all models, not just a particular branch selectionState = True # -- Return models that are selected, not deselected sortBySelectOrder = True # -- The last model in the list was selected most recently FBGetSelectedModels(selectedModels, topModel, selectionState, sortBySelectOrder) for model in selectedModels: for lProp in model.PropertyList: if lProp and lProp.IsAnimatable() and lProp.IsAnimated(): cleanFilter.Apply(lProp.GetAnimationNode(), True) reduceKeysOnSelected() ############################################################# # -- Quickly reduce all selected keys in the graph editor -- ############################################################# from pyfbsdk import * import pythonidelib pythonidelib.FlushOutput() def getSelectedModels(): # -- Create an empty FBModelList selectedModels = FBModelList() topModel = None # -- Search all models, not just a particular branch selectionState = True # -- Return models that are selected, not deselected sortBySelectOrder = True # -- The last model in the list was selected most recently FBGetSelectedModels(selectedModels, topModel, selectionState, sortBySelectOrder) return selectedModels def reduceSelectedKeys(): print "Starting Key Cleanup" # -- Create a Key Reducing filter. cleanFilter = FBFilterManager().CreateFilter( 'Key Reducing' ) cleanFilter.PropertyList.Find('Precision').Data = 0.04 # -- Create an empty list to be filled with nodes that have curves nodesWithCurves = [] # -- Create an empty dictionary for storing keyframe times selKeyTimes = {} # -- Create an empty list of frame times selKeyFrames = [] # -- For each model selected for model in getSelectedModels(): # -- Find its properties for lProp in model.PropertyList: # -- For each property, find if it is animated if lProp and lProp.IsAnimatable() and lProp.IsAnimated(): # ======== Finding Nodes capable of having FCurves ======= # -- If so, get the connected animation node animNode = lProp.GetAnimationNode() # -- Fine all children nodes of the connected animation node nodes = animNode.Nodes # -- If children nodes are found if len(nodes) > 0: # -- Add each one to our list for node in nodes: nodesWithCurves.append(node) # -- Otherwise add the anim node to our list else: nodesWithCurves.append(animNode) # ======== Finding Selected Keyframes ========== # -- For every node in our list for node in nodesWithCurves: # -- reset the selected key times dictionary selKeyTimes = {} # -- If the node has an FCurve if node.FCurve: # -- For each keyframe on the FCurve for key in node.FCurve.Keys: # -- If that key is selected if key.Selected == True: # -- Add the keyframe's time to the dictionary selKeyTimes[key.Time.GetFrame()] = key.Time # -- If at least one keyframe was selected if len(selKeyTimes) > 0: # -- Fill the list with the frame data from the dictionary for key in selKeyTimes: selKeyFrames.append(key) # -- Find the highest and lowest number in the frame list. This will be our filter range startTime = min(selKeyFrames) stopTime = max(selKeyFrames) # -- Set the range of our filter using the range of selected keyframes if startTime in selKeyTimes: if stopTime in selKeyTimes: cleanFilter.Start = selKeyTimes[startTime] cleanFilter.Stop = selKeyTimes[stopTime] # -- Apply the filter cleanFilter.Apply(node.FCurve) print "Cleaning keys on %s %s.%s from %r to %r" % (model.Name, animNode.Name, node.Name, startTime, stopTime) # -- Cleanup del (cleanFilter, nodesWithCurves, selKeyTimes, selKeyFrames) print "Key Cleanup Complete" reduceSelectedKeys() ################################################ # -- Lifted from Animal Tools created by Mangesh ################################################ from pyfbsdk import FBConstraintManager, FBModelList, FBGetSelectedModels def renameConstraint(con): if con.ReferenceGroupGetCount() in range(2,4): child = con.ReferenceGet(0) parent = con.ReferenceGet(1) type = con.Description if con.Description == 'Position From Positions': type = 'Position' elif con.Description == 'Rotation From Rotations': type = 'Rotation' elif con.Description == 'Scale From Scales': type = 'Scale' if child and parent: newName = type + ' - ' + parent.Name + ' > ' + child.Name con.Name = newName else: newName = type + ' - [EMPTY CONSTRAINT]' con.Name = newName def createConstraint(): selectedModels = FBModelList() FBGetSelectedModels(selectedModels, None, True, True) if len(selectedModels) <= 1 or len(selectedModels) > 2: lMgr = FBConstraintManager() lConst = lMgr.TypeCreateConstraint("Parent/Child") return lMgr = FBConstraintManager() lConst = lMgr.TypeCreateConstraint("Parent/Child") # get model & geometry lMdls = FBModelList() topModel = None selectionState = True sortBySelectOrder = True FBGetSelectedModels(lMdls, topModel, selectionState, sortBySelectOrder) mMdl = lMdls[1] lGeo = lMdls[0] # adding elements to the constraint slots lConst.ReferenceAdd(0, mMdl) lConst.ReferenceAdd(1, lGeo) # weight of the constraint lConst.Weight = 100 lConst.Active = False lConst.Snap() lConst.Lock = True renameConstraint(lConst) createConstraint()################################################ # -- Lifted from Animal Tools created by Mangesh ################################################ from pyfbsdk import FBConstraintManager, FBModelList, FBGetSelectedModels def renameConstraint(con): if con.ReferenceGroupGetCount() in range(2,4): child = con.ReferenceGet(0) parent = con.ReferenceGet(1) type = con.Description if con.Description == 'Position From Positions': type = 'Position' elif con.Description == 'Rotation From Rotations': type = 'Rotation' elif con.Description == 'Scale From Scales': type = 'Scale' if child and parent: newName = type + ' - ' + parent.Name + ' > ' + child.Name con.Name = newName else: newName = type + ' - [EMPTY CONSTRAINT]' con.Name = newName def createConstraint(): selectedModels = FBModelList() FBGetSelectedModels(selectedModels, None, True, True) if len(selectedModels) <= 1 or len(selectedModels) > 2: lMgr = FBConstraintManager() lConst = lMgr.TypeCreateConstraint("Parent/Child") return lMgr = FBConstraintManager() lConst = lMgr.TypeCreateConstraint("Parent/Child") # get model & geometry lMdls = FBModelList() topModel = None selectionState = True sortBySelectOrder = True FBGetSelectedModels(lMdls, topModel, selectionState, sortBySelectOrder) mMdl = lMdls[1] lGeo = lMdls[0] # adding elements to the constraint slots lConst.ReferenceAdd(0, mMdl) lConst.ReferenceAdd(1, lGeo) # weight of the constraint lConst.Weight = 100 lConst.Active = True lConst.Lock = True renameConstraint(lConst) createConstraint()################################################ # -- Lifted from Animal Tools created by Mangesh ################################################ from pyfbsdk import FBConstraintManager, FBModelList, FBGetSelectedModels def renameConstraint(con): if con.ReferenceGroupGetCount() in range(2,4): child = con.ReferenceGet(0) parent = con.ReferenceGet(1) type = con.Description if con.Description == 'Position From Positions': type = 'Position' elif con.Description == 'Rotation From Rotations': type = 'Rotation' elif con.Description == 'Scale From Scales': type = 'Scale' if child and parent: newName = type + ' - ' + parent.Name + ' > ' + child.Name con.Name = newName else: newName = type + ' - [EMPTY CONSTRAINT]' con.Name = newName def createConstraint(): selectedModels = FBModelList() FBGetSelectedModels(selectedModels, None, True, True) if len(selectedModels) <= 1 or len(selectedModels) > 2: lMgr = FBConstraintManager() lConst = lMgr.TypeCreateConstraint("Position") return lMgr = FBConstraintManager() lConst = lMgr.TypeCreateConstraint("Position") # get model & geometry lMdls = FBModelList() topModel = None selectionState = True sortBySelectOrder = True FBGetSelectedModels(lMdls, topModel, selectionState, sortBySelectOrder) mMdl = lMdls[1] lGeo = lMdls[0] # adding elements to the constraint slots lConst.ReferenceAdd(0, mMdl) lConst.ReferenceAdd(1, lGeo) # weight of the constraint lConst.Weight = 100 lConst.Active = False lConst.Snap() lConst.Lock = True renameConstraint(lConst) createConstraint()################################################ # -- Lifted from Animal Tools created by Mangesh ################################################ from pyfbsdk import FBConstraintManager, FBModelList, FBGetSelectedModels def renameConstraint(con): if con.ReferenceGroupGetCount() in range(2,4): child = con.ReferenceGet(0) parent = con.ReferenceGet(1) type = con.Description if con.Description == 'Position From Positions': type = 'Position' elif con.Description == 'Rotation From Rotations': type = 'Rotation' elif con.Description == 'Scale From Scales': type = 'Scale' if child and parent: newName = type + ' - ' + parent.Name + ' > ' + child.Name con.Name = newName else: newName = type + ' - [EMPTY CONSTRAINT]' con.Name = newName def createConstraint(): selectedModels = FBModelList() FBGetSelectedModels(selectedModels, None, True, True) if len(selectedModels) <= 1 or len(selectedModels) > 2: lMgr = FBConstraintManager() lConst = lMgr.TypeCreateConstraint("Position") return lMgr = FBConstraintManager() lConst = lMgr.TypeCreateConstraint("Position") # get model & geometry lMdls = FBModelList() topModel = None selectionState = True sortBySelectOrder = True FBGetSelectedModels(lMdls, topModel, selectionState, sortBySelectOrder) mMdl = lMdls[1] lGeo = lMdls[0] # adding elements to the constraint slots lConst.ReferenceAdd(0, mMdl) lConst.ReferenceAdd(1, lGeo) # weight of the constraint lConst.Weight = 100 lConst.Active = True lConst.Lock = True renameConstraint(lConst) createConstraint()################################################ # -- Lifted from Animal Tools created by Mangesh ################################################ from pyfbsdk import FBConstraintManager, FBModelList, FBGetSelectedModels def renameConstraint(con): if con.ReferenceGroupGetCount() in range(2,4): child = con.ReferenceGet(0) parent = con.ReferenceGet(1) type = con.Description if con.Description == 'Position From Positions': type = 'Position' elif con.Description == 'Rotation From Rotations': type = 'Rotation' elif con.Description == 'Scale From Scales': type = 'Scale' if child and parent: newName = type + ' - ' + parent.Name + ' > ' + child.Name con.Name = newName else: newName = type + ' - [EMPTY CONSTRAINT]' con.Name = newName def createConstraint(): selectedModels = FBModelList() FBGetSelectedModels(selectedModels, None, True, True) if len(selectedModels) <= 1 or len(selectedModels) > 2: lMgr = FBConstraintManager() lConst = lMgr.TypeCreateConstraint("Rotation") return lMgr = FBConstraintManager() lConst = lMgr.TypeCreateConstraint("Rotation") # get model & geometry lMdls = FBModelList() topModel = None selectionState = True sortBySelectOrder = True FBGetSelectedModels(lMdls, topModel, selectionState, sortBySelectOrder) mMdl = lMdls[1] lGeo = lMdls[0] # adding elements to the constraint slots lConst.ReferenceAdd(0, mMdl) lConst.ReferenceAdd(1, lGeo) # weight of the constraint lConst.Weight = 100 lConst.Active = False lConst.Snap() lConst.Lock = True renameConstraint(lConst) createConstraint()################################################ # -- Lifted from Animal Tools created by Mangesh ################################################ from pyfbsdk import FBConstraintManager, FBModelList, FBGetSelectedModels def renameConstraint(con): if con.ReferenceGroupGetCount() in range(2,4): child = con.ReferenceGet(0) parent = con.ReferenceGet(1) type = con.Description if con.Description == 'Position From Positions': type = 'Position' elif con.Description == 'Rotation From Rotations': type = 'Rotation' elif con.Description == 'Scale From Scales': type = 'Scale' if child and parent: newName = type + ' - ' + parent.Name + ' > ' + child.Name con.Name = newName else: newName = type + ' - [EMPTY CONSTRAINT]' con.Name = newName def createConstraint(): selectedModels = FBModelList() FBGetSelectedModels(selectedModels, None, True, True) if len(selectedModels) <= 1 or len(selectedModels) > 2: lMgr = FBConstraintManager() lConst = lMgr.TypeCreateConstraint("Rotation") return lMgr = FBConstraintManager() lConst = lMgr.TypeCreateConstraint("Rotation") # get model & geometry lMdls = FBModelList() topModel = None selectionState = True sortBySelectOrder = True FBGetSelectedModels(lMdls, topModel, selectionState, sortBySelectOrder) mMdl = lMdls[1] lGeo = lMdls[0] # adding elements to the constraint slots lConst.ReferenceAdd(0, mMdl) lConst.ReferenceAdd(1, lGeo) # weight of the constraint lConst.Weight = 100 lConst.Active = True lConst.Lock = True renameConstraint(lConst) createConstraint()from pyfbsdk import * def GetSelectedModels(): lModels = FBModelList() FBGetSelectedModels(lModels) return lModels def CreateMarker(name='Marker', color=FBColor(1, 0, 0)): marker = FBModelMarker(name) marker.Show = True marker.Look = FBMarkerLook.kFBMarkerLookHardCross marker.PropertyList.Find("Size").Data = 500 marker.PropertyList.Find("Color RGB").Data = color return marker def Align(pModel, pAlignTo): lAlignTransPos = FBVector3d(); lModelTransPos = FBVector3d(); lAlignRotPos = FBVector3d(); lModelRotPos = FBVector3d(); pAlignTo.GetVector(lAlignTransPos) pModel.GetVector(lModelTransPos) pAlignTo.GetVector(lAlignRotPos, FBModelTransformationType.kModelRotation) pModel.GetVector(lModelRotPos, FBModelTransformationType.kModelRotation) lModelTransPos[0] = lAlignTransPos[0] lModelTransPos[1] = lAlignTransPos[1] lModelTransPos[2] = lAlignTransPos[2] lModelRotPos[0] = lAlignRotPos[0] lModelRotPos[1] = lAlignRotPos[1] lModelRotPos[2] = lAlignRotPos[2] pModel.SetVector(lModelTransPos) pModel.SetVector(lModelRotPos, FBModelTransformationType.kModelRotation) del (lAlignRotPos, lAlignTransPos, lModelRotPos, lModelTransPos) def Run(): models = GetSelectedModels() if len(models) > 0: for model in models: color = FBColor(1, 0, 0) if model.PropertyList.Find("Color RGB"): color = model.Color marker = CreateMarker(model.Name + "_Marker", color) Align(marker, model) del (color, marker) else: CreateMarker() Run() from pyfbsdk import * import pythonidelib from RS.Tools.FirstPersonController import Core as fpsCore from RS import Globals from RS.Utils import Scene def getCharacterHeirarchyList(character): characterNodeList = [] hips = character.GetModel(FBBodyNodeId.kFBHipsNodeId) dummy = Scene.GetParent(hips) Scene.GetChildren(dummy, characterNodeList, "", True) return characterNodeList def findNode(name): foundNode = None # -- Get list of all nodes of current character currentCharacter = FBApplication().CurrentCharacter characterNodeList = getCharacterHeirarchyList(currentCharacter) # -- Check each node to see if it matches the desired name for node in characterNodeList: if node.Name == name: foundNode = node del (currentCharacter, characterNodeList) return foundNode def activateCamConstraint(): # -- Get the namespace of the current character charNSpace = Scene.Component.GetNamespace(FBApplication().CurrentCharacter) # -- Create empty variables to be filled camConstraint = None constraintFound = False charConstraints = [] # -- For each constraint in the scene, check if it matches the character's namespace for con in FBSystem().Scene.Constraints: if Scene.Component.GetNamespace(con) == charNSpace: charConstraints.append(con) # -- Go through each constraint that matched the character namespace and find the FPS_Cam_Constraint for con in charConstraints: if 'FPS_Cam_Constraint'.lower() in con.Name.lower(): camConstraint = con # -- If we found the FPS_Cam_Constraint, activate it if camConstraint: constraintFound = True camConstraint.Active = True # -- If we didn't, let the user know else: FBMessageBox("Quick Initialize CH Bones", "WARNING:\n No FPS Constraint found for current character. ", "Continue") del (charNSpace, camConstraint, charConstraints) return constraintFound def activateCHConstraints(activate): # -- Find the cone master coneM = findNode("coneMaster") # -- Create an empty list to fill with the constraint channels chConstraints = [] # -- If we found the cone master if coneM: # -- For For each property of the cone master # -- If it is one of the CH drivers # -- Add it to our list for prop in coneM.PropertyList: if prop.Name == "activate_L_constraint": chConstraints.append(prop) if prop.Name == "activate_R_constraint": chConstraints.append(prop) # -- If both channels are found if len(chConstraints) == 2: # -- Switch them on/off depending on how the function was called for constraint in chConstraints: constraint.Data = activate del (coneM, chConstraints) return True # -- If we didn't, let the user know else: FBMessageBox("Quick Initialize CH Bones", "WARNING:\n No coneMaster found for current character.", "Continue") del (coneM, chConstraints) return False def getNumberOfSelectedTakes(): number_of_selected_takes = 0 for take_index in range(len(FBSystem().Scene.Takes)): if FBSystem().Scene.Takes[take_index].Selected == True: number_of_selected_takes += 1 return number_of_selected_takes def plotOptions(): plot_options = FBPlotOptions() plot_options.PlotAllTakes = False plot_options.PlotOnFrame = True plot_options.PlotPeriod = FBTime(0, 0, 0, 1) plot_options.RotationFilterToApply = FBRotationFilter.kFBRotationFilterUnroll plot_options.UseConstantKeyReducer = False plot_options.ConstantKeyReducerKeepOneKey = True plot_options.PlotTranslationOnRootOnly = False return plot_options def plotSelected(): opt = plotOptions() FBSystem().CurrentTake.PlotTakeOnSelected(opt) def initializeCH(): # -- Check for animation nodes. If we find them, display an error message if keyedChannelCheck(): FBMessageBox("Quick Initialize CH Bones", "WARNING:\n Please remove any keys from 'activate_L_constraint' and ''activate_R_constraint' on the coneMaster ", "Continue") else: # -- Check to see if story mode is on isStoryMuted = FBStory().Mute # -- Then make sure its not muted and mute all the other tracks FBStory().Mute = False muteOtherCharTracks() # -- Then make sure its muted FBStory().Mute = True # -- Find the FPS_Cam and CH bones for the current character fpCam = findNode("FPS_Cam") chBones = [findNode("CH_L_Hand"), findNode("CH_R_Hand")] constraintFound = None coneMFound = None # -- If both ch bones are found if chBones[0] and chBones[1]: # -- And the first person camera is found if fpCam: # -- Switch on the cam constraint constraintFound = activateCamConstraint() # -- If the cam constraint was found if constraintFound: # --Switch on the CH Driver constraints coneMFound = activateCHConstraints(True) # -- If the cone master was found if coneMFound: # --Plot the CH bones to the selected takes for comp in FBSystem().Scene.Components: comp.Selected = False for bone in chBones: bone.Selected = True plotSelected() for bone in chBones: bone.Selected = False # --Switch off the CH Driver constraints activateCHConstraints(False) # -- If no ch bones were found let the user know else: FBMessageBox("Quick Initialize CH Bones", "WARNING:\n No CH DOFs found for current character. ", "Continue") # -- Set story mode back to how it was FBStory().Mute = isStoryMuted del (fpCam, chBones, isStoryMuted, constraintFound, coneMFound) def keyedChannelCheck(): # -- Find the cone master coneM = findNode("coneMaster") # -- Create an empty list to be filled with animation nodes animNodes = [] if coneM: # -- For each CH driver, see if it has an animation node. If so, add it to the list. for prop in coneM.PropertyList: if prop.Name == "activate_L_constraint": animNodes.append(prop.GetAnimationNode()) if prop.Name == "activate_R_constraint": animNodes.append(prop.GetAnimationNode()) # -- If any animation nodes ar found return true if any(animNodes): return True # -- otherwise false else: return False def ch_to_story(): chBones = [findNode("CH_L_Hand"), findNode("CH_R_Hand")] # -- Create a story track and clip for the current character track = FBStoryTrack(FBStoryTrackType.kFBStoryTrackAnimation, FBStory().RootFolder) track.ChangeDetailsBegin() for bone in chBones: track.Details.append(bone) track.ChangeDetailsEnd() track.Label = FBSystem().CurrentTake.Name clip = track.CopyTakeIntoTrack(FBSystem().CurrentTake.LocalTimeSpan, FBSystem().CurrentTake) return track def muteOtherCharTracks(): tracks = [] for lTrack in FBStory().RootFolder.Tracks: lTrack.Mute = True print lTrack.Name + " MUTED" print lTrack.Mute tracks.append(lTrack) return tracks def transfer(): FBSystem().Scene.Evaluate() take = FBSystem().CurrentTake chBones = [findNode("CH_L_Hand"), findNode("CH_R_Hand")] if take.Name.endswith("_FirstPersonPreview"): source_take_name = take.Name.rpartition("_")[0] source_take = None # switch to non preview take for t in FBSystem().Scene.Takes: if t.Name == source_take_name: source_take = t if source_take: dup_take = take.CopyTake("TEMP_" + take.Name) FBSystem().Scene.Evaluate() initializeCH() # add to story isStoryMuted = FBStory().Mute track = ch_to_story() FBStory().Mute = False FBSystem().CurrentTake = source_take FBSystem().Scene.Evaluate() for comp in FBSystem().Scene.Components: comp.Selected = False for bone in chBones: bone.Selected = True plotSelected() for bone in chBones: bone.Selected = False # delete story and delete dup take dup_take.FBDelete() track.FBDelete() FBStory().Mute = isStoryMuted FBSystem().CurrentTake = take else: FBMessageBox("Quick Initialize CH Bones", "WARNING:\n No source take found for: " + take.Name, "Continue") else: FBMessageBox("Quick Initialize CH Bones", "WARNING:\n" + take.Name + " is not a First Person Preview Take.", "Continue") def run(): # -- If more than 1 take is selected, if getNumberOfSelectedTakes() > 1: selected_takes = [] # -- go through each take for take in FBSystem().Scene.Takes: # -- If it is selected if take.Selected: selected_takes.append(take) for take in selected_takes: # -- Plot selected models to it FBSystem().CurrentTake = take transfer() else: transfer() run() pythonidelib.FlushOutput() # For each selected take # Duplicate it # Initialize the CH bones on it # Add the CH bones to story mode # Go to the "non preview" take and plot the ch bones # Delete the duplicate take from pyfbsdk import * def closest(list, Number): aux = [] for valor in list: aux.append(abs(Number - valor)) return aux.index(min(aux)) def ListMarkedTakes(): lSystem = FBSystem() markedTakes = [] for lTakeIdx in range(len(lSystem.Scene.Takes)): if lSystem.Scene.Takes[lTakeIdx].Name.startswith('>>>---'): markedTakes.append(lTakeIdx) return markedTakes def NextMarkedTake(): lSystem = FBSystem() lCurrentTakeName = lSystem.CurrentTake.Name markedTakes = ListMarkedTakes() # Look in the list until we find the index of the current take. if len(markedTakes) > 0: for lTakeIdx in range(len(lSystem.Scene.Takes)): if lSystem.Scene.Takes[lTakeIdx].Name == lCurrentTakeName: if lTakeIdx in markedTakes: lMarkedIdx = markedTakes.index(lTakeIdx) else: lMarkedIdx = closest(markedTakes, lTakeIdx) break; # Increment the index to point to the next take. lMarkedIdx = lMarkedIdx + 1 # Wrap around the end if the current take is the last. if lMarkedIdx == len(markedTakes): lMarkedIdx = 0 # Set the current take using our new index. lSystem.CurrentTake = lSystem.Scene.Takes[markedTakes[lMarkedIdx]] # Cleanup of local variables. del lMarkedIdx del (lSystem, lCurrentTakeName, markedTakes) NextMarkedTake() ################################################ # -- Lifted from Animal Tools created by Mangesh ################################################ from pyfbsdk import * def NextTake(): lSystem = FBSystem() lCurrentTakeName = lSystem.CurrentTake.Name # Look in the list until we find the index of the current take. for lTakeIdx in range( len( lSystem.Scene.Takes )): if lSystem.Scene.Takes[lTakeIdx].Name == lCurrentTakeName: break; # Increment the index to point to the next take. lTakeIdx = lTakeIdx + 1 # Wrap around the end if the current take is the last. if lTakeIdx == len( lSystem.Scene.Takes ): lTakeIdx = 0 # Set the current take using our new index. lSystem.CurrentTake = lSystem.Scene.Takes[lTakeIdx] # Cleanup of local variables. del( lSystem, lCurrentTakeName, lTakeIdx ) NextTake() from pyfbsdk import * def closest(list, Number): aux = [] for valor in list: aux.append(abs(Number - valor)) return aux.index(min(aux)) def ListMarkedTakes(): lSystem = FBSystem() markedTakes = [] for lTakeIdx in range(len(lSystem.Scene.Takes)): if lSystem.Scene.Takes[lTakeIdx].Name.startswith('>>>---'): markedTakes.append(lTakeIdx) return markedTakes def PrevMarkedTake(): lSystem = FBSystem() lCurrentTakeName = lSystem.CurrentTake.Name markedTakes = ListMarkedTakes() if len(markedTakes) > 0: # Look in the list until we find the index of the current take. for lTakeIdx in range(len(lSystem.Scene.Takes)): if lSystem.Scene.Takes[lTakeIdx].Name == lCurrentTakeName: if lTakeIdx in markedTakes: lMarkedIdx = markedTakes.index(lTakeIdx) else: lMarkedIdx = closest(markedTakes, lTakeIdx) break; # Decrement the index to point to the next take. # Here we take advantage of Python's subscripting access # where -1 points to the last object in the list, which is # where we want to be if the current take is the first in # the list. lMarkedIdx = lMarkedIdx - 1 # Set the current take using our new index. lSystem.CurrentTake = lSystem.Scene.Takes[markedTakes[lMarkedIdx]] # Cleanup of local variables. del lMarkedIdx del (lSystem, lCurrentTakeName, markedTakes) PrevMarkedTake() ################################################ # -- Lifted from Animal Tools created by Mangesh ################################################ from pyfbsdk import * def PrevTake(): lSystem = FBSystem() lCurrentTakeName = lSystem.CurrentTake.Name # Look in the list until we find the index of the current take. for lTakeIdx in range( len( lSystem.Scene.Takes )): if lSystem.Scene.Takes[lTakeIdx].Name == lCurrentTakeName: break; # Decrement the index to point to the next take. # Here we take advantage of Python's subscripting access # where -1 points to the last object in the list, which is # where we want to be if the current take is the first in # the list. lTakeIdx = lTakeIdx - 1 # Set the current take using our new index. lSystem.CurrentTake = lSystem.Scene.Takes[lTakeIdx] # Cleanup of local variables. del( lSystem, lCurrentTakeName, lTakeIdx ) PrevTake() from pyfbsdk import * from pyfbsdk_additions import * import pythonidelib from RS.Utils import Scene from RS import Globals from RS.Utils import Namespace, Creation #################################################################### # Utility Functions #################################################################### def PlotOptions(allTakes=False): # -- Default Options for plotting plot_options = FBPlotOptions() plot_options.PlotAllTakes = allTakes plot_options.PlotOnFrame = True plot_options.PlotPeriod = FBTime(0, 0, 0, 1) plot_options.RotationFilterToApply = FBRotationFilter.kFBRotationFilterUnroll plot_options.UseConstantKeyReducer = False plot_options.ConstantKeyReducerKeepOneKey = True plot_options.PlotTranslationOnRootOnly = False return plot_options def PlotModelList(listOfModels, allTakes=False): # -- Take a list of models and plot them Scene.DeSelectAll() for model in listOfModels: model.Selected = True FBSystem().CurrentTake.PlotTakeOnSelected(PlotOptions(allTakes)) Scene.DeSelectAll() def GetCharacterHeirarchyList(character): # -- Find all nodes for the current chatacyer characterNodeList = [] hips = character.GetModel(FBBodyNodeId.kFBHipsNodeId) dummy = Scene.GetParent(hips) Scene.GetChildren(dummy, characterNodeList, "", True) return characterNodeList def CreateMarker(name='Marker', look='HardCross', size=500, color=FBColor(1, 0, 0)): # -- Quick function for creating markers marker = FBModelMarker(name) looksDict = { "Cube": FBMarkerLook.kFBMarkerLookCube, "HardCross": FBMarkerLook.kFBMarkerLookHardCross, "LightCross": FBMarkerLook.kFBMarkerLookLightCross, "Sphere": FBMarkerLook.kFBMarkerLookSphere, "Capsule": FBMarkerLook.kFBMarkerLookCapsule, "Stick": FBMarkerLook.kFBMarkerLookStick, "Bone": FBMarkerLook.kFBMarkerLookBone, "None": FBMarkerLook.kFBMarkerLookNone } if look in looksDict.keys(): lookEnum = looksDict.get(look) else: lookEnum = FBMarkerLook.kFBMarkerLookHardCross marker.Show = True marker.Look = lookEnum marker.PropertyList.Find("Size").Data = size marker.PropertyList.Find("Color RGB").Data = color return marker def SwapConstraint(constraint): # -- Take a constraint and switch the 'Source' and 'objects child = constraint.ReferenceGet(0, 0) parent = constraint.ReferenceGet(1, 0) constraint.Active = False constraint.Lock = False constraint.ReferenceRemove(0, child) constraint.ReferenceRemove(1, parent) Globals.Scene.Evaluate() constraint.ReferenceAdd(0, parent) constraint.ReferenceAdd(1, child) constraint.Snap() constraint.Lock = True Globals.Scene.Evaluate() #################################################################### # UI Functions #################################################################### def PopulateTool(t): # -- Create a region for the main button x = FBAddRegionParam(5, FBAttachType.kFBAttachTop, "") y = FBAddRegionParam(5, FBAttachType.kFBAttachNone, "") w = FBAddRegionParam(240, FBAttachType.kFBAttachNone, "") h = FBAddRegionParam(30, FBAttachType.kFBAttachNone, "") t.AddRegion("main_button_region", "main_button_region", x, y, w, h) # -- Create the main button t.create_button = FBButton() t.SetControl("main_button_region", t.create_button) t.create_button.Visible = True t.create_button.ReadOnly = False t.create_button.Enabled = True t.create_button.Hint = "" t.create_button.Caption = "Create Camera Space Setup" t.create_button.State = 0 t.create_button.Style = FBButtonStyle.kFBPushButton t.create_button.Justify = FBTextJustify.kFBTextJustifyCenter t.create_button.Look = FBButtonLook.kFBLookNormal t.create_button.OnClick.Add(MainButtonCallback) # -- Set a bool to check if the setup has been created yet t.created = False ShowTool(t) def AddDeleteButton(t): # -- Add a second button the the UI # -- Create a region for the delete button x = FBAddRegionParam(5, FBAttachType.kFBAttachBottom, "") y = FBAddRegionParam(40, FBAttachType.kFBAttachNone, "") w = FBAddRegionParam(240, FBAttachType.kFBAttachNone, "") h = FBAddRegionParam(30, FBAttachType.kFBAttachNone, "") t.AddRegion("delete_button_region", "delete_button_region", x, y, w, h) # -- Create the delete button t.delete_button = FBButton() t.SetControl("delete_button_region", t.delete_button) t.delete_button.Visible = True t.delete_button.ReadOnly = False t.delete_button.Enabled = True t.delete_button.Hint = "" t.delete_button.Caption = "Delete Camera Space Setup" t.delete_button.State = 0 t.delete_button.Style = FBButtonStyle.kFBPushButton t.delete_button.Justify = FBTextJustify.kFBTextJustifyCenter t.delete_button.Look = FBButtonLook.kFBLookNormal t.delete_button.OnClick.Add(DeleteSetup) def CloseCallback(control, event): # -- Close the UI CloseTool(t) def CreateTool(): # -- Create the UI global t t = FBCreateUniqueTool("Hands To First Person Space") x = 250 y = 40 t.StartSizeX = x t.MinSizeX = x t.MaxSizeX = x t.StartSizeY = y t.MinSizeY = y t.MaxSizeY = y PopulateTool(t) #################################################################### # Setup Functions #################################################################### def MainButtonCallback(control, event): # -- Check to see if our setup has already been created if t.created == False: # -- If it hasn't, create one CreateSetup() else: # -- If it has, plot and delete PlotAndDeleteSetup() def CreateSetup(): # -- Find the current character character = FBApplication().CurrentCharacter # -- If a character is found if character: # -- Check to see if the character has a control rig if character.GetCurrentControlSet() == None: # -- If it doesn't, create one and plot from skeleton character.CreateControlRig(True) character.Active = False currentTake = FBSystem().CurrentTake for take_index in range(len(FBSystem().Scene.Takes)): # go to take FBSystem().CurrentTake = FBSystem().Scene.Takes[take_index] character.PlotAnimation(FBCharacterPlotWhere.kFBCharacterPlotOnControlRig, PlotOptions()) FBSystem().CurrentTake = currentTake # -- Set the character's source to "Control Rig" character.Active = True # -- Get all the character's nodes characterNodes = GetCharacterHeirarchyList(character) # -- Create an empty variable to be changed if we find a camera fpCam = None # -- Search through all the character's nodes for the first person camera for node in characterNodes: if node.Name == "FPS_Cam": # -- If it is found, change the empty variable fpCam = node # -- If a FPS camera was found if fpCam: # -- FInd the characters wrist effects lWrist = character.GetEffectorModel(FBEffectorId.kFBLeftWristEffectorId) rWrist = character.GetEffectorModel(FBEffectorId.kFBRightWristEffectorId) # -- Set the wrist IK to 100 on both wrists lWrist.PropertyList.Find("IK Reach Translation").Data = 100 lWrist.PropertyList.Find("IK Reach Rotation").Data = 100 rWrist.PropertyList.Find("IK Reach Translation").Data = 100 rWrist.PropertyList.Find("IK Reach Rotation").Data = 100 # -- Create a custom marker for our root camParent = CreateMarker("Root", 'Bone', 50, FBColor(0.0, 0.9, 1.0)) camParent.ProcessObjectNamespace(FBNamespaceAction.kFBConcatNamespace, "FPSpace") camParent.PropertyList.Find("Enable Transformation").Data = 0 camParent.PropertyList.Find("Enable Selection").Data = 0 # -- Create two markers for our custom hand controls lHandMarker = CreateMarker("Ctrl_LeftHand", 'Bone', 550, FBColor(0.0, 0.9, 1.0)) lHandMarker.ProcessObjectNamespace(FBNamespaceAction.kFBConcatNamespace, "FPSpace") rHandMarker = CreateMarker("Ctrl_RightHand", 'Bone', 550, FBColor(0.0, 0.9, 1.0)) rHandMarker.ProcessObjectNamespace(FBNamespaceAction.kFBConcatNamespace, "FPSpace") # -- Parent the hand controls to the root lHandMarker.Parent = camParent rHandMarker.Parent = camParent # -- Create a new constraint folder constraintFolder = Creation.rs_CreateFolder("Constraints", "FBConstraint") constraintFolder.ProcessObjectNamespace(FBNamespaceAction.kFBConcatNamespace, "FPSpace") # -- zero constrain the parent marker to the align point. Add a namespace rootCon = Scene.Constraint.Constraint( Scene.Constraint.PARENT_CHILD, "FPS_Cam > Root", camParent, fpCam, Active=True, Lock=True ) # -- Add the constraint to the constraint folder and add a namespace constraintFolder.Items.append(rootCon) rootCon.ProcessObjectNamespace(FBNamespaceAction.kFBConcatNamespace, "FPSpace") # -- zero constrain the left hand marker to the left hand. Add a namespace lHandCon = Scene.Constraint.Constraint( Scene.Constraint.PARENT_CHILD, "Ctrl_LeftHand > LeftWristEffector", lHandMarker, lWrist, Active=True, Lock=True ) # -- Add the constraint to the constraint folder and add a namespace constraintFolder.Items.append(lHandCon) lHandCon.ProcessObjectNamespace(FBNamespaceAction.kFBConcatNamespace, "FPSpace") # -- zero constrain the left hand marker to the left hand. Add a namespace rHandCon = Scene.Constraint.Constraint( Scene.Constraint.PARENT_CHILD, "Ctrl_RightHand > RightWristEffector", rHandMarker, rWrist, Active=True, Lock=True ) # -- Add the constraint to the constraint folder and add a namespace constraintFolder.Items.append(rHandCon) rHandCon.ProcessObjectNamespace(FBNamespaceAction.kFBConcatNamespace, "FPSpace") Globals.Scene.Evaluate() # -- Plot the custom hand controls and flip the constraints PlotModelList([lHandMarker, rHandMarker], allTakes=True) Globals.Scene.Evaluate() SwapConstraint(lHandCon) SwapConstraint(rHandCon) # -- Change the main button's caption t.create_button.Caption = "Plot and Delete Camera Space Setup" # -- Set a bool to check if the setup has been created yet t.created = True t.create_button.OnClick.Add(PlotAndDeleteSetup) # -- Run function that adds a new button AddDeleteButton(t) # -- Add some length to the UI to make room for the new button y = 75 t.MinSizeY = y t.MaxSizeY = y def PlotAndDeleteSetup(control=None, event=None): # -- Find the current Character character = FBApplication().CurrentCharacter # -- If a character was found if character: # -- Find the character's wrist effectors lWrist = character.GetEffectorModel(FBEffectorId.kFBLeftWristEffectorId) rWrist = character.GetEffectorModel(FBEffectorId.kFBRightWristEffectorId) # -- If both wrists were found if lWrist and rWrist: # -- Plot them on all takes PlotModelList([lWrist, rWrist], allTakes=True) # -- Delete the entire setup Globals.Scene.Evaluate() DeleteSetup() def DeleteSetup(control=None, event=None): # -- We gave all of objects and constraints in the setup a namespace # -- Get this namespace nameSpace = Namespace.GetFBNamespace("FPSpace") if nameSpace: # -- Delete all of the namespace's contents for item in Namespace.GetContents(nameSpace): item.FBDelete() Globals.Scene.Evaluate() # -- Delete the namespace nameSpace.FBDelete() del (nameSpace) # -- Close the UI CloseCallback(None, None) CreateTool() from pyfbsdk import * import pythonidelib from RS import Globals from RS.Utils.Scene import Component, Groups, GetParent, GetChildren def getCharacterHeirarchyList(character): characterNodeList = [] hips = character.GetModel(FBBodyNodeId.kFBHipsNodeId) dummy = GetParent(hips) GetChildren(dummy, characterNodeList, "", True) return characterNodeList def findNode(name): foundNode = None # -- Get list of all nodes of current character currentCharacter = FBApplication().CurrentCharacter characterNodeList = getCharacterHeirarchyList(currentCharacter) # -- Check each node to see if it matches the desired name for node in characterNodeList: if node.Name == name: foundNode = node del (currentCharacter, characterNodeList) return foundNode # -- Make a lest of meshes to add to group hideMeshes = [ findNode('player_zero_head_000'), findNode('player_zero_eyes_000'), findNode('player_zero_eyebrows_000'), findNode('player_zero_teeth_000'), ] groupnames = [] for group in Globals.Groups: groupnames.append(group.Name) # -- If any animation nodes ar found return true if "HeadMeshes" in groupnames: for group in Globals.Groups: if group.Name == "HeadMeshes": headGroup = group else: headGroup = FBGroup ("HeadMeshes") # -- If those meshes were found, select them them for mesh in hideMeshes: if mesh: # Adding the objects to the group headGroup.ConnectSrc(mesh) headGroup.Pickable = False if headGroup.Show == True: headGroup.Show = False else: headGroup.Show = Truefrom pyfbsdk import * from RS.Utils.Scene import Component, Groups, GetParent, GetChildren def getCharacterHeirarchyList(character): characterNodeList = [] hips = character.GetModel(FBBodyNodeId.kFBHipsNodeId) dummy = GetParent(hips) GetChildren(dummy, characterNodeList, "", True) return characterNodeList def findNode(name): foundNode = None # -- Get list of all nodes of current character currentCharacter = FBApplication().CurrentCharacter characterNodeList = getCharacterHeirarchyList(currentCharacter) # -- Check each node to see if it matches the desired name for node in characterNodeList: if node.Name == name: foundNode = node del (currentCharacter, characterNodeList) return foundNode # -- Get the namespace of the current character charNSpace = Component.GetNamespace(FBApplication().CurrentCharacter) # -- Get all groups associated with this namespace groups = Groups.GetGroupsFromNamespace(charNSpace) # -- Switch off the werables groups for group in groups: if group.Name == 'Wearables_Other' \ or group.Name == 'Wearables_Outfit' \ or group.Name == 'Sliders' \ or group.Name == 'FPSCamera': group.Show = False if group.Name == 'Geometry': group.Pickable = False # -- Make a lest of meshes to hide hideMeshes = [ findNode('player_zero_hair_000'), findNode('player_zero_scarf_002'), findNode('player_zero_scarf_002'), findNode('player_zero_satchel_strap_000'), findNode('CameraBasePivotOffset_Controller') ] # -- If those meshes were found, hiden them for mesh in hideMeshes: if mesh: mesh.Show = False#################################### # -- Quickly plot selected models -- #################################### from pyfbsdk import * import pythonidelib def getSelectedModels(): # -- Create an empty FBModelList selectedModels = FBModelList() topModel = None # -- Search all models, not just a particular branch selectionState = True # -- Return models that are selected, not deselected sortBySelectOrder = True # -- The last model in the list was selected most recently FBGetSelectedModels(selectedModels, topModel, selectionState, sortBySelectOrder) return selectedModels def getNumberOfSelectedTakes(): number_of_selected_takes = 0 for take_index in range(len(FBSystem().Scene.Takes)): if FBSystem().Scene.Takes[take_index].Selected == True: number_of_selected_takes += 1 return number_of_selected_takes def holdFirstFrame(): # -- Create an empty list to be filled with nodes that have curves nodesWithCurves = [] # -- Create an empty dictionary for storing keyframe times keyTimes = {} # -- Create an empty list of frame times keyFrames = [] # -- For each model selected for model in getSelectedModels(): # -- Find its properties for lProp in model.PropertyList: # -- For each property, find if it is animated if lProp and lProp.IsAnimatable() and lProp.IsAnimated(): # ======== Finding Nodes capable of having FCurves ======= # -- If so, get the connected animation node animNode = lProp.GetAnimationNode() # -- Find all children nodes of the connected animation node nodes = animNode.Nodes # -- If children nodes are found if len(nodes) > 0: # -- Add each one to our list for node in nodes: nodesWithCurves.append(node) # -- Otherwise add the anim node to our list else: nodesWithCurves.append(animNode) # ======== Finding Selected Keyframes ========== # -- For every node in our list for node in nodesWithCurves: # -- reset the selected key times dictionary curveKeys = node.FCurve.Keys keyTimes = {} # -- If the node has an FCurve if node.FCurve: # -- For each keyframe on the FCurve for key in curveKeys: print key pythonidelib.FlushOutput() # -- Add the keyframe's time to the dictionary keyTimes[key.Time.GetFrame()] = key.Time # -- Fill the list with the frame data from the dictionary for key in keyTimes: print key pythonidelib.FlushOutput() keyFrames.append(key) # -- Find the lowest number in the frame list. This will be our starting frame firstKey = min(keyFrames) secondKeyTime = FBTime(0, 0, 0, firstKey+1) lastKey = max(keyFrames) lastKeyTime = FBTime(0, 0, 0, lastKey) print firstKey print lastKey pythonidelib.FlushOutput() node.FCurve.KeyDeleteByTimeRange(secondKeyTime, lastKeyTime) # -- Cleanup del (nodesWithCurves, keyTimes, keyFrames) def Run(): # -- If at least one model is selected if len(getSelectedModels()) > 0: # -- If more than 1 take is selected, if getNumberOfSelectedTakes() > 1: # -- go through each take for take in FBSystem().Scene.Takes: # -- If it is selected if take.Selected == True: # -- Plot selected models to it FBSystem().CurrentTake = take holdFirstFrame() # -- annoying when you have one take selected different from the current - chances are the user didn't mean to. else: # -- Plot selected to current taKE holdFirstFrame() print "Plotting Complete" else: print "No Objects selected" Run() from pyfbsdk import * from pyfbsdk_additions import * import pythonidelib # -- For each constraint in the scene for con in FBSystem().Scene.Constraints: # -- For each constraint that is selected if con.Selected == True: # -- Set the weight channel as animated con.Weight.SetAnimated(True) # -- Apply the animation node and curve to variable weightNode = con.Weight.GetAnimationNode() weightCurve = weightNode.FCurve # -- Create a key with value 0 at the current frame key = weightCurve.KeyAdd(FBSystem().LocalTime, 0) # -- Assign the key to a variable weightKey = weightCurve.Keys[key] # -- Set the key to Auto and Clamped weightKey.TangentMode = FBTangentMode(2) weightKey.TangentClampMode = FBTangentClampMode(1) pythonidelib.FlushOutput() from pyfbsdk import * from pyfbsdk_additions import * import pythonidelib # -- For each constraint in the scene for con in FBSystem().Scene.Constraints: # -- For each constraint that is selected if con.Selected == True: # -- Set the weight channel as animated con.Weight.SetAnimated(True) # -- Apply the animation node and curve to variable weightNode = con.Weight.GetAnimationNode() weightCurve = weightNode.FCurve # -- Create a key with value 100 at the current frame key = weightCurve.KeyAdd(FBSystem().LocalTime, 100) # -- Assign the key to a variable weightKey = weightCurve.Keys[key] # -- Set the key to Auto and Clamped weightKey.TangentMode = FBTangentMode(2) weightKey.TangentClampMode = FBTangentClampMode(1) pythonidelib.FlushOutput() from pyfbsdk import * from pyfbsdk_additions import * def getSelectedModels(): # -- Create an empty FBModelList selectedModels = FBModelList() topModel = None # -- Search all models, not just a particular branch selectionState = True # -- Return models that are selected, not deselected sortBySelectOrder = True # -- The last model in the list was selected most recently FBGetSelectedModels(selectedModels, topModel, selectionState, sortBySelectOrder) return selectedModels def keySelectedIKOn(selected): for model in selected: ik_T = model.PropertyList.Find('IK Reach Translation') ik_R = model.PropertyList.Find('IK Reach Rotation') IKChannels = [ik_T, ik_R] for channel in IKChannels: if channel: # -- Set the channel as animated channel.SetAnimated(True) # -- Apply the animation node and curve to variable channelNode = channel.GetAnimationNode() channelCurve = channelNode.FCurve # -- Create a key with value 100 at the current frame key = channelCurve.KeyAdd(FBSystem().LocalTime, 0) # -- Assign the key to a variable channelKey = channelCurve.Keys[key] # -- Set the key to Auto and Clamped channelKey.TangentMode = FBTangentMode(2) channelKey.TangentClampMode = FBTangentClampMode(1) keySelectedIKOn(getSelectedModels()) from pyfbsdk import * from pyfbsdk_additions import * def getSelectedModels(): # -- Create an empty FBModelList selectedModels = FBModelList() topModel = None # -- Search all models, not just a particular branch selectionState = True # -- Return models that are selected, not deselected sortBySelectOrder = True # -- The last model in the list was selected most recently FBGetSelectedModels(selectedModels, topModel, selectionState, sortBySelectOrder) return selectedModels def keySelectedIKOn(selected): for model in selected: ik_T = model.PropertyList.Find('IK Reach Translation') ik_R = model.PropertyList.Find('IK Reach Rotation') IKChannels = [ik_T, ik_R] for channel in IKChannels: if channel: # -- Set the channel as animated channel.SetAnimated(True) # -- Apply the animation node and curve to variable channelNode = channel.GetAnimationNode() channelCurve = channelNode.FCurve # -- Create a key with value 100 at the current frame key = channelCurve.KeyAdd(FBSystem().LocalTime, 100) # -- Assign the key to a variable channelKey = channelCurve.Keys[key] # -- Set the key to Auto and Clamped channelKey.TangentMode = FBTangentMode(2) channelKey.TangentClampMode = FBTangentClampMode(1) keySelectedIKOn(getSelectedModels()) from pyfbsdk import * takes = FBSystem().Scene.Takes def getNumberOfSelectedTakes(): number_of_selected_takes = 0 for take_index in range(len(FBSystem().Scene.Takes)): if FBSystem().Scene.Takes[take_index].Selected == True: number_of_selected_takes += 1 return number_of_selected_takes if getNumberOfSelectedTakes() > 0: for take in takes: if take.Selected: newName = '>>>---' + take.Name take.Name = newName else: newName = '>>>---' + FBSystem().CurrentTake.Name FBSystem().CurrentTake.Name = newName #################################################### # Uses story mode to move the current take to zero #################################################### from pyfbsdk import * import pythonidelib # =================== Taken from Mike's mj_QuickPlot script ======================== def plotOptions(): plot_options = FBPlotOptions() plot_options.PlotAllTakes = False plot_options.PlotOnFrame = True plot_options.PlotPeriod = FBTime(0, 0, 0, 1) plot_options.RotationFilterToApply = FBRotationFilter.kFBRotationFilterUnroll plot_options.UseConstantKeyReducer = False plot_options.ConstantKeyReducerKeepOneKey = True plot_options.PlotTranslationOnRootOnly = False return plot_options def getNumberOfSelectedTakes(): number_of_selected_takes = 0 for take_index in range(len(FBSystem().Scene.Takes)): if FBSystem().Scene.Takes[take_index].Selected == True: number_of_selected_takes += 1 return number_of_selected_takes def plotToRig(character): character.PlotAnimation(FBCharacterPlotWhere.kFBCharacterPlotOnControlRig, plotOptions()) def plotToSkeleton(character): character.PlotAnimation(FBCharacterPlotWhere.kFBCharacterPlotOnSkeleton, plotOptions()) # ===================================================================================== def muteOtherCharTracks(): currChar = FBApplication().CurrentCharacter charTracks = [] for lTrack in FBStory().RootFolder.Tracks: lChar = lTrack.PropertyList.Find('Character') if lChar is not None: for d in lTrack.Details: if d == currChar: if lTrack.Mute == False: lTrack.Mute = True charTracks.append(lTrack) print "Story Track: %s temporarily muted" % lTrack.Name return charTracks def enableMutedTracks(charTracks): for lTrack in charTracks: lTrack.Mute = False print "Story Track: %s unmuted" % lTrack.Name def zeroStoryAndPlot(to_skeleton = True): # -- Assign important stuff to variables app = FBApplication() system = FBSystem() story = FBStory() take = system.CurrentTake char = FBApplication().CurrentCharacter # -- Create a story track and clip for the current character track = FBStoryTrack(FBStoryTrackType.kFBStoryTrackCharacter, story.RootFolder) track.Details.append(char) track.Label = system.CurrentTake.Name clip = track.CopyTakeIntoTrack(system.CurrentTake.LocalTimeSpan, system.CurrentTake) # -- Set the start of the clip to zero clip.PropertyList.Find('Start').Data = FBTime(0) # -- Assign the new end of the clip to a variable end = clip.PropertyList.Find('Stop').Data # -- Set the start and end of the current take to match the story clip take.LocalTimeSpan = FBTimeSpan( FBTime(0), end ) # -- If the character rig is active, plot it to the skeleton and plot to it back to the rig if to_skeleton == True: plotToSkeleton(char) plotToRig(char) # -- Otherwise just plot it straight to the skeleton else: plotToSkeleton(char) print "%s Moved to Zero" % (take.Name) clip.FBDelete() track.FBDelete() def moveTakesToZero(): # -- Get the current character current_character = FBApplication().CurrentCharacter # -- Need to create control rig first? if current_character.GetCurrentControlSet() == None: current_character.CreateControlRig(True) # -- Check if the current character is active if current_character.Active == True: to_skeleton = True else: to_skeleton = False # -- Get number of takes selected number_of_selected_takes = getNumberOfSelectedTakes() # if there is one selected take, still ignore it and use the current take # it's a bit annoying when you have one take selected different from the current - chances are the user didn't mean to. if number_of_selected_takes > 1: for take_index in range(len(FBSystem().Scene.Takes)): if FBSystem().Scene.Takes[take_index].Selected == True: # go to take FBSystem().CurrentTake = FBSystem().Scene.Takes[take_index] plotToSkeleton(current_character) zeroStoryAndPlot(to_skeleton) else: plotToSkeleton(current_character) zeroStoryAndPlot(to_skeleton) def Run(): if FBMessageBox("Move Take to Zero", "WARNING:\n This will plot the current character on all selected takes and cannot be undone.", "Continue", "Cancel" ) == 1: storymute = FBStory().Mute alreadymuted = False if storymute: alreadymuted = True FBStory().Mute = False mutedTracks = muteOtherCharTracks() moveTakesToZero() enableMutedTracks(mutedTracks) if alreadymuted == True: FBStory().Mute = True else: print "User cancelled" Run() pythonidelib.FlushOutput()from pyfbsdk import * from pyfbsdk_additions import * import pythonidelib # -- Create an empty list children = [] # -- For each selected constraint in the scene, add each child to the list for con in FBSystem().Scene.Constraints: if con.Selected == True: children.append(con.ReferenceGet(0)) # -- For each child in the list, set selection to true for c in children: c.Selected = True print str(c.Name) + " Selected" pythonidelib.FlushOutput()from pyfbsdk import * from pyfbsdk_additions import * import pythonidelib # -- Create an empty list parents = [] # -- For each selected constraint in the scene, add each child to the list for con in FBSystem().Scene.Constraints: if con.Selected == True: parents.append(con.ReferenceGet(1)) # -- For each parent in the list, set selection to true for p in parents: p.Selected = True print str(p.Name) + " Selected" pythonidelib.FlushOutput()from pyfbsdk import * from RS.Utils import Scene from RS import Globals def CreateConstraint(parent, child): con = Scene.Constraint.Constraint( Scene.Constraint.PARENT_CHILD, "Constraint", child, parent, Active=True, Lock=True ) return con def PlotOptions(): plot_options = FBPlotOptions() plot_options.PlotAllTakes = True plot_options.PlotOnFrame = True plot_options.PlotPeriod = FBTime(0, 0, 0, 1) plot_options.RotationFilterToApply = FBRotationFilter.kFBRotationFilterUnroll plot_options.UseConstantKeyReducer = False plot_options.ConstantKeyReducerKeepOneKey = True plot_options.PlotTranslationOnRootOnly = False return plot_options def PlotModelList(listOfModels): print listOfModels Scene.DeSelectAll() for model in listOfModels: model.Selected = True Globals.Scene.Evaluate() FBSystem().CurrentTake.PlotTakeOnSelected(PlotOptions()) Scene.DeSelectAll() def GetSelectedModels(): lModels = FBModelList() FBGetSelectedModels(lModels) return lModels def CreateMarker(name='Marker', color=FBColor(1, 0, 0)): marker = FBModelMarker(name) marker.Show = True marker.Look = FBMarkerLook.kFBMarkerLookHardCross marker.PropertyList.Find("Size").Data = 500 marker.PropertyList.Find("Color RGB").Data = color return marker def SwapConstraint(constraint): # -- Take a constraint and switch the 'Source' and 'objects child = constraint.ReferenceGet(0, 0) parent = constraint.ReferenceGet(1, 0) constraint.Active = False constraint.Lock = False constraint.ReferenceRemove(0, child) constraint.ReferenceRemove(1, parent) Globals.Scene.Evaluate() constraint.ReferenceAdd(0, parent) constraint.ReferenceAdd(1, child) constraint.Snap() constraint.Lock = True Globals.Scene.Evaluate() def Run(): models = GetSelectedModels() if len(models) > 0: constraints = [] markers = [] for model in models: color = FBColor(1, 0, 0) if model.PropertyList.Find("Color RGB"): color = model.Color marker = CreateMarker("PinToMarker - " + model.Name, color) markers.append(marker) con = CreateConstraint(model, marker) con.Name = "PinToMarker - " + model.Name constraints.append(con) if markers: PlotModelList(markers) Globals.Scene.Evaluate() if constraints: for con in constraints: SwapConstraint(con) Globals.Scene.Evaluate() Run() from pyfbsdk import * from RS.Utils import Scene from RS import Globals def CreateConstraint(parent, child): con = Scene.Constraint.Constraint( Scene.Constraint.PARENT_CHILD, "Constraint", child, parent, Active=True, Lock=True ) return con def PlotOptions(): plot_options = FBPlotOptions() plot_options.PlotAllTakes = True plot_options.PlotOnFrame = True plot_options.PlotPeriod = FBTime(0, 0, 0, 1) plot_options.RotationFilterToApply = FBRotationFilter.kFBRotationFilterUnroll plot_options.UseConstantKeyReducer = False plot_options.ConstantKeyReducerKeepOneKey = True plot_options.PlotTranslationOnRootOnly = False return plot_options def PlotModelList(listOfModels): print listOfModels Scene.DeSelectAll() for model in listOfModels: model.Selected = True Globals.Scene.Evaluate() FBSystem().CurrentTake.PlotTakeOnSelected(PlotOptions()) Scene.DeSelectAll() def GetSelectedModels(): lModels = FBModelList() FBGetSelectedModels(lModels) return lModels def CreateMarker(name='Marker', color=FBColor(1, 0, 0)): marker = FBModelMarker(name) marker.Show = True marker.Look = FBMarkerLook.kFBMarkerLookHardCross marker.PropertyList.Find("Size").Data = 500 marker.PropertyList.Find("Color RGB").Data = color return marker def Run(): models = GetSelectedModels() if len(models) > 0: constraints = [] markers = [] for model in models: color = FBColor(1, 0, 0) if model.PropertyList.Find("Color RGB"): color = model.Color marker = CreateMarker("PlotToMarker - " + model.Name, color) markers.append(marker) con = CreateConstraint(model, marker) con.Name = "PlotToMarker - " + model.Name constraints.append(con) if markers: PlotModelList(markers) if constraints: for constraint in constraints: constraint.FBDelete() Globals.Scene.Evaluate() Run() from pyfbsdk import * from RS import Globals from RS.Utils import Scene import pythonidelib def getCharacterHeirarchyList(character): characterNodeList = [] hips = character.GetModel(FBBodyNodeId.kFBHipsNodeId) dummy = Scene.GetParent(hips) Scene.GetChildren(dummy, characterNodeList, "", True) return characterNodeList def findNode(name): foundNode = None # -- Get list of all nodes of current character currentCharacter = FBApplication().CurrentCharacter characterNodeList = getCharacterHeirarchyList(currentCharacter) # -- Check each node to see if it matches the desired name for node in characterNodeList: if node.Name == name: foundNode = node del (currentCharacter, characterNodeList) return foundNode def activateCamConstraint(): # -- Get the namespace of the current character charNSpace = Scene.Component.GetNamespace(FBApplication().CurrentCharacter) # -- Create empty variables to be filled camConstraint = None constraintFound = False charConstraints = [] # -- For each constraint in the scene, check if it matches the character's namespace for con in FBSystem().Scene.Constraints: if Scene.Component.GetNamespace(con) == charNSpace: charConstraints.append(con) # -- Go through each constraint that matched the character namespace and find the FPS_Cam_Constraint for con in charConstraints: if 'FPS_Cam_Constraint'.lower() in con.Name.lower(): camConstraint = con # -- If we found the FPS_Cam_Constraint, activate it if camConstraint: constraintFound = True camConstraint.Active = True # -- If we didn't, let the user know else: FBMessageBox("Quick Initialize CH Bones", "WARNING:\n No FPS Constraint found for current character. ", "Continue") del (charNSpace, camConstraint, charConstraints) return constraintFound def activateCHConstraints(activate): # -- Find the cone master coneM = findNode("coneMaster") # -- Create an empty list to fill with the constraint channels chConstraints = [] # -- If we found the cone master if coneM: # -- For For each property of the cone master # -- If it is one of the CH drivers # -- Add it to our list for prop in coneM.PropertyList: if prop.Name == "activate_L_constraint": chConstraints.append(prop) if prop.Name == "activate_R_constraint": chConstraints.append(prop) # -- If both channels are found if len(chConstraints) == 2: # -- Switch them on/off depending on how the function was called for constraint in chConstraints: constraint.Data = activate del (coneM, chConstraints) return True # -- If we didn't, let the user know else: FBMessageBox("Quick Initialize CH Bones", "WARNING:\n No coneMaster found for current character.", "Continue") del (coneM, chConstraints) return False def getNumberOfSelectedTakes(): number_of_selected_takes = 0 for take_index in range(len(FBSystem().Scene.Takes)): if FBSystem().Scene.Takes[take_index].Selected == True: number_of_selected_takes += 1 return number_of_selected_takes def plotOptions(): plot_options = FBPlotOptions() plot_options.PlotAllTakes = False plot_options.PlotOnFrame = True plot_options.PlotPeriod = FBTime(0, 0, 0, 1) plot_options.RotationFilterToApply = FBRotationFilter.kFBRotationFilterUnroll plot_options.UseConstantKeyReducer = False plot_options.ConstantKeyReducerKeepOneKey = True plot_options.PlotTranslationOnRootOnly = False return plot_options def plotSelected(take): opt = plotOptions() take.PlotTakeOnSelected(opt) def plotOnSelectedTakes(bones): selection = [] # -- If more than 1 take is selected, if getNumberOfSelectedTakes() > 1: takesToPlot = [] # -- Store the takes the user has selected for take in FBSystem().Scene.Takes: if take.Selected == True: takesToPlot.append(take) # -- Store the user selection and deselect everything for comp in FBSystem().Scene.Components: if comp.Selected == True: selection.append(comp) comp.Selected = False # -- Select the ch bones for bone in bones: bone.Selected = True # -- Go through each selected take for take in takesToPlot: # -- Plot selected models to it plotSelected(take) print "CH Bones Initialized for take: " + str(take.Name) # -- Deselect the bones for bones in bones: bones.Selected = False # -- Reselect the user selection for object in selection: object.Selected = True del (selection, takesToPlot) # -- annoying when you have one take selected different from the current - chances are the user didn't mean to. else: # -- Store the user selection and deselect everything for comp in FBSystem().Scene.Components: if comp.Selected == True: selection.append(comp) comp.Selected = False # -- Select the ch bones for bone in bones: bone.Selected = True # -- Plot selected to current take take = FBSystem().CurrentTake plotSelected(take) print "CH Bones Initialized for current take" # -- Deselect the bones for bones in bones: bones.Selected = False # -- Reselect the user selection for object in selection: object.Selected = True del selection def initializeCH(): # -- Check for animation nodes. If we find them, display an error message if keyedChannelCheck(): FBMessageBox("Quick Initialize CH Bones", "WARNING:\n Please remove any keys from 'activate_L_constraint' and ''activate_R_constraint' on the coneMaster ", "Continue") else: # -- Check to see if story mode is on isStoryMuted = FBStory().Mute # -- Then make sure its off FBStory().Mute = True # -- Find the FPS_Cam and CH bones for the current character fpCam = findNode("FPS_Cam") chBones = [findNode("CH_L_Hand"), findNode("CH_R_Hand")] constraintFound = None coneMFound = None # -- If both ch bones are found if chBones[0] and chBones[1]: # -- And the first person camera is found if fpCam: # -- Switch on the cam constraint constraintFound = activateCamConstraint() # -- If the cam constraint was found if constraintFound: # --Switch on the CH Driver constraints coneMFound = activateCHConstraints(True) # -- If the cone master was found if coneMFound: # --Plot the CH bones to the selected takes plotOnSelectedTakes(chBones) # --Switch off the CH Driver constraints activateCHConstraints(False) # -- If no ch bones were found let the user know else: FBMessageBox("Quick Initialize CH Bones", "WARNING:\n No CH DOFs found for current character. ", "Continue") # -- Set story mode back to how it was FBStory().Mute = isStoryMuted del (fpCam, chBones, isStoryMuted, constraintFound, coneMFound) def keyedChannelCheck(): # -- Find the cone master coneM = findNode("coneMaster") # -- Create an empty list to be filled with animation nodes animNodes = [] if coneM: # -- For each CH driver, see if it has an animation node. If so, add it to the list. for prop in coneM.PropertyList: if prop.Name == "activate_L_constraint": animNodes.append(prop.GetAnimationNode()) if prop.Name == "activate_R_constraint": animNodes.append(prop.GetAnimationNode()) # -- If any animation nodes ar found return true if any(animNodes): return True # -- otherwise false else: return False initializeCH() Globals.Scene.Evaluate() pythonidelib.FlushOutput()from pyfbsdk import * from RS import Globals from RS.Utils import Scene import pythonidelib def getCharacterHeirarchyList(character): characterNodeList = [] hips = character.GetModel(FBBodyNodeId.kFBHipsNodeId) dummy = Scene.GetParent(hips) Scene.GetChildren(dummy, characterNodeList, "", True) return characterNodeList def findNode(name): foundNode = None # -- Get list of all nodes of current character currentCharacter = FBApplication().CurrentCharacter characterNodeList = getCharacterHeirarchyList(currentCharacter) # -- Check each node to see if it matches the desired name for node in characterNodeList: if node.Name == name: foundNode = node del (currentCharacter, characterNodeList) return foundNode def activateCamConstraint(): # -- Get the namespace of the current character charNSpace = Scene.Component.GetNamespace(FBApplication().CurrentCharacter) # -- Create empty variables to be filled camConstraint = None constraintFound = False charConstraints = [] # -- For each constraint in the scene, check if it matches the character's namespace for con in FBSystem().Scene.Constraints: if Scene.Component.GetNamespace(con) == charNSpace: charConstraints.append(con) # -- Go through each constraint that matched the character namespace and find the FPS_Cam_Constraint for con in charConstraints: if 'FPS_Cam_Constraint'.lower() in con.Name.lower(): camConstraint = con # -- If we found the FPS_Cam_Constraint, activate it if camConstraint: constraintFound = True camConstraint.Active = True # -- If we didn't, let the user know else: FBMessageBox("Quick Initialize CH Bones", "WARNING:\n No FPS Constraint found for current character. ", "Continue") del (charNSpace, camConstraint, charConstraints) return constraintFound def activateCHConstraints(activate): # -- Find the cone master coneM = findNode("coneMaster") # -- Create an empty list to fill with the constraint channels chConstraints = [] # -- If the conemaster was found: if coneM: # -- For For each property of the cone master # -- If it is one of the CH drivers # -- Add it to our list for prop in coneM.PropertyList: if prop.Name == "activate_L_constraint": chConstraints.append(prop) if prop.Name == "activate_R_constraint": chConstraints.append(prop) # -- If both channels are found if len(chConstraints) == 2: # -- Switch them on/off depending on how the function was called for constraint in chConstraints: constraint.Data = activate del (coneM, chConstraints) return True # -- If we didn't, let the user know else: FBMessageBox("Quick Initialize CH Bones", "WARNING:\n No coneMaster found for current character.", "Continue") del (coneM, chConstraints) return False def getNumberOfSelectedTakes(): number_of_selected_takes = 0 for take_index in range(len(FBSystem().Scene.Takes)): if FBSystem().Scene.Takes[take_index].Selected == True: number_of_selected_takes += 1 return number_of_selected_takes def plotOptions(): plot_options = FBPlotOptions() plot_options.PlotAllTakes = False plot_options.PlotOnFrame = True plot_options.PlotPeriod = FBTime(0, 0, 0, 1) plot_options.RotationFilterToApply = FBRotationFilter.kFBRotationFilterUnroll plot_options.UseConstantKeyReducer = False plot_options.ConstantKeyReducerKeepOneKey = True plot_options.PlotTranslationOnRootOnly = False return plot_options def plotSelected(take): opt = plotOptions() take.PlotTakeOnSelected(opt) def plotOnAllTakes(bones): selection = [] takesToPlot = [] # -- Get every take in the scene for take in FBSystem().Scene.Takes: takesToPlot.append(take) # -- Store the user selection and deselect everything for comp in FBSystem().Scene.Components: if comp.Selected == True: selection.append(comp) comp.Selected = False # -- Select the ch bones for bone in bones: bone.Selected = True # -- Go through each take for take in takesToPlot: # -- Plot selected models to it plotSelected(take) print "CH Bones Initialized for take: " + str(take.Name) # -- Deselect the bones for bones in bones: bones.Selected = False # -- Reselect the user selection for object in selection: object.Selected = True del (selection, takesToPlot) def initializeCH(): # -- Check for animation nodes. If we find them, display an error message if keyedChannelCheck(): FBMessageBox("Quick Initialize CH Bones", "WARNING:\n Please remove any keys from 'activate_L_constraint' and ''activate_R_constraint' on the coneMaster ", "Continue") else: # -- Check to see if story mode is on isStoryMuted = FBStory().Mute # -- Then make sure its off FBStory().Mute = True # -- Find the FPS_Cam and CH bones for the current character fpCam = findNode("FPS_Cam") chBones = [findNode("CH_L_Hand"), findNode("CH_R_Hand")] constraintFound = None coneMFound = None # -- If both ch bones are found if chBones[0] and chBones[1]: # -- And the first person camera is found if fpCam: # -- Switch on the cam constraint constraintFound = activateCamConstraint() # --If the cam constraint was found if constraintFound: # --Switch on the CH Driver constraints coneMFound = activateCHConstraints(True) # -- If the cne master was found if coneMFound: # --Plot the CH bones to the selected takes plotOnAllTakes(chBones) # --Switch off the CH Driver constraints activateCHConstraints(False) # -- If no ch bones were found let the user know else: FBMessageBox("Quick Initialize CH Bones", "WARNING:\n No CH DOFs found for current character. ", "Continue") # -- Set story mode back to how it was FBStory().Mute = isStoryMuted del (fpCam, chBones, isStoryMuted, constraintFound, coneMFound) def keyedChannelCheck(): # -- Find the cone master coneM = findNode("coneMaster") # -- Create an empty list to be filled with animation nodes animNodes = [] # -- If the cone master was found if coneM: # -- For each CH driver, see if it has an animation node. If so, add it to the list. for prop in coneM.PropertyList: if prop.Name == "activate_L_constraint": animNodes.append(prop.GetAnimationNode()) if prop.Name == "activate_R_constraint": animNodes.append(prop.GetAnimationNode()) # -- If any animation nodes ar found return true if any(animNodes): return True # -- otherwise false else: return False initializeCH() Globals.Scene.Evaluate() pythonidelib.FlushOutput()#################################################################### # Quickly Plot either down to skeleton or vice versa depending on current state #################################################################### from pyfbsdk import * import RS.Globals import RS.Core as Core def plotOptions(): plot_options = FBPlotOptions() plot_options.PlotAllTakes = False plot_options.PlotOnFrame = True plot_options.PlotPeriod = FBTime(0, 0, 0, 1) plot_options.RotationFilterToApply = FBRotationFilter.kFBRotationFilterUnroll plot_options.UseConstantKeyReducer = False plot_options.ConstantKeyReducerKeepOneKey = True plot_options.PlotTranslationOnRootOnly = False return plot_options def getNumberOfSelectedTakes(): number_of_selected_takes = 0 for take_index in range(len(FBSystem().Scene.Takes)): if FBSystem().Scene.Takes[take_index].Selected == True: number_of_selected_takes += 1 return number_of_selected_takes def plotToRig(character): character.PlotAnimation(FBCharacterPlotWhere.kFBCharacterPlotOnControlRig, plotOptions()) def plotToSkeleton(character): character.PlotAnimation(FBCharacterPlotWhere.kFBCharacterPlotOnSkeleton, plotOptions()) def ToggleDevices(): for device in FBSystem().Scene.Devices: device.Online = not device.Online def QuickPlot(): # ToggleDevices() current_character = FBApplication().CurrentCharacter # need to create control rig first? if current_character.GetCurrentControlSet() == None: current_character.CreateControlRig(True) if current_character.Active == True: to_skeleton = True else: to_skeleton = False number_of_selected_takes = getNumberOfSelectedTakes() # if there is one selected take, still ignore it and use the current take # it's a bit annoying when you have one take selected different from the current - chances are the user didn't mean to. if number_of_selected_takes > 1: for take_index in range(len(FBSystem().Scene.Takes)): if FBSystem().Scene.Takes[take_index].Selected == True: # go to take FBSystem().CurrentTake = FBSystem().Scene.Takes[take_index] if to_skeleton == True: plotToSkeleton(current_character) else: plotToRig(current_character) else: if to_skeleton == True: for character in Core.System.Scene.Characters: plotToSkeleton(character) else: for character in Core.System.Scene.Characters: plotToRig(character) # ToggleDevices() print "Plotting Complete" #################################################################### # Main #################################################################### QuickPlot()#################################### # -- Quickly plot selected models -- #################################### from pyfbsdk import * from pyfbsdk_additions import * def getSelectedModels(): # -- Create an empty FBModelList selectedModels = FBModelList() topModel = None # -- Search all models, not just a particular branch selectionState = True # -- Return models that are selected, not deselected sortBySelectOrder = True # -- The last model in the list was selected most recently FBGetSelectedModels(selectedModels, topModel, selectionState, sortBySelectOrder) return selectedModels def getNumberOfSelectedTakes(): number_of_selected_takes = 0 for take_index in range(len(FBSystem().Scene.Takes)): if FBSystem().Scene.Takes[take_index].Selected == True: number_of_selected_takes += 1 return number_of_selected_takes def plotOptions(): plot_options = FBPlotOptions() plot_options.PlotAllTakes = False plot_options.PlotOnFrame = True plot_options.PlotPeriod = FBTime(0, 0, 0, 1) plot_options.RotationFilterToApply = FBRotationFilter.kFBRotationFilterUnroll plot_options.UseConstantKeyReducer = False plot_options.ConstantKeyReducerKeepOneKey = True plot_options.PlotTranslationOnRootOnly = False return plot_options def plotSelected(take): opt = plotOptions() take.PlotTakeOnSelected(opt) def QuickPlot(): # -- Get selected models sel = getSelectedModels() # -- If at least one model is selected if len(sel) > 0: # -- If more than 1 take is selected, if getNumberOfSelectedTakes() > 1: # -- go through each take for take in FBSystem().Scene.Takes: # -- If it is selected if take.Selected == True: # -- Plot selected models to it plotSelected(take) print "Selected Objects plotted to " + str(take.Name) # -- annoying when you have one take selected different from the current - chances are the user didn't mean to. else: # -- Plot selected to current taKE take = FBSystem().CurrentTake plotSelected(take) print "Selected Objects plotted to current take" print "Plotting Complete" else: print "No Objects selected" QuickPlot()#################################################### # Uses story mode to move the current take to zero #################################################### from pyfbsdk import * import pythonidelib # =================== Taken from Mike's mj_QuickPlot script ======================== def plotOptions(): plot_options = FBPlotOptions() plot_options.PlotAllTakes = False plot_options.PlotOnFrame = True plot_options.PlotPeriod = FBTime(0, 0, 0, 1) plot_options.RotationFilterToApply = FBRotationFilter.kFBRotationFilterUnroll plot_options.UseConstantKeyReducer = False plot_options.ConstantKeyReducerKeepOneKey = True plot_options.PlotTranslationOnRootOnly = False return plot_options def getNumberOfSelectedTakes(): number_of_selected_takes = 0 for take_index in range(len(FBSystem().Scene.Takes)): if FBSystem().Scene.Takes[take_index].Selected == True: number_of_selected_takes += 1 return number_of_selected_takes def plotToRig(character): character.PlotAnimation(FBCharacterPlotWhere.kFBCharacterPlotOnControlRig, plotOptions()) def plotToSkeleton(character): character.PlotAnimation(FBCharacterPlotWhere.kFBCharacterPlotOnSkeleton, plotOptions()) # ===================================================================================== def muteOtherCharTracks(): currChar = FBApplication().CurrentCharacter charTracks = [] for lTrack in FBStory().RootFolder.Tracks: lChar = lTrack.PropertyList.Find('Character') if lChar is not None: for d in lTrack.Details: if d == currChar: if lTrack.Mute == False: lTrack.Mute = True charTracks.append(lTrack) # print "Story Track: %s temporarily muted" % lTrack.Name return charTracks def enableMutedTracks(charTracks): for lTrack in charTracks: lTrack.Mute = False # print "Story Track: %s unmuted" % lTrack.Name def scaleStoryAndPlot(ratescale, to_skeleton = True): # -- Assign important stuff to variables app = FBApplication() system = FBSystem() story = FBStory() take = system.CurrentTake char = FBApplication().CurrentCharacter # -- Create a story track and clip for the current character track = FBStoryTrack(FBStoryTrackType.kFBStoryTrackCharacter, story.RootFolder) track.Details.append(char) track.Label = system.CurrentTake.Name clip = track.CopyTakeIntoTrack(system.CurrentTake.LocalTimeSpan, system.CurrentTake) # -- Get some time information about the clip we created lSpeed = clip.PropertyList.Find('Speed') lStart = clip.PropertyList.Find('Start') lStop = clip.PropertyList.Find('Stop') # -- Use the start and end of the clip to determine the length oldLength = lStop.Data.GetFrame() - lStart.Data.GetFrame() # -- Calculate a new length based on the ratescale fScaledLength = float(oldLength / ratescale) # -- Convert length to an integer (and round up) iScaledLength = int(fScaledLength) # -- Set the speed of the clip to the desired ratescale lSpeed.Data = ratescale # -- Use the new length, added to the current start time, to assign a new stop time lStop.Data = FBTime(0, 0, 0, lStart.Data.GetFrame() + iScaledLength, 0) # -- Assign the new end of the clip to a variable end = clip.PropertyList.Find('Stop').Data # -- Set the start and end of the current take to match the story clip take.LocalTimeSpan = FBTimeSpan( lStart.Data, end ) # -- Add 1 frame to the end of the clip as padding lStop.Data = FBTime(0, 0, 0, lStop.Data.GetFrame() + 1, 0) # -- If the character rig is active, plot it to the skeleton and plot to it back to the rig if to_skeleton == True: plotToSkeleton(char) plotToRig(char) # -- Otherwise just plot it straight to the skeleton else: plotToSkeleton(char) print "%s rate scaled to %s" % (take.Name, round(ratescale,1)) clip.FBDelete() track.FBDelete() def ratescaleTakes(ratescale): # -- Get the current character current_character = FBApplication().CurrentCharacter # -- Need to create control rig first? if current_character.GetCurrentControlSet() == None: current_character.CreateControlRig(True) # -- Check if the current character is active if current_character.Active == True: to_skeleton = True else: to_skeleton = False # -- Get number of takes selected number_of_selected_takes = getNumberOfSelectedTakes() # if there is one selected take, still ignore it and use the current take # it's a bit annoying when you have one take selected different from the current - chances are the user didn't mean to. if number_of_selected_takes > 1: for take_index in range(len(FBSystem().Scene.Takes)): if FBSystem().Scene.Takes[take_index].Selected == True: # go to take FBSystem().CurrentTake = FBSystem().Scene.Takes[take_index] plotToSkeleton(current_character) scaleStoryAndPlot(ratescale, to_skeleton) else: plotToSkeleton(current_character) scaleStoryAndPlot(ratescale, to_skeleton) def Run(): # -- Get the amount that the user wants to scale and let them confirm they want to plot all selected takes pUpTitle = "Rate Scale Takes" pUpMessage = """WARNING:\n This will plot the current character on all selected takes and cannot be undone.\n\nRate Scale Amount:""" input = FBMessageBoxGetUserValue( pUpTitle, pUpMessage, 1.0, FBPopupInputType.kFBPopupFloat, "Continue", "Cancel" ) if input[0] == 1: storymute = FBStory().Mute alreadymuted = False if storymute: alreadymuted = True FBStory().Mute = False mutedTracks = muteOtherCharTracks() ratescaleTakes(input[1]) enableMutedTracks(mutedTracks) if alreadymuted == True: FBStory().Mute = True else: print "User cancelled" Run() pythonidelib.FlushOutput()from pyfbsdk import * from pyfbsdk_additions import * def renameConstraint(con): if con.ReferenceGroupGetCount() in range(2,4): child = con.ReferenceGet(0) parent = con.ReferenceGet(1) type = con.Description if con.Description == 'Position From Positions': type = 'Position' elif con.Description == 'Rotation From Rotations': type = 'Rotation' elif con.Description == 'Scale From Scales': type = 'Scale' if child and parent: newName = type + ' - ' + parent.Name + ' > ' + child.Name con.Name = newName else: newName = type + ' - [EMPTY CONSTRAINT]' con.Name = newName # -- For each constraint in the scene for con in FBSystem().Scene.Constraints: # -- If the constraint is selected if con.Selected == True: renameConstraint(con) from pyfbsdk import * import pythonidelib from RS.Tools.FirstPersonController import Core as fpsCore from RS import Globals from RS.Utils import Scene def getCharacterHeirarchyList(character): characterNodeList = [] hips = character.GetModel(FBBodyNodeId.kFBHipsNodeId) dummy = Scene.GetParent(hips) Scene.GetChildren(dummy, characterNodeList, "", True) return characterNodeList def findNode(name): foundNode = None # -- Get list of all nodes of current character currentCharacter = FBApplication().CurrentCharacter characterNodeList = getCharacterHeirarchyList(currentCharacter) # -- Check each node to see if it matches the desired name for node in characterNodeList: if node.Name == name: foundNode = node del (currentCharacter, characterNodeList) return foundNode def getNumberOfSelectedTakes(): number_of_selected_takes = 0 for take_index in range(len(FBSystem().Scene.Takes)): if FBSystem().Scene.Takes[take_index].Selected == True: number_of_selected_takes += 1 return number_of_selected_takes def bakeRot(): currentCharacter = FBApplication().CurrentCharacter # -- If more than 1 take is selected, if getNumberOfSelectedTakes() > 1: # -- go through each take for take in FBSystem().Scene.Takes: # -- If it is selected if take.Selected: # -- Plot selected models to it FBSystem().CurrentTake = take Globals.Scene.Evaluate() startTime = FBSystem().CurrentTake.LocalTimeSpan.GetStart() endTime = FBSystem().CurrentTake.LocalTimeSpan.GetStop() fpsCore.TransferConeMasterAnimationToMoverSpace(currentCharacter, startTime, endTime) Globals.Scene.Evaluate() cleanCurves() # -- annoying when you have one take selected different from the current - chances are the user didn't mean to. else: startTime = FBSystem().CurrentTake.LocalTimeSpan.GetStart() endTime = FBSystem().CurrentTake.LocalTimeSpan.GetStop() fpsCore.TransferConeMasterAnimationToMoverSpace(currentCharacter, startTime, endTime) Globals.Scene.Evaluate() def plotOptions(): plot_options = FBPlotOptions() plot_options.PlotAllTakes = False plot_options.PlotOnFrame = True plot_options.PlotPeriod = FBTime(0, 0, 0, 1) plot_options.RotationFilterToApply = FBRotationFilter.kFBRotationFilterUnroll plot_options.UseConstantKeyReducer = False plot_options.ConstantKeyReducerKeepOneKey = True plot_options.PlotTranslationOnRootOnly = False return plot_options def plotSelected(): opt = plotOptions() FBSystem().CurrentTake.PlotTakeOnSelected(opt) def cleanCurves(): # -- Find the cone master coneM = findNode("coneMaster") for comp in FBSystem().Scene.Components: comp.Selected = False coneM.Selected = True plotSelected() bakeRot() Globals.Scene.Evaluate() pythonidelib.FlushOutput() ########################################### # -- Quickly pick the IK Hand Extentions -- ########################################### from pyfbsdk import * from pyfbsdk import * from RS.Utils import Scene def getCharacterHeirarchyList(character): characterNodeList = [] hips = character.GetModel(FBBodyNodeId.kFBHipsNodeId) dummy = Scene.GetParent(hips) Scene.GetChildren(dummy, characterNodeList, "", True) return characterNodeList def findNodesForCurrentCharacter(name): foundNode = None foundNodes = [] # -- Get list of all nodes of current character currentCharacter = FBApplication().CurrentCharacter characterNodeList = getCharacterHeirarchyList(currentCharacter) # -- Check each node to see if it matches the desired name for node in characterNodeList: if node.Name == name: foundNode = node foundNodes.append(foundNode) del (currentCharacter, characterNodeList) return foundNodes def findNodesForEntireScene(name): foundComponents = FBComponentList() includeNamespace = True modelsOnly = True FBFindObjectsByName('*' + name, foundComponents, includeNamespace, modelsOnly) return foundComponents def selectNode(input, character = True): nodes = [] names = [x.strip() for x in input.split(',')] if character == True: for name in names: for node in findNodesForCurrentCharacter(name): nodes.append(node) else: for name in names: for node in findNodesForEntireScene(name): nodes.append(node) if len(nodes) > 0: clearSelection() for node in nodes: if node: if node.PropertyList.Find('Look'): node.PropertyList.Find('Look').Data = 1 if node.PropertyList.Find('Size'): node.PropertyList.Find('Size').Data = 5.0 if node.PropertyList.Find('Pickable'): node.PropertyList.Find('Pickable').Data = True if node.PropertyList.Find('Transformable'): node.PropertyList.Find('Transformable').Data = True if node.PropertyList.Find('Show'): node.PropertyList.Find('Show').Data = True node.Selected = True return nodes def TestMessageBox(pVal): # The result from the call will be a tuple containing the index of the # button pressed (or -1 in case of error). The second element will be # the value entered. lRes = FBMessageBoxGetUserValue("Search and Select", "Search For: ", pVal, FBPopupInputType.kFBPopupString, "Character", "Scene", "Cancel") # Did the user press 'Ok'? if lRes[0] == 1: found = selectNode(lRes[1], True) if len(found) > 0: FBMessageBox("Result", "%s object found for current character" % len(found), "Ok") else: FBMessageBox("Result", "No objects found for current character", "Ok") if lRes[0] == 2: found = selectNode(lRes[1], False) if len(found) > 0: FBMessageBox("Result", "%s objects found in scene" % len(found), "Ok") else: FBMessageBox("Result", "No objects found in scene", "Ok") del (lRes) def clearSelection(): for comp in FBSystem().Scene.Components: comp.Selected = False TestMessageBox("") ########################################### # -- Quickly pick the IK Hand Extentions -- ########################################### from pyfbsdk import * from pyfbsdk import * from RS.Utils import Scene def getCharacterHeirarchyList(character): characterNodeList = [] hips = character.GetModel(FBBodyNodeId.kFBHipsNodeId) dummy = Scene.GetParent(hips) Scene.GetChildren(dummy, characterNodeList, "", True) return characterNodeList def findNode(name): foundNode = None # -- Get list of all nodes of current character currentCharacter = FBApplication().CurrentCharacter characterNodeList = getCharacterHeirarchyList(currentCharacter) # -- Check each node to see if it matches the desired name for node in characterNodeList: if node.Name == name: foundNode = node del (currentCharacter, characterNodeList) return foundNode def selectFromList(names): for name in names: node = findNode(name) if node: node.PropertyList.Find('Look').Data = 1 node.Look = 1 node.Size = 5.0 node.Pickable = True node.Transformable = True node.Show = True node.Selected = True selectList = [ "CH_L_Hand", "CH_R_Hand" ] selectFromList(selectList) ########################################### # -- Quickly pick the IK Hand Extentions -- ########################################### from pyfbsdk import * from pyfbsdk import * from RS.Utils import Scene def getCharacterHeirarchyList(character): characterNodeList = [] hips = character.GetModel(FBBodyNodeId.kFBHipsNodeId) dummy = Scene.GetParent(hips) Scene.GetChildren(dummy, characterNodeList, "", True) return characterNodeList def findNode(name): foundNode = None # -- Get list of all nodes of current character currentCharacter = FBApplication().CurrentCharacter characterNodeList = getCharacterHeirarchyList(currentCharacter) # -- Check each node to see if it matches the desired name for node in characterNodeList: if node.Name == name: foundNode = node del (currentCharacter, characterNodeList) return foundNode def selectFromList(names): for name in names: node = findNode(name) if node: node.PropertyList.Find('Look').Data = 1 node.Look = 1 node.Size = 5.0 node.Pickable = True node.Transformable = True node.Show = True node.Selected = True selectList = [ "IK_L_Hand", "IK_R_Hand" ] selectFromList(selectList) ########################################### # -- Quickly pick the IK Hand Extentions -- ########################################### from pyfbsdk import * from pyfbsdk import * from RS.Utils import Scene def getCharacterHeirarchyList(character): characterNodeList = [] hips = character.GetModel(FBBodyNodeId.kFBHipsNodeId) dummy = Scene.GetParent(hips) Scene.GetChildren(dummy, characterNodeList, "", True) return characterNodeList def findNode(name): foundNode = None # -- Get list of all nodes of current character currentCharacter = FBApplication().CurrentCharacter characterNodeList = getCharacterHeirarchyList(currentCharacter) # -- Check each node to see if it matches the desired name for node in characterNodeList: if node.Name == name: foundNode = node del (currentCharacter, characterNodeList) return foundNode def selectFromList(names): for name in names: node = findNode(name) if node: node.PropertyList.Find('Look').Data = 1 node.Look = 1 node.Size = 5.0 node.Pickable = True node.Transformable = True node.Show = True node.Selected = True selectList = [ "PH_L_Hand", "PH_R_Hand" ] selectFromList(selectList) from pyfbsdk import * import pythonidelib def SelectMarkedTakes(): lSystem = FBSystem() print "\nMarked Takes:\n" for lTakeIdx in range(len(lSystem.Scene.Takes)): take = lSystem.Scene.Takes[lTakeIdx] take.Selected = False if take.Name.startswith('>>>---'): take.Selected = True print take.Name[6:] pythonidelib.FlushOutput() SelectMarkedTakes() from pyfbsdk import * from pyfbsdk_additions import * # -- For each constraint in the scene for con in FBSystem().Scene.Constraints: if con.Selected == True: newName = con.Name + ' [ANIMATED]' con.Name = newName #################################################################### # Adds current character as a story track with current take added #################################################################### from pyfbsdk import * import pythonidelib def addCharacterTrack(): track = FBStoryTrack(FBStoryTrackType.kFBStoryTrackCharacter, story.RootFolder) track.Details.append(app.CurrentCharacter) track.Label = system.CurrentTake.Name clip = track.CopyTakeIntoTrack(system.CurrentTake.LocalTimeSpan, system.CurrentTake) clip.Selected = True interp = clip.PropertyList.Find('Timewarp Interpolation') interp.Data = 0 FBStory().Mute = False app = FBApplication() system = FBSystem() story = FBStory() scene = system.Scene addCharacterTrack() pythonidelib.FlushOutput() from pyfbsdk import * takes = FBSystem().Scene.Takes def getNumberOfSelectedTakes(): number_of_selected_takes = 0 for take_index in range(len(FBSystem().Scene.Takes)): if FBSystem().Scene.Takes[take_index].Selected == True: number_of_selected_takes += 1 return number_of_selected_takes if getNumberOfSelectedTakes() > 0: for take in takes: if take.Selected: if take.Name.startswith('>>>---'): take.Name = take.Name[6:] else: if FBSystem().CurrentTake.Name.startswith('>>>---'): FBSystem().CurrentTake.Name = FBSystem().CurrentTake.Name[6:]