Files
gtav-src/tools_ng/dcc/debug/max2011/scripts/startup/statedAnim.ms
T
2025-09-29 00:52:08 +02:00

688 lines
20 KiB
Plaintext
Executable File

filein "pipeline/util/xml.ms"
filein "pipeline/export/models/RsObjectFlags.ms"
filein "pipeline/export/maps/globals.ms"
struct sRsStatedAnim
(
objectArray = #(),
animLengthArray = #(),
looped = false,
fn Reset =
(
objectArray = #()
animLengthArray = #()
looped = false
),
fn getAnimationLength obj =
(
local maxLength = 0
if undefined==obj.children then
(
print "object doesn't have anim - start or end state"
)
for c in obj.children do
(
allKeys = c.pos.controller.keys
if allKeys.count<=0 then
(
continue
)
local lastKey = allKeys[allKeys.count]
local lastFrame = lastKey.time.frame
if lastFrame>maxLength then maxLength = lastFrame
)
--print ("animation length:"+maxLength as string)
return maxLength
),
fn selectWithChildren obj =
(
selectMore obj
for c in obj.children where IsValidNode c do selectWithChildren c
),
fn selectObject num =
(
if undefined==objectArray[num] then return false
clearSelection()
selectWithChildren objectArray[num]
),
fn addObject newobj listSelectionIndex =
(
while undefined!=newobj.parent do newobj = newobj.parent
for obj in objectArray do if obj==newobj then
(
messagebox "already added"
return false
)
if objectArray.count<3 then
(
append objectArray newobj
append animLengthArray (getAnimationLength newobj)
)
else
(
local oldObject = objectArray[listSelectionIndex]
local groupIdx = getattrindex "Gta Object" "groupName"
local stateIdx = getattrindex "Gta Object" "animState"
if (IsValidNode oldObject) then
(
setAttr newobj groupIdx (getAttr oldObject groupIdx)
setAttr newobj stateIdx (getAttr oldObject stateIdx)
)
else
(
local otherStatesGroupNames = "DEFAULT"
for o in objectArray where (IsValidNode o) and ("Gta Object"==getAttrClass) do (otherStatesGroupNames = (getAttr o groupIdx); break)
setAttr newobj groupIdx otherStatesGroupNames
setAttr newobj stateIdx (case listSelectionIndex of (1:"Start"; 2:"Animation"; 3:"End");)
)
messagebox ("old object reset in addObject:"+oldObject as string)
setAttr oldObject groupIdx "DEFAULT"
setAttr oldObject stateIdx ""
objectArray[listSelectionIndex] = newobj
animLengthArray[listSelectionIndex] = (getAnimationLength newobj)
)
return newobj
),
fn deleteObject objName =
(
if objectArray.count<1 then return false
for objIndex=1 to objectArray.count do
(
print (objectArray[objIndex].name)
if objectArray[objIndex].name==objName then
(
deleteItem objectArray objIndex
deleteItem animLengthArray objIndex
return true
)
objIndex+=1
)
return false
)
)
struct sRsStatedAnimTool
(
currAnim = sRsStatedAnim(),
hideObjs = true,
currActiveObjectIndex = 1,
fn findSameAnimGroup animGroupName =
(
local groupIdx = getattrindex "Gta Object" "groupName"
local stateIdx = getattrindex "Gta Object" "animState"
local tempStates = #()
for obj in objects where "Gta Object"==(getAttrClass obj) do
(
if animGroupName==(getAttr obj groupIdx) then
(
case (getAttr obj stateIdx) of
(
"Start":tempStates[1] = obj
"Animation":tempStates[2] = obj
"End":tempStates[3] = obj
)
)
)
return tempStates
),
fn getCurrentAnimGroupName =
(
if currAnim.objectArray.count<1 then return "DEFAULT"
local obj = currAnim.objectArray[1]
local groupIdx = getattrindex "Gta Object" "groupName"
if "Gta Object"==(getAttrClass obj) then
return getAttr obj groupIdx
else
return "DEFAULT"
),
fn loadAnim animGroupName =
(
if animGroupName==getCurrentAnimGroupName() then return false
currAnim = sRsStatedAnim()
local loopIdx = getattrindex "Gta Object" "looped"
local tempStates = findSameAnimGroup animGroupName
if undefined==tempStates[1] or undefined==tempStates[2] or undefined==tempStates[3] then
(
print ("Not enough states found for group: \""+animGroupName+"\"\n\nObjects"+tempStates as string)
return false
)
else
(
for oi=1 to tempStates.count do currAnim.addObject tempStates[oi] oi
currAnim.looped = getAttr tempStates[1] loopIdx
)
return true
),
fn findAnimGroups theProgressbar:undefined =
(
local groupIdx = getattrindex "Gta Object" "groupName"
local stateIdx = getattrindex "Gta Object" "animState"
local loopIdx = getattrindex "Gta Object" "looped"
local animGroups = #()
local index = 1
for obj in objects where "Gta Object"==(getAttrClass obj) do
(
local currGroupName = (getAttr obj groupIdx)
if undefined!=theProgressbar then
(
local percentage = ((index as float)/objects.count)*100
theProgressbar.value = percentage
)
index = index+1
if "DEFAULT"==currGroupName or 0!=(findItem animGroups currGroupName) then continue
tempStates = findSameAnimGroup currGroupName
if undefined!=tempStates[1] and undefined!=tempStates[2] and undefined!=tempStates[3] then
append animGroups currGroupName
)
if undefined!=theProgressbar then
theProgressbar.value = 0
return animGroups
),
fn selectObject num =
(
if undefined==currAnim then return false
currAnim.selectObject num
),
fn isCurrentAnimGroupName checkName =
(
local groupIdx = getattrindex "Gta Object" "groupName"
if currAnim.objectArray.count<1 then return false
if checkName==(getAttr currAnim.objectArray[1] groupIdx) then
return true
else
return false
),
fn getObjectNames =
(
objectNames = #()
for obj in currAnim.objectArray do
(
if not IsValidNode obj then
(
currAnim.Reset()
return #()
)
append objectNames obj.name
)
return objectNames
),
fn addObject newobj listSelectionIndex =
(
local retObj = false
if undefined==currAnim then
return false
else
retObj = currAnim.addObject newobj listSelectionIndex
if undefined!=RsStatedAnimRollout and RsStatedAnimRollout.open then
RsStatedAnimRollout.updateList()
return newObj
),
fn deleteObject objName =
(
if undefined==currAnim then return false
else currAnim.deleteObject objName
),
fn setObjHierVisible obj vis =
(
if undefined==obj or not IsValidNode obj then return false
if vis then unhide obj else hide obj
if undefined==obj.children then return false
for c in obj.children do
(
if vis then unhide c else hide c
)
),
fn unhideAll =
(
for objIndex=1 to currAnim.objectArray.count do
(
setObjHierVisible currAnim.objectArray[objIndex] true
)
),
fn hideInactiveObjects activeIndex =
(
if undefined==currAnim then return false
if hideObjs then
(
for objIndex=1 to currAnim.objectArray.count do
(
setObjHierVisible currAnim.objectArray[objIndex] (objIndex==activeIndex)
)
)
else
unhideAll()
),
fn advancePlaybackState =
(
currActiveObjectIndex+=1
hideInactiveObjects currActiveObjectIndex
print ("currActiveObjectIndex:"+currActiveObjectIndex as string)
if currAnim.animLengthArray[currActiveObjectIndex]>animationRange.end.frame then messagebox "Warning:Animation longer than current global animation range: animation will loop."
slidertime = 0
),
fn playbackCallback =
(
-- print ((currActiveObjectIndex as string)+", "+(objectArray.count as string))
if currActiveObjectIndex>=currAnim.objectArray.count then
(
stopanimation()
unRegisterTimeCallback playbackCallback
slidertime = 0
return false
)
if currAnim.objectArray==undefined or currAnim.objectArray.count<1 then
return false
local activeStateObject = currAnim.objectArray[currActiveObjectIndex]
if activeStateObject!=undefined then
(
if slidertime>=currAnim.animLengthArray[currActiveObjectIndex] then
advancePlaybackState()
)
else print "activeStateObject=undefined"
),
-- can't use this in the callback above since it's not defined yet and cant define before since then the callback doesn't get deleted properly on stop. =(
fn stopPlayback =
(
stopanimation()
unRegisterTimeCallback playbackCallback
slidertime = 0
),
fn Deinit =
(
currActiveObjectIndex=1
stopplayback()
unhideAll()
currAnim = sRsStatedAnim()
unRegisterTimeCallback playbackCallback
),
fn selectionChanged =
(
if undefined==selection[1] then
(
return false
)
local obj = selection[1]
while undefined!=obj.parent do obj = obj.parent
local groupIdx = getattrindex "Gta Object" "groupName"
if "Gta Object"==(getAttrClass obj) then
(
local theGroupName = getAttr obj groupIdx
if "DEFAULT"==theGroupName then
return false
if not (isCurrentAnimGroupName theGroupName) then
return (loadAnim theGroupName)
return true
)
else if statedAnimProxy==(classof obj) then
(
if undefined==(findString obj.name "_anim") then
(
messagebox "no _anim suffix found on animation proxy. Deleting."
delete obj
return false
)
local theGroupName = substring obj.name 1 ((findString obj.name "_anim")-1)
if not (isCurrentAnimGroupName theGroupName) then
(
print "reloading"
return (loadAnim theGroupName)
)
return true
)
else return false
),
fn startplayback =
(
slidertime = 0
currActiveObjectIndex = 1
print ("start animation- currActiveObjectIndex:"+currActiveObjectIndex as string)
registerTimeCallback playbackCallback
-- hideInactiveObjects 1
playanimation immediatereturn:true
),
fn buildProxy thename = (
if currAnim.objectArray.count<3 then
(
messagebox "Need to have all states set."
return false
)
if "DEFAULT"==thename or ""==thename then
(
messagebox "Need to have a senseful group name."
return false
)
local newName = thename+"_anim"
-- delete old
local oldProxies = for o in objects where o.name==newName collect o
delete oldProxies
local proxyObj = statedAnimProxy()
proxyObj.testNodeForAnimation currAnim.objectArray[1]
),
fn saveAttributes groupName =
(
if currAnim.objectArray.count<3 then
(
local msg = stringstream ""
format "You need to set all states before saving the group %" (currAnim.objectArray as string) to:msg
messagebox msg
return false
)
local groupIdx = getattrindex "Gta Object" "groupName"
local stateIdx = getattrindex "Gta Object" "animState"
local loopIdx = getattrindex "Gta Object" "looped"
idxDontAddIPL = getattrindex "Gta Object" "Dont Add To IPL"
local oldGroupName = getAttr currAnim.objectArray[1] groupIdx
local buildNewProxy = true
if "DEFAULT"==groupName then
(
messagebox "groupname must not be DEFAULT for saving"
return false
)
else if oldGroupName!=groupName then
(
print ("oldProxy:"+oldGroupName)
-- check for old proxy
local newName = oldGroupName+"_anim"
-- delete old
local oldProxies = for o in objects where o.name==newName collect o
delete oldProxies
buildNewProxy = true
)
for i=1 to 3 do
(
setAttr currAnim.objectArray[i] groupIdx groupName
setAttr currAnim.objectArray[i] loopIdx currAnim.looped
setattr currAnim.objectArray[i] idxDontAddIPL true
)
setAttr currAnim.objectArray[1] stateIdx "Start"
setAttr currAnim.objectArray[2] stateIdx "Animation"
setAttr currAnim.objectArray[3] stateIdx "End"
if buildNewProxy then
buildProxy groupName
),
fn deleteAttributes =
(
local groupIdx = getattrindex "Gta Object" "groupName"
local stateIdx = getattrindex "Gta Object" "animState"
for i=1 to currAnim.objectArray.count do
(
setAttr currAnim.objectArray[i] groupIdx "DEFAULT"
setAttr currAnim.objectArray[i] stateIdx ""
)
),
fn findAnimations =
(
local anims = #()
-- for obj in objects do collect
),
fn HasSceneAnyAnimations =
(
local groups = findAnimGroups()
if groups.count<1 then
return false
else
return true
),
fn ExportXML =
(
local groups = findAnimGroups()
if groups.count<1 then
(
print "No stated anims to export!"
return true -- valid, just skip.
)
-- RsStatedAnimFilename = "D:/temp.xml"
if undefined==RsStatedAnimFilename then
(
Messagebox "stated anim xml export only works on export!"
return false
)
else if ""==RsStatedAnimFilename then
(
print "Trying to export a stated anim from a generic map... bailing out."
return true -- valid, just skip.
)
else print ("Exporting anim to "+RsStatedAnimFilename)
-- init xml doc
local animDoc = XmlDocument()
animDoc.init()
-- <?xml version="1.0" encoding="UTF-8"?>
-- <CMapTypes>
-- <compositeEntityTypes>
-- <Item>
-- <Name>blocktest</Name>
-- <lodDist value = "10.00"/>
-- <flags value = "256"/>
-- <specialAttribute value = "1"/>
-- <bbMin x="-1.000000" y="-1.000000" z="-1.000000"/>
-- <bbMax x="1.000000" y="1.000000" z="1.000000"/>
-- <bsCentre x="0.000000" y="0.000000" z="0.000000"/>
-- <bsRadius value = "1.0"/>
-- <AnimDict>v_inttest</AnimDict>
-- <AnimName>v_ray_root</AnimName>
-- <StartModel>V_RAY_START</StartModel>
-- <AnimatedModel>V_RAY_ROOT</AnimatedModel>
-- <EndModel>V_RAY_END</EndModel>
-- <effectBones>
-- <effectBone value="boneID" start="0.0">
-- <effectBone value="boneID" start="">
-- <effectBone value="boneID" start="">
-- <effectBone value="boneID" start="">
-- </effectBones>
-- </Item>
local animDocRoot = animDoc.createelement("CMapTypes")
animDoc.document.AppendChild animDocRoot
local rfArrayXML = animDoc.createelement("compositeEntityTypes")
animDocRoot.AppendChild rfArrayXML
for g in groups do (
local rfItem = animDoc.createelement("Item")
rfArrayXML.AppendChild rfItem
loadAnim g
-- safety save
saveAttributes g
-- find effects on animated children
local effectBones = #()
local boneHier = currAnim.objectArray[2]
if undefined!=currAnim.objectArray[2].modifiers[#Skin] then
(
boneHier = rexGetSkinRootBone currAnim.objectArray[2]
)
for c in boneHier.children do
(
for b in c.children where (classof b)==GtaExplosion or (classof b)==RAGE_Particle do
(
append effectBones c.name
break
)
)
print effectBones
if undefined==currAnim.objectArray[1] or undefined==currAnim.objectArray[2] or undefined==currAnim.objectArray[3] then
(
print ("anim "+g+" hasn't got enough states")
continue
)
local rfNodeNameXML = animDoc.createelement("Name")
local rfname = animDoc.createTextNode g
rfItem.AppendChild rfNodeNameXML
rfNodeNameXML.AppendChild rfname
local lodIdx = getAttrIndex "Gta Object" "LOD distance"
local rfNodeLodDistXML = animDoc.createelement("lodDist")
local rflodDist = animDoc.createattribute "value" attributeValue:((getattr currAnim.objectArray[1] lodIdx) as string)
rfItem.AppendChild rfNodeLodDistXML
rfNodeLodDistXML.Attributes.Append rflodDist
local rfNodeFlagsXML = animDoc.createelement("flags")
local rfFlags = animDoc.createattribute "value" attributeValue:((getObjectFlags currAnim.objectArray[1]) as string)
rfItem.AppendChild rfNodeFlagsXML
rfNodeFlagsXML.Attributes.Append rfFlags
local attrIdx = getAttrIndex "Gta Object" "Attribute"
local rfNodeSpecialXML = animDoc.createelement("specialAttribute")
local rfSpecial = animDoc.createattribute "value" attributeValue:((getattr currAnim.objectArray[1] attrIdx) as string)
rfItem.AppendChild rfNodeSpecialXML
rfNodeSpecialXML.Attributes.Append rfSpecial
local themin = (point3 0 0 0)
local themax = (point3 0 0 0)
for o in currAnim.objectArray do
(
bb= nodeLocalBoundingBox o
local localmin = bb[1]
local localmax = bb[2]
if localmin[1]<themin[1] then themin[1]=localmin[1]
if localmin[2]<themin[2] then themin[2]=localmin[2]
if localmin[3]<themin[3] then themin[3]=localmin[3]
if localmax[1]>themax[1] then themax[1]=localmax[1]
if localmax[2]>themax[2] then themax[2]=localmax[2]
if localmax[3]>themax[3] then themax[3]=localmax[3]
)
local thecentre = (themin+themax)/2
local rfNodeMinXML = animDoc.createelement("bbMin")
rfItem.AppendChild rfNodeMinXML
local x = animDoc.createattribute "x" attributeValue:themin[1]
local y = animDoc.createattribute "y" attributeValue:themin[2]
local z = animDoc.createattribute "z" attributeValue:themin[3]
rfNodeMinXML.Attributes.Append x
rfNodeMinXML.Attributes.Append y
rfNodeMinXML.Attributes.Append z
local rfNodeMaxXML = animDoc.createelement("bbMax")
rfItem.AppendChild rfNodeMaxXML
local x = animDoc.createattribute "x" attributeValue:themax[1]
local y = animDoc.createattribute "y" attributeValue:themax[2]
local z = animDoc.createattribute "z" attributeValue:themax[3]
rfNodeMaxXML.Attributes.Append x
rfNodeMaxXML.Attributes.Append y
rfNodeMaxXML.Attributes.Append z
local rfNodeCentreXML = animDoc.createelement("bsCentre")
rfItem.AppendChild rfNodeCentreXML
local x = animDoc.createattribute "x" attributeValue:thecentre[1]
local y = animDoc.createattribute "y" attributeValue:thecentre[2]
local z = animDoc.createattribute "z" attributeValue:thecentre[3]
rfNodeCentreXML.Attributes.Append x
rfNodeCentreXML.Attributes.Append y
rfNodeCentreXML.Attributes.Append z
local radius = length (theCentre - themin)
local rfNodeRadiusXML = animDoc.createelement("bsRadius")
local rfRadius = animDoc.createattribute "value" attributeValue:(radius as string)
rfItem.AppendChild rfNodeRadiusXML
rfNodeRadiusXML.Attributes.Append rfRadius
local rfNodeDictnameXML = animDoc.createelement("AnimDict")
local rfdictname = animDoc.createTextNode (getFilenameFile maxFileName)
rfItem.AppendChild rfNodeDictnameXML
rfNodeDictnameXML.AppendChild rfdictname
local rfNodeAnimNameXML = animDoc.createelement("AnimName")
-- get skin root node if it's a skinned mesh
local model = currAnim.objectArray[2]
local rootbone = rexGetSkinRootBone currAnim.objectArray[2]
if undefined!=rootbone then
(
while undefined!=rootbone.parent do rootbone=rootbone.parent
model = rootbone
)
local rfgroupname = animDoc.createTextNode model.name -- animName
rfItem.AppendChild rfNodeAnimNameXML
rfNodeAnimNameXML.AppendChild rfgroupname
local rfNodeStartModelXML = animDoc.createelement("StartModel")
local rfStartname = animDoc.createTextNode currAnim.objectArray[1].name
rfItem.AppendChild rfNodeStartModelXML
rfNodeStartModelXML.AppendChild rfStartname
local rfNodeAnimModelXML = animDoc.createelement("AnimatedModel")
local rfAnimname = animDoc.createTextNode currAnim.objectArray[2].name
rfItem.AppendChild rfNodeAnimModelXML
rfNodeAnimModelXML.AppendChild rfAnimname
local rfNodeEndmodelXML = animDoc.createelement("EndModel")
local rfendname = animDoc.createTextNode currAnim.objectArray[3].name
rfItem.AppendChild rfNodeEndmodelXML
rfNodeEndmodelXML.AppendChild rfendname
-- particleEffect bones
local rfEffectBones = animDoc.createelement("effectBones")
rfItem.AppendChild rfEffectBones
for eb in effectBones do
(
local rfEffectBone = animDoc.createelement("effectBone")
local rfBone = animDoc.createattribute "value" attributeValue:((rexgetbonehash eb) as string)
rfEffectBones.AppendChild rfEffectBone
rfEffectBone.Attributes.Append rfBone
)
)
try(
animDoc.save RsStatedAnimFilename
)catch(messagebox (getCurrentException()))
)
)
try gRsStatedAnimTool.Deinit() catch()
global gRsStatedAnimTool = sRsStatedAnimTool()