mirror of https://github.com/zeldaret/oot.git
280 lines
8.6 KiB
Python
280 lines
8.6 KiB
Python
# SPDX-FileCopyrightText: © 2025 ZeldaRET
|
|
# SPDX-License-Identifier: CC0-1.0
|
|
|
|
from typing import TYPE_CHECKING
|
|
|
|
from ..oot64_data.misc_ids import SKIN_LIMB_TYPES
|
|
|
|
if TYPE_CHECKING:
|
|
from ..extase.memorymap import MemoryContext
|
|
|
|
from ..extase.cdata_resources import (
|
|
CDataResource,
|
|
CDataArrayResource,
|
|
CDataExt_Value,
|
|
CDataExt_Struct,
|
|
CDataExtWriteContext,
|
|
cdata_ext_Vec3s,
|
|
)
|
|
|
|
from . import dlist_resources
|
|
from . import skeleton_resources
|
|
|
|
|
|
class SkinVertexArrayResource(CDataArrayResource):
|
|
elem_cdata_ext = CDataExt_Struct(
|
|
(
|
|
("index", CDataExt_Value.u16),
|
|
("s", CDataExt_Value.s16),
|
|
("t", CDataExt_Value.s16),
|
|
("normX", CDataExt_Value.s8),
|
|
("normY", CDataExt_Value.s8),
|
|
("normZ", CDataExt_Value.s8),
|
|
("alpha", CDataExt_Value.u8),
|
|
)
|
|
)
|
|
|
|
def get_c_declaration_base(self):
|
|
return f"SkinVertex {self.symbol_name}[]"
|
|
|
|
def get_h_includes(self):
|
|
return ("skin.h",)
|
|
|
|
|
|
class SkinTransformationArrayResource(CDataArrayResource):
|
|
elem_cdata_ext = CDataExt_Struct(
|
|
(
|
|
("limbIndex", CDataExt_Value.u8),
|
|
("pad1", CDataExt_Value.pad8),
|
|
("x", CDataExt_Value.s16),
|
|
("y", CDataExt_Value.s16),
|
|
("z", CDataExt_Value.s16),
|
|
("scale", CDataExt_Value.u8),
|
|
("pad9", CDataExt_Value.pad8),
|
|
)
|
|
)
|
|
|
|
def get_c_declaration_base(self):
|
|
return f"SkinTransformation {self.symbol_name}[]"
|
|
|
|
def get_h_includes(self):
|
|
return ("skin.h",)
|
|
|
|
|
|
class SkinLimbModifArrayResource(CDataArrayResource):
|
|
def report_elem(resource, memory_context: "MemoryContext", v):
|
|
assert isinstance(v, dict)
|
|
|
|
address = v["skinVertices"]
|
|
assert isinstance(address, int)
|
|
skin_vertices_res = memory_context.report_resource_at_segmented(
|
|
resource,
|
|
address,
|
|
SkinVertexArrayResource,
|
|
lambda file, offset: SkinVertexArrayResource(
|
|
file,
|
|
offset,
|
|
f"{resource.name}_{offset:08X}_SkinVertices",
|
|
),
|
|
)
|
|
skin_vertices_res.set_length(v["vtxCount"])
|
|
|
|
address = v["limbTransformations"]
|
|
assert isinstance(address, int)
|
|
skin_vertices_res = memory_context.report_resource_at_segmented(
|
|
resource,
|
|
address,
|
|
SkinTransformationArrayResource,
|
|
lambda file, offset: SkinTransformationArrayResource(
|
|
file,
|
|
offset,
|
|
f"{resource.name}_{offset:08X}_SkinTransforms",
|
|
),
|
|
)
|
|
skin_vertices_res.set_length(v["transformCount"])
|
|
|
|
def write_skinVertices(
|
|
resource, memory_context: "MemoryContext", v, wctx: CDataExtWriteContext
|
|
):
|
|
assert isinstance(v, int)
|
|
address = v
|
|
wctx.f.write(wctx.line_prefix)
|
|
wctx.f.write(memory_context.get_c_reference_at_segmented(address))
|
|
return True
|
|
|
|
def write_limbTransformations(
|
|
resource, memory_context: "MemoryContext", v, wctx: CDataExtWriteContext
|
|
):
|
|
assert isinstance(v, int)
|
|
address = v
|
|
wctx.f.write(wctx.line_prefix)
|
|
wctx.f.write(memory_context.get_c_reference_at_segmented(address))
|
|
return True
|
|
|
|
elem_cdata_ext = CDataExt_Struct(
|
|
(
|
|
("vtxCount", CDataExt_Value.u16),
|
|
("transformCount", CDataExt_Value.u16),
|
|
("unk_4", CDataExt_Value.u16),
|
|
("pad6", CDataExt_Value.pad16),
|
|
(
|
|
"skinVertices",
|
|
(CDataExt_Value("I").set_write(write_skinVertices)),
|
|
), # SkinVertex*
|
|
(
|
|
"limbTransformations",
|
|
(CDataExt_Value("I").set_write(write_limbTransformations)),
|
|
), # SkinTransformation*
|
|
)
|
|
).set_report(report_elem)
|
|
|
|
def get_c_declaration_base(self):
|
|
return f"SkinLimbModif {self.symbol_name}[]"
|
|
|
|
def get_h_includes(self):
|
|
return ("skin.h",)
|
|
|
|
|
|
class SkinAnimatedLimbDataResource(CDataResource):
|
|
def report_limbModifications(resource, memory_context: "MemoryContext", v):
|
|
assert isinstance(v, int)
|
|
address = v
|
|
skin_vertices_res = memory_context.report_resource_at_segmented(
|
|
resource,
|
|
address,
|
|
SkinLimbModifArrayResource,
|
|
lambda file, offset: SkinLimbModifArrayResource(
|
|
file,
|
|
offset,
|
|
f"{resource.name}_{offset:08X}_SkinLimbModifs",
|
|
),
|
|
)
|
|
skin_vertices_res.set_length(resource.cdata_unpacked["limbModifCount"])
|
|
|
|
def write_limbModifications(
|
|
resource, memory_context: "MemoryContext", v, wctx: CDataExtWriteContext
|
|
):
|
|
assert isinstance(v, int)
|
|
address = v
|
|
wctx.f.write(wctx.line_prefix)
|
|
wctx.f.write(memory_context.get_c_reference_at_segmented(address))
|
|
return True
|
|
|
|
cdata_ext = CDataExt_Struct(
|
|
(
|
|
("totalVtxCount", CDataExt_Value.u16),
|
|
("limbModifCount", CDataExt_Value.u16),
|
|
(
|
|
"limbModifications",
|
|
(
|
|
CDataExt_Value("I")
|
|
.set_report(report_limbModifications)
|
|
.set_write(write_limbModifications)
|
|
),
|
|
), # SkinLimbModif*
|
|
("dlist", dlist_resources.cdata_ext_gfx_segmented),
|
|
)
|
|
)
|
|
|
|
def get_c_declaration_base(self):
|
|
return f"SkinAnimatedLimbData {self.symbol_name}"
|
|
|
|
def get_c_reference(self, resource_offset: int):
|
|
if resource_offset == 0:
|
|
return f"&{self.symbol_name}"
|
|
else:
|
|
raise ValueError()
|
|
|
|
def get_h_includes(self):
|
|
return ("skin.h",)
|
|
|
|
|
|
class SkinLimbResource(CDataResource):
|
|
def report_segment(resource, memory_context: "MemoryContext", v):
|
|
assert isinstance(v, int)
|
|
address = v
|
|
segmentType = resource.cdata_unpacked["segmentType"]
|
|
if segmentType == 4: # SKIN_LIMB_TYPE_ANIMATED
|
|
# segment is SkinAnimatedLimbData*
|
|
assert address != 0
|
|
memory_context.report_resource_at_segmented(
|
|
resource,
|
|
address,
|
|
SkinAnimatedLimbDataResource,
|
|
lambda file, offset: SkinAnimatedLimbDataResource(
|
|
file, offset, f"{resource.name}_{address:08X}_SkinAnimatedLimbData"
|
|
),
|
|
)
|
|
elif segmentType == 11: # SKIN_LIMB_TYPE_NORMAL
|
|
# segment is Gfx*
|
|
assert address != 0
|
|
dlist_resources.report_gfx_segmented(resource, memory_context, address)
|
|
|
|
def write_segment(
|
|
resource, memory_context: "MemoryContext", v, wctx: CDataExtWriteContext
|
|
):
|
|
assert isinstance(v, int)
|
|
address = v
|
|
wctx.f.write(wctx.line_prefix)
|
|
if address == 0:
|
|
wctx.f.write("NULL")
|
|
else:
|
|
wctx.f.write(memory_context.get_c_reference_at_segmented(address))
|
|
return True
|
|
|
|
cdata_ext = CDataExt_Struct(
|
|
(
|
|
("jointPos", cdata_ext_Vec3s),
|
|
(
|
|
"child",
|
|
CDataExt_Value("B").set_write(
|
|
skeleton_resources.StandardLimbResource.write_limb_index
|
|
),
|
|
),
|
|
(
|
|
"sibling",
|
|
CDataExt_Value("B").set_write(
|
|
skeleton_resources.StandardLimbResource.write_limb_index
|
|
),
|
|
),
|
|
(
|
|
"segmentType",
|
|
CDataExt_Value("i").set_write_str_v(
|
|
lambda v: SKIN_LIMB_TYPES.get(v, f"{v}")
|
|
),
|
|
),
|
|
(
|
|
"segment",
|
|
CDataExt_Value("I").set_report(report_segment).set_write(write_segment),
|
|
),
|
|
)
|
|
)
|
|
|
|
def __init__(self, file, range_start, name):
|
|
super().__init__(file, range_start, name)
|
|
self.enum_member_name = f"LIMB_{file.name.upper()}_{range_start:06X}"
|
|
|
|
def set_enum_member_name(self, enum_member_name: str):
|
|
self.enum_member_name = enum_member_name
|
|
|
|
def get_c_declaration_base(self):
|
|
return f"SkinLimb {self.symbol_name}"
|
|
|
|
def get_c_reference(self, resource_offset: int):
|
|
if resource_offset == 0:
|
|
return f"&{self.symbol_name}"
|
|
else:
|
|
raise ValueError()
|
|
|
|
def get_h_includes(self):
|
|
return ("skin.h",)
|
|
|
|
|
|
class SkinLimbsArrayResource(skeleton_resources.LimbsArrayResourceABC):
|
|
limb_type = SkinLimbResource
|
|
c_limb_type = "SkinLimb"
|
|
|
|
|
|
class SkeletonSkinResource(skeleton_resources.SkeletonResourceABC):
|
|
limbs_array_type = SkinLimbsArrayResource
|