def ReadSyflexXMLPreset(filename, cloth): if not CheckFileExists(filename): XSI.LogMessage("[Read Syflex XML Preset] File : " + filename + " doesn't exists...") return if not cloth: XSI.LogMessage("[Read Syflex XML Preset] Invalid Output syCloth Operator ...") return tree = xml.parse(filename) root = tree.getroot() all_operators = root.findall("operator") all_parameters = root.findall("parameter") for item in cloth.NestedObjects: if item.IsClassOf(constants.siParameterID): if not item.ReadOnly and item.Animatable: value = GetParameterValueFromList(item.Name, all_parameters) if value: item.Value = value elif item.IsClassOf(constants.siOperatorID): op = GetOperatorFromList(item, all_operators) if op: op_parameters = op.findall("parameter") for op_parameter in op_parameters: SetParameterValueFromElement(op_parameter, item)
def bbppTransformation_DeleteCorrespondancePoints_OnClicked( ): oModel = PPG.Inspected(0).Parent3DObject if XSI.Selection.Count == 0: oElem = bPickElement(constants.siNullFilter,"Pick Point to Delete") else: oElem = XSI.Selection(0) if not oElem: XSI.LogMessage("bbppTransformation Delete Points : Operation Aborted !", constants.siInfo) return if oElem.Model.FullName == oModel.FullName and oElem.Type == "null": if oElem.Name.find("Start") != -1: sSplit = oElem.Name.split("Start") oOther = oModel.FindChild("End"+sSplit[1]) oCurve = oModel.FindChild("Link"+sSplit[1]) elif oElem.Name.find("End") != -1: sSplit = oElem.Name.split("End") oOther = oModel.FindChild("Start"+sSplit[1]) oCurve = oModel.FindChild("Link"+sSplit[1]) XSI.DeleteObj(str(oElem) + "," + str(oOther) + "," + str(oCurve)) else: XSI.LogMessage("bbppTransformation Delete Points : Invalid Selection ---> Nothing Deleted!", constants.siError)
def CheckGeometryMatch(a, b, precision): ag = a.ActivePrimitive.Geometry bg = b.ActivePrimitive.Geometry ap = ag.Points bp = bg.Points if not ap.Count == bp.Count: XSI.LogMessage( "Geometries (" + a.FullName + "," + b.FullName + ") DOESN'T match : they don't have the same number of points") return False apa = ap.PositionArray bpa = bp.PositionArray for i in range(len(apa[0]) / 3): ax = apa[0][i * 3] ay = apa[0][i * 3 + 1] az = apa[0][i * 3 + 2] bx = bpa[0][i * 3] by = bpa[0][i * 3 + 1] bz = bpa[0][i * 3 + 2] if not EpsilonEqual(ax, bx, precision) or not EpsilonEqual( ay, by, precision) or not EpsilonEqual(az, bz, precision): XSI.LogMessage( "Geometries (" + a.FullName + "," + b.FullName + ") DOESN'T match : Points are not at the same location") return False return True
def ClusterCenterTarget(inPntSubComponent=None, inTarget=None, inName="PntCls"): if not inPntSubComponent: sel = XSI.Selection(0) if not sel or not sel.Type == "pntSubComponent": XSI.LogMessage( "[ClusterCenterTarget] Invalid Selection : Need some points selected ---> Aborted!" ) return else: inPntSubComponent = sel.SubComponent if not inTarget: pick = PickElement(constants.siObjectFilter, "Pick Target Object") if not pick: XSI.LogMessage( "[ClusterCenterTarget] Invalid Target : Need one target object ---> Aborted!" ) return else: inTarget = pick obj = inPntSubComponent.Parent3DObject geo = obj.ActivePrimitive.Geometry elem = inPntSubComponent.ElementArray cls = geo.AddCluster(constants.siVertexCluster, inName, elem) XSI.ApplyOp("ClusterCenter", str(cls) + ";" + str(inTarget), 0, 0, None, 2)
def CreateCompleteButNotAlwaysCluster(obj, _type=constants.siVertexCluster, name='CompleteButNotAlwaysCls'): geom = obj.ActivePrimitive.Geometry if not geom: XSI.LogMessage( '[CreateCompleteButNotAlwaysCluster] : input object invalid !') return None # check if cluster doesn't exists if geom.Clusters(name): cluster = geom.Clusters(name) return cluster else: if _type == constants.siVertexCluster: indices = geom.Points.IndexArray cluster = geom.AddCluster(_type, name, indices) return cluster elif _type == constants.siEdgeCluster: indices = geom.Segments.IndexArray cluster = geom.AddCluster(_type, name, indices) return cluster elif _type == constants.siPolygonCluster: indices = geom.Facets.IndexArray cluster = geom.AddCluster(_type, name, indices) return cluster else: XSI.LogMessage( '[CreateAlwaysCompleteCluster] : cluster type {} isn\'t supported !' .format(_type)) return None
def BuildFKRig(parent, crv, ppg, side=MIDDLE, simple=False): prefix = 'M_' if side == LEFT: prefix = 'L_' elif side == RIGHT: prefix = 'R_' r = ppg.Parameters('{}ColorR_FK'.format(prefix)).Value g = ppg.Parameters('{}ColorG_FK'.format(prefix)).Value b = ppg.Parameters('{}ColorB_FK'.format(prefix)).Value model = parent.Model builder = model.Properties('RigBuilder') if not builder: XSI.LogMessage('[RigControl] Invalid parent object, aborted !') return False elem_ppg = crv.Properties('RigElement') if not elem_ppg: XSI.LogMessage( '[RigControl] Guide curve is not a rig element, aborted !') return False ctrls = XSIFactory.CreateActiveXObject('XSI.Collection') basename = crv.Name.replace('_Crv', '') vertices = crv.ActivePrimitive.Geometry.Points up_x = elem_ppg.Parameters('UpVectorX').Value up_y = elem_ppg.Parameters('UpVectorY').Value up_z = elem_ppg.Parameters('UpVectorZ').Value up_vector = XSIMath.CreateVector3(up_x, up_y, up_z) direction = XSIMath.CreateVector3() for idx, vertex in enumerate(vertices): transform = XSIMath.CreateTransform() p0 = vertex.Position transform.SetTranslation(p0) if idx < vertices.Count - 1: p1 = vertices[idx + 1].Position direction.Sub(p1, p0) direction.NormalizeInPlace() rot = Utils.GetRotationFromTwoVectors(direction, up_vector) transform.SetRotation(rot) fk = Icon.simple(parent, '{}_FK{}_Ctrl'.format(basename, idx + 1), [r, g, b], transform, p1) else: fk = Icon.simple(parent, '{}_FK{}_Ctrl'.format(basename, idx + 1), [r, g, b], transform, p0) parent = fk ctrls.Add(fk) Utils.ResetStaticKinematicState(ctrls) XSI.SetNeutralPose(ctrls, 'siSRT', '') Utils.GroupSetup(model, ctrls, inGroupName='FK_Rig') return True
def FindChildFromParameterValue(prop, param): value = prop.Parameters(param).Value if not value: XSI.LogMessage('[FindChildFromParameterValue] Parameter "{}" is empty !'.format(param)) return None model = FindPPGModel(prop) XSI.LogMessage(model) out = model.FindChild(value) return out
def Correct(obj, mode): cmdLog = XSI.Preferences.GetPreferenceValue("scripting.cmdlog") XSI.Preferences.SetPreferenceValue("scripting.cmdlog", False) cmdName = "Cloth_Corrective"+mode clsName = "Corrective"+mode+"Cls" # get datas if not obj or not obj.Type == "polymsh": XSI.LogMessage(cmdName + " ---> invalid Input", constants.siError) return current = int(Utils.GetCurrentFrame()) # get Cluster cls = Utils.CreateAlwaysCompleteCluster(obj, constants.siVertexCluster, clsName) # freeze all weight painter op for performance reasons props = cls.Properties for p in props: if (mode == "Smooth" or mode == "Push") and p.Type == "wtmap": XSI.FreezeObj(p) elif mode == "Shape" and p.Type == "clskey": XSI.FreezeObj(p) # check if a weight map already exists for this frame exist = False wmap = None if not mode == "Shape": if cls.Properties("Frame"+str(current)): exist = True toolkit = Dispatch("XSI.UIToolkit") buttonPressed = toolkit.MsgBox("A corrective weight map already exists for this frame...", constants.siMsgOkOnly, cmdName ) if buttonPressed == constants.siMsgCancel: XSI.LogMessage("Store Corrective Map cancelled by you !", constants.siInfo) return else: wmap = cls.AddProperty("Weight Map Property", False, "Frame"+str(current)) if mode == "Push": CorrectPush(obj, wmap, current, exist) elif mode == "Smooth": CorrectSmooth(obj, wmap, current, exist) elif mode == "Shape": CorrectShape(obj, cls, current) XSI.Preferences.SetPreferenceValue("scripting.cmdlog", cmdLog)
def Cloth_Control_SetDampingPercentage_OnClicked(): prop = PPG.Inspected(0) tmp = XSI.ActiveSceneRoot.AddProperty("CustomProperty", false, "Cloth_Control_SetDampingPercentage") p = tmp.AddParameter3( "Value", constants.siFloat, 100, 1, 1000, False, False ) layout = tmp.PPGLayout layout.Clear() layout.AddGroup("Set Damping : Stiffness divided by ") layout.AddItem( "Value") layout.EndGroup() bCancelled = XSI.InspectObj(tmp, None, "Set Syflex Damping", constants.siModal, False) if not bCancelled: prop.StretchDamping.Value = prop.StretchStiffness.Value / p.Value prop.ShearDamping.Value = prop.ShearStiffness.Value / p.Value prop.BendDamping.Value = prop.BendStiffness.Value / p.Value Cloth_Control_StretchDamping_OnChanged() Cloth_Control_ShearDamping_OnChanged() Cloth_Control_BendDamping_OnChanged() XSI.DeleteObj(tmp) else: XSI.DeleteObj(tmp) XSI.LogMessage("[Cloth_Control]Set Syflex Damping Aborted..")
def BuildCurveOnPositions(inPositions, inDegree=0, inClose=0, inOffset=XSIMath.CreateVector3()): if len(inPositions) < 2: XSI.LogMessage( "BuildCurveOnPosition aborted :: Not enough input positions!!", constants.siError) return if len(inPositions) < 4: inDegree = 0 aPos = [] for p in inPositions: aPos.append(p.X + inOffset.X) aPos.append(p.Y + inOffset.Y) aPos.append(p.Z + inOffset.Z) aPos.append(1) if inDegree == 0: outCrv = XSI.ActiveSceneRoot.AddNurbsCurve(aPos, None, inClose, 1) else: outCrv = XSI.ActiveSceneRoot.AddNurbsCurve(aPos, None, inClose, 3) return outCrv
def Symmetrize(self): if self.side == MIDDLE: XSI.LogMessage( "[ICERig] : Can't symmetrize middle elements ---> aborted...!") return None sibling = IRMuscle(None, self.GetSymParent(self.parent), self.name, self.GetOppositeSide(), self.mirror, self.suffix) sibling.position = self.position sibling.rotation = self.rotation sibling.sibling = self self.sibling = sibling sibling.CreateGuide() # add symmetrize element data ICE Tree t = tre.CreateICETree(sibling.crv, "SymmetrizeMuscleGuide", 2) n = XSI.AddICECompoundNode("IRSymetrizeMuscleDatas", str(t)) XSI.ConnectICENodes(str(t) + ".port1", str(n) + ".Execute") name = tre.ReplaceModelNameByThisModel(self.crv, self.model) XSI.SetValue(str(n) + ".Reference", name, "") return sibling
def CreateClusterFromSelection(name='ClsFromSelection'): """ Create cluster from selection """ selection = XSI.Selection(0) if not selection: XSI.LogMessage( '[Utils] CreateClusterFromSelection failed as nothing selected !') return None obj = selection.SubComponent.Parent3DObject if obj.ActivePrimitive.Geometry.Clusters(name): cluster = obj.ActivePrimitive.Geometry.Clusters(name) return cluster if selection.Type == 'pntSubComponent': sub = selection.SubComponent if sub.Parent3DObject.FullName == obj.FullName: cluster = sub.CreateCluster(name) return cluster elif selection.Type == 'polySubComponent': sub = selection.SubComponent if sub.Parent3DObject.FullName == obj.FullName: cluster = sub.CreateCluster(name) return cluster
def Cloth_DeformOutputMesh(prop): out = Cloth_GetOutputMesh(prop) cloth = prop.Parent3DObject if not out: XSI.LogMessage( '[Cloth_Rigger]There is no Output Mesh set for "{}"'.format( cloth.FullName), constants.siWarning) return # delete cage if already exists cage = out.ActivePrimitive.ConstructionHistory.Find('cagedeformop') if cage: XSI.DeleteObj(cage) # delete all cagedeform cluster all_clusters = out.ActivePrimitive.Geometry.Clusters for cluster in all_clusters: if not cluster.Name.find('CageWeightCls') == -1: XSI.DeleteObj(cluster) cage = XSI.ApplyDeformByCage('{};{}'.format(out.FullName, cloth.FullName), constants.siConstructionModeAnimation)(0) cage.Strength = 10 cage.Falloff = 0.2 # Deactivate EnvelopeOp env = out.ActivePrimitive.ConstructionHistory.Find('envelopop') if env: env.Mute = True
def Symmetrize(self): if self.side == MIDDLE: XSI.LogMessage( '[BuildRigElement] : Can\'t symmetrize middle elements !') return None sibling = IRSkeleton(None, self.GetSymParent(self.parent), self.name, self.mode, self.GetOppositeSide(), self.divisions, self.mirror, self.suffix) sibling.position = self.position sibling.rotation = self.rotation sibling.sibling = self self.sibling = sibling sibling.CreateGuide() # add symmetrize element data ICE Tree tree = ICETree.CreateICETree(sibling.crv, 'SymmetyrizeDatas', 2) node = XSI.AddICECompoundNode('IRSymetrizeSkeletonDatas', str(tree)) XSI.ConnectICENodes('{}.port1'.format(tree), '{}.Execute'.format(node)) name = ICETree.ReplaceModelNameByThisModel(self.crv, self.model) XSI.SetValue('{}.Reference'.format(node), name, '') return sibling
def AddToRig(self): sel = XSI.Selection self.list = 'GeometryList' self.chooser = 'GeometryChooser' sList = self.builder.Parameters(self.list).Value if sel.Count > 0: for s in sel: if s.Type == "polymsh" or s.Type == "crvlist": sList = self.UpdateGeometryList(s) else: XSI.LogMessage( "[RigBuilder] Accepts only POLYMESH or CRVLIST ---> " + str(s) + " : Skipped!!") else: objs = Utils.PickMultiElement(constants.siPolyMeshFilter, 'Pick Geometries To Deform') for o in objs: sList = self.UpdateGeometryList(o) ui_items = Element.BuildListFromString(sList) layout = self.builder.PPGLayout cnt = layout.Count for i in range(cnt): if layout.Item(i).Name == self.chooser: layout.Item(i).UIItems = ui_items
def Cloth_Control_ClearSyflexCache_OnClicked(): scene = XSI.ActiveProject2.ActiveScene folder = XSI.InstallationPath(constants.siProjectPath) scene = XSI.ActiveProject.ActiveScene folder = XSIUtils.BuildPath(folder,"Caches",scene) prop = PPG.Inspected(0) cloth = Cloth_Control_GetClothObjects(prop) model = cloth[0].Model # Reset to First Frame remote = XSI.Dictionary.GetObject("PlayControl") v = remote.Parameters("In").Value remote.Parameters( "Current" ).Value = prop.Parameters("FirstFrame").Value #deactivate delta storing state previousdelta = uti.DeactivateDelta(model) for c in cloth: syflex = c.ActivePrimitive.ConstructionHistory.Find( "syCloth" ) #clear all cache. XSI.LogMessage("{Cloth_Control] Delete All Syflex Cache File for " + c.FullName) syflex.Parameters("ClearCache").Value = 2 syflex.Parameters("Cache").Value = "" #reactivate delta if previousdelta>-1: uti.ReactivateDelta(model,previousdelta) '''
def Cloth_Control_GetCorrectiveList(prop,correctivetype): clothes = Cloth_Control_GetClothObjects(prop) if len(clothes) ==1: outstr = "" outlist = [] proptype = None if correctivetype == "Shape": proptype = "clskey" elif correctivetype == "Smooth": proptype = "wtmap" elif correctivetype == "Push": proptype = "wtmap" if prop.Parameters("Corrective"+correctivetype+"List"): cls = clothes[0].ActivePrimitive.Geometry.Clusters("Corrective"+correctivetype+"Cls"); if cls: props = cls.Properties for p in props: if p.Type == proptype: outstr+=p.Name+";" outlist.append(p.Name) outlist.append(p.Name) prop.Parameters("Corrective"+correctivetype+"List").Value = outstr return outlist else: XSI.LogMessage("[Cloth_Control] Get Corrective List only works in Single Item Mode!!", constants.siError)
def Cloth_Control_PaintRestoreMap_OnClicked(): prop = PPG.Inspected(0) clothes = Cloth_Control_GetClothObjects(prop) if len(clothes)==1: cls = clothes[0].ActivePrimitive.Geometry.Clusters("ClothCls"); if not cls: return map = cls.Properties("RestoreMap") if map: Cloth_Control_PaintMap(map) else: XSI.LogMessage("[Cloth_Control]Can't find RestoreMap on " + clothes[0].FullName) else: XSI.LogMessage("[Cloth_Control] Paint Restore Map only works in Single Item Mode!!", constants.siError)
def FindPropertyFromParameterValue(prop, param, parent): value = prop.Parameters(param).Value if not value: XSI.LogMessage('[FindPropertyFromParameterValue] Parameter "{}" is empty !'.format(param)) return None out = parent.Properties(value) return out
def GetWeightMap(inObject, name="WeightMap", value=0, inMin=0, inMax=1, cls=None): cluster = None # if cls provided check only it if cls: cluster = cls for w in cls.LocalProperties.Filter("wtmap"): if w.Name == name: return w else: XSI.LogMessage(inObject) if inObject.ActivePrimitive.Geometry.Clusters: # check all cluster for weightmap already exists for cls in inObject.ActivePrimitive.Geometry.Clusters.Filter( "pnt"): if cls.Name == "WeightMapCls": cluster = cls for w in cls.LocalProperties.Filter("wtmap"): if w.Name == name: return w # create cluster if not exist if not cluster: cluster = inObject.ActivePrimitive.Geometry.AddCluster( constants.siVertexCluster, "WeightMapCls") # create and set weight map wm = cluster.AddProperty("Weight Map Property", False, name) # clamp between -1 and 1 (maximum possible values) if inMin < -1: inMin = -1 elif inMin > 0: inMin = 0 if inMax > 1: inMax = 1 elif inMax < 0: inMax = 0 wm.Parameters("wmin").Value = inMin wm.Parameters("wmax").Value = inMax elems_tuple = wm.Elements.Array elems = [ value for _ in range(len(elems_tuple[0])) for _ in range(len(elems_tuple)) ] wm.Elements.Array = elems XSI.FreezeObj(wm) return wm
def PickPosition(self): self.position = uti.PickMultiPosition(-1, False) if len(self.position) < 2: XSI.LogMessage( "[Create Element] : You need to pick at least TWO points ---> aborted...!", siConstants.siWarning) return False self.rotation = uti.GetOrientationFromPickPosition(self.position) return True
def DistanceBetweenTwoObjects(start, end): if not start or not end: XSI.LogMessage("[Distance between two objects] Invalid Inputs!!", constants.siWarning) sT = start.Kinematics.Global.Transform eT = end.Kinematics.Global.Transform delta = XSIMath.CreateVector3() delta.Sub(eT.Translation, sT.Translation) return delta.Length()
def PickPosition(self): self.position = Utils.PickMultiPosition() if len(self.position) < 2: XSI.LogMessage( '[Create Element] You need to pick at least two points !', constants.siWarning) return False self.rotation = Utils.GetOrientationFromPickPosition(self.position) return True
def WriteCompoundXMLPreset(pth, compound): XSI.LogMessage("Write Compound XML Preset called :: " + pth) root = xml.Element(compound.Name) ports = compound.InputPorts for p in ports: AddInputPortToXML(root, p) f = open(pth, 'w') xml.ElementTree(root).write(f) f.close()
def Cloth_Control_FindCollideOp(syflex,id): collides = [] for n in syflex.NestedObjects: if n.Type == "syCollide": collides.append(n) XSI.LogMessage(n) if len(collides)>=id: return collides[id] return None
def Cloth_Control_PaintPush_OnClicked(): prop = PPG.Inspected(0) clothes = Cloth_Control_GetClothObjects(prop) if len(clothes) == 1: selectedpush = prop.CorrectivePushList.value cls = clothes[0].ActivePrimitive.Geometry.Clusters("CorrectivePushCls") XSI.SelectObj(cls.Properties(selectedpush)) XSI.PaintTool() else: XSI.LogMessage("[Cloth_Control] Paint Corrective Push only works in Single Item Mode!!", constants.siError)
def Cloth_Control_SetSyflexCache_OnClicked(): scene = XSI.ActiveProject2.ActiveScene folder = XSI.InstallationPath(constants.siProjectPath) scene = XSI.ActiveProject.ActiveScene folder = XSIUtils.BuildPath(folder,"Caches",scene) prop = PPG.Inspected(0) cloth = Cloth_Control_GetClothObjects(prop) for c in cloth: syflex = c.ActivePrimitive.ConstructionHistory.Find( "syCloth" ) modelfolder = XSIUtils.BuildPath(folder,prop.Parent3DObject.FullName) XSIUtils.EnsureFolderExists(modelfolder,False) path = XSIUtils.BuildPath(modelfolder,c.Name+".") syflex.Parameters("Cache").Value = path XSI.LogMessage("--------------------------------------------------") XSI.LogMessage("[Cloth_Control] Set Syflex Cache Path done for " + c.FullName + " : ") XSI.LogMessage(path)
def Cloth_Control_InspectCorrectiveShape_OnClicked(): prop = PPG.Inspected(0) clothes = Cloth_Control_GetClothObjects(prop) if len(clothes) == 1: tree = clothes[0].ActivePrimitive.ICETrees("CorrectiveShape") if(tree): compound = tree.Nodes("CorrectiveShape"); if(compound): XSI.InspectObj(compound) else: XSI.LogMessage("[Cloth_Control] Store CorrectiveShape only works in Single item Mode!!", constants.siError)
def Cloth_Rigger_SelectSoftMimicCluster_OnClicked(): target = PPG.Inspected(0).Parent3DObject cls = XSI.OpenTransientExplorer( target, constants.siSEFilterPropertiesAndPrimitives, 3)(0) if cls and cls.Type == 'pnt': PPG.Inspected(0).Parameters('SoftMimicCluster').Value = cls.Name Utils.GetWeightMap(target, 'SoftMimicMap', 1, 0, 1, cls) else: XSI.LogMessage( '[Cloth_Rigger] Invalid Selection : Select a Point Cluster on Cloth Geometry', constants.siWarning)
def CopyWeightMap(src, dst, wmName): # first check geometry input snbp = src.ActivePrimitive.Geometry.Points.Count dnbp = dst.ActivePrimitive.Geometry.Points.Count if not snbp == dnbp: XSI.LogMessage( "[Utils.py] Copy Weight Map Aborted!!!(Objects doesn't have same number of points)", constants.siWarning) return False swm = GetWeightMap(src, wmName) dwm = GetWeightMap(dst, wmName) if swm and dwm: XSI.LogMessage(swm) XSI.LogMessage(dwm) XSI.LogMessage(dwm.Elements.Array) dwm.Elements.Array = swm.Elements.Array XSI.LogMessage(dwm.Elements.Array)