688 lines
20 KiB
Plaintext
Executable File
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()
|