Exemplo n.º 1
0
 def read(self, reader: ByteIO):
     self.hash = reader.read_uint32()
     self.name_offset = reader.read_uint32()
     self.name = reader.read_from_offset(0x90 + self.name_offset,
                                         reader.read_ascii_string)
     self.unknown08 = reader.read_uint32()
     self.unknown0C = reader.read_uint32()
     self.unknown10 = reader.read_uint32()
Exemplo n.º 2
0
 def read(self, reader: ByteIO):
     self.name_hash = reader.read_uint32()
     self.type_hash = reader.read_uint32()
     self.fileNo = reader.read_uint16()
     self.size = reader.read_uint16()
     self.unk4 = reader.read_uint32()
     self.size1 = reader.read_uint64()
     self.size2 = reader.read_uint64()
Exemplo n.º 3
0
 def write(self, writer: ByteIO):
     writer.write_uint32(self.name_hash)
     writer.write_uint32(self.type_hash)
     writer.write_uint16(self.fileNo)
     writer.write_uint16(self.size)
     writer.write_uint32(self.unk4)
     writer.write_uint64(self.size1)
     writer.write_uint64(self.size2)
Exemplo n.º 4
0
    def read(self, reader: ByteIO):
        self.name_offset = reader.read_uint32()
        self.hash = reader.read_uint32()
        self.type = reader.read_uint16()
        self.loader_index = reader.read_uint16()

        self.name = reader.read_from_offset(0x90 + self.name_offset,
                                            reader.read_ascii_string)
Exemplo n.º 5
0
    def __init__(self, path):
        self.path = Path(path)
        self.reader = ByteIO(self.path.open('rb'))
        self.header = OVLHeader()
        self.types = []  # type:List[OVLTypeHeader]
        self.files = []  # type:List[OVLFileDescriptor]
        self.archive_name_table_offset = 0
        self.archives = []  # type: List[OVLArchiveV2]
        self.dirs = []  # type:List[OVLDir]
        self.parts = []  # type:List[OVLPart]
        self.others = []  # type:List[OVLOther]
        self.unknown = []  # type:List[OVLUnk]
        self.archives2 = []  # type:List[OVLArchive2]
        self.static_archive = None  # type: OVLArchiveV2

        self.files_by_hash = {}  #type: Dict[int,OVLFileDescriptor]
        self.hash_by_name = {}  #type: Dict[str,int]
Exemplo n.º 6
0
    def __init__(self, parent):
        from OVL_COMPRESSED_DATA import OVLCompressedData
        self.parent: OVLCompressedData = parent

        self.readers = []
        self.resources = {}  # type: Dict[int,OVSResourceHeader]
        if len(self.parent.parent.archives) > 1:
            self.textures_1 = self.parent.parent.path.with_suffix(
                '.ovs.textures_l1')
            self.reader_t1 = ByteIO(file=self.textures_1.open('rb')).unzip()
            self.readers.append(self.reader_t1)
            self.read_archive(self.reader_t1)
        if len(self.parent.parent.archives) > 2:
            self.textures_2 = self.parent.parent.path.with_suffix(
                '.ovs.textures_l0')
            self.reader_t2 = ByteIO(file=self.textures_2.open('rb')).unzip()
            self.readers.append(self.reader_t2)
        else:
            pass
Exemplo n.º 7
0
 def read(self, reader: ByteIO):
     self.unk1 = reader.read_uint32()
     self.unk2 = reader.read_uint32()
     self.size = reader.read_uint32()
     self.offset = reader.read_uint32()
     self.file_hash = reader.read_uint32()
     self.unk6 = reader.read_uint32()
     self.type_hash = reader.read_uint32()
     self.unk8 = reader.read_uint32()
Exemplo n.º 8
0
 def __init__(self, parent):
     from OVL_COMPRESSED_DATA import OVLCompressedData
     self.parent: OVLCompressedData = parent
     if len(self.parent.parent.archives)>1:
         self.filepath = self.parent.parent.path.with_suffix('.ovs.textures_l1')
     elif len(self.parent.parent.archives)>2:
         self.filepath = self.parent.parent.path.with_suffix('.ovs.textures_l0')
     else:
         print('INVALID')
         exit(0xDEAD)
     self.reader = ByteIO(file=self.filepath.open('rb')).unzip()
Exemplo n.º 9
0
    def __init__(self, path):
        self.reader = ByteIO(path=path)
        self.name = Path(path).name
        self.version = 0
        self.i32_count = 0
        self.i16_count = 0
        self.i8_count = 0
        self.i1_count = 0
        self.export_time = 0

        self.i32_offset = 0
        self.i16_offset = 0
        self.i8_offset = 0
        self.i1_offset = 0
        self.bit_cursor = 0

        self._i1_array = []

        self.options = {}
        self.geometry = HeroGeomerty()
        self.vertex_count = 0
Exemplo n.º 10
0
 def write(self, writer: ByteIO):  # TODO: FIX IT
     self.archive.file_type_header_count = len(self.ovs_headers)
     for header in self.ovs_headers:
         header.sub_type_count = len(header.subs)
         header.write(writer)
     for chunk_id, sub_header in enumerate(self.ovs_sub_headers):
         sub_header.size = len(self.chunks[chunk_id].data)
         sub_header.write(writer)
     self.archive.file_data_header_count = len(self.ovs_file_headers)
     for file_header in self.ovs_file_headers:
         file_header.write(writer)
     self.archive.embedded_file_count = len(self.embedded_file_headers)
     for embedded_file_id, embedded_file_header in enumerate(self.embedded_file_headers):
         embedded_file_header.size = len(self.embedded_files[embedded_file_id])
         embedded_file_header.write(writer)
     self.archive.asset_count = len(self.ovs_assets)
     for file3_header in self.ovs_assets:
         file3_header.write(writer)
     self.archive.relocation_num = len(self.relocations)
     for file4_header in self.relocations:
         file4_header.write(writer)
     writer.write_bytes(self.extra_data)
     for chunk in self.chunks:
         writer.write_bytes(chunk.data)
     for embedded_file in self.embedded_files:
         writer.write_bytes(embedded_file)
Exemplo n.º 11
0
 def read(self, reader: ByteIO, is_x64=True):
     if is_x64:
         self.name_offset = reader.read_uint64()
     else:
         self.name_offset = reader.read_uint32()
     self.type_hash = reader.read_uint32()
     self.loader_type = reader.read_uint32()
     self.symbol_start = reader.read_uint32()
     self.symbols_to_resolve = reader.read_uint32()
     self.name = reader.read_from_offset(0x90 + self.name_offset,
                                         reader.read_ascii_string)
Exemplo n.º 12
0
 def read(self, reader: ByteIO):
     self.file_hash = reader.read_uint32()
     self.type_hash = reader.read_uint32()
     self.fileNo = reader.read_uint16()
     self.part_count = reader.read_uint16()
     self.unk4 = reader.read_uint32()
     self.size1 = reader.read_uint64()
     self.total_size = reader.read_uint64()
Exemplo n.º 13
0
 def read(self, reader: ByteIO):
     self.name = reader.read_ascii_string()
     self.index = reader.read_uint32()
     self.offset = reader.read_uint32()
     self.size = reader.read_uint32()
     self.type_map_elements = reader.read_uint32()
     self.types = [reader.read_uint32() for _ in range(self.type_map_elements)]
     return self
Exemplo n.º 14
0
 def __init__(self, path: str):
     self.path = Path(path)
     self.reader = ByteIO(path=self.path)
     self.dump_path = self.path.parent / 'dump' / self.path.stem  # type: Path
     os.makedirs(self.dump_path, exist_ok=True)
     self.magic = b''
     self.model_name = ''
     self.model_name2 = ''
     self.copyright = ''
     self.textures = []  # type: List[Texture]
     self.meshes = []  # type: List[Mesh]
     self.models = []  # type: List[Model]
     self.materials = []  # type: List[Material]
     self.audio = []  # type: List[Audio]
     self.animation = []  # type: List[Animation]
Exemplo n.º 15
0
    def read(self, reader: ByteIO):
        items = reader.get_items()
        for item in items:
            item.seek_to()

            if item.type == 20:
                self.chunk_name = reader.read_ascii_string(reader.read_int32())
            if item.type == 21:
                self.name = reader.read_ascii_string(reader.read_int32())
            if item.type == 100:
                self.temp_path = reader.read_ascii_string(reader.read_int32())

            if item.type == 1:
                items2 = item.get_items()
                for item2 in items2:
                    item2.seek_to()
                    if item2.type == 30:
                        item2.seek_to()
                        self.size = reader.read_uint32()
                    if item2.type == 31:
                        self.data = reader.read_bytes(self.size)
Exemplo n.º 16
0
 def read(self, reader: ByteIO):
     self.magic = reader.read_uint32()
     self.magic_s = "%X" % self.magic
     self.version = reader.read_uint32()
     self.face_count = reader.read_uint32()
     self.vertex_count = reader.read_uint32()
     self.vertex_size = reader.read_uint32()
     self.texture_count = reader.read_uint32()
     self.shader_count = reader.read_uint32()
     self.attrib_count = reader.read_uint32()
     self.read_attributes(reader)
     self.read_textures(reader)
     self.read_shaders(reader)
     self.read_indexes(reader)
     self.read_vertexes(reader)
Exemplo n.º 17
0
 def read_vertexes(self, reader: ByteIO):
     for i in range(self.vertex_count):
         vertex_entry = reader.tell()
         vertex = RIPVertex()
         for attrib in self.attributes:
             reader.seek(vertex_entry + attrib.offset)
             if attrib.name == RIPAttrTypes.POSITION:
                 vertex.pos.read(reader,attrib.types)
             elif attrib.name == RIPAttrTypes.NORMAL:
                 vertex.norm.read(reader,attrib.types)
             elif attrib.name == RIPAttrTypes.TEXCOORD:
                 vertex.UV.append(RIPVarVector().read(reader,attrib.types))
             elif attrib.name == RIPAttrTypes.COLOR:
                 vertex.color.read(reader,attrib.types)
             elif attrib.name == RIPAttrTypes.TANGENT:
                 reader.skip(attrib.size)
             elif attrib.name == RIPAttrTypes.BLENDINDICES:
                 vertex.blend.read(reader,attrib.types)
             else:
                 print('Found unknown attribute! Please report about this')
         reader.seek(vertex_entry + self.vertex_size)
         self.vertexes.append(vertex)
Exemplo n.º 18
0
 def write(self, writer: ByteIO):
     writer.write_uint32(self.unknown00)
     writer.write_uint64(self.unknown08)
Exemplo n.º 19
0
class OVL(OVLBase):
    is_x64 = False
    unknown_type = OVLTypeHeader()

    def __init__(self, path):
        self.path = Path(path)
        self.reader = ByteIO(self.path.open('rb'))
        self.header = OVLHeader()
        self.types = []  # type:List[OVLTypeHeader]
        self.files = []  # type:List[OVLFileDescriptor]
        self.archive_name_table_offset = 0
        self.archives = []  # type: List[OVLArchiveV2]
        self.dirs = []  # type:List[OVLDir]
        self.parts = []  # type:List[OVLPart]
        self.others = []  # type:List[OVLOther]
        self.unknown = []  # type:List[OVLUnk]
        self.archives2 = []  # type:List[OVLArchive2]
        self.static_archive = None  # type: OVLArchiveV2

        self.files_by_hash = {}  #type: Dict[int,OVLFileDescriptor]
        self.hash_by_name = {}  #type: Dict[str,int]

    def read(self):
        self.header.read(self.reader)
        self.is_x64 = True  # self.header.flags & 0x08
        self.reader.skip(self.header.names_length)
        for _ in range(self.header.type_count):
            ovl_type = OVLTypeHeader()
            self.register(ovl_type)
            ovl_type.read(self.reader, is_x64=self.is_x64)
            self.types.append(ovl_type)
        for _ in range(self.header.file_count):
            ovl_file = OVLFileDescriptor()
            self.register(ovl_file)
            ovl_file.read(self.reader)
            self.files.append(ovl_file)
        self.files_by_hash = {f.file_hash: f for f in self.files}
        self.hash_by_name = {f.name: f.file_hash for f in self.files}
        self.archive_name_table_offset = self.reader.tell()
        self.reader.skip(self.header.archive_names_length)
        for _ in range(self.header.archive_count):
            ovl_archive = OVLArchiveV2()
            self.register(ovl_archive)
            ovl_archive.read(self.reader, self.archive_name_table_offset)
            self.archives.append(ovl_archive)

        for _ in range(self.header.dir_count):
            ovl_dir = OVLDir()
            self.register(ovl_dir)
            ovl_dir.read(self.reader)
            self.dirs.append(ovl_dir)

        for _ in range(self.header.part_count):
            ovl_part = OVLPart()
            self.register(ovl_part)
            ovl_part.read(self.reader)
            for file in self.files:
                if ovl_part.hash == file.file_hash:
                    ovl_part.name = file.name
            self.parts.append(ovl_part)

        for _ in range(self.header.other_count):
            ovl_other = OVLOther()
            self.register(ovl_other)
            ovl_other.read(self.reader)
            self.others.append(ovl_other)

        for _ in range(self.header.unknown_count):
            ovl_unk = OVLUnk()
            self.register(ovl_unk)
            ovl_unk.read(self.reader)
            self.unknown.append(ovl_unk)

        for _ in range(self.header.archive_count):
            ovl_archive2 = OVLArchive2()
            self.register(ovl_archive2)
            ovl_archive2.read(self.reader)
            self.archives2.append(ovl_archive2)

        for archive in self.archives:
            print(archive)
            try:
                if archive.name == 'STATIC':
                    archive.uncompressed_data = zlib.decompress(
                        self.reader.read_bytes(archive.packed_size))
                    self.static_archive = archive
                else:
                    self.reader.seek(archive.ovs_offset)
                    archive.uncompressed_data = zlib.decompress(
                        self.reader.read_bytes(archive.packed_size))

                with open(
                        r'test_data\{}-{}.decompressed'.format(
                            self.path.stem, archive.name), 'wb') as fp:
                    fp.write(self.static_archive.uncompressed_data)
            except:
                pass

    def write(self, writer: ByteIO):
        self.header.write(writer)
        # not all header fields are accurate yet,
        # but we'll come back and re-write this section
        names_start = writer.tell()
        for ovl_type in sorted(self.types, key=lambda x: x.name_offset):
            ovl_type.name_offset = writer.tell() - names_start
            writer.write_ascii_string(ovl_type.name, True)
        for ovl_file in sorted(self.files, key=lambda x: x.name_offset):
            ovl_file.name_offset = writer.tell() - names_start
            writer.write_ascii_string(ovl_file.name, True)
        for ovl_dir in sorted(self.dirs, key=lambda x: x.name_offset):
            ovl_dir.name_offset = writer.tell() - names_start
            writer.write_ascii_string(ovl_dir.name, True)
        for ovl_part in sorted(self.parts, key=lambda x: x.name_offset):
            ovl_part.name_offset = writer.tell() - names_start
            writer.write_ascii_string(ovl_part.name, True)
        for ovl_other in sorted(self.others, key=lambda x: x.name_offset):
            ovl_other.name_offset = writer.tell() - names_start
            writer.write_ascii_string(ovl_other.name, True)
        writer.align(8)
        self.header.names_length = writer.tell() - names_start
        for ovl_type in self.types:
            ovl_type.write(writer, self.is_x64)
        for ovl_file in self.files:
            ovl_file.write(writer)
        archive_name_table_start = writer.tell()
        for ovl_archive in self.archives:
            ovl_archive.nameIndex = writer.tell() - archive_name_table_start
            writer.write_ascii_string(ovl_archive.name, True)
        writer.align(8, archive_name_table_start)
        self.header.archive_names_length = writer.tell(
        ) - archive_name_table_start
        for ovl_archive in self.archives:
            ovl_archive.unpacked_size = len(ovl_archive.uncompressed_data)
            ovl_archive.compressed_data = zlib.compress(
                ovl_archive.uncompressed_data)
            ovl_archive.packed_size = len(ovl_archive.compressed_data)
            ovl_archive.write(writer)
        for ovl_dir in self.dirs:
            ovl_dir.write(writer)
        for ovl_part in self.parts:
            ovl_part.write(writer)
        for ovl_other in self.others:
            ovl_other.write(writer)
        for ovl_unk in self.unknown:
            ovl_unk.write(writer)
        for ovl_archive2 in self.archives2:
            ovl_archive2.write(writer)
        for ovl_archive in self.archives:
            writer.write_bytes(ovl_archive.compressed_data)
        writer.seek(0)
        self.header.write(writer)

    def get_file_by_hash(self, hash_value) -> OVLFileDescriptor:
        if not self.files_by_hash:
            self.files_by_hash = {f.file_hash: f for f in self.files}
        return self.files_by_hash.get(hash_value)

    def get_type_by_hash(self, hash_value) -> OVLTypeHeader:
        for t in self.types:
            if t.type_hash == hash_value:
                return t
        return self.unknown_type
Exemplo n.º 20
0
 def write(self, writer: ByteIO):
     self.header.write(writer)
     # not all header fields are accurate yet,
     # but we'll come back and re-write this section
     names_start = writer.tell()
     for ovl_type in sorted(self.types, key=lambda x: x.name_offset):
         ovl_type.name_offset = writer.tell() - names_start
         writer.write_ascii_string(ovl_type.name, True)
     for ovl_file in sorted(self.files, key=lambda x: x.name_offset):
         ovl_file.name_offset = writer.tell() - names_start
         writer.write_ascii_string(ovl_file.name, True)
     for ovl_dir in sorted(self.dirs, key=lambda x: x.name_offset):
         ovl_dir.name_offset = writer.tell() - names_start
         writer.write_ascii_string(ovl_dir.name, True)
     for ovl_part in sorted(self.parts, key=lambda x: x.name_offset):
         ovl_part.name_offset = writer.tell() - names_start
         writer.write_ascii_string(ovl_part.name, True)
     for ovl_other in sorted(self.others, key=lambda x: x.name_offset):
         ovl_other.name_offset = writer.tell() - names_start
         writer.write_ascii_string(ovl_other.name, True)
     writer.align(8)
     self.header.names_length = writer.tell() - names_start
     for ovl_type in self.types:
         ovl_type.write(writer, self.is_x64)
     for ovl_file in self.files:
         ovl_file.write(writer)
     archive_name_table_start = writer.tell()
     for ovl_archive in self.archives:
         ovl_archive.nameIndex = writer.tell() - archive_name_table_start
         writer.write_ascii_string(ovl_archive.name, True)
     writer.align(8, archive_name_table_start)
     self.header.archive_names_length = writer.tell(
     ) - archive_name_table_start
     for ovl_archive in self.archives:
         ovl_archive.unpacked_size = len(ovl_archive.uncompressed_data)
         ovl_archive.compressed_data = zlib.compress(
             ovl_archive.uncompressed_data)
         ovl_archive.packed_size = len(ovl_archive.compressed_data)
         ovl_archive.write(writer)
     for ovl_dir in self.dirs:
         ovl_dir.write(writer)
     for ovl_part in self.parts:
         ovl_part.write(writer)
     for ovl_other in self.others:
         ovl_other.write(writer)
     for ovl_unk in self.unknown:
         ovl_unk.write(writer)
     for ovl_archive2 in self.archives2:
         ovl_archive2.write(writer)
     for ovl_archive in self.archives:
         writer.write_bytes(ovl_archive.compressed_data)
     writer.seek(0)
     self.header.write(writer)
Exemplo n.º 21
0
        writer.seek(0)
        self.header.write(writer)

    def get_file_by_hash(self, hash_value) -> OVLFileDescriptor:
        if not self.files_by_hash:
            self.files_by_hash = {f.file_hash: f for f in self.files}
        return self.files_by_hash.get(hash_value)

    def get_type_by_hash(self, hash_value) -> OVLTypeHeader:
        for t in self.types:
            if t.type_hash == hash_value:
                return t
        return self.unknown_type


if __name__ == '__main__':
    # model = r'test_data\Tyrannosaurus.ovl'
    model = sys.argv[1]
    # model = r'JWEDinos\Tyrannosaurus\Tyrannosaurus.ovl'
    a = OVL(model)
    a.read()
    # a.read_uncompressed()
    compressed = OVLCompressedData(a, a.static_archive)
    compressed.read(ByteIO(byte_object=a.static_archive.uncompressed_data))
    compressed.read_files()
    b = OVSTextureArchive(compressed)
    b.read()
    # out = ByteIO(path='test_data/compressed_repacked', mode='w')
    # compressed.write(out)
    # out.close()
Exemplo n.º 22
0
 def write(self, writer: ByteIO):
     writer.write_uint32(self.name_offset)
Exemplo n.º 23
0
 def write(self, writer: ByteIO):
     writer.write_fourcc(self.sig)
     writer.write_fmt('4B', self.flags, self.version, self.need_bswap,
                      self.unknown07)
     writer.write_uint32(self.flags2)
     writer.write_uint32(self.unknown0C)
     writer.write_uint32(self.names_length)
     writer.write_uint32(self.unknown2_count)
     writer.write_uint32(self.other_count)
     writer.write_uint16(self.dir_count)
     writer.write_uint16(self.type_count)
     writer.write_uint32(self.file_count)
     writer.write_uint32(self.file_count2)
     writer.write_uint32(self.part_count)
     writer.write_uint32(self.archive_count)
     writer.write_uint32(self.unknown30)
     writer.write_uint32(self.unknown34)
     writer.write_uint32(self.unknown38)
     writer.write_uint32(self.unknown3C)
     writer.write_uint32(self.unknown_count)
     writer.write_uint32(self.unknown44)
     writer.write_uint32(self.unknown48)
     writer.write_uint32(self.unknown4C)
     writer.write_uint32(self.archive_names_length)
     writer.write_uint32(self.file_count3)
     writer.write_uint32(self.type_names_length)
     writer.write_uint32(self.zero0C)
     writer.write_uint32(self.zero10)
     writer.write_uint32(self.zero14)
     writer.write_uint32(self.zero18)
     writer.write_uint32(self.zero1C)
     writer.write_uint32(self.zero20)
     writer.write_uint32(self.zero24)
     writer.write_uint32(self.zero28)
     writer.write_uint32(self.zero2C)
     writer.write_uint32(self.zero30)
     writer.write_uint32(self.zero34)
     writer.write_uint32(self.zero38)
     writer.write_uint32(self.zero3C)
Exemplo n.º 24
0
 def read(self, reader: ByteIO):
     self.sig = reader.read_fourcc()
     assert self.sig == 'FRES'
     self.flags, self.version, self.need_bswap, self.unknown07 = reader.read_fmt(
         '4B')
     self.flags2 = reader.read_uint32()
     self.unknown0C = reader.read_uint32()
     self.names_length = reader.read_uint32()
     self.unknown2_count = reader.read_uint32()
     self.other_count = reader.read_uint32()
     self.dir_count = reader.read_uint16()
     self.type_count = reader.read_uint16()
     self.file_count = reader.read_uint32()
     self.file_count2 = reader.read_uint32()
     self.part_count = reader.read_uint32()
     self.archive_count = reader.read_uint32()
     self.unknown30 = reader.read_uint32()
     self.unknown34 = reader.read_uint32()
     self.unknown38 = reader.read_uint32()
     self.unknown3C = reader.read_uint32()
     self.unknown_count = reader.read_uint32()
     self.unknown44 = reader.read_uint32()
     self.unknown48 = reader.read_uint32()
     self.unknown4C = reader.read_uint32()
     self.archive_names_length = reader.read_uint32()
     self.file_count3 = reader.read_uint32()
     self.type_names_length = reader.read_uint32()
     self.zero0C = reader.read_uint32()
     self.zero10 = reader.read_uint32()
     self.zero14 = reader.read_uint32()
     self.zero18 = reader.read_uint32()
     self.zero1C = reader.read_uint32()
     self.zero20 = reader.read_uint32()
     self.zero24 = reader.read_uint32()
     self.zero28 = reader.read_uint32()
     self.zero2C = reader.read_uint32()
     self.zero30 = reader.read_uint32()
     self.zero34 = reader.read_uint32()
     self.zero38 = reader.read_uint32()
     self.zero3C = reader.read_uint32()
Exemplo n.º 25
0
 def write(self, writer: ByteIO):
     writer.write_uint32(self.unknown00)
     writer.write_uint32(self.data_size)
Exemplo n.º 26
0
class HeroFile:
    me = (2 ** 8) - 1
    ge = (2 ** 16) - 1
    H = math.pow(2, 16) - 1
    X = (math.pow(2, 16) - 2) / 2

    def __init__(self, path):
        self.reader = ByteIO(path=path)
        self.name = Path(path).name
        self.version = 0
        self.i32_count = 0
        self.i16_count = 0
        self.i8_count = 0
        self.i1_count = 0
        self.export_time = 0

        self.i32_offset = 0
        self.i16_offset = 0
        self.i8_offset = 0
        self.i1_offset = 0
        self.bit_cursor = 0

        self._i1_array = []

        self.options = {}
        self.geometry = HeroGeomerty()
        self.vertex_count = 0

    def read_float(self, offset=0):
        self.reader.seek(self.i32_offset + offset)
        ret = self.reader.read_float()
        self.i32_offset += 4
        return ret

    def read_uint32(self, offset=0):
        self.reader.seek(self.i32_offset + offset)
        val = self.read_float()
        ret = round(val)
        return ret

    def read_uint16(self, offset=0, increment=True):
        self.reader.seek(self.i16_offset + offset)
        ret = self.reader.read_uint16()
        if increment:
            self.i16_offset += 2
        return ret

    def read_int8(self, offset=0):
        self.reader.seek(self.i8_offset + offset)
        ret = self.reader.read_uint8()
        self.i8_offset += 1
        return ret

    def read_string(self, offset=0):
        self.reader.seek(self.i8_offset + offset)
        l = self.read_int8()
        ret = self.reader.read_ascii_string(l)
        self.i8_offset += len(ret)
        return ret

    def read_bit(self):
        bit = self._i1_array[self.bit_cursor]
        self.bit_cursor += 1
        return bit

    def get_quaternion_array(self, e):
        e *= 4
        r = np.zeros(e)
        for i in range(e):
            r[i] = self.read_uint16() / self.H * 2 - 1
        return r

    def get_position_array(self, e, t):
        n = np.zeros(e * 3)
        for a in range(e):
            for r in range(3):
                n[3 * a + r] = (self.read_uint16() - self.X) / self.X * t
        return n

    def get_scale_array(self, e, t):
        n = np.zeros(e * 3)
        for a in range(e):
            for r in range(3):
                n[3 * a + r] = self.read_uint16() / self.H * t
        return n

    def read(self):
        reader = self.reader
        self.version = round(reader.read_float(), 2)
        self.get_start_points()
        with reader.save_current_pos():
            reader.seek(self.i1_offset)
            for _ in range(math.ceil(self.i1_count / 8)):
                byte = reader.read_int8()
                for i in range(8):
                    self._i1_array.append(bool(byte & (1 << i)))
        self._init_settings()
        self._init_indices()
        self._init_points()
        self._init_normals()
        self._init_uvs()
        self._init_vertex_colors()
        self._init_blends()
        self._init_weights()
        self._init_parent()
        try:
            self._init_poses();
        except:
            pass

    def get_bit(self):
        self.bit_cursor += 1
        return self._i1_array[self.bit_cursor - 1]

    def get_start_points(self):
        reader = self.reader
        self.i32_count = reader.read_float_int32()
        self.i16_count = reader.read_float_int32()
        self.i8_count = reader.read_float_int32()
        self.i1_count = reader.read_float_int32()
        e = 20
        if self.version >= 1.4:
            e += 4
            self.export_time = reader.read_float()
        self.i32_offset = e
        self.i16_offset = self.i32_offset + 4 * self.i32_count
        self.i8_offset = self.i16_offset + 2 * self.i16_count
        self.i1_offset = self.i8_offset + self.i8_count

    def _init_settings(self):
        default_attributes = ["mesh", "normals", "uv1", "uv2", "blendTargets", "blendNormals", "weights", "animations",
                              "jointScales", "addon", "paintMapping", "singleParent", "frameMappings", "indices32bit",
                              "originalIndices", "vertexColors"]
        if self.version >= 1.2:
            default_attributes.append('posGroups')
        t = 32
        if self.version >= 1.25:
            default_attributes.append('uvSeams')
            default_attributes.append('rivets')
            t -= 2
        r = {}
        for attr in default_attributes:
            r[attr] = self.get_bit()
        if self.version >= 1.2:
            self.bit_cursor += t
            self.options = r
            self.geometry.main_skeleton = not self.options['addon'] and self.options['weights']

    def _init_indices(self):
        if self.options['mesh']:
            indices_count = self.read_uint32()
            if self.options['indices32bit']:
                self.geometry.index = [self.read_uint32() for _ in range(indices_count)]
            else:
                self.geometry.index = [self.read_uint16() for _ in range(indices_count)]
            if self.options['originalIndices']:
                if self.options['indices32bit']:
                    self.geometry.original_indices = [self.read_uint32() for _ in range(indices_count)]
                else:
                    self.geometry.original_indices = [self.read_uint16() for _ in range(indices_count)]

    def _init_points(self):
        if self.options['mesh']:
            vertex_count = self.read_uint32() if self.options['indices32bit'] else self.read_uint16()
            self.vertex_count = vertex_count
            self.geometry.has_geometry = True
            # Z Y X
            bbox = [self.read_float() for _ in range(6)]
            scale = [bbox[3] - bbox[0], bbox[4] - bbox[1], (bbox[5] - bbox[2])]
            self.geometry.offset = [bbox[0] * scale[0], bbox[1] * scale[1], bbox[2] * scale[2]]
            self.geometry.bounds = [bbox[0:3], bbox[3:6]]
            verts = []
            for _ in range(vertex_count):
                verts.append((self.read_uint16() / self.ge * scale[0] + bbox[0],
                              self.read_uint16() / self.ge * scale[1] + bbox[1],
                              self.read_uint16() / self.ge * scale[2] + bbox[2]
                              ))
                self.geometry.positions = verts

    def _init_normals(self):
        if self.options['normals']:
            if self.vertex_count != 0:
                normals = []
                r = 0
                for _ in range(self.vertex_count):
                    normals.append(self.read_int8() / self.me * 2 - 1)
                    normals.append(self.read_int8() / self.me * 2 - 1)
                    normals.append(
                        (2 * self.get_bit() - 1) * (1 - math.pow(normals[r], 2) - math.pow(normals[r + 1], 2)))
                    r += 3
                self.geometry.normals = split(normals, 3)

    def _init_uvs(self):
        if self.options['uv1']:
            uvs = ['uv', 'uv2'] if self.options['uv2'] else ['uv']
            for uv in uvs:
                n = [self.read_float() for _ in range(4)]
                s = [n[2] - n[0], n[3] - n[1]]
                u = []
                for i in range(self.vertex_count):
                    u.append((self.read_uint16() / self.ge * s[0] + n[0], self.read_uint16() / self.ge * s[1] + n[1]))
                setattr(self.geometry, uv, u)

    def _init_vertex_colors(self):
        if self.options['vertexColors']:
            layer_count = self.read_int8()
            for t in range(layer_count):
                layer_name = self.read_string()
                v_colors = []
                for _ in range(self.vertex_count):
                    col = self.read_int8()
                    v_colors.append(col / 255)
                    v_colors.append(col / 255)
                    v_colors.append(col / 255)
                    v_colors.append(1)
                self.geometry.vertex_colors[layer_name] = np.array(v_colors).reshape((-1, 4))

    def _init_blends(self):
        if self.options['blendTargets']:
            shape_key_count = self.read_int8()
            if shape_key_count:
                shape_key_data = {}
                for shape_key_id in range(shape_key_count):
                    shape_key_name = self.read_string()
                    o = [self.read_float() for _ in range(6)]
                    u = [o[3] - o[0], o[4] - o[1], o[5] - o[2]]
                    c = []
                    for d in range(self.vertex_count):
                        c.append(self.read_int8() / self.me * u[0] + o[0])
                        c.append(self.read_int8() / self.me * u[1] + o[1])
                        c.append(self.read_int8() / self.me * u[2] + o[2])
                    shape_key_data[shape_key_name] = split(c, 3)
                    if self.options['blendNormals']:
                        for _ in range(self.vertex_count):
                            self.read_int8()
                            self.read_int8()
                            self.get_bit()
                self.geometry.shape_key_data = shape_key_data

    def _init_weights(self):
        if self.options['weights']:
            self.geometry.skinned = True
            weight_per_vert = self.read_int8()
            additional_weights = max(0, weight_per_vert - 4)
            skin_indices = np.zeros(4 * self.vertex_count, dtype=np.int16)
            additional_skin_indices = np.zeros(additional_weights * self.vertex_count, dtype=np.int16)
            u = 4 if weight_per_vert < 4 else weight_per_vert
            for l in range(u):
                if weight_per_vert > l:
                    if l < 4:
                        for t in range(self.vertex_count):
                            skin_indices[4 * t + l] = self.read_uint16(2 * (t * weight_per_vert + l), False)
                    else:
                        for t in range(self.vertex_count):
                            additional_skin_indices[t * additional_weights + (l - 4)] = self.read_uint16(
                                2 * (t * additional_weights + l), False)
            self.geometry.skin_indices = skin_indices.reshape((-1, u,))
            self.geometry.additional_skin_indices = additional_skin_indices.reshape((-1, u,))
            self.i16_offset = self.i16_offset + weight_per_vert * self.vertex_count * 2;
            skin_weights = np.zeros(4 * self.vertex_count, dtype=np.float32)
            additional_skin_weights = np.zeros(additional_weights * self.vertex_count, dtype=np.float32)
            u = 4 if weight_per_vert < 4 else weight_per_vert
            for f in range(u):
                if weight_per_vert > f:
                    if f < 4:
                        for c in range(self.vertex_count):
                            skin_weights[4 * c + f] = self.read_uint16(2 * (c * weight_per_vert + f), False) / self.ge
                    else:
                        for c in range(self.vertex_count):
                            additional_skin_weights[c * additional_weights + (f - 4)] = self.read_uint16(
                                2 * (c * weight_per_vert + f), False) / self.ge
            self.geometry.skin_weights = skin_weights.reshape((-1, u))
            self.geometry.additional_skin_weights = additional_skin_weights.reshape((-1, weight_per_vert))
            self.i16_offset = self.i16_offset + weight_per_vert * self.vertex_count * 2

    def _init_parent(self):
        if self.options['singleParent']:
            name = self.read_string()
            e = self.read_uint16()
            r = np.zeros(4 * self.vertex_count)
            i = np.zeros(4 * self.vertex_count)
            a = 4 * self.vertex_count
            for n in range(a):
                r[n] = e if n % 4 == 0 else 0
                i[n] = 1 if n % 4 == 0 else 0

            self.geometry.skin_indices = r.reshape((-1, 4))
            self.geometry.skin_weights = i.reshape((-1, 4))

    def _init_poses(self):
        if self.options['animations']:
            bone_count = self.read_int8()
            if self.options['frameMappings']:
                n = self.read_uint16()
                a = [self.read_uint16() for _ in range(n)]
                if n:
                    i = {}
                    for s in range(n):
                        i[a[s]] = s
            p = self.read_float()
            m = self.options['jointScales']
            g = self.read_float() if m else 1
            poses = {}
            locators = {}
            bones = []
            for y in range(bone_count):
                o = self.read_string()
                l = self.read_uint16()
                u = self.read_uint16()
                # print(o, l, u)
                v = lambda: {
                    "pos": self.get_position_array(1, p) if self.get_bit() else self.get_position_array(u, p),
                    "rot": self.get_quaternion_array(1) if self.get_bit() else self.get_quaternion_array(u),
                    "scl": self.get_scale_array(1, g) if self.get_bit() else self.get_scale_array(u, g) if m else [1, 1,
                                                                                                                   1],
                    "frameMapping": i if self.options["frameMappings"] else None
                }
                if o == 'main':
                    for S in range(l):
                        b = self.read_uint16()
                        w = HeroBone()
                        w.bone_id = S
                        w.name = self.read_string()
                        # print(w.name)
                        if b == 5e3:
                            self.geometry.main_skeleton = True
                            w.parent_id = -1
                            print(w.name, b, S)
                        else:
                            w.parent_id = b
                        k = v()
                        w.pos = k['pos']
                        w.quat = k['rot']
                        w.scale = k['scl']
                        bones.append(w)
                elif o == 'locators':
                    for R in range(l):
                        bone = HeroBone()
                        bone.name = self.read_string()
                        C = v()
                        bone.pos = C['pos']
                        bone.scale = C['cls']
                        bone.quat = C['rot']
                        locators[bone.name] = bone
                else:
                    c = {}
                    for x in range(l):
                        c[self.read_string()] = v()
                    poses[o] = c
            # print(h)
            self.geometry.bones = bones
            self.geometry.poses = poses
            self.geometry.locations = locators
Exemplo n.º 27
0
 def read(self, reader: ByteIO):
     self.unknown00 = reader.read_uint32()
     self.unknown08 = reader.read_uint64()
Exemplo n.º 28
0
 def write(self, writer: ByteIO):
     writer.write_uint32(self.unknown00)
     writer.write_uint32(self.name_offset)
     writer.write_uint32(self.unknown08)
Exemplo n.º 29
0
 def write(self, writer: ByteIO):
     writer.write_uint32(self.hash)
     writer.write_uint32(self.name_offset)
     writer.write_uint32(self.unknown08)
     writer.write_uint32(self.unknown0C)
     writer.write_uint32(self.unknown10)
Exemplo n.º 30
0
 def read(self, reader: ByteIO):
     self.unknown00 = reader.read_uint32()
     self.data_size = reader.read_uint32()