-- 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
)