예제 #1
0
 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 = []
예제 #2
0
    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!")
예제 #3
0
    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!")
예제 #4
0
 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 = []
예제 #5
0
 def __init__(self, iff_fname):
     from iff_read import IffReader
     self.iff = IffReader(iff_fname)
     # self.out_mode = out_mode
     self.lods = {}
     self.hardpoints = []
예제 #6
0
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)
예제 #7
0
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!")
예제 #8
0
 def __init__(self, iff_fname):
     from iff_read import IffReader
     self.iff = IffReader(iff_fname)
     self.pal = None
     self.pxld = array.array("B")
예제 #9
0
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"])
예제 #10
0
 def __init__(self, iff_fname):
     from iff_read import IffReader
     self.iff = IffReader(iff_fname)
     self.pal = None
     self.pxld = array.array("B")
예제 #11
0
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"])
예제 #12
0
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!")
예제 #13
0
 def __init__(self, iff_fname):
     from iff_read import IffReader
     self.iff = IffReader(iff_fname)
     # self.out_mode = out_mode
     self.lods = {}
     self.hardpoints = []
예제 #14
0
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)