Files
2025-09-29 00:52:08 +02:00

689 lines
16 KiB
Plaintext
Executable File

filein "pipeline/export/models/RsObjectFlags.ms"
filein "rockstar/util/anim.ms"
try gRsStatedAnimTool.Deinit() catch()
global gStatedAnimFoundTXDs = #()
global allowedStateClasses = #("Gta Object", "RS IMAP Group")
global allowedAnimStateClasses = #("Gta Object")
fn StatedAnimAddNewTxd thename =
(
if undefined!=thename and 0==findItem gStatedAnimFoundTXDs thename then
append gStatedAnimFoundTXDs thename
)
struct sRsStatedAnim
(
animGroup = "DEFAULT",
objectArray = #(),
looped = false,
compression = "Stated_Anim_Default",
txdIdx = getattrindex "Gta Object" "TXD",
loopIdx = getattrindex "Gta Object" "looped",
idxDontAddIPL = getattrindex "Gta Object" "Dont Add To IPL",
IsFixedIdx = getattrindex "Gta Object" "Is Fixed",
HasAnimIdx = getattrindex "Gta Object" "Has Anim",
fn Reset =
(
animGroup = "DEFAULT"
objectArray = #()
looped = false
gStatedAnimFoundTXDs = #()
),
fn getAnimationStates =
(
for o in objectArray where
( (not isDeleted o) and
(0!=finditem allowedStateClasses (Getattrclass o)) and
("Animation"==(getAttr o (getattrindex (getattrclass o) "animState"))) )
collect o
),
fn GetObjAnimationRangeRec obj &range =
(
local maxLength = 0
local skel = rexGetSkinRootBone obj
if undefined!=skel then
(
-- print ("using skeleton for animation length calculation"+skel as string)
obj = skel
)
RsGetControllerKeyRangeRec obj.controller &range
for c in obj.children do
(
GetObjAnimationRangeRec c &range
)
--print ("animation length:"+maxLength as string)
return maxLength
),
fn getAnimationRange =
(
local range = sNegInterval start:9999f end:0f
for o in getAnimationStates() do
(
GetObjAnimationRangeRec o &range
)
return range
),
fn getChildren obj outVal:#() =
(
append outVal obj
for c in obj.children where IsValidNode c do (getChildren c outVal:outVal)
return outVal
),
fn selectObject num =
(
if 0==num or undefined==objectArray[num] then return false
clearSelection()
select (getChildren objectArray[num])
),
fn sortObjList v1 v2 =
(
local stateIdxV1 = getattrindex (getattrclass v1) "animState"
local stateIdxV2 = getattrindex (getattrclass v2) "animState"
case of
(
(getAttr v1 stateIdxV1 == "Start"):-1
(getAttr v2 stateIdxV2 == "Start"):1
(getAttr v1 stateIdxV1 == "End"):1
(getAttr v2 stateIdxV2 == "End"):-1
default:
(
case of
(
(undefined!=v1.modifiers[#skin]):-1
(undefined!=v2.modifiers[#skin]):1
default:striCmp v1.name v2.name
)
)
)
),
fn addObject newObj loading:false =
(
while undefined!=newObj.parent do newObj = newobj.parent
if ((findItem objectArray newObj) != 0) do
(
return false
)
if 0==findItem allowedStateClasses (getattrclass newobj) then
(
return false
)
local groupIdx = getattrindex (getattrclass newObj) "groupName"
if loading then
(
if (animGroup == undefined) do
(
animGroup = (getAttr newObj groupIdx)
)
)
else
(
local isStartEnd = true
setAttr newObj groupIdx animGroup
local stateIdx = getattrindex (getattrclass newObj) "animState"
case of
(
(matchPattern newObj.name pattern:"*_START*"):
(
setAttr newObj stateIdx "Start"
)
(matchPattern newObj.name pattern:"*_END*"):
(
setAttr newObj stateIdx "End"
)
default:
(
setAttr newObj stateIdx "Animation"
isStartEnd = false
)
)
if 0!=findItem allowedAnimStateClasses (getattrclass newobj) then
(
setattr newObj idxDontAddIPL true
-- Set start/end animation-roots to "Is Fixed":
setAttr newObj IsFixedIdx isStartEnd
-- Set other anim-roots to "Has Anim"
setAttr newObj HasAnimIdx (not isStartEnd)
)
)
append objectArray newObj
qsort objectArray sortObjList
local insertIdx = findItem objectArray newObj
if 0!=findItem allowedAnimStateClasses (getattrclass newobj) then
StatedAnimAddNewTxd (getattr newobj txdIdx)
return newobj
),
fn setLooped state =
(
looped = state
for obj in objectArray do
(
setAttr obj loopIdx state
)
),
fn resetAttributes objs =
(
if classof objs!=array then
objs = #(objs)
for obj in objs do
(
if 0!=findItem allowedStateClasses (getattrclass obj) then
(
local groupIdx = getattrindex (getattrclass obj) "groupName"
local stateIdx = getattrindex (getattrclass obj) "animState"
setAttr obj groupIdx "DEFAULT"
setAttr obj stateIdx "None"
if 0!=findItem allowedAnimStateClasses (getattrclass newobj) then
(
setAttr obj IsFixedIdx false
setAttr obj HasAnimIdx false
)
)
else
(
gRsUlog.LogError ("Object "+obj as string+" is not a valid statedAnim state. Please select Meshes or IMAP groups only to reset their related attributes.") context:obj
)
)
gRsUlog.Validate()
),
-- If objNum is -1, all objects are reset
fn deleteObject objNum =
(
if (objNum == 0) or (objNum > objectArray.count) then
(
return false
)
else
(
local objs = if (objNum == -1) then objectArray else #(objectArray[objNum])
-- Unset anim-flags:
resetAttributes objs
if (objNum == -1) then
(
format "Clearing StatedAnim data for animgroup: %\n" (animGroup as string)
Reset()
)
else
(
format "Clearing StatedAnim data for object: %, %\n" objectArray[objNum].name objNum
deleteItem objectArray objNum
)
return true
)
)
)
struct sRsStatedAnimTool
(
txdIdx = getattrindex "Gta Object" "TXD",
loopIdx = getattrindex "Gta Object" "looped",
IsFixedIdx = getattrindex "Gta Object" "Is Fixed",
HasAnimIdx = getattrindex "Gta Object" "Has Anim",
idxStatedAnimCompression = getAttrindex "RsStatedAnim" "Compression",
idxAnimStart = getAttrindex "RsStatedAnim" "Animation Start",
idxAnimEnd = getAttrindex "RsStatedAnim" "Animation End",
currAnim = sRsStatedAnim(),
hideObjs = true,
currActiveObjectIndex = 1,
-- not in particular order
fn findSameAnimGroup animGroupName =
(
for obj in objects where (0!=findItem allowedStateClasses (getAttrClass obj)) and (getAttr obj (getattrindex (getattrclass obj) "groupName") == animGroupName) collect obj
),
fn IsInValidAnimGroup animgroupname tempStates: =
(
local groupStates = findSameAnimGroup animgroupname
if unsupplied!=tempStates then
*tempStates = groupStates
-- print ("groupStates for "+animgroupname+":"+*tempStates as string)
local startStates = for o in groupStates where ((0!=finditem allowedStateClasses (Getattrclass o)) and ("Start"==(getAttr o (getattrindex (getattrclass o) "animState")))) collect o
local animationStates = for o in groupStates where ((0!=finditem allowedStateClasses (Getattrclass o)) and ("Animation"==(getAttr o (getattrindex (getattrclass o) "animState")))) collect o
local endStates = for o in groupStates where ((0!=finditem allowedStateClasses (Getattrclass o)) and ("End"==(getAttr o (getattrindex (getattrclass o) "animState")))) collect o
if startStates.count>=1 and animationStates.count>=1 and endStates.count>=1 then
return true
else
return false
),
fn getCurrentAnimGroupName =
(
if currAnim == undefined then "DEFAULT" else currAnim.animGroup
),
fn GetStatedAnimGroupName obj =
(
local className = getattrclass obj
if undefined==className then
return undefined
local groupIdx = getattrindex className "groupName"
if undefined==groupIdx then
return undefined
return getattr obj groupIdx
),
fn IsStatedAnimGroupMember obj =
(
isInStatedAnimGroup = false
stateAnimGroup = GetStatedAnimGroupName obj
if stateAnimGroup != "Default" and stateAnimGroup != "DEFAULT" then isInStatedAnimGroup = true
isInStatedAnimGroup
),
fn setTxdNames newName =
(
for obj in currAnim.objectArray where 0!=findItem allowedAnimStateClasses (getattrclass obj) do setattr obj txdIdx newName
),
fn getAnimationRange =
(
return currAnim.getAnimationRange()
),
fn StoreAnimationRange =
(
local newrange = getAnimationRange()
local myProxy = getnodeByName (curranim.animGroup+"_anim")
if undefined!=myProxy then
(
setAttr myProxy idxAnimStart newrange.start
setAttr myProxy idxAnimEnd newrange.end
gRsUlog.LogMessage ("Animation range ("+newrange.start as string+".."+newrange.end as string+") stored on "+myProxy.name) context:myProxy
)
),
fn loadAnim animGroupName =
(
if isValidNode animGroupName then
animGroupName = GetStatedAnimGroupName animGroupName
gStatedAnimFoundTXDs = #()
if animGroupName == getCurrentAnimGroupName() then return false
currAnim = sRsStatedAnim animGroup:animGroupName
local states = #()
local validGroup = IsInValidAnimGroup animGroupName tempStates:&states
if not validGroup then
(
print ("Not enough states found for group: \""+animGroupName+"\"\n\nObjects"+states as string)
return false
)
else
(
for obj in states do
(
currAnim.addObject obj loading:true
)
-- currAnim.looped = getAttr states[1] loopIdx
)
local proxyObj = getNodeByName (animGroupName+"_anim")
if proxyObj != undefined then
(
local compressionName = getattr proxyObj idxStatedAnimCompression
if matchPattern compressionName pattern:"*default*" then
compressionName = "Stated_Anim_Default"
currAnim.compression = compressionName
)
StoreAnimationRange()
return true
),
fn setCompression compression =
(
if undefined==currAnim then
return false
local proxyObj = getNodeByName (curranim.animGroup+"_anim")
local success = false
if proxyObj != undefined then
(
success = setattr proxyObj idxStatedAnimCompression compression
)
currAnim.compression = compression
return success
),
fn getCompression =
(
return currAnim.compression
),
fn ResetAttributes objs =
(
currAnim.resetAttributes objs
),
fn findAnimGroups theProgressbar:undefined =
(
local animGroups = #()
local index = 1
for obj in objects where 0!=findItem allowedStateClasses (getAttrClass obj) do
(
local groupIdx = getattrindex (getattrclass obj) "groupName"
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 "undefined"==(toLower currGroupName) or 0!=(findItem animGroups currGroupName) then continue
local validGroup = IsInValidAnimGroup currGroupName
if validGroup then
appendIfUnique 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 =
(
checkName == currAnim.animGroup
),
fn getObjectNames =
(
local objectNames = for obj in currAnim.objectArray collect
(
if not IsValidNode obj then
(
currAnim.Reset()
return #()
)
local stateIdx = getattrindex (getattrclass obj) "animState"
local objState = getAttr obj stateIdx
local prefix = case objState of
(
"Start": "start: "
"Animation": "anim: "
"End": "end: "
default: "undefined: "
)
prefix + obj.name
)
return objectNames
),
fn addObject newobj =
(
local retObj = false
if undefined==currAnim then
return false
else
retObj = currAnim.addObject newobj
if undefined!=RsStatedAnimRollout and RsStatedAnimRollout.open then
RsStatedAnimRollout.updateList()
StoreAnimationRange()
return newObj
),
fn deleteObject objNum =
(
if undefined==currAnim then (return false) else
(
currAnim.deleteObject objNum
)
),
fn deleteAttributes =
(
deleteObject -1
),
fn changeAnimGroup newName =
(
if (matchPattern newName pattern:"DEFAULT") then
(
deleteAttributes()
)
else
(
if (undefined==currAnim) then (return false) else
(
local existingAnims = findAnimGroups()
if (findItem existingAnims newName) != 0 then
(
-- Add listed states to existing named state:
local currObjs = for obj in currAnim.objectArray collect obj
loadAnim newName
for obj in currObjs do
(
currAnim.addObject obj
)
)
else
(
currAnim.animGroup = newName
if (currAnim.objectArray.count != 0) do
(
for obj in currAnim.objectArray do
(
setAttr obj groupIdx newName
)
loadAnim newName
)
)
)
)
),
fn setLooped state =
(
if (currAnim != undefined) do (currAnim.setLooped state)
),
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 Deinit =
(
currActiveObjectIndex=1
unhideAll()
currAnim = sRsStatedAnim()
gStatedAnimFoundTXDs = #()
),
fn selectionChanged =
(
local groupName
for obj in selection do
(
local objGrpName
local checkName = true
if (isKindOf obj statedAnimProxy) then
(
if not matchPattern obj.name pattern:"*_anim*" then
(
messagebox "no _anim suffix found on animation proxy. Deleting." title:"StatedAnim Warning"
delete obj
)
else
(
objGrpName = substring obj.name 1 ((findString obj.name "_anim")-1)
)
)
else
(
-- Find topmost Gta Object parent:
while (0!=findItem allowedStateClasses (getAttrClass obj)) and (not isKindOf obj.parent Container) and (obj.parent != undefined) do obj = obj.parent
if (0!=findItem allowedStateClasses (getAttrClass obj)) then
(
local groupIdx = getattrindex (getattrclass obj) "groupName"
objGrpName = getAttr obj groupIdx
)
else
(
checkName = false
)
)
if checkName do
(
if (groupName == undefined) then
(
groupName = objGrpName
)
else
(
-- Exit if multiple groupNames were found
if (groupName != objGrpName) do (return false)
)
)
)
-- Exit if groupname is default, or no groupNames were found
if (groupName == undefined) or (objGrpName == "DEFAULT") do (return false)
if (isCurrentAnimGroupName groupName) then
(
return true
)
else
(
return (loadAnim groupName)
)
),
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 sensible group name."
return false
)
local newName = thename+"_anim"
-- delete old
local oldProxies = for o in objects where o.name==newName collect o
local selNewProxy = false
for item in oldProxies where item.isSelected do (selNewProxy = true)
local proxyObj = ::statedAnimProxy()
proxyObj.testNodeForAnimation currAnim.objectArray[1]
setattr proxyObj idxStatedAnimCompression curranim.compression
if selNewProxy do (selectMore proxyObj)
delete oldProxies
StoreAnimationRange()
return proxyObj
),
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 PreExportSetup =
(
local groups = findAnimGroups()
for g in groups do
loadAnim g
)
)
global gRsStatedAnimTool = sRsStatedAnimTool()