skn + anm
This commit is contained in:
parent
4f45346980
commit
55bb2e423b
267
anm.py
Normal file
267
anm.py
Normal file
@ -0,0 +1,267 @@
|
|||||||
|
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()
|
377
skn.py
377
skn.py
@ -1,65 +1,193 @@
|
|||||||
from lib.fileutils import *
|
from lib.fileutils import *
|
||||||
|
from dataclasses import dataclass, field
|
||||||
|
from typing import List, Union
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Vec3Indexed:
|
||||||
|
x: float
|
||||||
|
y: float
|
||||||
|
z: float
|
||||||
|
index: int
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create(cls, b, offset=None):
|
||||||
|
old = b.tell()
|
||||||
|
if offset:
|
||||||
|
b.seek(offset)
|
||||||
|
x = read_float_and_print("Vec3->x", b)
|
||||||
|
y = read_float_and_print("Vec3->y", b)
|
||||||
|
z = read_float_and_print("Vec3->z", b)
|
||||||
|
index = read_int_and_print("Vec3->index", b)
|
||||||
|
if offset:
|
||||||
|
b.seek(old)
|
||||||
|
return cls(x=x, y=y, z=z, index=index)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Vec3:
|
||||||
|
x: float
|
||||||
|
y: float
|
||||||
|
z: float
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create(cls, b, offset=None):
|
||||||
|
old = b.tell()
|
||||||
|
if offset:
|
||||||
|
b.seek(offset)
|
||||||
|
x = read_float_and_print("Vec3->x", b)
|
||||||
|
y = read_float_and_print("Vec3->y", b)
|
||||||
|
z = read_float_and_print("Vec3->z", b)
|
||||||
|
if offset:
|
||||||
|
b.seek(old)
|
||||||
|
return cls(x=x, y=y, z=z)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class AnmObj:
|
||||||
|
custom: int
|
||||||
|
skin: int = field(repr=False)
|
||||||
|
zero_cluster: int
|
||||||
|
total_number_vertices: int
|
||||||
|
num_clusters: int
|
||||||
|
clusters: List['AnmCluster']
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create(cls, b, offset=None):
|
||||||
|
old = b.tell()
|
||||||
|
if offset:
|
||||||
|
b.seek(offset)
|
||||||
|
custom = read_int_and_print("ANM_Obj->Custom", b)
|
||||||
|
skin = read_int_and_print("ANM_Obj->Skin", b)
|
||||||
|
zero = read_int_and_print("ANM_Obj->ZeroCluster", b)
|
||||||
|
total_vertices = read_int_and_print("ANM_Obj->TotalNumberOfVertices", b)
|
||||||
|
num_clusters = read_int_and_print("ANM_Obj->NumberOfClusters", b)
|
||||||
|
clusters_offset = read_int_and_print("ANM_Obj->Clusters", b)
|
||||||
|
clusters = []
|
||||||
|
_old1 = b.tell()
|
||||||
|
b.seek(clusters_offset)
|
||||||
|
for _ in range(num_clusters):
|
||||||
|
cluster = AnmCluster.create(b)
|
||||||
|
clusters.append(cluster)
|
||||||
|
|
||||||
|
b.seek(_old1)
|
||||||
|
if offset:
|
||||||
|
b.seek(old)
|
||||||
|
r = cls(custom=custom, skin=skin, zero_cluster=zero, total_number_vertices=total_vertices, num_clusters=num_clusters, clusters=clusters)
|
||||||
|
for cluster in clusters:
|
||||||
|
cluster.obj = r
|
||||||
|
return r
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class AnmCluster:
|
||||||
|
custom: int = field(repr=False)
|
||||||
|
obj: Union[AnmObj, None]
|
||||||
|
handle: int
|
||||||
|
bounding_box: List[Vec3] = field(repr=False) # size 2
|
||||||
|
num_vertices: int
|
||||||
|
vertices: List[Vec3Indexed] = field(repr=False)
|
||||||
|
bone_name: str = ""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create(cls, b, offset=None):
|
||||||
|
old = b.tell()
|
||||||
|
if offset:
|
||||||
|
b.seek(offset)
|
||||||
|
custom = read_int_and_print("ANM_Cluster->Custom", b)
|
||||||
|
obj_offset = read_int_and_print("ANM_Cluster->Obj", b)
|
||||||
|
if obj_offset == 0: # ugly hack, dunno why we need that
|
||||||
|
_ = read_int_and_print("ANM_Cluster->Custom", b)
|
||||||
|
_ = read_int_and_print("ANM_Cluster->Obj", b)
|
||||||
|
obj = None # is set by parent Obj
|
||||||
|
handle = read_int_and_print("ANM_Cluster->Handle", b)
|
||||||
|
bbox1 = Vec3.create(b)
|
||||||
|
bbox2 = Vec3.create(b)
|
||||||
|
bounding_box = [bbox1, bbox2]
|
||||||
|
num_vertices = read_int_and_print("ANM_Cluster->num_vertices", b)
|
||||||
|
vertices = []
|
||||||
|
for _ in range(num_vertices):
|
||||||
|
v = Vec3Indexed.create(b)
|
||||||
|
vertices.append(v)
|
||||||
|
|
||||||
|
if offset:
|
||||||
|
b.seek(old)
|
||||||
|
return cls(custom=custom, obj=obj, handle=handle, bounding_box=bounding_box, num_vertices=num_vertices, vertices=vertices)
|
||||||
|
|
||||||
|
|
||||||
|
class NamDictionnary:
|
||||||
|
@staticmethod
|
||||||
|
def create(b, cls, depth=1, offset=None):
|
||||||
|
r = {}
|
||||||
|
|
||||||
|
old = b.tell()
|
||||||
|
if offset:
|
||||||
|
b.seek(offset)
|
||||||
|
|
||||||
|
read_int_and_print("NAM_Dictionnary->pMemGroup", b)
|
||||||
|
namemapper = read_int_and_print("NAM_Dictionnary->pNameMapper", b)
|
||||||
|
flags = read_int_and_print("NAM_Dictionnary->Flags", b)
|
||||||
|
print("Flags: NAM_FlagHasHandles: %s, NAM_FlagCaseInsensitive: %s" % (flags & NAM_FlagHasHandles, flags & NAM_FlagCaseInsensitive))
|
||||||
|
read_short_and_print("NAM_Dictionnary->NameHandle", b)
|
||||||
|
|
||||||
|
b.seek(namemapper)
|
||||||
|
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)
|
||||||
|
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)
|
||||||
|
p_key_contexts = read_int_and_print("pKeyContexts", b)
|
||||||
|
|
||||||
|
print("MAP_Image->ANM_Skin->NAM_Dictionnary->MAP_Mapper->MAP_KeyContext")
|
||||||
|
b.seek(p_key_contexts)
|
||||||
|
print("\tMAP_Image->ANM_Skin->NAM_Dictionnary->MAP_Mapper->MAP_KeyContext->MAP_BinSearchContext")
|
||||||
|
_ = read_int_and_print("\tSize", b)
|
||||||
|
read_int_and_print("\tpCallback", b)
|
||||||
|
read_int_and_print("\tIndex", b)
|
||||||
|
read_int_and_print("\tTest", b)
|
||||||
|
p_lut = read_int_and_print("pLUT", b)
|
||||||
|
read_int_and_print("Reserve", b)
|
||||||
|
read_int_and_print("pData", b)
|
||||||
|
|
||||||
|
for i in range(totalmappings):
|
||||||
|
b.seek(p_lut)
|
||||||
|
pindx = read_int(b)
|
||||||
|
for _ in range(i):
|
||||||
|
pindx = read_int(b)
|
||||||
|
print("LUT INDEX: %s" % pindx)
|
||||||
|
b.seek(pindx)
|
||||||
|
if not flags & NAM_FlagHasHandles:
|
||||||
|
read_short_and_print("pPtr", b)
|
||||||
|
read_short_and_print("pPtr2", b)
|
||||||
|
val = read_int_and_print("Value", b)
|
||||||
|
name = read_string_until_none_and_print("name", b)
|
||||||
|
if depth > 1:
|
||||||
|
item = NamDictionnary.create(b, cls, depth-1, val)
|
||||||
|
else:
|
||||||
|
item = cls.create(b, val)
|
||||||
|
r[name] = item
|
||||||
|
else:
|
||||||
|
refcnt = read_short_and_print("RefCnt", b)
|
||||||
|
handle = read_short_and_print("Handle", b)
|
||||||
|
read_int_and_print("Test", b)
|
||||||
|
read_int_and_print("Test", b)
|
||||||
|
bone_name = read_string_until_none_and_print("BoneName", b)
|
||||||
|
r[str(i)] = {"RefCnt": refcnt, "Handle": handle, "BoneName": bone_name}
|
||||||
|
|
||||||
|
if offset:
|
||||||
|
b.seek(old)
|
||||||
|
|
||||||
|
return r
|
||||||
|
|
||||||
|
|
||||||
NAM_FlagHasHandles = (1 << 0)
|
NAM_FlagHasHandles = (1 << 0)
|
||||||
NAM_FlagCaseInsensitive = (1 << 1)
|
NAM_FlagCaseInsensitive = (1 << 1)
|
||||||
|
|
||||||
|
|
||||||
class MAP_KeyContext:
|
|
||||||
def __init__(self):
|
|
||||||
self.context = 0
|
|
||||||
self.ppLUT = 0
|
|
||||||
self.reserve = 0
|
|
||||||
self.pData = 0
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def parse(cls, b):
|
|
||||||
r = cls()
|
|
||||||
r.context = read_int(b)
|
|
||||||
r.ppLUT = read_int(b)
|
|
||||||
r.reserve = read_int(b)
|
|
||||||
r.pData = read_int(b)
|
|
||||||
return r
|
|
||||||
|
|
||||||
|
|
||||||
class MAP_Mapper:
|
|
||||||
def __init__(self):
|
|
||||||
self.pMemgroup = 0
|
|
||||||
self.MemBaseSize = 0
|
|
||||||
self.MemBlocks = 0
|
|
||||||
self.MemSize = 0
|
|
||||||
self.MemFree = 0
|
|
||||||
self.pMem = 0
|
|
||||||
self.MaxMappings = 0
|
|
||||||
self.TotalMappings = 0
|
|
||||||
self.TotalKeys = 0
|
|
||||||
self.pKeyContexts = 0
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def parse(cls, b):
|
|
||||||
r = cls()
|
|
||||||
r.pMemgroup = read_int(b)
|
|
||||||
r.MemBaseSize = read_int(b)
|
|
||||||
r.MemBlocks = read_int(b)
|
|
||||||
r.MemSize = read_int(b)
|
|
||||||
r.MemFree = read_int(b)
|
|
||||||
r.pMem = read_int(b)
|
|
||||||
r.MaxMappings = read_int(b)
|
|
||||||
r.TotalMappings = read_int(b)
|
|
||||||
r.TotalKeys = read_int(b)
|
|
||||||
r.pKeyContexts = read_int(b)
|
|
||||||
return r
|
|
||||||
|
|
||||||
class MAP_Mapping:
|
|
||||||
def __init__(self):
|
|
||||||
self.index = 0
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def parse(cls, b):
|
|
||||||
r = cls()
|
|
||||||
r.index = read_short(b)
|
|
||||||
return r
|
|
||||||
|
|
||||||
|
|
||||||
def read_int_and_print(n, b):
|
def read_int_and_print(n, b):
|
||||||
a = read_int(b)
|
a = read_int(b)
|
||||||
print("%s=%s" % (n, a))
|
print("%s=%s" % (n, a))
|
||||||
@ -84,24 +212,21 @@ def read_short_and_print(n, b):
|
|||||||
return a
|
return a
|
||||||
|
|
||||||
|
|
||||||
class MAP_MemGroup:
|
def read_string_until_none_and_print(n, b):
|
||||||
def __init__(self):
|
s = read_string_until_none(b)
|
||||||
self.mem = 0
|
print("%s=%s" % (n, s))
|
||||||
self.memgroup = 0
|
return s
|
||||||
self.memlist = 0
|
|
||||||
self.total_size = 0
|
|
||||||
self.total_blocks = 0
|
|
||||||
self.base = 0
|
|
||||||
|
|
||||||
|
|
||||||
class MAP_Image:
|
def link(nodedict, defaultobjtree):
|
||||||
def __init__(self):
|
for obj_name, obj in defaultobjtree.items():
|
||||||
self.size = 0
|
for cluster in obj.clusters:
|
||||||
self.memgroupoffset = 0
|
cluster_handle = cluster.handle
|
||||||
|
k = str(cluster_handle-1)
|
||||||
|
cluster.bone_name = nodedict[k]["BoneName"]
|
||||||
|
|
||||||
|
|
||||||
|
class AnmSkin:
|
||||||
class ANM_Skin:
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.custom = 0
|
self.custom = 0
|
||||||
self.file_version = 0
|
self.file_version = 0
|
||||||
@ -117,9 +242,7 @@ class ANM_Skin:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def parse(cls, b):
|
def parse(cls, b):
|
||||||
print("MAP_Image")
|
_ = read_int_and_print("size", b)
|
||||||
read_int_and_print("size", b)
|
|
||||||
ret = b.tell()
|
|
||||||
memgroupoffset = read_int_and_print("memgroupoffset", b)
|
memgroupoffset = read_int_and_print("memgroupoffset", b)
|
||||||
|
|
||||||
b.seek(memgroupoffset)
|
b.seek(memgroupoffset)
|
||||||
@ -143,110 +266,36 @@ class ANM_Skin:
|
|||||||
read_int_and_print("FileVersion", b)
|
read_int_and_print("FileVersion", b)
|
||||||
read_int_and_print("pImage", b)
|
read_int_and_print("pImage", b)
|
||||||
read_int_and_print("pMemGroup", b)
|
read_int_and_print("pMemGroup", b)
|
||||||
read_int_and_print("pNodeDictionary", b)
|
node = read_int_and_print("pNodeDictionary", b)
|
||||||
tree = read_int_and_print("pTreeDictionary", b)
|
tree = read_int_and_print("pTreeDictionary", b)
|
||||||
defaultobj = read_int_and_print("pDefaultObjDictionary", b)
|
defaultobj = read_int_and_print("pDefaultObjDictionary", b)
|
||||||
read_int_and_print("TotalNumberOfTrees", b)
|
read_int_and_print("TotalNumberOfTrees", b)
|
||||||
read_int_and_print("TotalNumberOfObjs", b)
|
read_int_and_print("TotalNumberOfObjs", b)
|
||||||
read_int_and_print("TotalNumberOfClusters", b)
|
read_int_and_print("TotalNumberOfClusters", b)
|
||||||
print(read_string_until_none(b))
|
read_string_until_none_and_print("Name", b)
|
||||||
print("=========")
|
print("=========")
|
||||||
|
|
||||||
print("ANM_Skin->pTreeDictionary NAM_Dictionary")
|
nodedict = NamDictionnary.create(b, AnmObj, offset=node)
|
||||||
b.seek(defaultobj)
|
treedict = NamDictionnary.create(b, AnmObj, depth=2, offset=tree)
|
||||||
read_int_and_print("pMemGroup", b)
|
defaultobjdict = NamDictionnary.create(b, AnmObj, offset=defaultobj)
|
||||||
namemapper = read_int_and_print("pNameMapper", b)
|
|
||||||
flags = read_int_and_print("Flags", b)
|
|
||||||
print("Flags: NAM_FlagHasHandles: %s, NAM_FlagCaseInsensitive: %s" % (flags & NAM_FlagHasHandles, flags & NAM_FlagCaseInsensitive))
|
|
||||||
namehandle = read_short_and_print("NameHandle", b)
|
|
||||||
|
|
||||||
|
link(nodedict, defaultobjdict)
|
||||||
|
|
||||||
print("MAP_Image->ANM_Skin->NAM_Dictionnary->MAP_Mapper")
|
print("nodedict_len:%s" % len(nodedict))
|
||||||
b.seek(namemapper)
|
print("treedict_len:%s" % len(treedict))
|
||||||
pMemGroup = read_int_and_print("pMemGroup", b)
|
print(defaultobjdict)
|
||||||
read_int_and_print("MemBaseSize", b)
|
print("defaultobjtreedict_len:%s" % len(defaultobjdict))
|
||||||
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)
|
|
||||||
|
|
||||||
print("MAP_Image->ANM_Skin->NAM_Dictionnary->MAP_Mapper->MAP_KeyContext NAM_STRING_KEY")
|
|
||||||
b.seek(pKeyContexts)
|
|
||||||
print("\tMAP_Image->ANM_Skin->NAM_Dictionnary->MAP_Mapper->MAP_KeyContext NAM_STRING_KEY->MAP_BinSearchContext")
|
|
||||||
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)
|
|
||||||
print("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)
|
|
||||||
print("NAM_StringData")
|
|
||||||
b.seek(pind0_string)
|
|
||||||
print("BELOW IS CUSTOM vv")
|
|
||||||
pptr = read_short_and_print("pPtr->ANM_Obj", b)
|
|
||||||
pptr2 = read_short_and_print("pPtr2->ANM_Obj", b)
|
|
||||||
val = read_int_and_print("Value", b)
|
|
||||||
print(b.tell())
|
|
||||||
print(read_string_until_none(b))
|
|
||||||
|
|
||||||
b.seek(val)
|
|
||||||
read_int_and_print("ANM_Obj->Custom", b)
|
|
||||||
read_int_and_print("ANM_Obj->Skin", b)
|
|
||||||
read_int_and_print("ANM_Obj->ZeroCluster", b)
|
|
||||||
total_vertices = read_int_and_print("ANM_Obj->TotalNumberOfVertices", b)
|
|
||||||
num_clusters = read_int_and_print("ANM_Obj->NumberOfClusters", b)
|
|
||||||
clusters = read_int_and_print("ANM_Obj->Clusters", b)
|
|
||||||
|
|
||||||
SEEN_VERTICES_INDEX = []
|
|
||||||
|
|
||||||
b.seek(clusters)
|
|
||||||
for i in range(num_clusters):
|
|
||||||
print("READING CLUSTER %s" % i)
|
|
||||||
read_int_and_print("ANM_Cluster->Custom", b)
|
|
||||||
read_int_and_print("ANM_Cluster->Obj", b)
|
|
||||||
read_int_and_print("ANM_Cluster->Handle", b)
|
|
||||||
print("ANM_Cluster->BoundingBox")
|
|
||||||
print("ANM_BoundingBox->Box[0]")
|
|
||||||
read_float_and_print("X", b)
|
|
||||||
read_float_and_print("Y", b)
|
|
||||||
read_float_and_print("Z", b)
|
|
||||||
print("ANM_BoundingBox->Box[1]")
|
|
||||||
read_float_and_print("X", b)
|
|
||||||
read_float_and_print("Y", b)
|
|
||||||
read_float_and_print("Z", b)
|
|
||||||
numverts = read_int_and_print("ANM_Cluster->NumberOfVertices", b)
|
|
||||||
|
|
||||||
for _ in range(numverts):
|
|
||||||
read_float_and_print("X", b)
|
|
||||||
read_float_and_print("Y", b)
|
|
||||||
read_float_and_print("Z", b)
|
|
||||||
vindex = read_int_and_print("Index", b)
|
|
||||||
# read_int_and_print("Weight", b)
|
|
||||||
assert(vindex not in SEEN_VERTICES_INDEX)
|
|
||||||
SEEN_VERTICES_INDEX.append(vindex)
|
|
||||||
|
|
||||||
read_int_and_print("Unk", b)
|
|
||||||
read_int_and_print("Unk", b)
|
|
||||||
print("%s vertices in this cluster (vs %s reported)" % (len(SEEN_VERTICES_INDEX), total_vertices))
|
|
||||||
showdictbyindex(2)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
with open("/home/tasty/Projects/gck-map-extract-objects/anm_skn/mc_l0.skn", "rb") as fp:
|
with open("/home/tasty/Projects/gck-map-extract-objects/anm_skn/mc_l0.skn", "rb") as fp:
|
||||||
# with open("/home/tasty/Projects/gck-map-extract-objects/anm_skn/dust.skn", "rb") as fp:
|
AnmSkin.parse(fp)
|
||||||
ANM_Skin.parse(fp)
|
|
||||||
|
with open("/home/tasty/Projects/gck-map-extract-objects/anm_skn/rp_l0.skn", "rb") as fp:
|
||||||
|
AnmSkin.parse(fp)
|
||||||
|
|
||||||
|
with open("/home/tasty/Projects/gck-map-extract-objects/anm_skn/kb_l0.skn", "rb") as fp:
|
||||||
|
AnmSkin.parse(fp)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
Loading…
Reference in New Issue
Block a user