def _convert_texture( tex_info: Tuple[int, str], data_folder_path: Path ) -> Tuple[Material, Texture, Image, FileResource]: tex_id, texture_name = tex_info texture_path = PureWindowsPath(texture_name) full_texture_path = data_folder_path / "texture" / texture_path texture_data: Union[io.BytesIO, BinaryIO] alpha_mode = "MASK" if texture_path.suffix.lower() == ".bmp": texture_data = convert_bmp_to_png(full_texture_path) dest_path = texture_path.with_suffix(".png") elif texture_path.suffix.lower() == ".tga": alpha_mode = "BLEND" texture_data = convert_tga_to_png(full_texture_path) dest_path = texture_path.with_suffix(".png") else: texture_data = full_texture_path.open("rb") dest_path = texture_path return (Material(pbrMetallicRoughness=PBRMetallicRoughness( baseColorTexture=TextureInfo(index=tex_id), metallicFactor=0.0, roughnessFactor=1.0), doubleSided=True, alphaMode=alpha_mode), Texture(sampler=0, source=tex_id), Image(uri=dest_path.name, mimeType="image/png"), FileResource(dest_path.name, data=texture_data.read()))
def get_filtered_tag_ids(self, halo_map): tag_index = halo_map.tag_index.STEPTREE tag_ids = self tag_index_ids = set() tag_ids = self.detokenize_tag_ids(halo_map) for tag_id in tag_ids: if isinstance(tag_id, int): tag_index_ids.add(tag_id) continue tag_path = PureWindowsPath(tag_id) tag_class = tag_path.suffix if len(tag_path.parts) > 1: # tag path has multiple parts. use the whole # path as the tag_path, minus the extension. tag_path = str(tag_path.with_suffix("")) else: # only one piece in the tag path. use the only # piece(minus the extension) as the tag_path. tag_path = tag_path.stem if set(tag_path) == set("*"): # tag path is all asterisks. This means we're only # matching based on extension, so match all tag paths tag_path = "" exact = tag_path and tag_class tag_index_ids.update( get_filtered_tag_index_ids(tag_index, tag_path, tag_class.lstrip("."), exact)) # make sure all the tag_ids are valid tag_id_range = range(len(tag_index)) for i in tuple(tag_index_ids): if i not in tag_id_range: tag_index_ids.remove(i) return list(tag_index_ids)
class RefineryActionsWindow(tk.Toplevel, BinillaWidget): app_root = None settings = None renamable = True propagatable = False accept_rename = None accept_settings = None tag_index_ref = None rename_string = None newtype_string = None recursive_rename = None original_name = "" def __init__(self, *args, **kwargs): title = kwargs.pop('title', None) self.renamable = kwargs.pop('renamable', self.renamable) self.settings = settings = kwargs.pop('settings', {}) self.tag_index_ref = kwargs.pop('tag_index_ref', self.tag_index_ref) # Zatarita, added propagatable kwarg for displaying checkbox self.propagatable = kwargs.pop('propagatable', self.propagatable) BinillaWidget.__init__(self, *args, **kwargs) tk.Toplevel.__init__(self, *args, **kwargs) try: self.iconbitmap(e_c.REFINERY_ICON_PATH) except Exception: if not e_c.IS_LNX: print("Could not load window icon.") self.bind('<Escape>', lambda e=None, s=self, *a, **kw: s.destroy()) if self.app_root is None and hasattr(self.master, 'app_root'): self.app_root = self.master.app_root self.accept_rename = settings.get('accept_rename', tk.IntVar(self)) self.accept_settings = settings.get('accept_settings', tk.IntVar(self)) self.rename_string = settings.get('rename_string', tk.StringVar(self)) self.newtype_string = settings.get('newtype_string', tk.StringVar(self)) self.extract_to_dir = settings.get('out_dir', tk.StringVar(self)) self.tagslist_path = settings.get('tagslist_path', tk.StringVar(self)) self.extract_mode = settings.get('extract_mode', tk.StringVar(self)) self.recursive_rename = tk.IntVar(self) self.resizable(1, 0) if title is None: title = self.rename_string.get() if not title: title = "Options" self.title(title) self.original_name = PureWindowsPath(self.rename_string.get()) if self.tag_index_ref is not None: # this ActionsWindow is displaying a single tag. the # original name will have an extension. remove it self.original_name = self.original_name.with_suffix("") self.rename_string.set(str(self.original_name)) self.newtype_string.set("") self.accept_rename.set(0) self.accept_settings.set(0) # frames self.rename_frame = tk.LabelFrame(self, text="Rename to") self.rename_frame_inner0 = tk.Frame(self.rename_frame) self.rename_frame_inner1 = tk.Frame(self.rename_frame) self.tags_list_frame = tk.LabelFrame( self, text="Tags list log(erase to disable logging)") self.extract_to_frame = tk.LabelFrame(self, text="Directory to extract to") self.settings_frame = tk.LabelFrame(self, text="Extract settings") self.button_frame = tk.Frame(self) self.accept_frame = tk.Frame(self.button_frame) self.cancel_frame = tk.Frame(self.button_frame) # rename self.rename_entry = tk.Entry(self.rename_frame_inner0, width=50, textvariable=self.rename_string) self.rename_button = tk.Button(self.rename_frame_inner0, text="Rename", command=self.rename, width=6) self.class_scroll_menu = ScrollMenu(self.rename_frame_inner1, menu_width=35) self.recursive_rename_cbtn = tk.Checkbutton( self.rename_frame_inner1, text="Recursive", variable=self.recursive_rename) if self.tag_index_ref: # populate the class_scroll_menu options opts = sorted([n for n in self.tag_index_ref.class_1.NAME_MAP]) self.class_scroll_menu.set_options(opts) try: self.class_scroll_menu.sel_index = opts.index( self.tag_index_ref.class_1.enum_name) except ValueError: pass # tags list self.tags_list_entry = tk.Entry(self.tags_list_frame, width=50, textvariable=self.tagslist_path) self.browse_tags_list_button = tk.Button(self.tags_list_frame, text="Browse", command=self.tags_list_browse) # extract to dir self.extract_to_entry = tk.Entry(self.extract_to_frame, width=50, textvariable=self.extract_to_dir) self.browse_extract_to_button = tk.Button( self.extract_to_frame, text="Browse", command=self.extract_to_browse) # settings self.recursive_cbtn = tk.Checkbutton(self.settings_frame, text="Recursive extraction", variable=settings.get( "recursive", tk.IntVar(self))) self.overwrite_cbtn = tk.Checkbutton( self.settings_frame, text="Overwrite tags(not recommended)", variable=settings.get("overwrite", tk.IntVar(self))) self.do_printout_cbtn = tk.Checkbutton( self.settings_frame, text="Print extracted tag names", variable=settings.get("do_printout", tk.IntVar(self))) # zatarita added do_propegate_settings to place the check box in frame, and link value to variable self.do_propegate_settings = tk.Checkbutton( self.settings_frame, text="Use these settings for each item", variable=settings.get("propagate_settings", tk.IntVar(self))) # accept/cancel self.accept_button = tk.Button(self.accept_frame, text="Add to queue", command=self.add_to_queue, width=14) self.cancel_button = tk.Button(self.cancel_frame, text="Cancel", command=self.destroy, width=14) self.show_meta_button = tk.Button(self, text="Display metadata", command=self.show_meta) # pack everything # frames if self.renamable: self.rename_frame.pack(padx=4, pady=2, expand=True, fill="x") self.rename_frame_inner0.pack(expand=True, fill="x") self.rename_frame_inner1.pack(expand=True, fill="x") self.tags_list_frame.pack(padx=4, pady=2, expand=True, fill="x") self.extract_to_frame.pack(padx=4, pady=2, expand=True, fill="x") self.settings_frame.pack(padx=4, pady=2, expand=True, fill="x") self.button_frame.pack(pady=2, expand=True, fill="x") self.accept_frame.pack(padx=4, side='left', fill='x', expand=True) self.cancel_frame.pack(padx=4, side='right', fill='x', expand=True) # rename self.rename_entry.pack(padx=4, side='left', fill='x', expand=True) self.rename_button.pack(padx=4, side='left', fill='x') if self.tag_index_ref: self.class_scroll_menu.pack(padx=4, side='left', fill='x') #self.recursive_rename_cbtn.pack(padx=4, side='left', fill='x') # extract to self.extract_to_entry.pack(padx=4, side='left', fill='x', expand=True) self.browse_extract_to_button.pack(padx=4, side='left', fill='x') # tags list self.tags_list_entry.pack(padx=4, side='left', fill='x', expand=True) self.browse_tags_list_button.pack(padx=4, side='left', fill='x') # settings # zatarita, added propagatable check box to top of settings frame. (if enabled) if self.propagatable: self.do_propegate_settings.pack(padx=4, anchor='w') self.recursive_cbtn.pack(padx=4, anchor='w') self.overwrite_cbtn.pack(padx=4, anchor='w') self.do_printout_cbtn.pack(padx=4, anchor='w') # accept/cancel self.accept_button.pack(side='right') self.cancel_button.pack(side='left') if self.tag_index_ref is not None: self.show_meta_button.pack(padx=4, pady=4, expand=True, fill='x') # make the window not show up on the start bar self.transient(self.master) self.wait_visibility() self.lift() self.grab_set() self.apply_style() try: self.update() self.app_root.place_window_relative(self) # I would use focus_set, but it doesn't seem to always work self.accept_button.focus_force() except AttributeError: pass def apply_style(self, seen=None): BinillaWidget.apply_style(self, seen) self.update() w, h = self.winfo_reqwidth(), self.winfo_reqheight() self.geometry("%sx%s" % (w, h)) self.minsize(width=w, height=h) def add_to_queue(self, e=None): self.accept_settings.set(1) self.destroy() def rename(self, e=None): if not self.renamable: return new_name = self.rename_string.get() new_name = str(PureWindowsPath(new_name)).lower().strip(".") if self.tag_index_ref is None and new_name: # directory of tags new_name += "\\" old_class = new_class = None try: old_class = self.tag_index_ref.class_1.enum_name except Exception: pass try: new_class = self.class_scroll_menu.get_option() except Exception: new_class = "" #new_name = os.path.splitext(new_name)[0] self.rename_string.set(new_name) str_len = len(new_name) if str_len > MAX_TAG_NAME_LEN: messagebox.showerror( "Max name length exceeded", ("The max length for a tag is limited to %s characters\n" + "Remove %s characters(excluding extension).") % (MAX_TAG_NAME_LEN, str_len - MAX_TAG_NAME_LEN), parent=self) return elif is_protected_tag(new_name): messagebox.showerror("Invalid name", "The entered string is not a valid filename.", parent=self) return elif not str_len and self.tag_index_ref is not None: messagebox.showerror("Invalid name", "The entered string cannot be empty.", parent=self) return self.accept_rename.set(1) # change the type if applicable if new_class and new_class != old_class: self.newtype_string.set(new_class) self.destroy() def tags_list_browse(self): try: init_dir = os.path.dirname(self.tagslist_path.get()) except Exception: init_dir = None dirpath = asksaveasfilename( initialdir=init_dir, parent=self, title="Select where to save the tag list log", filetypes=(("text log", "*.txt"), ("All", "*"))) if not dirpath: return self.tagslist_path.set(str(Path(dirpath))) def extract_to_browse(self): dirpath = askdirectory(initialdir=self.extract_to_dir.get(), parent=self, title="Select the directory to extract tags to") if not dirpath: return self.extract_to_dir.set(str(Path(dirpath))) def show_meta(self): index_ref = self.tag_index_ref if not index_ref: return try: halo_map = self.settings.get("halo_map") if halo_map is None: print("Could not get map.") return disable_safe_mode = getattr(self.app_root, "disable_safe_mode") disable_tag_cleaning = getattr(self.app_root, "disable_tag_cleaning") meta = halo_map.get_meta( index_ref.id & 0xFFff, True, allow_corrupt=self.settings["allow_corrupt"].get(), disable_safe_mode=disable_safe_mode, disable_tag_cleaning=disable_tag_cleaning) if meta is None: print("Could not get meta.") return meta_tag = meta_tag_def.build() meta_tag.data.tagdata = meta tag_path = index_ref.path meta_tag.filepath = tag_path if index_ref.class_1.enum_name not in BAD_CLASSES: ext = ".%s" % index_ref.class_1.enum_name else: ext = ".INVALID" w = MetaWindow(self.app_root, meta_tag, engine=halo_map.engine, tag_path=tag_path + ext) self.destroy() w.focus_set() except Exception: print(format_exc()) return