689 lines
16 KiB
Plaintext
Executable File
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()
|