def _start_saving(self, mdl0): AutoFix.info('Exporting {} to {}...'.format( os.path.basename(self.brres.name), self.mdl_file)) self.start = time.time() self.image_library = set() if mdl0 is None: mdl0 = self.mdl0 if mdl0 is None: self.mdl0 = mdl0 = self.brres.models[0] else: self.mdl0 = mdl0 if type(mdl0) == str: self.mdl0 = mdl0 = self.brres.get_model(mdl0) if mdl0 is None: raise RuntimeError('No mdl0 file found to export!') self.polygons = [ x for x in mdl0.objects if self._should_include_geometry(x) ] mats = [] for x in self.polygons: if x.material not in mats: mats.append(x.material) self.materials = mats self.cwd = os.getcwd() work_dir, name = os.path.split(self.mdl_file) if work_dir: os.chdir(work_dir) base_name, ext = os.path.splitext(name) self.image_dir = base_name + '_maps' self.json_file = base_name + '.json' self.influences = mdl0.get_influences() self.bones = {} self.tex0_map = {} return base_name, mdl0
def add_texture_link(self, name): if name != 'Null' and not self.parent.get_texture(name): tex = fuzzy_match(name, self.parent.textures) notify = 'Adding reference to unknown texture "{}"'.format(name) if tex: notify += ', did you mean ' + tex.name + '?' AutoFix.info(notify, 4)
def info(self, key=None, indentation_level=0): trace = ' ' * indentation_level + '>' + self.name if indentation_level else self.parent.name + "->" + self.name AutoFix.info("{}:\t{} material(s)".format(trace, len(self.materials)), 1) indentation_level += 1 # pass it along for x in self.materials: x.info(key, indentation_level)
def info(self, key=None, indentation=0): prefix = '>' + ' ' * indentation + self.name if indentation else '>(PAT0)' + self.name if key: AutoFix.info('{}: {}'.format(prefix, self.get_str(key)), 1) else: val = prefix + ': ' for x in self.SETTINGS: val += ' ' + x + ':' + str(self.get_str(x)) AutoFix.info(val, 1)
def encode(self, mdl, visible_bone=None, encoder=None, use_default_colors_if_none_found=True, priority=None, has_uv_mtx=None): if priority is not None: self.priority = priority if has_uv_mtx is not None: self.has_uv_mtx = has_uv_mtx if not visible_bone: if not mdl.bones: mdl.add_bone(mdl.name) visible_bone = mdl.bones[0] # if not linked_bone: # self.linked_bone = visible_bone visible_bone.has_geometry = True self.encoded = p = Polygon(self.name, mdl) if encoder is not None: self.encoder = encoder encoder.before_encode(self) self.fmt_str = '>' if self.__encode_influences(p, self.influences, mdl, visible_bone): p.weight_index = self.ipp() self.__encode_tex_matrices(p, self.has_uv_mtx) if self.__encode_vertices(p, self.vertices, mdl): p.vertex_index = self.ipp() if self.__encode_normals(p, self.normals, mdl): p.normal_index = self.ipp() if self.__encode_colors(p, self.colors, mdl, use_default_colors_if_none_found): p.color0_index = self.ipp() self.__encode_texcoords(p, self.texcoords, mdl) tris = self.__construct_tris(p, p.has_weights()) data, p.face_count, p.facepoint_count = self.__encode_tris( tris, p.has_weights()) past_align = len(data) % 0x20 if past_align: data.extend(b'\0' * (0x20 - past_align)) if p.face_count <= 0: # todo, cleanup? return None p.data = data p.encode_str = self.fmt_str mdl.objects.append(p) material = mdl.get_material_by_name(self.material_name) mdl.add_definition(material, p, visible_bone, self.priority) if self.colors and self.ENABLE_VERTEX_COLORS: AutoFix.info( '{} has colors, enabled vertex color in light channel.'.format( self.name)) material.enable_vertex_color() if encoder: encoder.after_encode(p) return p
def info(self, key=None, indentation_level=0): trace = ' ' * indentation_level + self.name if indentation_level else '>' + self.parent.name + "->" + self.name if key: val = self.get_str(key) AutoFix.info("{}\t{}:{}".format(trace, key, val), 1) else: AutoFix.info( "{}:\tScale:{} Rot:{} Trans:{}".format(trace, self.scale, self.rotation, self.translation), 1)
def _end_saving(self, writer): # dump json materials, create image library, write file MatsToJsonConverter(self.json_file).export(self.mdl0.materials) self.__add_pat0_images() self._create_image_library(self.tex0_map.values()) os.chdir(self.cwd) writer.write(self.mdl_file) AutoFix.info('\t...finished in {} seconds.'.format( round(time.time() - self.start, 2))) return self.mdl_file
def rename_texture_link(self, layer, name): """Attempts to rename a layer, raises value error if the texture can't be found""" # No link found, try to find texture matching and create link if name != 'Null' and not self.parent.get_texture(name): tex = fuzzy_match(name, self.parent.textures) notify = 'Adding reference to unknown texture "{}"'.format(name) if tex: notify += ', did you mean ' + tex.name + '?' AutoFix.info(notify, 4) return name
def info(self, key='', indentation_level=0): if not key: m = max(3, len(self.SETTINGS)) for i in range(m): setting = self.SETTINGS[i] key += setting + ':' + self.get_str(setting) + ' ' else: key += ':' + self.get_str(key) start = '>' + indentation_level * ' ' AutoFix.info('{}{}> {}'.format(start, self.name, key), 1)
def info(self, key=None, indentation_level=0): trace = '>' + ' ' * indentation_level if indentation_level else '>' + str( self.parent.get_material_name()) if key: AutoFix.info( '{}->Stage:{}\t{}:{}'.format(trace, self.name, key, self[key]), 1) else: AutoFix.info( '{}Stage:{}\tMapId:{} ColorScale:{}'.format( trace, self.name, self['mapid'], self['colorscale']), 1)
def info(self, key=None, indentation_level=0): trace = '>' + ' ' * indentation_level if indentation_level else '>' if not key: AutoFix.info( '{}(Shader){}'.format(trace, self.get_material_name()), 1) indentation_level += 1 for x in self.stages: x.info(key, indentation_level) else: AutoFix.info( '{}(Shader){}: {}:{} '.format(trace, self.get_material_name(), key, self[key]), 1)
def on_submit(self): path = self.path_edit.text() dir = os.path.dirname(path) if not os.path.exists(dir): AutoFix.error('Path {} does not exist!'.format(path)) else: ImgConverter().decode(self.tex0, path, overwrite=True, num_mips=self.mipmap_count.value()) AutoFix.info('Exported {} to {}'.format(self.tex0.name, path)) self.close()
def run(self): try: AutoFix.info('Started image manager...', 5) self.__clean() while self.enabled: if len(self.queue): self.__decode_brres_images(self.queue.pop(0)) else: self.is_ready = True sleep(0.3) except: AutoFix.exception(shutdown=True)
def info(self, key=None, indentation_level=0): id = str(self.name) trace = '>' + ' ' * indentation_level + 'Tex:' + id if indentation_level else '>(SRT0)' \ + self.parent.name + '->Tex:' + id if not key: for x in self.SETTINGS: anim = self.get_str(x) if len(anim) > 1: trace += ' ' + x + ':' + str(anim) AutoFix.info(trace, 1) else: AutoFix.info('{}\t{}:{}'.format(trace, key, self.get_str(key)), 1)
def check(self, verts, norms, uvs, colors, materials ): # as we go along, gather verts norms uvs colors materials modified = False vertices = self.get_vertex_group() if vertices: verts.add(vertices.name) if self.linked_bone: vertices.check_vertices(self.linked_bone) normals = self.get_normal_group() if normals: norms.add(normals.name) material = self.get_material() if material: materials.add(material.name) # Colors my_colors = self.get_color_group() uses_vertex_colors = material.is_vertex_color_enabled() if my_colors: colors.add(my_colors.name) if not uses_vertex_colors: AutoFix.info(f'{self.name} has unused vertex colors', 4) elif uses_vertex_colors: b = Bug( 2, 2, f'{material.name} uses vertex colors but {self.name} has no colors!', 'Disable vertex colors') material.enable_vertex_color(False) b.resolve() modified = True # UVs uvs_used = material.get_uv_channels() uv_count = 0 for i in range(8): tex = self.get_uv_group(i) if tex: uv_count += 1 uvs.add(tex.name) if i in uvs_used: uvs_used.remove(i) else: AutoFix.info( f'{self.name} UV Channel {i} is not used by material.', 3) else: break if uvs_used: AutoFix.warn( f'{self.name} does not have UV channel(s) {uvs_used} but the material uses them!' ) self.uv_count = uv_count return modified
def __init__(self, path): if self.LIBRARY is not None: raise RuntimeError('Already Initialized library!') if path is None: path = os.path.join(os.getcwd(), 'mat_lib.brres') self.LIBRARY_PATH = path try: self.brres = Brres(path) except FileNotFoundError as e: AutoFix.info(f'Material library "{path}" not found.') self.brres = Brres(path, read_file=False) self.brres.add_mdl0(Mdl0('lib', self.brres)) self.on_brres_update()
def info(self, key=None, indentation_level=0): AutoFix.info( '{}{}:\t{} model(s)\t{} texture(s)'.format( ' ' * indentation_level + '>', self.name, len(self.models), len(self.textures)), 1) indentation_level += 2 self.sub_info('MDL0', self.models, key, indentation_level) self.sub_info('TEX0', self.textures, key, indentation_level) # self.sub_info('PAT0', self.pat0, key, indentation_level) # self.sub_info('SRT0', self.srt0, key, indentation_level) self.sub_info('CHR0', self.chr0, key, indentation_level) self.sub_info('SCN0', self.scn0, key, indentation_level) self.sub_info('SHP0', self.shp0, key, indentation_level) self.sub_info('CLR0', self.clr0, key, indentation_level)
def add_tex0(self, tex0, replace=True, mark_modified=True): if tex0.name in self.texture_map: if not replace: return False self.remove_tex0(tex0.name) AutoFix.info('Replaced tex0 {}'.format(tex0.name)) if tex0.parent is not None and tex0.parent is not self: t = Tex0(tex0.name, self) t.paste(tex0) tex0 = t self.textures.append(tex0) self.texture_map[tex0.name] = tex0 tex0.parent = self # this may be redundant if mark_modified: self.mark_modified() return True
def run(self): AutoFix.info('Started converter... ', 5) try: while True: if len(self.queue): self.item = self.queue.pop(0) self.item.convert() self.signals.on_conversion_finish.emit(self.item) self.item = None # for x in self.observers: # x.on_conversion_finish(self.item) if not self.is_running: break sleep(0.2) except: AutoFix.exception(shutdown=True)
def __init__(self, brres_files=[]): super().__init__() self.open_files = [] self.brres = None self.image_updater = {} # maps brres to list of subscribers self.cwd = os.getcwd() self.__init_threads() self.locked_files = set( ) # lock files that are pending conversion etc... # AutoFix.set_pipe(self) self.__init_UI() self.shell_is_shown = False self.shell = None for file in brres_files: self.open(file.name) AutoFix.info('Initialized main window', 5) self.show()
def save(self, filename=None, overwrite=None, check=True): if not filename: filename = self.name if overwrite is None: overwrite = self.OVERWRITE if not overwrite and os.path.exists(filename): AutoFix.error('File {} already exists!'.format(filename), 1) else: if check: self.check() f = BinFile(filename, mode="w") self.pack(f) if f.commitWrite(): AutoFix.info("Wrote file '{}'".format(filename), 2) self.rename(filename) self.has_new_model = False self.mark_unmodified() return True return False
def info(self, key=None, indentation_level=0): trace = '>' + ' ' * indentation_level + self.name if indentation_level else '>' \ + self.parent.name + "->" + self.name if key in self.SETTINGS: val = self.getKey(key) if val is not None: AutoFix.info("{}\t{}:{}".format(trace, key, val), 1) return elif not key: AutoFix.info( "{}\txlu:{} cull:{}".format(trace, self.xlu, self.CULL_STRINGS[self.cullmode]), 1) indentation_level += 1 for x in self.layers: x.info(key, indentation_level) if self.srt0: self.srt0.info(key, indentation_level) elif self.pat0: self.pat0.info(key, indentation_level)
def __init_threads(self): AutoFix.info('Starting threads...', 5) self.threadpool = QThreadPool() # for multi-threading self.threadpool.setMaxThreadCount(5) self.converter = converter = ConvertManager.get() converter.signals.on_conversion_finish.connect( self.on_conversion_finish) self.image_manager = image_manager = ImageManager.get() if image_manager.enabled: image_manager.signals.on_image_update.connect(self.on_image_update) self.threadpool.start(image_manager) else: AutoFix.warn( 'Image Manager disabled, do you have Wiimms SZS Tools installed?' ) self.threadpool.start(converter) log_pipe = LoggerPipe() log_pipe.info_sig.connect(self.info) log_pipe.warn_sig.connect(self.warn) log_pipe.error_sig.connect(self.error)
def check_group(self, group, used_set, extras=None): """ helper function for check :param group, the group to check :param used_set, set of items with references """ to_remove = [] for x in group: if x.name not in used_set: AutoFix.info('Unused reference {}'.format(x.name), 3) if self.REMOVE_UNUSED_REFS: to_remove.append(x) if extras and x.check(extras): self.mark_modified() elif x.check(): self.mark_modified() if to_remove: AutoFix.info('(FIXED) Removed unused refs') for x in to_remove: group.remove(x)
def perform_analysis(brres): s = '' has_count = 0 if brres.chr0: s += ' has chr0' if brres.shp0: s += ' has shp0' has_count += 1 if brres.clr0: s += ' has clr0' has_count += 1 if brres.unused_pat0: s += ' has unused pat0' if brres.unused_srt0: s += ' has unused srt0' if brres.scn0: s += ' has scn0' has_count += 1 if has_count: AutoFix.info(f'{brres.name} {s}') # AutoFix.info('Analyzing {}'.format(brres.name)) export = False
def check(self): AutoFix.info('checking file {}'.format(self.name), 4) expected = self.get_expected_mdl_name() if self.MOONVIEW: self.check_moonview() Brres.MOONVIEW = False for mdl in self.models: mdl.check(expected) expected = None tex_names = set(self.get_texture_map().keys()) tex_used = self.get_used_textures() unused = tex_names - tex_used if unused: b = Bug(4, 3, 'Unused textures: {}'.format(unused), 'Remove textures') if self.REMOVE_UNUSED_TEXTURES: self.remove_unused_textures(unused) b.resolve() self.mark_modified() all_tex = [x for x in self.textures] for tex in all_tex: tex.check()
def _start_loading(self, model_name): AutoFix.info('Converting {}... '.format(self.mdl_file)) self.start = time.time() self.image_library = set() self.geometries = [] self.cwd = os.getcwd() self.import_textures_map = {} self.mdl_file = os.path.abspath(self.mdl_file) library = MaterialLibrary.get() self.material_library = library.materials if library else None brres_dir, brres_name = os.path.split(self.brres.name) base_name = os.path.splitext(brres_name)[0] mdl_file_base_name = os.path.splitext(os.path.basename( self.mdl_file))[0] self.is_map = True if 'map' in base_name or mdl_file_base_name == 'map_model' else False work_dir, name = os.path.split(self.mdl_file) self.json_file = os.path.join(work_dir, os.path.splitext(name)[0]) + '.json' if work_dir: os.chdir(work_dir) # change to the dir to help find relative paths return self._init_mdl0(brres_name, os.path.splitext(name)[0], model_name)
def _end_loading(self): mdl0 = self.mdl0 import_path_map = self.__normalize_image_path_map( self.import_textures_map) self._import_images(import_path_map) mdl0.rebuild_header() self.brres.add_mdl0(mdl0) if self.is_map: mdl0.add_map_bones() os.chdir(self.cwd) if self.ENCODE_PRESET: if not self.ENCODE_PRESET_ON_NEW or ( self.replacement_model is None and self.json_polygon_encoding is None): Command('preset ' + self.ENCODE_PRESET + ' for * in ' + self.brres.name + ' model ' + self.mdl0.name).run_cmd() AutoFix.info('\t... finished in {} secs'.format( round(time.time() - self.start, 2))) if self.encoder: self.encoder.after_encode(mdl0) return mdl0
def info(self, key=None, indentation=0): AutoFix.info( '{} {}: {} {}x{} mips:{}'.format(self.MAGIC, self.name, self.FORMATS[self.format], self.width, self.height, self.num_mips), 1)