def tag_browse(self):
        if self._extracting:
            return
        filetypes = [('All', '*')]

        for def_id in sorted(self.tag_data_extractors.keys()):
            if def_id in self.tag_class_fcc_to_ext:
                filetypes.append(
                    (def_id, "." + self.tag_class_fcc_to_ext[def_id]))

        fp = askopenfilename(initialdir=str(self.app_root.last_load_dir),
                             filetypes=filetypes,
                             parent=self,
                             title="Select a tag to extract from")

        if not fp:
            return

        fp = Path(fp)
        self.app_root.last_load_dir = fp.parent
        if not is_in_dir(fp, self.handler.tagsdir):
            print("Tag %s is not located in tags directory %s" %
                  (fp, self.handler.tagsdir))
            return

        self.app_root.last_load_dir = fp.parent
        self.tag_path.set(fp)
Beispiel #2
0
    def scenario_browse(self):
        dirpath = askopenfilename(initialdir=self.scenario_path.get(),
                                  parent=self,
                                  title="Select scenario to remove sauce from")

        if not dirpath:
            return
        self.app_root.last_load_dir = os.path.dirname(dirpath)
        self.scenario_path.set(dirpath)
Beispiel #3
0
def get_tags(coll_path, model_in_path):
    mod2_path = str(Path(model_in_path).with_suffix('')) + "_COLL.gbxmodel"

    # get whether or not the collision tag is stubbs
    stubbs = tag_header_def.build(filepath=coll_path).version == 11

    if stubbs:
        coll_tag = stubbs_coll_def.build(filepath=coll_path)
    else:
        coll_tag = coll_def.build(filepath=coll_path)

    mod2_tag = mod2_def.build()
    mod2_tag.filepath = mod2_path
    model_in_rawdata = None

    guessed_mode = False
    while model_in_rawdata is None and model_in_path:
        try:
            model_in_rawdata = get_rawdata(filepath=model_in_path)
        except Exception:
            if guessed_mode:
                model_in_rawdata = None
                model_in_path = Path(askopenfilename(
                    initialdir=model_in_path.parent, filetypes=(
                        ('All', '*'), ('Gbxmodel', '*.gbxmodel')),
                    title="Select the gbxmodel to extract nodes from"))
            else:
                model_in_path = model_in_path.with_suffix(".model")
                guessed_mode = True

    if model_in_rawdata is not None:
        # we dont actually care about the geometries or shaders of the gbxmodel
        # tag we're loading, so null them out to speed up the loading process.
        geom_off = 64 + 4*9 + 2*5 + 126 + 12*3

        # make a copy so we dont edit the file
        model_in_rawdata = bytearray(model_in_rawdata)
        model_in_rawdata[geom_off:64 + 232] = b'\x00'*(64 + 232 - geom_off)

        if model_in_rawdata[36:40] == b"mod2":
            model_in_tag = mod2_def.build(rawdata=model_in_rawdata)
        elif stubbs:
            model_in_tag = stubbs_mode_def.build(rawdata=model_in_rawdata)
        else:
            model_in_tag = mode_def.build(rawdata=model_in_rawdata)

        mod2_tag.data.tagdata.nodes = model_in_tag.data.tagdata.nodes
    else:
        model_in_tag = None
        mod2_tag.data.tagdata.nodes.STEPTREE.append()
        node = mod2_tag.data.tagdata.nodes.STEPTREE[-1]
        node.name = "COLLISION ROOT"
        print("    %s" % model_in_path)
        print("    Could not load gbxmodel. Gbxmodel wont have nodes and "
              "the geometry will not be positioned or rotated properly.")

    return coll_tag, model_in_tag, mod2_tag
Beispiel #4
0
    def tag_path_browse(self):
        initialdir = self.tag_path.get()
        if not initialdir:
            initialdir = self.tags_dir.get()

        filetypes = (("%s tag" % self.src_ext, "*.%s" % self.src_ext), )
        filetypes += tuple(("%s tag" % ext, "*.%s" % ext)
                           for ext in self.src_exts if ext != self.src_ext)
        filetypes += (('All', '*'), )
        tag_path = askopenfilename(initialdir=initialdir, filetypes=filetypes)
        if tag_path:
            self.tag_path.set(tag_path)
Beispiel #5
0
    def browse(self):
        if self._zipping:
            return

        filetypes = [('All', '*')]

        defs = self.app_root.handler.defs
        for def_id in sorted(defs.keys()):
            filetypes.append((def_id, defs[def_id].ext))
        fp = askopenfilename(title="Select a tag",
                             filetypes=filetypes,
                             parent=self,
                             initialdir=self.app_root.last_load_dir)

        if not fp:
            return

        self.app_root.last_load_dir = Path(fp).parent
        self.tag_filepath.set(fp)
Beispiel #6
0
    def model_animations_path_browse(self, force=False):
        if not force and (self._working or self._loading):
            return

        antr_dir = os.path.dirname(self.model_animations_path.get())
        if self.model_animations_dir.get() and not antr_dir:
            antr_dir = self.model_animations_dir.get()

        fp = askopenfilename(initialdir=antr_dir,
                             title="Model_animations to compress/decompress",
                             parent=self,
                             filetypes=(("Model animations graph",
                                         "*.model_animations"), ('All', '*')))

        if not fp:
            return

        fp = Path(fp)
        if not fp.suffix:
            fp = fp.with_suffix(".model_animations")

        self.app_root.last_load_dir = str(fp.parent)
        self.model_animations_path.set(str(fp))
Beispiel #7
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()
Beispiel #8
0
    def import_node(self):
        '''Prompts the user for an exported node file.
        Imports data into the node from the file.'''
        if None in (self.parent, self.node):
            return

        try:
            initialdir = self.tag_window.app_root.last_load_dir
        except AttributeError:
            initialdir = None

        ext = self.field_ext

        filepath = askopenfilename(initialdir=initialdir,
                                   defaultextension=ext,
                                   filetypes=[(self.name, "*" + ext),
                                              ('All', '*')],
                                   title="Import '%s' from..." % self.name,
                                   parent=self)

        if not filepath:
            return

        curr_size = None
        index = self.attr_index

        try:
            undo_node = self.node
            curr_size = self.parent.get_size(attr_index=index)

            with get_rawdata_context(writable=False,
                                     filepath=filepath) as rawdata:
                try:
                    self.parent.set_size(len(rawdata), attr_index=index)
                except Exception:
                    # sometimes rawdata has an explicit size, so an exception
                    # will be raised when trying to change it. just ignore it
                    pass

                self.parent.parse(rawdata=rawdata, attr_index=index)
                self.node = self.parent[index]
                self.set_edited()

                self.edit_create(undo_node=undo_node, redo_node=self.node)

                # until i come up with a better method, i'll have to rely on
                # reloading the root field widget so stuff(sizes) will be updated
                try:
                    root = self.f_widget_parent
                    while hasattr(root, 'f_widget_parent'):
                        if root.f_widget_parent is None:
                            break
                        root = root.f_widget_parent

                    root.reload()
                except Exception:
                    print(format_exc())
                    print("Could not reload after importing '%s' node." %
                          self.name)
        except Exception:
            print(format_exc())
            print("Could not import '%s' node." % self.name)
            if curr_size is None:
                pass
            elif hasattr(self.node, 'parse'):
                self.node.set_size(curr_size)
            else:
                self.parent.set_size(curr_size, attr_index=index)
Beispiel #9
0
    def import_node(self):
        '''Prompts the user for an exported node file.
        Imports data into the node from the file.'''
        try:
            initialdir = self.tag_window.app_root.last_load_dir
        except AttributeError:
            initialdir = None

        ext = self.field_ext

        filepath = askopenfilename(
            initialdir=initialdir, defaultextension=ext,
            filetypes=[(self.name, "*" + ext), ('All', '*')],
            title="Import sound data from...", parent=self)

        if not filepath:
            return

        filepath = Path(filepath)
        ext = filepath.suffix.lower()

        curr_size = None
        index = self.attr_index

        try:
            curr_size = self.parent.get_size(attr_index=index)
            if ext == '.wav':
                # if the file is wav, we need to give it a header
                wav_file = wav_def.build(filepath=filepath)

                sound_data = self.parent.get_root().data.tagdata
                channel_count = sound_data.encoding.data + 1
                sample_rate = 22050 * (sound_data.sample_rate.data + 1)

                wav_header = wav_file.data.wav_header
                wav_format = wav_file.data.wav_format
                wav_chunks = wav_file.data.wav_chunks
                typ = wav_format.fmt.enum_name
                block_align = (2 if typ == "pcm" else 36) * wav_format.channels

                data_chunk = None
                for chunk in wav_chunks:
                    if chunk.sig.enum_name == "data":
                        data_chunk = chunk
                        break

                if wav_header.riff_sig != wav_header.get_desc("DEFAULT", "riff_sig"):
                    raise ValueError(
                        "RIFF signature is invalid. Not a valid wav file.")
                elif wav_header.wave_sig != wav_header.get_desc("DEFAULT", "wave_sig"):
                    raise ValueError(
                        "WAVE signature is invalid. Not a valid wav file.")
                elif wav_format.sig != wav_format.get_desc("DEFAULT", "sig"):
                    raise ValueError(
                        "Format signature is invalid. Not a valid wav file.")
                elif data_chunk is None:
                    raise ValueError(
                        "Data chunk not present. Not a valid wav file.")
                elif typ not in ('ima_adpcm', 'xbox_adpcm', 'pcm'):
                    raise TypeError(
                        "Wav file audio format must be either IMA ADPCM " +
                        "Xbox ADPCM, or PCM, not %s" % wav_format.fmt.enum_name)
                elif sound_data.encoding.data + 1 != wav_format.channels:
                    raise TypeError(
                        "Wav file channel count does not match this sound " +
                        "tags channel count. Expected %s, not %s" %
                        (channel_count, wav_format.channels))
                elif sample_rate != wav_format.sample_rate:
                    raise TypeError(
                        "Wav file sample rate does not match this sound " +
                        "tags sample rate. Expected %skHz, not %skHz" %
                        (sample_rate, wav_format.sample_rate))
                elif block_align != wav_format.block_align:
                    raise TypeError(
                        "Wav file block size does not match this sound " +
                        "tags block size. Expected %sbytes, not %sbytes" %
                        (block_align, wav_format.block_align))

                rawdata = data_chunk.data
                do_pcm_byteswap = (typ == 'pcm')
            else:
                rawdata = get_rawdata(filepath=filepath, writable=False)
                do_pcm_byteswap = False

            undo_node = self.node
            self.parent.set_size(len(rawdata), attr_index=index)
            self.parent.parse(rawdata=rawdata, attr_index=index)

            if do_pcm_byteswap:
                byteswap_pcm16_samples(self.parent)

            self.node = self.parent[index]

            self.set_edited()
            self.edit_create(undo_node=undo_node, redo_node=self.node)

            # reload the parent field widget so sizes will be updated
            try:
                self.f_widget_parent.reload()
            except Exception:
                print(format_exc())
                print("Could not reload after importing sound data.")
        except Exception:
            print(format_exc())
            print("Could not import sound data.")
            try: self.parent.set_size(curr_size, attr_index=index)
            except Exception: pass
Beispiel #10
0
    def browse_tag(self):
        '''Opens a filepicker window to aid the user in referencing their
        wished tag file.'''
        if self.node is None:
            return

        try:
            try:
                tags_dir = self.tag_window.tag.tags_dir
            except AttributeError:
                return

            init_dir = tags_dir

            try:
                init_dir = Path(
                    tagpath_to_fullpath(tags_dir,
                                        self.node.filepath,
                                        extension=self.tag_window.tag.ext,
                                        force_windows=True)).parent
            except Exception:
                # This path is not valid, so use our earlier assignment instead.
                pass

            filetypes = []
            for ext in sorted(self.node.tag_class.NAME_MAP):
                if ext == 'NONE':
                    continue
                filetypes.append((ext, '*.%s' % ext))
            # TODO: Create a function that can generate globs
            # that support all types valid for this field.
            if len(filetypes) > 1:
                filetypes = (('All', '*'), ) + tuple(filetypes)
            else:
                filetypes.append(('All', '*'))

            filepath = askopenfilename(initialdir=init_dir,
                                       filetypes=filetypes,
                                       title="Select a tag",
                                       parent=self)

            if not filepath:
                # askopenfilename returned nothing. Quit.
                return

            # Halo tagpaths require backslashes( \ ) as dividers.
            # We take the path we got, interpret it as a native Path, then
            # convert it to a PureWindowsPath to get the backslashes safely.
            filepath = Path(filepath)
            try:
                tag_path = filepath.relative_to(tags_dir)
            # If the path is not relative just only take the filename.
            except ValueError:
                tag_path = Path(filepath.name)

            # get file extension.
            ext = tag_path.suffix.lower()
            # Remove file extension.
            tag_path = tag_path.with_suffix('')

            orig_tag_class = copy(self.node.tag_class)
            # Try to set the tagtype to the type that we selected.
            try:
                self.node.tag_class.set_to(ext[1:])
            # If we fail, try to set the tagtype to the first one that
            # has a file that exists, otherwise, set type to NONE.
            except Exception:
                self.node.tag_class.set_to('NONE')
                for filetype in filetypes:
                    ext = filetype[1][1:]
                    if tagpath_to_fullpath(tags_dir, tag_path,
                                           extension=ext) is not None:
                        self.node.tag_class.set_to(ext[1:])
                        break

            internal_tag_path = str(PureWindowsPath(tag_path)).lower()

            self.edit_create(attr_index=('tag_class', 'filepath'),
                             redo_node=dict(tag_class=self.node.tag_class,
                                            filepath=internal_tag_path),
                             undo_node=dict(tag_class=orig_tag_class,
                                            filepath=self.node.filepath))

            self.node.filepath = internal_tag_path
            self.reload()
            self.set_edited()
        except Exception:
            print(format_exc())
Beispiel #11
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()
Beispiel #12
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()