-- Rockstar Anim Utility -- Rockstar North -- 26/7/2005 -- by Greg Smith -- edited by Fraser Tomison -- -- Set of utility functions for dealing with animations global XMLDoc = undefined global elmntTrackSpecs = undefined global boneArray = #() filein "pipeline/util/userprops.ms" filein "pipeline/util/cloth.ms" -------------------------------------------------------------- -- add all the nodes of a hierarchy into a list -------------------------------------------------------------- fn RsAddHierarchyToList obj addList = ( append addList obj for childobj in obj.children do ( RsAddHierarchyToList childobj addList ) ) -------------------------------------------------------------- -- -------------------------------------------------------------- fn RsCreateSpecFileRec boneval specfile blendShapeOnly foranim formap = ( if (formap == true) or boneval.isSelected then ( format " \n" to:specfile format " %\n" (RsRemoveSpaces boneval.name) to:specfile format " \n" to:specfile format " \n" to:specfile local transVal = getuserprop boneval "exportTrans" local scaleVal = getuserprop boneval "exportScale" local rotVal = getuserprop boneval "exportRotation" local bonetag = getuserprop boneval "tag" local gentransVal = getuserprop boneval "exportGenericTrans" local visVal = getuserprop boneval "exportVisibility" if transVal=="" or scaleVal=="" or rotVal=="" or bonetag=="" or gentransVal=="" or visVal=="" do ( gRsULog.LogError ("A User Property is malformed on object '" + boneval.name + "'. Line must contain only one equality sign and must have a value") context:obj ) -- AJM: Had to convert to string as there were some tags with IDs that crashed here local doExport = undefined==bonetag or not (matchPattern (bonetag as string) pattern:"*DO_NOT_EXPORT*") --toleranceTransVal = getuserprop boneval "exportTransTolerance" --toleranceRotVal = getuserprop boneval "exportRotTolerance" if blendShapeOnly == false and doExport then ( --if true then ( if transVal == true then ( format " \n" to:specfile format " translate\n" to:specfile format " trans\n" to:specfile format " X,Y,Z\n" to:specfile /* if toleranceTransVal != undefined then ( format " \n" toleranceTransVal to:specfile ) */ format " \n" to:specfile ) else if gentransVal == true then ( format " \n" to:specfile format " genericTranslation\n" to:specfile format " trans\n" to:specfile format " X,Y,Z\n" to:specfile format " \n" to:specfile ) if scaleVal == true then ( format " \n" to:specfile format " scale\n" to:specfile format " scale\n" to:specfile format " X,Y,Z\n" to:specfile format " \n" to:specfile ) if rotVal != false then ( format " \n" to:specfile format " rotate\n" to:specfile format " rot\n" to:specfile format " X,Y,Z\n" to:specfile /* if toleranceRotVal != undefined then ( format " \n" toleranceRotVal to:specfile ) */ format " \n" to:specfile ) if visVal == true then ( format " \n" to:specfile format " visibility0\n" to:specfile format " visibility0\n" to:specfile format " \n" to:specfile ) if foranim then ( for i = 0 to 7 do ( outputName = "projectData" + (i as string) format " \n" to:specfile format " %\n" outputName to:specfile format " %\n" outputName to:specfile format " X,Y,Z\n" to:specfile format " \n" to:specfile ) ) ) format " \n" to:specfile format " \n" to:specfile ) for childobj in boneval.children do ( RsCreateSpecFileRec childobj specfile blendShapeOnly foranim formap ) ) -------------------------------------------------------------- -- -------------------------------------------------------------- fn RsCreateSpecFileRecNew boneroot filename blendShapeOnly foranim formap = ( specfile = openfile filename mode:"w+" if specfile == undefined then ( return false ) format "\n" to:specfile format " \n" to:specfile RsCreateSpecFileRec boneroot specfile blendShapeOnly foranim formap format " \n" to:specfile format "\n" to:specfile close specfile ) -------------------------------------------------------------- -- -------------------------------------------------------------- fn RsCreateSpecFileNew boneroot filename blendShapeOnly foranim formap useWildcard:true = ( specfile = openfile filename mode:"w+" if specfile == undefined then ( gRsUlog.LogError "Couldn't open/create spec file for writing." context:boneroot return false ) format "\n" to:specfile format " \n" to:specfile if boneroot.isSelected then ( format " \n" to:specfile format " root\n" to:specfile format " \n" to:specfile format " \n" to:specfile local transVal = getuserprop boneroot "exportTrans" if blendShapeOnly == false then ( --if true then ( format " \n" to:specfile format " translate\n" to:specfile format " trans\n" to:specfile format " X,Y,Z\n" to:specfile format " \n" to:specfile format " \n" to:specfile format " rotate\n" to:specfile format " rot\n" to:specfile format " X,Y,Z\n" to:specfile format " \n" to:specfile ) for i = 0 to 7 do ( outputName = "projectData" + (i as string) format " \n" to:specfile format " %\n" outputName to:specfile format " %\n" outputName to:specfile format " X,Y,Z\n" to:specfile format " \n" to:specfile ) format " \n" to:specfile format " \n" to:specfile ) if blendShapeOnly == false then ( --if true then ( for childobj in boneroot.children do ( RsCreateSpecFileRec childobj specfile blendShapeOnly foranim formap ) ) if useWildcard then ( format " \n" to:specfile format " *\n" to:specfile format " \n" to:specfile format " \n" to:specfile if blendShapeOnly == false then ( --if true then ( format " \n" to:specfile format " rotate\n" to:specfile format " rot\n" to:specfile format " X,Y,Z\n" to:specfile format " \n" to:specfile ) format " \n" to:specfile format " \n" to:specfile ) format " \n" to:specfile format "\n" to:specfile close specfile true ) fn RsCreateSpecFile boneroot filename foranim:false formap:false useWildcard:true = ( return (RsCreateSpecFileNew boneroot filename false foranim formap useWildcard:useWildcard) ) -------------------------------------------------------------- -- Above functions edited to avoid using select as bit flag bugstar:1880733 + added xml code to clean up -------------------------------------------------------------- fn RsCreateSpecFileRecFromArray boneval specfile blendShapeOnly foranim formap = ( if (formap == true) or findItem boneArray boneval != 0 then ( elmntItem = XMLDoc.createelement "Item" appendTo:elmntTrackSpecs elmntTemp = XMLDoc.createelement "nameExpr" appendTo:elmntItem elmntTemp.AppendChild ( XMLDoc.createTextNode (RsRemoveSpaces boneval.name) ) elmntTemp = XMLDoc.createelement "bIncludeChildren" appendTo:elmntItem boolAttr = XMLDoc.CreateAttribute "value" boolAttr.value = "false" elmntTemp.Attributes.append boolAttr elmntTracks = XMLDoc.createelement "Tracks" appendTo:elmntItem local userProps = RsGetUserProps boneval local bonetag local transVal local scaleVal local rotVal local gentransVal local visVal for prop in userProps do ( if (prop.count != 2) then ( -- Instead of validating every prop, only validate the ones we want if (prop[1]!=undefined) do ( if (prop[1]=="exportTrans" or prop[1]=="exportScale" or prop[1]=="exportRotation" or prop[1]=="tag" or prop[1]=="exportGenericTrans" or prop[1]=="exportVisibility") do ( gRsULog.LogError ("The User Property '" + prop[1] + "' is malformed on object '" + boneval.name + "'. Line must contain only one equality sign and must have a value") context:boneval ) ) ) else ( if (prop[1] == "exportTrans") then ( transVal = RsStrtoB prop[2] ) else if (prop[1] == "exportScale") then ( scaleVal = RsStrtoB prop[2] ) else if (prop[1] == "exportRotation") then ( rotVal = RsStrtoB prop[2] ) else if (prop[1] == "tag") then ( bonetag = prop[2] ) else if (prop[1] == "exportGenericTrans") then (gentransVal = RsStrtoB prop[2] ) else if (prop[1] == "exportVisibility") then ( visVal = RsStrtoB prop[2] ) ) ) -- AJM: Had to convert to string as there were some tags with IDs that crashed here local doExport = undefined==bonetag or not (matchPattern (bonetag as string) pattern:"*DO_NOT_EXPORT*") --toleranceTransVal = getuserprop boneval "exportTransTolerance" --toleranceRotVal = getuserprop boneval "exportRotTolerance" if blendShapeOnly == false and doExport then ( --if true then ( if transVal == true then ( elmntItem = XMLDoc.createelement "Item" appendTo:elmntTracks elmntTemp = XMLDoc.createelement "inputName" appendTo:elmntItem elmntTemp.AppendChild ( XMLDoc.createTextNode "translate" ) elmntTemp = XMLDoc.createelement "outputName" appendTo:elmntItem elmntTemp.AppendChild ( XMLDoc.createTextNode "trans" ) elmntTemp = XMLDoc.createelement "components" appendTo:elmntItem elmntTemp.AppendChild ( XMLDoc.createTextNode "X,Y,Z" ) ) else if gentransVal == true then ( elmntItem = XMLDoc.createelement "Item" appendTo:elmntTracks elmntTemp = XMLDoc.createelement "inputName" appendTo:elmntItem elmntTemp.AppendChild ( XMLDoc.createTextNode "genericTranslation" ) elmntTemp = XMLDoc.createelement "outputName" appendTo:elmntItem elmntTemp.AppendChild ( XMLDoc.createTextNode "trans" ) elmntTemp = XMLDoc.createelement "components" appendTo:elmntItem elmntTemp.AppendChild ( XMLDoc.createTextNode "X,Y,Z" ) ) if scaleVal == true then ( elmntItem = XMLDoc.createelement "Item" appendTo:elmntTracks elmntTemp = XMLDoc.createelement "inputName" appendTo:elmntItem elmntTemp.AppendChild ( XMLDoc.createTextNode "scale" ) elmntTemp = XMLDoc.createelement "outputName" appendTo:elmntItem elmntTemp.AppendChild ( XMLDoc.createTextNode "scale" ) elmntTemp = XMLDoc.createelement "components" appendTo:elmntItem elmntTemp.AppendChild ( XMLDoc.createTextNode "X,Y,Z" ) ) if rotVal != false then ( elmntItem = XMLDoc.createelement "Item" appendTo:elmntTracks elmntTemp = XMLDoc.createelement "inputName" appendTo:elmntItem elmntTemp.AppendChild ( XMLDoc.createTextNode "rotate" ) elmntTemp = XMLDoc.createelement "outputName" appendTo:elmntItem elmntTemp.AppendChild ( XMLDoc.createTextNode "rot" ) elmntTemp = XMLDoc.createelement "components" appendTo:elmntItem elmntTemp.AppendChild ( XMLDoc.createTextNode "X,Y,Z" ) ) if visVal == true then ( elmntItem = XMLDoc.createelement "Item" appendTo:elmntTracks elmntTemp = XMLDoc.createelement "inputName" appendTo:elmntItem elmntTemp.AppendChild ( XMLDoc.createTextNode "visibility0" ) elmntTemp = XMLDoc.createelement "outputName" appendTo:elmntItem elmntTemp.AppendChild ( XMLDoc.createTextNode "visibility0" ) ) if foranim then ( for i = 0 to 7 do ( outputName = "projectData" + (i as string) elmntItem = XMLDoc.createelement "Item" appendTo:elmntTracks elmntTemp = XMLDoc.createelement "inputName" appendTo:elmntItem elmntTemp.AppendChild ( XMLDoc.createTextNode outputName ) elmntTemp = XMLDoc.createelement "outputName" appendTo:elmntItem elmntTemp.AppendChild ( XMLDoc.createTextNode outputName ) elmntTemp = XMLDoc.createelement "components" appendTo:elmntItem elmntTemp.AppendChild ( XMLDoc.createTextNode "X,Y,Z" ) ) ) ) ) for childobj in boneval.children do ( local retval = RsCreateSpecFileRecFromArray childobj specfile blendShapeOnly foranim formap if not retval do return false ) true ) -------------------------------------------------------------- -- -------------------------------------------------------------- fn RsCreateSpecFileRecNewFromArray boneroot filename bArray blendShapeOnly foranim formap = ( boneArray = bArray XMLDoc = XmlDocument() XMLDoc.init() elmntRoot = XMLDoc.createelement "rage__AnimExportCtrlSpec" XMLDoc.document.AppendChild elmntRoot elmntTrackSpecs = XMLDoc.createelement "TrackSpecs" appendTo:elmntRoot local retval = RsCreateSpecFileRecFromArray boneroot specfile blendShapeOnly foranim formap if not retval do return false XMLDoc.save (filename) true ) -------------------------------------------------------------- -- -------------------------------------------------------------- fn RsCreateSpecFileNewFromArray boneroot filename bArray blendShapeOnly foranim formap useWildcard:true = ( boneArray = bArray XMLDoc = XmlDocument() XMLDoc.init() elmntRoot = XMLDoc.createelement "rage__AnimExportCtrlSpec" XMLDoc.document.AppendChild elmntRoot elmntTrackSpecs = XMLDoc.createelement "TrackSpecs" appendTo:elmntRoot if findItem boneArray boneroot != 0 then ( elmntItem = XMLDoc.createelement "Item" appendTo:elmntTrackSpecs elmntTemp = XMLDoc.createelement "nameExpr" appendTo:elmntItem elmntTemp.AppendChild ( XMLDoc.createTextNode "root" ) elmntTemp = XMLDoc.createelement "bIncludeChildren" appendTo:elmntItem boolAttr = XMLDoc.CreateAttribute "value" boolAttr.value = "false" elmntTemp.Attributes.append boolAttr elmntTracks = XMLDoc.createelement "Tracks" appendTo:elmntItem local transVal = getuserprop boneroot "exportTrans" if blendShapeOnly == false then ( --if true then ( elmntItem = XMLDoc.createelement "Item" appendTo:elmntTracks elmntTemp = XMLDoc.createelement "inputName" appendTo:elmntItem elmntTemp.AppendChild ( XMLDoc.createTextNode "translate" ) elmntTemp = XMLDoc.createelement "outputName" appendTo:elmntItem elmntTemp.AppendChild ( XMLDoc.createTextNode "trans" ) elmntTemp = XMLDoc.createelement "components" appendTo:elmntItem elmntTemp.AppendChild ( XMLDoc.createTextNode "X,Y,Z" ) elmntItem = XMLDoc.createelement "Item" appendTo:elmntTracks elmntTemp = XMLDoc.createelement "inputName" appendTo:elmntItem elmntTemp.AppendChild ( XMLDoc.createTextNode "rotate" ) elmntTemp = XMLDoc.createelement "outputName" appendTo:elmntItem elmntTemp.AppendChild ( XMLDoc.createTextNode "rot" ) elmntTemp = XMLDoc.createelement "components" appendTo:elmntItem elmntTemp.AppendChild ( XMLDoc.createTextNode "X,Y,Z" ) ) for i = 0 to 7 do ( outputName = "projectData" + (i as string) elmntItem = XMLDoc.createelement "Item" appendTo:elmntTracks elmntTemp = XMLDoc.createelement "inputName" appendTo:elmntItem elmntTemp.AppendChild ( XMLDoc.createTextNode outputName ) elmntTemp = XMLDoc.createelement "outputName" appendTo:elmntItem elmntTemp.AppendChild ( XMLDoc.createTextNode outputName ) elmntTemp = XMLDoc.createelement "components" appendTo:elmntItem elmntTemp.AppendChild ( XMLDoc.createTextNode "X,Y,Z" ) ) ) if blendShapeOnly == false then ( --if true then ( for childobj in boneroot.children do ( local retval = RsCreateSpecFileRecFromArray childobj specfile blendShapeOnly foranim formap if not retval do return false ) ) if useWildcard then ( elmntItem = XMLDoc.createelement "Item" appendTo:elmntTrackSpecs elmntTemp = XMLDoc.createelement "nameExpr" appendTo:elmntItem elmntTemp.AppendChild ( XMLDoc.createTextNode "*" ) elmntTemp = XMLDoc.createelement "bIncludeChildren" appendTo:elmntItem boolAttr = XMLDoc.CreateAttribute "value" boolAttr.value = "false" elmntTemp.Attributes.append boolAttr elmntTracks = XMLDoc.createelement "Tracks" appendTo:elmntItem if blendShapeOnly == false then ( --if true then ( elmntItem = XMLDoc.createelement "Item" appendTo:elmntTracks elmntTemp = XMLDoc.createelement "inputName" appendTo:elmntItem elmntTemp.AppendChild ( XMLDoc.createTextNode "rotate" ) elmntTemp = XMLDoc.createelement "outputName" appendTo:elmntItem elmntTemp.AppendChild ( XMLDoc.createTextNode "rot" ) elmntTemp = XMLDoc.createelement "components" appendTo:elmntItem elmntTemp.AppendChild ( XMLDoc.createTextNode "X,Y,Z" ) ) ) XMLDoc.save (filename) true ) -------------------------------------------------------------- -- -------------------------------------------------------------- fn RsCreateSpecFileFromArray boneroot filename bArray foranim:false formap:false useWildcard:true = ( return (RsCreateSpecFileNewFromArray boneroot filename bArray false foranim formap useWildcard:useWildcard) ) fn IsValidBoneName b = ( not (matchPattern b pattern:"*footsteps*") and not (matchPattern b pattern:"*nub") ) -------------------------------------------------------------- -- -------------------------------------------------------------- fn RsGetBoneListInner objnode boneList = ( if objnode == undefined then ( return 0 ) if 0!=findItem gToleratedSkelBoneTypes (classof objnode) then ( local nameCheck = RsLowercase objnode.name if IsValidBoneName nameCheck then ( append boneList objnode ) ) for childobj in objnode.children do ( RsGetBoneListInner childobj boneList ) ) -------------------------------------------------------------- -- -------------------------------------------------------------- fn RsGetBoneList objnode boneList = ( RsGetBoneListInner objnode boneList ) fn GetBoneListFromSkin obj boneNodeOrName:0 = ( local ret = #() local theSkin = obj.modifiers[#skin] if undefined==theSkin then return ret max modify mode modPanel.setCurrentObject theSkin for i=1 to (skinOps.GetNumberBones theSkin) do ( local boneName = skinOps.GetBoneName theSkin i 0 if not (IsValidBoneName boneName) then continue if (boneNodeOrName==0) then ( local objsWithBoneName = getnodebyname boneName all:true local validBone = objsWithBoneName[1] if objsWithBoneName.count>1 then print ("more than one object with bone name "+boneName+": "+objsWithBoneName as string) if objsWithBoneName.count<1 then append objsWithBoneName (getnodebyname boneName) for b in objsWithBoneName where isValidNode b do validBone = b if isValidNode validBone then append ret validBone ) else append ret boneName ) local clothObj = obj local simMesh = RsLodDrawable_GetSimulationModel clothObj if undefined!=simMesh then clothObj = simMesh if (RsCloth.IsCloth clothObj) then ( local clothColls = #() RsSceneLink.getChildren linkType_ClothCollision clothObj &clothColls for col in clothColls do ( if undefined!=col.parent then ( gRsUlog.LogMessage ("Appended bone "+col.parent as string+" from cloth collision "+col as string+" to skeleton") append ret col.parent ) ) ) return ret ) fn RsCreateDummyAndMover charbone = ( --Get selected Biped part object = charbone --get COM name bipname = biped.getNode object #horizontal --Delete any existing Dummy or Mover Nodes moverNode = getnodebyname "mover" exact:true if moverNode != undefined then delete moverNode dummyNode = getnodebyname "Dummy01" exact:true if dummyNode != undefined then delete dummyNode axisNode = getnodebyname "axis_helper" exact:true if axisNode != undefined then delete axisNode layer = layermanager.getlayerfromname "Mover Node" if layer != undefined then layermanager.deleteLayerByName "Mover Node" --move slider to start slidertime = animationrange.start --get root bone z height bipname.transform.controller.figureMode = true z_height = bipname.transform[4].z bipname.transform.controller.figureMode = false --create Dummy node newDummyNode = Dummy() newDummyNode.name = "Dummy01" newDummyNode.boxsize = [.2,.2,.2] newDummyNode.pos = [0.0,0.0,z_height] --parent biped to it bipname.parent = newDummyNode --create Mover Node newMoverNode = Dummy() newMoverNode.name = "mover" newMoverNode.boxsize = [.3,.3,.3] newMoverNode.pos = [0.0,0.0,z_height] --create axis helper node axis_helper = Point pos:[0,0,1] isSelected:off cross:off axistripod:on size:0.25 name:"axis_helper" setTransformLockFlags axis_helper #all --parent nodes correctly newMoverNode.parent = newDummyNode axis_helper.parent = newMoverNode --create a new layer for Dummy and Mover nodes layer = layermanager.newlayerfromname "Mover Node" layer.addnode axis_helper layer.addnode newMoverNode layer.addnode newDummyNode ) fn RsUpdateMover xp yp zp yaw pitch roll = ( --check selection if (($mover != undefined) and ($mover.name == "mover")) then ( select $mover dummyNode = selection[1].parent biproot=$char.controller for child in dummyNode.children do ( if classof child == biped_object then biproot = child ) biproot.transform.controller.figuremode = true figureModeBipRot = biproot.transform as eulerAngles figureModeBipPos = biproot.transform[4] biproot.transform.controller.figuremode = false --delete all the keys on the mover track deleteKeys $.controller #allKeys dividorLimit = (ceil (((animationrange.end.frame - animationrange.start.frame) as float) / 50)) as integer with animate on ( dividorCount = 0 for i = animationrange.start to animationrange.end do ( if dividorCount == 0 then ( slidertime = i --get position and rotation bipPos = biped.getTransform biproot #pos bipRot = (biped.getTransform biproot #rotation) as eulerAngles --translate mover node if (xp ==true) then ( $mover.pos.x = bipPos.x ) else ( $mover.pos.x =0.0 ) if (yp == true) then ( $mover.pos.y = bipPos.y ) else ( $mover.pos.y =0.0 ) if (zp == true) then ( $mover.pos.z = bipPos.z ) else ( $mover.pos.z = figureModeBipPos.z ) -- rotate mover node if (pitch == true) then ( $mover.rotation.x_rotation = 0.0 ) else ( $mover.rotation.x_rotation=0.0 ) if (roll == true) then ( $mover.rotation.y_rotation = 0.0 ) else ( $mover.rotation.y_rotation = 0.0 ) if (yaw == true) then ( $mover.rotation.z_rotation = bipRot.z + figureModeBipRot.z ) else ( $mover.rotation.z_rotation = 0.0 ) ) dividorCount = dividorCount + 1 if dividorCount == dividorLimit then dividorCount = 0 ) ) ) else ( messagebox "Invalid mover" ) ) struct sNegInterval ( start, end ) fn RsGetControllerKeyRangeRec cntrl &range = ( local allKeys = cntrl.keys if allkeys.count>0 then ( if allkeys[1].time < range.start then range.start = allkeys[1].time if allkeys[allkeys.count].time > range.end then range.end = allkeys[allkeys.count].time ) for dependency in refs.dependsOn cntrl where (isproperty dependency "keys") do ( RsGetControllerKeyRangeRec dependency &range ) ) fn RsGetControllerKeyRange obj &range = ( for dependency in refs.dependsOn obj where (isproperty dependency "keys") do ( RsGetControllerKeyRangeRec dependency &range ) ) -- recurse through lists and return on first found keys... fn HasControllerType c level:0 types:#() = ( if undefined==c then return false for t in types do ( if isKindOf c t then ( return true ) ) -- ins = "" -- for d=1 to level do append ins " " -- print (ins + (classof c) as string + ":"+ (isKindOf c Constraint) as string) if isproperty c "count" then ( for subc = 1 to c.count do ( if HasControllerType c[subc] level:(level+1) types:types then ( return true ) ) ) for subc in (refs.dependsOn c) do ( if HasControllerType subc level:(level+1) types:types then return true ) return false )