Advertisement
Sim_Piko

setup_skin_bodygroups_animation.py

Jun 14th, 2014
712
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.31 KB | None | 0 0
  1. # Skin and bodygroups animation setup script
  2. # Written by DiFFtY (diffty@gmail.com)
  3. # Inspired by Miek's cloaking script (https://github.com/miek/sfm_scripts/tree/master/setup_cloaking)
  4. # Impulsed by doc_ock_rokc and VoxBombarde suggestions
  5. #
  6. # This script allows you to create a new channel in an Animation Set to control the skin number of a game model.
  7. #
  8. # Usage : Right click on a model Animation Set, go to Rig -> Load Rig Script, then open this .py
  9. #
  10. # Tested on SFM 0.9.7.6, 14/05/2013
  11. #
  12. # http://www.youtube.com/watch?v=cM0DW6jKCvs
  13.  
  14. import vs
  15.  
  16. def ControlGroupExists(controlGroupName):
  17.     animSet = sfm.GetCurrentAnimationSet()
  18.  
  19.     return (animSet.FindControlGroup(controlGroupName) != None)
  20.  
  21. def SetupSkin():
  22.     # Get the currently selected animation set and shot, and the corresponding gamemodel
  23.     shot = sfm.GetCurrentShot()
  24.     animSet = sfm.GetCurrentAnimationSet()
  25.     gameModel = animSet.gameModel
  26.    
  27.     BuildBodygroupSelectorExpression(gameModel)
  28.  
  29.     # Creating the control group
  30.     controlGroup = animSet.FindOrAddControlGroup(animSet.GetRootControlGroup(), "Skin")
  31.    
  32.     # Creating the control in the animation set
  33.     skinControl, skinValue = sfmUtils.CreateControlledValue("skin", "value", vs.AT_FLOAT, 0.0, animSet, shot)
  34.     controlGroup.AddControl(skinControl)
  35.    
  36.     # Creating an operator/expression, to adapt the 0.0 -> 1.0 float information provided by the slider to a 0 -> number of skins in the gamemodel
  37.     expression = sfmUtils.CreateExpression("skin_selector", "floor(lerp(value, lo, hi))", animSet)
  38.     expression.AddAttribute("lo", vs.AT_FLOAT)
  39.     expression.AddAttribute("hi", vs.AT_FLOAT)
  40.     expression.SetValue("hi", gameModel.GetSkinCount()-1)
  41.     expression.AddAttribute("value", vs.AT_FLOAT)
  42.  
  43.     # Connecting the normalized slider user-provided info to the expression
  44.     skinControl.channel.SetOutput(expression, "value")
  45.  
  46.     # Creating the second channel, which take the result of the expression and assign it to the gamemodel skin info
  47.     rescaleChannel = sfmUtils.CreateChannel("denormalized_skin_channel", vs.AT_FLOAT, 0., animSet, shot)
  48.     rescaleChannel.SetInput(expression, "result")
  49.     rescaleChannel.SetOutput(gameModel, "skin")
  50.  
  51.     # Removing keyframes from the second channel
  52.     # (to avoid the default blank key (added in the CreateChannel() function) to override ones from the first channel, which are the ones set by the user)
  53.     for i in range(0, rescaleChannel.log.GetKeyCount()):
  54.         rescaleChannel.log.RemoveKey(0)
  55.  
  56.     return
  57.  
  58. def BuildBodygroupSelectorExpression(gameModel):
  59.     bodyParts = []
  60.  
  61.     nbModels = 0
  62.  
  63.     # Building body parts list array (with body part name and model count in each one)
  64.     for i in range(0, gameModel.GetBodyPartCount()):
  65.         if gameModel.GetBodyPart(i).nummodels > 1:
  66.             bodyParts.append([gameModel.GetBodyPart(i).pszName(), gameModel.GetBodyPart(i).nummodels])
  67.             nbModels += gameModel.GetBodyPart(i).nummodels-1
  68.  
  69.     expressions = {"strings":[""], "nbValues":[0]}
  70.  
  71.     currentRank = 0
  72.     bodyPartCount = len(bodyParts)
  73.     cumulatedBodyNumber = 1
  74.  
  75.     # Building the expression
  76.     for idBodyPart in range(0, bodyPartCount):
  77.         modelCount = bodyParts[idBodyPart][1]-1
  78.  
  79.         if idBodyPart == 0:
  80.             #expression += "pow(2, (floor(value" + str(idBodyPart) + "*" + str(modelCount) + ") - 1)) * (floor(value" + str(idBodyPart) + "*" + str(modelCount) + ") > 0)"
  81.             expressionNewPart = "floor(value" + str(idBodyPart) + " * " + str(modelCount) + ")"
  82.         else:
  83.             #expression += "pow(2, (" + str(currentRank) + " + floor(value" + str(idBodyPart) + "*" + str(modelCount) + ") - 1)) * (floor(value" + str(idBodyPart) + "*" + str(modelCount) + ") > 0)"
  84.             expressionNewPart = "floor(value" + str(idBodyPart) + " * " + str(modelCount) + ") * " + str(cumulatedBodyNumber)
  85.  
  86.         if len(expressions['strings'][-1]+expressionNewPart) > 256:
  87.             expressions['strings'].append(expressionNewPart)
  88.             expressions['nbValues'].append(1)
  89.         else:
  90.             if idBodyPart > 0:
  91.                 expressions['strings'][-1] += " + "
  92.  
  93.             expressions['strings'][-1] += expressionNewPart
  94.             expressions['nbValues'][-1] += 1
  95.  
  96.             print idBodyPart,bodyPartCount
  97.  
  98.         cumulatedBodyNumber += cumulatedBodyNumber*modelCount
  99.        
  100.     print expressions
  101.  
  102.     return expressions
  103.  
  104. def SetupBodygroup():
  105.     # Get the currently selected animation set and shot, and the corresponding gamemodel
  106.     shot = sfm.GetCurrentShot()
  107.     animSet = sfm.GetCurrentAnimationSet()
  108.     gameModel = animSet.gameModel
  109.    
  110.     # Creating the expression, which will process every single bodygroup selector to one unique integer bodygroup number
  111.     expressions = BuildBodygroupSelectorExpression(gameModel)
  112.  
  113.     # Creating the Bodygroup control group
  114.     controlGroup = animSet.FindOrAddControlGroup(animSet.GetRootControlGroup(), "BodyGroups")
  115.    
  116.     # Listing every bodygroup, which have more than 1 model (basically, every bodygroup except the base one)
  117.     usefulBodyparts = [i for i in range(0, gameModel.GetBodyPartCount()) if gameModel.GetBodyPart(i).nummodels > 1]
  118.  
  119.     # Initializing the control arrays
  120.     bodyControl = [0]*len(usefulBodyparts)
  121.  
  122.     # Creating the controls in the animation set for each bodygroup
  123.     for i, idBodypart in enumerate(usefulBodyparts):
  124.         bodyControl[i], bodyValue = sfmUtils.CreateControlledValue(gameModel.GetBodyPart(idBodypart).pszName(), "value" + str(i), vs.AT_FLOAT, 0.0, animSet, shot)
  125.         controlGroup.AddControl(bodyControl[i])
  126.    
  127.     resultExpression = sfmUtils.CreateExpression("bodygroup_selector_result", "", animSet)
  128.     resultExpressionStr = ""
  129.  
  130.     startId = endId = 0
  131.     # Creating an operator/expression, to adapt the 0.0 -> 1.0 float information provided by each slider to a 0 -> number of bodygroups in the gamemodel
  132.     for exprId, currentExprStr in enumerate(expressions['strings']):
  133.         resultExpression.AddAttribute("resultpart" + str(exprId+1), vs.AT_FLOAT)
  134.  
  135.         if exprId > 0:
  136.             startId = endId
  137.             resultExpressionStr += " + "
  138.  
  139.         resultExpressionStr += "resultpart" + str(exprId+1)
  140.  
  141.         endId = startId+expressions['nbValues'][exprId]
  142.  
  143.         expression = sfmUtils.CreateExpression("bodygroup_selector_part" + str(exprId+1), currentExprStr, animSet)
  144.         for i in range(startId, endId):
  145.             expression.AddAttribute("value"+str(i), vs.AT_FLOAT)
  146.             # Connecting the normalized slider user-provided info to the expression
  147.             bodyControl[i].channel.SetOutput(expression, "value" + str(i))
  148.  
  149.         processedChannel = sfmUtils.CreateChannel("computed_bodygroup_part" + str(exprId+1) + "_channel", vs.AT_FLOAT, 0., animSet, shot)
  150.         processedChannel.SetInput(expression, "result")
  151.         processedChannel.SetOutput(resultExpression, "resultpart" + str(exprId+1))
  152.  
  153.         for i in range(0, processedChannel.log.GetKeyCount()):
  154.             processedChannel.log.RemoveKey(0)
  155.  
  156.     resultExpression.SetValue("expr", resultExpressionStr)
  157.  
  158.     # Creating the last channel, which take the result of the final sum and assign it to the gamemodel bodygroup info
  159.     finalProcessedChannel = sfmUtils.CreateChannel("computed_bodygroup_channel", vs.AT_FLOAT, 0., animSet, shot)
  160.     finalProcessedChannel.SetInput(resultExpression, "result")
  161.     finalProcessedChannel.SetOutput(gameModel, "body")
  162.  
  163.     # Removing keyframes from the new channel
  164.     # (to avoid the default blank key (added in the CreateChannel() function) to override ones from the first channel, which are the ones set by the user)
  165.     for i in range(0, finalProcessedChannel.log.GetKeyCount()):
  166.         finalProcessedChannel.log.RemoveKey(0)
  167.  
  168.     return
  169.  
  170.  
  171. #==================================================================================================
  172. # Script entry
  173. #==================================================================================================
  174.  
  175. # Setup skin and bodygroup selector channels for the selected animation set
  176. if not ControlGroupExists("Skin"):
  177.     SetupSkin()
  178. else:
  179.     print "The control group for skins has already been built. Skipping."
  180.  
  181. if not ControlGroupExists("BodyGroups"):
  182.     SetupBodygroup()
  183. else:
  184.     print "The control group for bodygroups has already been built. Skipping."
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement