Example #1
0
    def add_tag(self, tag, filepath=None):
        '''
        Adds the provided tag to this handlers tag collection.
        filepath is expected to be a relative filepath if
        self.tagsdir_relative == True
        If it isnt provided, then tag.filepath is expected to be
        an absolute filepath. If self.tagsdir_relative = True,
        tag.filepath is relative expected to be relative to self.tagsdir,
        where is_in_dir(tag.filepath, self.tagsdir) == True
        '''
        def_id = tag.def_id
        tag_coll = self.tags.get(def_id, {})

        abs_filepath = tag.filepath
        filepath = Path(filepath)
        if not is_path_empty(abs_filepath):
            if is_path_empty(filepath) and self.tagsdir_relative:
                filepath = Path(relpath(str(abs_filepath), str(self.tagsdir)))
        elif not is_path_empty(filepath):
            abs_filepath = self.tagsdir.joinpath(filepath)
        else:
            raise ValueError("No filepath provided to index tag under")

        tag.filepath = abs_filepath
        tag_coll[filepath] = tag
        self.tags[def_id] = tag_coll
Example #2
0
    def get_resource_map_paths(self, maps_dir=""):
        map_paths = {name: None for name in HALO2_MAP_TYPES[1:]}
        if self.engine == "halo2alpha":
            map_paths.pop("single_player_shared", None)

        if not is_path_empty(maps_dir):
            maps_dir = Path(maps_dir)
        else:
            maps_dir = self.filepath.parent

        # detect the map paths for the resource maps
        for map_name in sorted(map_paths):
            map_path = str(maps_dir.joinpath(map_name))
            if self.maps.get(map_name) is not None:
                map_path = self.maps[map_name].filepath
            elif os.path.exists(map_path + ".map"):
                map_path = Path(map_path + ".map")
            elif os.path.exists(map_path + "_DECOMP.map"):
                map_path = Path(map_path + "_DECOMP.map")
            elif os.path.exists(map_path + ".map.dtz"):
                map_path = Path(map_path + ".map.dtz")
            else:
                map_path = None

            map_paths[map_name] = map_path

        return map_paths
Example #3
0
    def make_log_file(self, logstr, logpath=None):
        '''
        Writes the supplied string to a log file.

        Required arguments:
            logstr(str)

        If self.log_filename is a non-blank string it will be used as the
        log filename. Otherwise the current timestamp will be used as the
        filename in the format "YY-MM-DD  HH:MM SS".
        If the file already exists it will be appended to with the current
        timestamp separating each write. Otherwise the file will be created.
        '''
        # get the timestamp for the debug log's name
        timestamp = datetime.now().strftime("%Y-%m-%d  %H:%M:%S")

        if not is_path_empty(logpath):
            pass
        elif isinstance(self.log_filename, str) and self.log_filename:
            logpath = self.tagsdir.joinpath(self.log_filename)
            logstr = '\n' + '-'*80 + '\n' + timestamp + '\n' + logstr
        else:
            logpath = self.tagsdir.joinpath(timestamp.replace(':', '.') + ".log")

        logpath = Path(logpath)

        mode = 'w'
        if logpath.is_file():
            mode = 'a'

        # open a debug file and write the debug string to it
        with logpath.open(mode) as logfile:
            logfile.write(logstr)
Example #4
0
def bitmap_from_multiple_dds(app, fps=()):
    load_dir = app.bitmap_load_dir
    data_dir = app.data_dir
    if is_path_empty(data_dir):
        data_dir = Path("")
    if is_path_empty(load_dir):
        load_dir = data_dir

    if not fps:
        fps = askopenfilenames(
            initialdir=load_dir,
            parent=app,
            filetypes=(("DDS image", "*.dds"), ("All", "*")),
            title="Select dds files to turn into a single bitmap tag")
        fps = [fp for fp in fps if fp.lower().endswith(".dds")]

    if not fps:
        return

    # make the tag window
    window = app.load_tags(filepaths='', def_id='bitm')
    if not window:
        return

    print("Creating bitmap from dds files")
    window = window[0]
    window.is_new_tag = True

    fps = sorted(fps)

    for fp in fps:
        pure_path = Path(fp)
        window.update_title(list(pure_path.parts)[-1])
        app.bitmap_load_dir = pure_path.parent
        break

    compile_bitmap_from_dds_files(window.tag, fps)

    # reload the window to display the newly entered info
    window.reload()
    # prompt the user to save the tag somewhere
    app.save_tag_as()
Example #5
0
    def parse(self, **kwargs):
        '''
        Optional keywords arguments:
        # bool:
        init_attrs -----
        allow_corrupt --

        # buffer:
        rawdata --------

        # int:
        root_offset ----
        offset ---------

        # iterable:
        initdata -------

        #str:
        filepath -------
        '''
        if not kwargs.get('rawdata'):
            kwargs.setdefault('filepath', self.filepath)
        kwargs.setdefault('root_offset', self.root_offset)
        filepath = kwargs.get('filepath')

        desc = self.definition.descriptor
        block_type = desc.get(NODE_CLS, desc[TYPE].node_cls)

        # Create the root node and set self.data to it before parsing.
        new_tag_data = self.data = block_type(desc, parent=self)

        if not is_path_empty(filepath):
            self.filepath = filepath
            # If this is an incomplete object then we
            # need to keep a path to the source file
            if self.definition.incomplete:
                self.sourcepath = filepath
        elif 'rawdata' not in kwargs:
            kwargs['init_attrs'] = True

        # whether or not to allow corrupt tags to be built.
        # this is a debugging tool.
        if kwargs.pop('allow_corrupt', False):
            try:
                new_tag_data.parse(**kwargs)
            except OSError:
                # file was likely not found, or something similar
                raise
            except Exception:
                print(format_exc())
        else:
            new_tag_data.parse(**kwargs)
Example #6
0
def bitmap_from_bitmap_source(app, e=None):
    load_dir = app.bitmap_load_dir
    if is_path_empty(load_dir):
        load_dir = app.last_data_load_dir

    fps = askopenfilenames(initialdir=load_dir,
                           parent=app,
                           filetypes=(("bitmap", "*.bitmap"), ("All", "*")),
                           title="Select a bitmap tag to get the source tiff")

    if not fps:
        return

    app.bitmap_load_dir = os.path.dirname(fps[0])

    print('Creating bitmap from uncompressed source image of these bitmaps:')
    for fp in fps:
        print("  %s" % fp)

        width, height, pixels = extract_bitmap_tiff_data(fp)
        if not pixels:
            continue

        # make the tag window
        try:
            window = app.load_tags(filepaths='', def_id='bitm')
        except LookupError:
            print('    Could not make a new bitmap. Change the tag set.')
        if not window:
            continue

        window = window[0]
        window.is_new_tag = True

        add_bitmap_to_bitmap_tag(window.tag, width, height, 1, "texture_2d",
                                 "a8r8g8b8", 0, pixels)

        window.tag.rel_filepath = "untitled%s.bitmap" % app.untitled_num
        window.tag.filepath = app.tags_dir.joinpath(window.tag.rel_filepath)

        app.update_tag_window_title(window)

        # reload the window to display the newly entered info
        window.reload()
        # prompt the user to save the tag somewhere
        app.save_tag_as()
Example #7
0
    def delete_tag(self, *, tag=None, def_id=None, filepath=''):
        filepath = Path(filepath)
        if tag is not None:
            def_id = tag.def_id
            if not is_path_empty(filepath):
                pass
            elif self.tagsdir_relative:
                filepath = Path(self.tagsdir, tag.filepath)
            else:
                filepath = tag.filepath
        elif def_id is None:
            def_id = self.get_def_id(filepath)

        if filepath in self.tags.get(def_id, {}):
            del self.tags[def_id][filepath]
        elif Path(self.tagsdir, filepath) in self.tags.get(def_id, {}):
            del self.tags[def_id][Path(self.tagsdir, filepath)]
        else:
            print("Warning: Tried to delete tag %s [%s] from handler, "
                  "but tag couldn't be found." % (filepath, def_id))
Example #8
0
    def get_resource_map_paths(self, maps_dir=""):
        play_meta = self.root_tags.get("cache_file_resource_layout_table")
        if not play_meta:
            return {}

        map_paths = {
            name.split(".")[0]: None
            for name in self.shared_map_names
        }
        if not is_path_empty(maps_dir):
            maps_dir = Path(maps_dir)
        else:
            maps_dir = self.filepath.parent

        # detect/ask for the map paths for the resource maps
        for map_name in sorted(map_paths):
            map_path = str(maps_dir.joinpath("%s.map" % map_name))
            if self.maps.get(map_name) is not None:
                map_paths[map_name] = self.maps[map_name].filepath
            elif os.path.exists(map_path):
                map_paths[map_name] = map_path

        return map_paths
Example #9
0
    def post_toplevel_init(self):
        if not is_path_empty(e_c.MOZZ_ICON_PATH):
            self.iconbitmap_filepath = e_c.MOZZ_ICON_PATH

        ConfigWindow.post_toplevel_init(self)
Example #10
0
def hud_message_text_from_hmt(app, fp=None):
    load_dir = app.last_data_load_dir
    tags_dir = app.tags_dir
    data_dir = app.data_dir
    if is_path_empty(tags_dir):
        tags_dir = Path("")
    if is_path_empty(data_dir):
        data_dir = Path("")

    if is_path_empty(load_dir):
        load_dir = data_dir

    if is_path_empty(fp):
        fp = askopenfilename(
            initialdir=load_dir,
            parent=app,
            filetypes=(("HUD messages", "*.hmt"), ("All", "*")),
            title="Select hmt file to turn into a hud_message_text tag")

    fp = Path(fp)
    if is_path_empty(fp):
        return

    try:
        app.last_data_load_dir = fp.parent

        print("Creating hud_message_text from this hmt file:")
        print("    %s" % fp)

        with fp.open("r", encoding=hacky_detect_encoding(fp)) as f:
            hmt_string_data = f.read()

    except Exception:
        print(format_exc())
        print("    Could not load hmt file.")
        return

    try:
        rel_filepath = fp.relative_to(data_dir)
    except ValueError:
        rel_filepath = Path("hud messages")

    rel_filepath = rel_filepath.with_suffix(".hud_message_text")

    tag_path = Path("")
    if not is_path_empty(rel_filepath):
        tag_path = tags_dir.joinpath(rel_filepath)

    # make the tag window
    window = app.load_tags(
        filepaths=(tag_path, ) if tag_path.is_file() else "", def_id='hmt ')
    if not window:
        return

    window = window[0]
    window.is_new_tag = False
    window.tag.filepath = tag_path
    window.tag.rel_filepath = rel_filepath

    error = compile_hud_message_text(window.tag, hmt_string_data)

    # reload the window to display the newly entered info
    window.reload()
    app.update_tag_window_title(window)
    if error:
        print("    Errors occurred while compiling. " +
              "Tag will not be automatically saved.")
        window.is_new_tag = True
    elif not tag_path.is_file():
        # save the tag if it doesnt already exist
        app.save_tag()
Example #11
0
    def _do_compression(self, compress, antr_path=None):
        state = "compress" if compress else "decompress"
        if not antr_path:
            antr_path = self.model_animations_path.get()

        antr_path = Path(antr_path)

        while is_path_empty(antr_path):
            self.model_animations_path_browse(True)
            antr_path = Path(self.model_animations_path.get())
            if is_path_empty(antr_path) and self.warn_cancel():
                return

        print("%sing %s." % (state.capitalize(), antr_path))

        self.app_root.update()
        antr_def = None
        try:
            with antr_path.open('rb') as f:
                f.seek(36)
                tag_type = f.read(4)
                if tag_type == b'antr':
                    f.seek(56)
                    antr_ver = f.read(2)
                    if antr_ver == b'\x00\x05':
                        antr_def = stubbs_antr_def
                    elif antr_ver == b'\x00\x04':
                        antr_def = halo_antr_def
        except Exception:
            pass

        if antr_def is None:
            print("Could not determine model_animation tag version.")
            return

        antr_tag = antr_def.build(filepath=antr_path)
        anims = antr_tag.data.tagdata.animations.STEPTREE
        errors = False
        edited = False
        for anim in anims:
            try:
                if not anim.flags.compressed_data:
                    continue

                if compress:
                    edited |= compress_animation(anim)
                else:
                    edited |= decompress_animation(
                        anim, self.preserve_compressed.get())
            except Exception:
                print(format_exc())
                self.update()
                errors = True

        if not edited:
            print("    No changes made. Not saving.")
            return

        if errors:
            self.update()
            if not messagebox.askyesno(
                    "Model_animations %sing failed" % state,
                ("Errors occurred while %sing(check console). " % state) +
                    "Do you want to save the model_animations tag anyway?",
                    icon='warning',
                    parent=self):
                print("    Model_animations compilation failed.")
                return

        try:
            if not self.overwrite.get():
                fp = Path(antr_tag.filepath)
                antr_tag.filepath = Path(fp.parent,
                                         fp.stem + "_DECOMP" + fp.suffix)

            antr_tag.calc_internal_data()
            antr_tag.serialize(temp=False,
                               backup=False,
                               calc_pointers=False,
                               int_test=False)
            print("    Finished")
        except Exception:
            print(format_exc())
            print("    Could not save %sed model_animations." % state)
Example #12
0
def physics_from_jms(app, fp=None):
    load_dir = app.jms_load_dir
    tags_dir = app.tags_dir
    data_dir = app.data_dir
    if is_path_empty(tags_dir):
        tags_dir = Path("")
    if is_path_empty(data_dir):
        data_dir = Path("")

    if is_path_empty(load_dir):
        load_dir = data_dir

    if is_path_empty(fp):
        fp = askopenfilename(
            initialdir=load_dir, parent=app,
            filetypes=(("JMS model", "*.jms"), ("All", "*")),
            title="Select jms file to turn into a physics tag")

    fp = Path(fp)
    if is_path_empty(fp):
        return

    try:
        app.jms_load_dir = fp.parent
        with fp.open("r") as f:
            jms_model = read_jms(f.read(), "regions")
    except Exception:
        print(format_exc())
        print("    Could not parse jms file")
        return

    try:
        rel_filepath = fp.relative_to(data_dir).parent.parent
        rel_filepath = rel_filepath.joinpath(rel_filepath.stem + ".physics")
    except ValueError:
        rel_filepath = Path("unnamed.physics")

    tag_path = Path("")
    if not is_path_empty(rel_filepath):
        tag_path = tags_dir.joinpath(rel_filepath)

    # make the tag window
    window = app.load_tags(
        filepaths=(tag_path, ) if tag_path.is_file() else "",
        def_id='phys')
    if not window:
        return

    window = window[0]
    window.is_new_tag = False
    window.tag.filepath = tag_path
    window.tag.rel_filepath = rel_filepath

    compile_physics(window.tag, jms_model.markers, tag_path.is_file())

    # reload the window to display the newly entered info
    window.reload()
    app.update_tag_window_title(window)
    if not tag_path.is_file():
        # save the tag if it doesnt already exist
        app.save_tag()
Example #13
0
def strings_from_txt(app, fp=None):
    load_dir = app.last_data_load_dir
    tags_dir = app.tags_dir
    data_dir = app.data_dir
    if is_path_empty(tags_dir):
        tags_dir = Path("")
    if is_path_empty(data_dir):
        data_dir = Path("")

    if is_path_empty(load_dir):
        load_dir = data_dir

    if is_path_empty(fp):
        fp = askopenfilename(
            initialdir=load_dir,
            parent=app,
            filetypes=(("strings list", "*.txt"), ("All", "*")),
            title="Select hmt file to turn into a (unicode_)string_list tag")

    fp = Path(fp)
    if is_path_empty(fp):
        return

    try:
        app.last_data_load_dir = fp.parent
        tag_ext = "unicode_string_list"
        tag_cls = "ustr"

        encoding = hacky_detect_encoding(fp)

        if encoding == "latin-1":
            tag_ext = "string_list"
            tag_cls = "str#"

        print("Creating %s from this txt file:" % tag_ext)
        print("    %s" % fp)

        with fp.open("r", encoding=encoding) as f:
            string_data = f.read()
            if "utf-16" in encoding:
                string_data = string_data.lstrip('\ufeff').lstrip('\ufffe')

    except Exception:
        print(format_exc())
        print("    Could not parse file.")
        return

    try:
        rel_filepath = fp.relative_to(data_dir)
    except ValueError:
        rel_filepath = Path("strings")

    rel_filepath = rel_filepath.with_suffix("." + tag_ext)

    tag_path = Path("")
    if not is_path_empty(rel_filepath):
        tag_path = tags_dir.joinpath(rel_filepath)

    # make the tag window
    window = app.load_tags(
        filepaths=(tag_path, ) if tag_path.is_file() else "", def_id=tag_cls)
    if not window:
        return

    window = window[0]
    window.is_new_tag = True
    window.tag.filepath = tag_path
    window.tag.rel_filepath = rel_filepath

    if 'utf-16' in encoding:
        compile_unicode_string_list(window.tag, string_data)
    else:
        compile_string_list(window.tag, string_data)

    # reload the window to display the newly entered info
    window.reload()
    app.update_tag_window_title(window)
    if not tag_path.is_file():
        # save the tag if it doesnt already exist
        app.save_tag()
Example #14
0
def get_rawdata(**kwargs):
    '''
    This function serves as a macro for returning a Buffer object.
    'filepath' and 'rawdata' may be given as keyword arguments.
    Accepts any number of keyword arguments and ignores invalid ones.

    If filepath is given, this function will open the file as a PeekableMmap.
    If rawdata is a bytes object, it will be converted into a BytesBuffer.
    If rawdata is a bytearray, it will be converted into a BytearrayBuffer.
    If rawdata is not a bytearray or bytes and is not None, it will
    be checked to make sure it has read, seek, and peek methods.

    Returns the rawdata, or None if rawdata and filepath were unsupplied.

    Raises TypeError if rawdata doesnt have read, seek, or peek methods.
    Raises TypeError if rawdata and filepath are both provided.
    '''
    filepath = kwargs.get('filepath')
    if filepath is not None:
        filepath = Path(filepath)
    rawdata = kwargs.get('rawdata')
    writable = kwargs.get('writable', True)

    if not is_path_empty(filepath):
        if rawdata:
            raise TypeError("Provide either rawdata or filepath, not both.")

        access = ACCESS_WRITE
        # to avoid 'open' failing if windows files are hidden,
        # we open in 'r+b' mode if the file exists.
        if not writable:
            open_mode = 'rb'
            access = ACCESS_READ
        elif filepath.is_file():
            open_mode = 'r+b'
        else:
            open_mode = 'w+b'

        # try to open the file as the rawdata
        rawdata_file = filepath.open(open_mode)
        try:
            rawdata = PeekableMmap(rawdata_file.fileno(), 0, access=access)
            rawdata_file.close()
        except ValueError:
            # can't mmap an empty file
            rawdata = rawdata_file

    elif not rawdata:
        rawdata = None
    elif isinstance(rawdata, bytes):
        rawdata = BytesBuffer(rawdata)
    elif isinstance(rawdata, bytearray):
        rawdata = BytearrayBuffer(rawdata)
    elif not (hasattr(rawdata, 'read') and hasattr(rawdata, 'seek')):
        raise TypeError(
            ("If rawdata is provided it must either be one of " +
             "the following:\n    %s, %s, %s, %s\nor it must have " +
             "'read' and 'seek' attributes.\nGot %s instead.") %
            (BytesBuffer, BytearrayBuffer, mmap, PeekableMmap, type(rawdata)))

    return rawdata