def __init__(self, iff_fname): from iff_read import IffReader self.iff = IffReader(iff_fname) # self.out_mode = out_mode self.pal = None self.alfd = None self.pald = array.array("B") self.pxld = array.array("B") self.info = {} self.hots = []
def set_palette(self, pal_file): from iff_read import IffReader pal_reader = IffReader(pal_file) pald = pal_reader.read_data() if pald["type"] == 'form' and pald["name"] == b'PAL ': cmap = pal_reader.read_data() if cmap["type"] == 'chunk' and cmap["name"] == b'CMAP': self.pald = cmap["data"] else: print_iff_data(cmap) raise TypeError("Expected CMAP chunk in palette file!")
def __init__(self, iff_fname): from iff_read import IffReader self.iff = IffReader(iff_fname) # self.out_mode = out_mode self.lods = {} self.hardpoints = []
class IffMeshReader: FACE_FMT = "<if5i" HARD_FMT = "<12f" def __init__(self, iff_fname): from iff_read import IffReader self.iff = IffReader(iff_fname) # self.out_mode = out_mode self.lods = {} self.hardpoints = [] def parse_deta_form(self, deta_form): deta_read = 4 while deta_read < deta_form["length"]: mdata = self.iff.read_data() if mdata["type"] == "chunk" and mdata["name"] == b"RANG": self.parse_rang_chunk(mdata) elif mdata["type"] == "form" and mdata["name"] == b"MESH": self.parse_major_mesh_form(mdata) elif mdata["type"] == "form" and mdata["name"] == b"HARD": self.parse_hard_form(mdata) elif mdata["type"] == "form" and mdata["name"] == b"COLL": self.parse_coll_form(mdata) elif mdata["type"] == "chunk" and mdata["name"] == b"FAR ": self.parse_far_chunk(mdata) deta_read += 8 + mdata["length"] # Don't add bytes read if type of data is form # if mdata["type"] == "chunk": deta_read += 8 def parse_rang_chunk(self, rang_data): if rang_data["length"] % 4 != 0: raise TypeError("RANG chunk length must be a multiple of 4!") # The RANG chunk is just a bunch of floats num_ranges = rang_data["length"] // 4 ranges = struct.unpack("<" + ("f" * num_ranges), rang_data["data"]) return ranges def parse_major_mesh_form(self, mesh_form): mjrmsh_read = 4 while mjrmsh_read < mesh_form["length"]: lod_form = self.iff.read_data() # print("LOD FORM offset:", lod_form["offset"]) # print("LOD FORM name:", lod_form["name"]) # print("LOD FORM length:", lod_form["length"]) lod_lev = int(lod_form["name"].decode("ascii")) mnrmsh = self.iff.read_data() # Minor MESH form if mnrmsh["type"] == "form" and mnrmsh["name"] == b"MESH": self.parse_minor_mesh_form(mnrmsh, lod_lev) else: print_iff_data(mnrmsh) mjrmsh_read += 8 + lod_form["length"] # Header and data bytes # print("mjrmsh_read:", mjrmsh_read, "of", mesh_form["length"]) def parse_minor_mesh_form(self, mesh_form, lod_lev=0): if lod_lev not in self.lods: self.lods[lod_lev] = {} self.lods[lod_lev]["mats"] = [] self.lods[lod_lev]["altmats"] = [] self.lods[lod_lev]["lightflags"] = [] vers_form = self.iff.read_data() mesh_vers = int(vers_form["name"].decode("ascii")) self.lods[lod_lev]["version"] = mesh_vers mnrmsh_read = 16 # Bytes for version form header while mnrmsh_read < mesh_form["length"]: mdat = self.iff.read_data() mnrmsh_read += 8 + mdat["length"] mnrmsh_read += 1 if mdat["length"] % 2 == 1 else 0 if mdat["name"] == b"NAME": self.lods[lod_lev]["name"] = ( self.parse_cstr(mdat["data"], 0)) elif mdat["name"] == b"FACE": # This isn't part of Wing Blender, so I'm using features # from newer versions of Python 3. for f in struct.iter_unpack(self.FACE_FMT, mdat["data"]): if f[2] not in self.lods[lod_lev]["mats"]: self.lods[lod_lev]["mats"].append(f[2]) if f[5] not in self.lods[lod_lev]["lightflags"]: self.lods[lod_lev]["lightflags"].append(f[5]) if f[6] not in self.lods[lod_lev]["altmats"]: self.lods[lod_lev]["altmats"].append(f[6]) def parse_hard_form(self, hard_form): hard_read = 4 while hard_read < hard_form["length"]: hard_chunk = self.iff.read_data() hard_name_offset = struct.calcsize(self.HARD_FMT) hard_read += 8 + hard_chunk["length"] hard_read += 1 if hard_chunk["length"] % 2 == 1 else 0 hard_name = self.parse_cstr(hard_chunk["data"], hard_name_offset) hard_xfm = struct.unpack_from(self.HARD_FMT, hard_chunk["data"]) hard_matrix = ( (hard_xfm[0], hard_xfm[1], hard_xfm[2]), (hard_xfm[4], hard_xfm[5], hard_xfm[6]), (hard_xfm[8], hard_xfm[9], hard_xfm[10]) ) hard_loc = (hard_xfm[3], hard_xfm[7], hard_xfm[11]) self.hardpoints.append({"rot": hard_matrix, "loc": hard_loc}) def parse_far_chunk(self, far_data): pass def parse_coll_form(self, coll_form): pass def parse_cstr(self, data, offset): cstr = bytearray() while data[offset] != 0: cstr.append(data[offset]) offset += 1 return cstr.decode("ascii", "ignore") def read(self): root_form = self.iff.read_data() root_read = 4 if root_form["name"] == b"DETA": self.parse_deta_form(root_form) elif root_form["name"] == b"MESH": self.parse_minor_mesh_form(root_form)
class IffMatReader: PAL_FMT = "<3B" def __init__(self, iff_fname): from iff_read import IffReader self.iff = IffReader(iff_fname) # self.out_mode = out_mode self.pal = None self.alfd = None self.pald = array.array("B") self.pxld = array.array("B") self.info = {} self.hots = [] def parse_info_chunk(self, info_chunk): return struct.unpack("<3i", info_chunk["data"]) def parse_hots_chunk(self, hots_chunk): return struct.unpack("<2i", hots_chunk["data"]) def parse_pal_form(self, pal_form): pal_read = 4 pal = '' pald = array.array("B") while pal_read < pal_form["length"]: pal_chunk = self.iff.read_data() if pal_chunk["type"] == 'chunk' and pal_chunk["name"] == b"NAME": pal = 'external:{}'.format(self.parse_cstr(pal_chunk["data"])) elif pal_chunk["type"] == 'chunk' and pal_chunk["name"] == b"CMAP": pal = 'embedded' pald.frombytes(pal_chunk["data"]) pal_read += 8 + pal_chunk["length"] return pal, pald def parse_pxls_chunk(self, pxls_chunk): if self.pal == "embedded": pxld = array.array("B") for index in pxls_chunk["data"]: bindex = index * 3 pxld.extend(self.pald[bindex:bindex + 3]) return pxld def get_default_alpha(self, pxls_chunk): alfd = array.array("B") for index in pxls_chunk["data"]: alfd.append(0 if index == 0 else 255) return alfd def parse_cstr(self, data, offset=0): cstr = bytearray() while data[offset] != 0: cstr.append(data[offset]) offset += 1 return cstr.decode("ascii", "ignore") def read(self): root_form = self.iff.read_data() if root_form["name"] == b"BITM": fram_form = self.iff.read_data() if fram_form["name"] == b"FRAM": fram_read = 4 while fram_read < fram_form["length"]: mdata = self.iff.read_data() if mdata["type"] == 'chunk' and mdata["name"] == b'INFO': (self.info["width"], self.info["height"], self.info["wrap"]) = self.parse_info_chunk(mdata) elif mdata["type"] == 'chunk' and mdata["name"] == b'HOTS': self.hots = self.parse_hots_chunk(mdata) elif mdata["type"] == 'form' and mdata["name"] == b'PAL ': self.pal, self.pald = self.parse_pal_form(mdata) elif mdata["type"] == 'chunk' and mdata["name"] == b'PXLS': self.pxld = self.parse_pxls_chunk(mdata) self.alfd = self.get_default_alpha(mdata) elif mdata["type"] == 'chunk' and mdata["name"] == b'ALPH': self.alfd = array.array("B") self.alfd.fromlist( [chr(255 - ord(x)) for x in mdata["data"]]) else: print_iff_data(mdata) fram_read += 8 + mdata["length"] else: print_iff_data(fram_form) raise TypeError("Invalid MAT! (no FRAM form found! " "fram_form is %s)" % fram_form["name"]) else: print_iff_data(root_form) raise TypeError("Invalid MAT type! (no BITM form found! " "Root form is: %s)" % root_form["name"]) def set_palette(self, pal_file): from iff_read import IffReader pal_reader = IffReader(pal_file) pald = pal_reader.read_data() if pald["type"] == 'form' and pald["name"] == b'PAL ': cmap = pal_reader.read_data() if cmap["type"] == 'chunk' and cmap["name"] == b'CMAP': self.pald = cmap["data"] else: print_iff_data(cmap) raise TypeError("Expected CMAP chunk in palette file!")
def __init__(self, iff_fname): from iff_read import IffReader self.iff = IffReader(iff_fname) self.pal = None self.pxld = array.array("B")
class IffPalReader: PAL_FMT = "<3B" def __init__(self, iff_fname): from iff_read import IffReader self.iff = IffReader(iff_fname) self.pal = None self.pxld = array.array("B") def parse_pal_form(self, pal_form): pal_read = 4 pal = '' pald = array.array("B") while pal_read < pal_form["length"]: pal_chunk = self.iff.read_data() if pal_chunk["type"] == 'chunk' and pal_chunk["name"] == b"NAME": pal = 'external:{}'.format(self.parse_cstr(pal_chunk["data"])) elif pal_chunk["type"] == 'chunk' and pal_chunk["name"] == b"CMAP": pal = 'embedded' pald.frombytes(pal_chunk["data"]) pal_read += 8 + pal_chunk["length"] return pal, pald def parse_cstr(self, data, offset=0): cstr = bytearray() while data[offset] != 0: cstr.append(data[offset]) offset += 1 return cstr.decode("ascii", "ignore") def read(self): root_form = self.iff.read_data() if root_form["name"] == b"BITM": fram_form = self.iff.read_data() if fram_form["name"] == b"FRAM": fram_read = 4 while fram_read < fram_form["length"]: mdata = self.iff.read_data() if mdata["type"] == 'form' and mdata["name"] == b'PAL ': self.pal, self.pald = self.parse_pal_form(mdata) fram_read += 8 + mdata["length"] else: print_iff_data(fram_form) raise TypeError("Invalid MAT! (no FRAM form found! first " "child of root form is {})".format( fram_form["name"])) elif root_form["name"] == b"PAL ": self.pal, self.pald = self.parse_pal_form(mdata) else: print_iff_data(root_form) raise TypeError("Invalid root form! (must be either BITM or PAL," "root form is %s)" % root_form["name"])
class IffMeshReader: FACE_FMT = "<if5i" HARD_FMT = "<12f" def __init__(self, iff_fname): from iff_read import IffReader self.iff = IffReader(iff_fname) # self.out_mode = out_mode self.lods = {} self.hardpoints = [] def parse_deta_form(self, deta_form): deta_read = 4 while deta_read < deta_form["length"]: mdata = self.iff.read_data() if mdata["type"] == "chunk" and mdata["name"] == b"RANG": self.parse_rang_chunk(mdata) elif mdata["type"] == "form" and mdata["name"] == b"MESH": self.parse_major_mesh_form(mdata) elif mdata["type"] == "form" and mdata["name"] == b"HARD": self.parse_hard_form(mdata) elif mdata["type"] == "form" and mdata["name"] == b"COLL": self.parse_coll_form(mdata) elif mdata["type"] == "chunk" and mdata["name"] == b"FAR ": self.parse_far_chunk(mdata) deta_read += 8 + mdata["length"] # Don't add bytes read if type of data is form # if mdata["type"] == "chunk": deta_read += 8 def parse_rang_chunk(self, rang_data): if rang_data["length"] % 4 != 0: raise TypeError("RANG chunk length must be a multiple of 4!") # The RANG chunk is just a bunch of floats num_ranges = rang_data["length"] // 4 ranges = struct.unpack("<" + ("f" * num_ranges), rang_data["data"]) return ranges def parse_major_mesh_form(self, mesh_form): mjrmsh_read = 4 while mjrmsh_read < mesh_form["length"]: lod_form = self.iff.read_data() # print("LOD FORM offset:", lod_form["offset"]) # print("LOD FORM name:", lod_form["name"]) # print("LOD FORM length:", lod_form["length"]) lod_lev = int(lod_form["name"].decode("ascii")) mnrmsh = self.iff.read_data() # Minor MESH form if mnrmsh["type"] == "form" and mnrmsh["name"] == b"MESH": self.parse_minor_mesh_form(mnrmsh, lod_lev) else: print_iff_data(mnrmsh) mjrmsh_read += 8 + lod_form["length"] # Header and data bytes # print("mjrmsh_read:", mjrmsh_read, "of", mesh_form["length"]) def parse_minor_mesh_form(self, mesh_form, lod_lev=0): if lod_lev not in self.lods: self.lods[lod_lev] = {} self.lods[lod_lev]["mats"] = [] self.lods[lod_lev]["altmats"] = [] self.lods[lod_lev]["lightflags"] = [] vers_form = self.iff.read_data() mesh_vers = int(vers_form["name"].decode("ascii")) self.lods[lod_lev]["version"] = mesh_vers mnrmsh_read = 16 # Bytes for version form header while mnrmsh_read < mesh_form["length"]: mdat = self.iff.read_data() mnrmsh_read += 8 + mdat["length"] mnrmsh_read += 1 if mdat["length"] % 2 == 1 else 0 if mdat["name"] == b"NAME": self.lods[lod_lev]["name"] = (self.parse_cstr(mdat["data"], 0)) elif mdat["name"] == b"FACE": # This isn't part of Wing Blender, so I'm using features # from newer versions of Python 3. for f in struct.iter_unpack(self.FACE_FMT, mdat["data"]): if f[2] not in self.lods[lod_lev]["mats"]: self.lods[lod_lev]["mats"].append(f[2]) if f[5] not in self.lods[lod_lev]["lightflags"]: self.lods[lod_lev]["lightflags"].append(f[5]) if f[6] not in self.lods[lod_lev]["altmats"]: self.lods[lod_lev]["altmats"].append(f[6]) def parse_hard_form(self, hard_form): hard_read = 4 while hard_read < hard_form["length"]: hard_chunk = self.iff.read_data() hard_name_offset = struct.calcsize(self.HARD_FMT) hard_read += 8 + hard_chunk["length"] hard_read += 1 if hard_chunk["length"] % 2 == 1 else 0 hard_name = self.parse_cstr(hard_chunk["data"], hard_name_offset) hard_xfm = struct.unpack_from(self.HARD_FMT, hard_chunk["data"]) hard_matrix = ((hard_xfm[0], hard_xfm[1], hard_xfm[2]), (hard_xfm[4], hard_xfm[5], hard_xfm[6]), (hard_xfm[8], hard_xfm[9], hard_xfm[10])) hard_loc = (hard_xfm[3], hard_xfm[7], hard_xfm[11]) self.hardpoints.append({"rot": hard_matrix, "loc": hard_loc}) def parse_far_chunk(self, far_data): pass def parse_coll_form(self, coll_form): pass def parse_cstr(self, data, offset): cstr = bytearray() while data[offset] != 0: cstr.append(data[offset]) offset += 1 return cstr.decode("ascii", "ignore") def read(self): root_form = self.iff.read_data() root_read = 4 if root_form["name"] == b"DETA": self.parse_deta_form(root_form) elif root_form["name"] == b"MESH": self.parse_minor_mesh_form(root_form)