gck-map-extract-objects/anm.py

268 lines
9.8 KiB
Python
Raw Normal View History

2021-02-23 19:04:32 +01:00
from lib.fileutils import *
import logging
import sys
class MConsoleHandler(logging.StreamHandler):
special_code = '[!n]'
def emit(self, record) -> None:
record.msg = str(record.msg)
if self.special_code in record.msg:
record.msg = record.msg.replace(self.special_code, '')
self.terminator = ''
else:
self.terminator = '\n'
return super().emit(record)
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
cs = MConsoleHandler(sys.stdout)
fmt = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
fmt = logging.Formatter("%(message)s")
cs.setFormatter(fmt)
logger.addHandler(cs)
NAM_FlagHasHandles = (1 << 0)
NAM_FlagCaseInsensitive = (1 << 1)
ANM_NODE_FLAG_POS_ANIMATED = (1 << 0)
ANM_NODE_FLAG_ROT_ANIMATED = (1 << 1)
ANM_NODE_FLAG_ROL_ANIMATED = (1 << 2)
ANM_NODE_FLAG_SCL_ANIMATED = (1 << 3)
ANM_NODE_FLAG_AFF_ANIMATED = (1 << 4)
ANM_NODE_FLAG_USR_ANIMATED = (1 << 5)
ANM_NODE_FLAG_ANIMATED = ((1 << 6) - 1)
def printdebug(msg):
logger.debug(msg)
def printinfo(msg):
logger.info(msg, )
def tb(i):
return 1 if i > 0 else 0
def read_int_and_print(n, b):
a = read_int(b)
printdebug("%s=%s" % (n, a))
return a
def read_float_and_print(n, b):
a = read_float(b)
printdebug("%s=%s" % (n, a))
return a
def read_byte_and_print(n, b):
a = read_byte(b)
printdebug("%s=%s" % (n, a))
return a
def read_short_and_print(n, b):
a = read_short(b)
printdebug("%s=%s" % (n, a))
return a
class ANM_Anim:
def __init__(self):
self.custom = 0
self.file_version = 0
self.image = 0
self.memgroup = 0
self.node_dictionary = 0
self.tree_dictionary = 0
self.default_obj_dictionnary = 0
self.total_number_trees = 0
self.total_number_objs = 0
self.total_number_clusters = 0
self.name = 0
@classmethod
def parse(cls, b):
printinfo("Decoding %s" % b.name)
printdebug("MAP_Image")
read_int_and_print("size", b)
memgroupoffset = read_int_and_print("memgroupoffset", b)
b.seek(memgroupoffset)
printdebug("MAP_MemGroup")
printdebug("\tMAP_Mem")
read_int_and_print("\tNode", b)
read_int_and_print("\tSize", b)
read_int_and_print("\tFlags", b)
read_int_and_print("pMemGroup", b)
read_int_and_print("MemList", b)
read_int_and_print("TotalSize", b)
read_int_and_print("TotalBlocks", b)
base = read_int_and_print("pBase", b)
b.seek(base)
printdebug("=========")
printdebug("ANM_Anim")
read_int_and_print("pCustom", b)
read_int_and_print("FileVersion", b)
read_int_and_print("pImage", b)
read_int_and_print("pMemGroup", b)
starttime = read_int_and_print("StartTime", b)
endtime = read_int_and_print("EndTime", b)
ticksperframe = read_int_and_print("TicksPerFrame", b)
framerate = read_int_and_print("FrameRate", b)
tree = read_int_and_print("pTreeDictionary", b)
defaultobj = read_int_and_print("pDefaultObjDictionary", b)
numnodes = read_int_and_print("NumberOfNodes", b)
printdebug("ANM_AnimExtra")
read_int_and_print("ANM_AnimExtra->Stamp", b)
read_int_and_print("ANM_AnimExtra->Flags", b)
read_int_and_print("ANM_AnimExtra->Time1", b)
read_int_and_print("ANM_AnimExtra->Stamp1", b)
read_int_and_print("ANM_AnimExtra->Time2", b)
read_int_and_print("ANM_AnimExtra->Stamp2", b)
read_float_and_print("ANM_AnimExtra->Factor", b)
read_int_and_print("ANM_AnimExtra->OtherAnim", b)
name = read_string_until_none(b)
printdebug(name)
printinfo("[%s] StartTime:%s EndTime:%s TicksPerFrame:%s FrameRate:%s NumNodes:%s" % (name, starttime, endtime, ticksperframe , framerate, numnodes))
printdebug("=========")
printdebug("ANM_Anim->pTreeDictionary NAM_Dictionary")
b.seek(defaultobj)
read_int_and_print("pMemGroup", b)
namemapper = read_int_and_print("pNameMapper", b)
flags = read_int_and_print("Flags", b)
printdebug("Flags: NAM_FlagHasHandles: %s, NAM_FlagCaseInsensitive: %s" % (flags & NAM_FlagHasHandles, flags & NAM_FlagCaseInsensitive))
namehandle = read_short_and_print("NameHandle", b)
printdebug("MAP_Image->ANM_Anim->NAM_Dictionnary->MAP_Mapper")
b.seek(namemapper)
pMemGroup = read_int_and_print("pMemGroup", b)
read_int_and_print("MemBaseSize", b)
read_int_and_print("MemBlocks", b)
read_int_and_print("MemSize", b)
read_int_and_print("MemFree", b)
mem = read_int_and_print("pMem", b)
read_int_and_print("MaxMappings", b)
totalmappings = read_int_and_print("TotalMappings", b)
read_int_and_print("TotalKeys", b)
pKeyContexts = read_int_and_print("pKeyContexts", b)
printdebug("MAP_Image->ANM_Anim->NAM_Dictionnary->MAP_Mapper->MAP_KeyContext NAM_STRING_KEY")
b.seek(pKeyContexts)
read_int_and_print("\tSize", b)
read_int_and_print("\tpCallback", b)
read_int_and_print("\tIndex", b)
read_int_and_print("\tTest", b)
pLUTNAM_STRING_KEY = read_int_and_print("pLUT", b)
read_int_and_print("Reserve", b)
read_int_and_print("pData", b)
def showdictbyindex(i):
assert(0 <= i < totalmappings)
printdebug("LUT NAM_STRING_KEY")
b.seek(pLUTNAM_STRING_KEY)
pind0_string = read_int_and_print("LUT NAM_STRING_KEY[0]", b)
for _ in range(i):
pind0_string = read_int_and_print("LUT NAM_STRING_KEY[0]", b)
printdebug("NAM_StringData")
b.seek(pind0_string)
read_int_and_print("pPtr->ANM_Obj", b)
val = read_int_and_print("Value", b)
printdebug(b.tell())
nodename = read_string_until_none(b)
printdebug(nodename)
b.seek(val)
read_int_and_print("ANM_Node->Custom", b)
read_short_and_print("ANM_Node->Type", b)
read_short_and_print("ANM_Node->XformType", b)
nodeflags = read_int_and_print("ANM_Node->Flags", b)
read_int_and_print("ANM_Node->pAnim", b)
read_int_and_print("ANM_Node->pParent", b)
read_int_and_print("ANM_Node->pTarget", b)
read_int_and_print("ANM_Node->pUserCall", b)
read_int_and_print("ANM_Node->pUserContext", b)
stamp = read_int_and_print("ANM_Node->Stamp", b)
printdebug("ANM_Node->Mat")
read_int_and_print("GEO_Mat->Class", b)
for _i in range(4):
for _j in range(4):
read_float_and_print("GEO_Mat->E", b)
printdebug("ANM_Node->Transform")
transformtime = read_int_and_print("ANM_Transform->Time", b)
printdebug("ANM_Transform->Affine")
read_float_and_print("GEO_Affine->Trans[x]", b)
read_float_and_print("GEO_Affine->Trans[y]", b)
read_float_and_print("GEO_Affine->Trans[z]", b)
read_float_and_print("GEO_Affine->Quat[x]", b)
read_float_and_print("GEO_Affine->Quat[y]", b)
read_float_and_print("GEO_Affine->Quat[z]", b)
read_float_and_print("GEO_Affine->Quat[w]", b)
read_float_and_print("GEO_Affine->Scale[x]", b)
read_float_and_print("GEO_Affine->Scale[y]", b)
read_float_and_print("GEO_Affine->Scale[z]", b)
read_int_and_print("GEO_Affine->Class", b)
posKeys = read_int_and_print("ANM_Node->pPosKeys", b)
rotKeys = read_int_and_print("ANM_Node->pRotKeys", b)
sclKeys = read_int_and_print("ANM_Node->pSclKeys", b)
printinfo("\t[%s] Animated:%s[!n]" % (nodename, bool(nodeflags & ANM_NODE_FLAG_ANIMATED)))
if nodeflags & ANM_NODE_FLAG_POS_ANIMATED:
printinfo(" PosAnimated:True[!n]")
if nodeflags & ANM_NODE_FLAG_ROT_ANIMATED:
printinfo(" RotAnimated:True[!n]")
if nodeflags & ANM_NODE_FLAG_ROL_ANIMATED:
printinfo(" RolAnimated:True[!n]")
if nodeflags & ANM_NODE_FLAG_SCL_ANIMATED:
printinfo(" SclAnimated:True[!n]")
if nodeflags & ANM_NODE_FLAG_AFF_ANIMATED:
printinfo(" AffAnimated:True[!n]")
if nodeflags & ANM_NODE_FLAG_USR_ANIMATED:
printinfo(" UsrAnimated:True[!n]")
printinfo("")
"""
printinfo("\t[%s] Anim:%s Pos:%s Rot:%s Rol:%s Scl:%s Aff:%s Usr:%s" % (
nodename, tb(nodeflags & ANM_NODE_FLAG_ANIMATED), tb(nodeflags & ANM_NODE_FLAG_POS_ANIMATED), tb(nodeflags & ANM_NODE_FLAG_ROT_ANIMATED),
tb(nodeflags & ANM_NODE_FLAG_ROL_ANIMATED), tb(nodeflags & ANM_NODE_FLAG_SCL_ANIMATED), tb(nodeflags & ANM_NODE_FLAG_AFF_ANIMATED),
tb(nodeflags & ANM_NODE_FLAG_USR_ANIMATED)))
"""
if nodeflags & ANM_NODE_FLAG_POS_ANIMATED:
b.seek(posKeys)
read_byte_and_print("\t\tType", b)
read_byte_and_print("\t\tORTBefore", b)
read_byte_and_print("\t\tORTAfter", b)
read_byte_and_print("\t\tFlags", b)
read_int_and_print("\t\tpInterpolate", b)
read_int_and_print("\t\tNumberOfKeys", b)
read_int_and_print("\t\tpKeys", b)
for p in range(totalmappings):
showdictbyindex(p)
def main():
#with open("/home/tasty/Projects/gck-map-extract-objects/anm_skn/sm_book.anm", "rb") as fp:
# with open("/home/tasty/Projects/gck-map-extract-objects/anm_skn/vp_hit.anm", "rb") as fp:
with open("/home/tasty/Projects/gck-map-extract-objects/anm_skn/Mc_salute.anm", "rb") as fp:
ANM_Anim.parse(fp)
if __name__ == "__main__":
main()