""" Description: Methods for manipulating and interacting with 3D Curves within motion builder Authors: David Vega """ import pyfbsdk import RS.Utils.Creation import RS.Utils.Math from RS.Utils.Scene import Constraint def CreatePath(*args, **kwargs): return RS.Utils.Creation.CreatePath(*args, **kwargs) def EditPath(*args, **kwargs): return RS.Utils.Creation.EditPath(*args, **kwargs) def SimplifyPath(path, samples=10, startRange=0, endRange=1): if isinstance(path, basestring): path = pyfbsdk.FBFindModelByLabelName(path) return RS.Utils.Creation.CreatePath("Simple {}".format(path.Name), *[path.Total_GlobalPathEvaluate( (((each/float(samples - 1)) * (endRange - startRange)) + startRange) * 100) for each in xrange(samples)]) def AttachComponentToPath(component, path, offset=[0,0,0], position=0): constraint = Constraint.CreateConstraint(Constraint.PATH) constraint.ReferenceAdd (0, component) constraint.ReferenceAdd (1, path) constraint.Snap() constraint.PropertyList.Find("Translation Offset").Data = pyfbsdk.FBVector3d(*offset) constraint.PropertyList.Find("Follow Path").Data = True warp = constraint.PropertyList.Find("Warp") warp.Data = position warp.SetAnimated(True) animationNode = warp.GetAnimationNode() animationNode.FCurve.EditClear() warp.SetAnimated(False) return constraint def GetPathConstraint(component, path=None): constraints = [component.GetSrc(index) for index in xrange(component.GetSrcCount()) if getattr(component.GetSrc(index), "Description", "") == "Path Constraint"] if constraints: return constraints[0] elif not constraints and path: return AttachComponentToPath(component, path) def MapBoneChainLength(*bones, **kwargs): children = kwargs.get("children", False) if not bones: return if children: def getchildren(child): children = [child] for each in child.Children: if isinstance(each, pyfbsdk.FBModelSkeleton): children.extend(getchildren(each)) return children bones = getchildren(bones[0]) length = 0 totalLengthProperties = [] for index, bone in enumerate(bones): if index: matrixA = pyfbsdk.FBMatrix() bone.GetMatrix(matrixA) matrixB = pyfbsdk.FBMatrix() bones[index - 1].GetMatrix(matrixB) matrix = matrixA - matrixB lengthVector = [matrix[12], matrix[13], matrix[14]] length += RS.Utils.Math.Length(*lengthVector) for propertyName in ["ChainLength", "TotalLength"]: property = bone.PropertyList.Find(propertyName) if not property: property = bone.PropertyCreate(propertyName, pyfbsdk.FBPropertyType.kFBPT_double, 'Double', True, True, None) if property == "TotalLength": totalLengthProperties.append(property) property.Data = length [setattr(each, "Data", length) for each in totalLengthProperties] def KeepBoneEqualDistance(path, *joints, **kwargs): frame = kwargs.get("Frame", pyfbsdk.FBSystem().LocalTime.GetFrame()) for joint in joints: constraint = GetPathConstraint(joint, path) length = joint.PropertyList.Find("ChainLength").Data * 100 position = length/float(path.PathLength) warp = constraint.PropertyList.Find("Warp") warp.Data = position #warp.SetAnimated(True) #animationNode = warp.GetAnimationNode() #animationNode.FCurve.EditClear() #warp.SetAnimated(False) #animationNode.KeyAdd( # pyfbsdk.FBTime(0, 0, 0, frame), position) """ import RS.Utils.Math as p reload(p) import RS.Utils.Path3D as p reload(p) p.MapBoneChainLength(FBFindModelByLabelName("Skeleton node")) p.KeepBoneEqualDistance(FBFindModelByLabelName("3D Curve"), *var) """