# NormalizeWeights # Initial code generated by Softimage SDK Wizard # Executed Fri Oct 2 10:24:27 EDT 2009 by flord from win32com.client import Dispatch from win32com.client import constants as c import win32com xsi = Dispatch('XSI.Application').Application log = xsi.__getattr__('LogMessage') null = None false = 0 true = 1 def XSILoadPlugin( in_reg ): in_reg.Author = "flord" in_reg.Name = "NormalizeWeights" in_reg.Email = "me@francoislord.com" in_reg.URL = "" in_reg.Major = 1 in_reg.Minor = 0 in_reg.RegisterCommand("NormalizeWeights","NormalizeWeights") in_reg.RegisterMenu(c.siMenuTbAnimateDeformEnvelopeID,"NormalizeWeights_Menu",False,False) #RegistrationInsertionPoint - do not remove this line return True def NormalizeWeights_Init( in_ctxt ): oCmd = in_ctxt.Source oCmd.Description = "Makes all points assigned at 100%" oCmd.ReturnValue = True oArgs = oCmd.Arguments oArgs.AddWithHandler("Objects","Collection") return True def NormalizeWeights_Execute( Objects ): oPointColl = win32com.client.Dispatch( "XSI.Collection" ) iModified = 0 iNotAssigned = 0 for oObj in Objects: if xsi.ClassName(oObj) != "X3DObject": log(oObj.FullName +" is not an X3DObject.",2) continue try: oEnvelope = oObj.ActivePrimitive.NestedObjects("Envelope Operator") except: log(oObj.FullName + " doesn't have an envelope operator.",2) continue if not oEnvelope: log(oObj.FullName + " doesn't have an envelope operator.",2) continue tW = oEnvelope.Weights.Array # Inverse the two dimentions of the tuple so that we can work on points, not deformers. lWeights = [[r[column] for r in tW] for column in range(len(tW[0]))] for iPoint in range(len(lWeights)): fTotalValue = 0 for iDeformer in range(len(lWeights[0])): fTotalValue = fTotalValue + lWeights[iPoint][iDeformer] # Isolate vertices with less than 100% weight. if fTotalValue < 99.9999 or fTotalValue > 100.00001: # Find corresponding Vertex. Envelope could be applied on a partial cluster. oPoint = oEnvelope.Elements(iPoint) # Select points that are not assigned to anything. if fTotalValue == 0: #log("Point: " + str(oEnvelope.Elements(iPoint)) + " is not assigned to anything",4) oPointColl.AddItems(oObj.ActivePrimitive.Geometry.Points(oEnvelope.Elements(iPoint))) iNotAssigned = iNotAssigned + 1 # Normalise others. else: #log(str(oPoint) + " " + str(fTotalValue ) + " " + str(lWeights[iPoint])) for iDeformer in range(len(lWeights[0])): if lWeights[iPoint][iDeformer] > 0: sFormat = "Point %d: %s %.1f -> %.1f" fNewVal = lWeights[iPoint][iDeformer] / (fTotalValue / 100) #log(sFormat % (oEnvelope.Elements(iPoint), oEnvelope.Deformers(iDeformer).Name, lWeights[iPoint][iDeformer], fNewVal)) lWeights[iPoint][iDeformer] = fNewVal iModified = iModified + 1 # Revert back the two dimensions of the tuple and assign. if iModified: tNewW = [[r[column] for r in lWeights] for column in range(len(lWeights[0]))] oEnvelope.Weights.Array = tNewW sFormat = "%s: %d points (%.1f%%) have been modified" log(sFormat % (oObj.Name, iModified, iModified / float(len(lWeights))*100)) #log((iModified, len(lWeights), float(iModified) / float(len(lWeights)))) if iNotAssigned: log(str(iNotAssigned) + " points are not assigned to anything, they are now selected.",1) if oPointColl.Count: xsi.Selection.Clear() xsi.Selection.SetAsText(oPointColl.GetAsText()) return True def NormalizeWeights_Menu_Init( in_ctxt ): oMenu = in_ctxt.Source oMenu.AddCommandItem("Normalize Weights","NormalizeWeights") return True