def rename(self): node = self.get_indexed_item(self.clicked_index) if self.level == 0: self.handler.save_as_dialog() elif self.level == 1: brres = node.parent old_name = node.name text, ok = QInputDialog.getText(self, 'Rename Node', 'Rename to:', text=old_name) if ok and text != old_name: if brres.getModel(text): AutoFix.get().error( 'Model with name {} already exists!'.format(text)) return node.rename(text) self.handler.on_rename_update(node, old_name) elif self.level == 2: mdl0 = node.parent text, ok = QInputDialog.getText(self, 'Rename Node', 'Rename to:', text=node.name) if ok: if text in [x.name for x in mdl0.objects]: AutoFix.get().error( 'Polygon with name {} already exists!'.format(text)) return node.rename(text)
def __init__(self, filename, read_file=True): self.geometries = [] self.vertices = [] self.normals = [] self.texcoords = [] self.materials = {} self.images = set() self.filename = filename if read_file: self.mtllib = None self.parse_file(filename) to_remove = [] for geo in self.geometries: try: geo.normalize(self.vertices, self.normals, self.texcoords) except ValueError: to_remove.append(geo) AutoFix.get().warn('No geometry found for {}'.format( geo.name)) if to_remove: self.geometries = [ x for x in self.geometries if x not in to_remove ] else: dir, name = os.path.split(filename) base_name = os.path.splitext(name)[0] self.mtllib = base_name + '.mtl'
def add_texture_link(self, name): if name != 'Null' and not self.parent.getTexture(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.get().info(notify, 4)
def remove_tex0(self, name): try: tex = self.texture_map.pop(name) self.textures.remove(tex) self.mark_modified() except KeyError: AutoFix.get().warn('No texture {} in {}'.format(name, self.name))
def info(self, key=None, indentation_level=0): trace = '>' + ' ' * indentation_level if indentation_level else '>' + str(self.parent.getMaterialName()) if key: AutoFix.get().info('{}->Stage:{}\t{}:{}'.format(trace, self.name, key, self[key]), 1) else: AutoFix.get().info('{}Stage:{}\tMapId:{} ColorScale:{}'.format( trace, self.name, self['mapid'], self['colorscale']), 1)
def run(self, prefix, cmd): line = prefix + ' ' + cmd self.cmd_queue.append(line) try: Command.run_commands([Command(line)]) except (ParsingException, NoSuchFile) as e: AutoFix.get().exception(e)
def __encode_vertices(self, polygon, vertices, mdl0): vert = Vertex(self.name, mdl0) mdl0.add_to_group(mdl0.vertices, vert) linked_bone = self.linked_bone points = vertices.points if polygon.has_weighted_matrix(): AutoFix.get().warn( f'Polygon weighting is experimental, {polygon.name} will likely be incorrect.' ) for i in range(len(vertices)): influence = self.influences[i] points[i] = influence.apply_to(points[i], decode=False) vertex_format, vertex_divisor, remapper = vertices.encode_data( vert, True) if remapper is not None: new_inf_map = {} old_inf_map = self.influences.influences for i in old_inf_map: new_inf_map[remapper[i]] = old_inf_map[i] self.influences.influences = new_inf_map else: rotation_matrix = get_rotation_matrix( np.array(linked_bone.get_transform_matrix(), dtype=float)) for i in range(len(points)): points[i] = np.dot(rotation_matrix, points[i]) inv_matrix = np.array(linked_bone.get_inv_transform_matrix(), dtype=float) vertices.points = apply_matrix(inv_matrix, vertices.points) vertices.encode_data(vert, False) polygon.vertices = vert self.fmt_str += get_index_format(vert) return True
def info(self, key=None, indentation_level=0): trace = ' ' * indentation_level + '>' + self.name if indentation_level else self.parent.name + "->" + self.name AutoFix.get().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 hook_textures(self, textures): m = len(textures) for x in self.node.frames: if x.tex >= m: x.tex = textures[0] AutoFix.get().warn('Unpacked Pat0 {} tex_id out of range'.format(self.node.name), 1) else: x.tex = textures[x.tex]
def on_submit(self): path = self.path_edit.text() dir = os.path.dirname(path) if not os.path.exists(dir): AutoFix.get().error('Path {} does not exist!'.format(path)) else: ImgConverter().decode(self.tex0, path, overwrite=True, num_mips=self.mipmap_count.value()) AutoFix.get().info('Exported {} to {}'.format(self.tex0.name, path)) self.close()
def try_parse(self, text): try: self.cmds_run.append(text) if len(self.cmds_run) > 10: self.cmds_run.pop(0) return Command.run_commands([Command(text)]) except ParsingException as e: AutoFix.get().error(str(e)) return False
def info(self, key=None, indentation=0): prefix = '>' + ' ' * indentation + self.name if indentation else '>(PAT0)' + self.name if key: AutoFix.get().info('{}: {}'.format(prefix, self.get_str(key)), 1) else: val = prefix + ': ' for x in self.SETTINGS: val += ' ' + x + ':' + str(self.get_str(x)) AutoFix.get().info(val, 1)
def rename(self): if self.material is not None: current_name = self.material.name text, ok = QInputDialog.getText(self, 'Rename Node', 'Rename to:', text=current_name) if ok and text != current_name: if self.material.parent.get_material_by_name(text) is not None: AutoFix.get().error('Material with name {} already exists!'.format(text)) return self.material.rename(text)
def run_commands(commandlist): try: for cmd in commandlist: cmd.run_cmd() except (ValueError, SaveError, PasteError, MaxFileLimit, NoSuchFile, FileNotFoundError, ParsingException, OSError, UnpackingError, PackingError, NotImplementedError, NoImgConverterError, RuntimeError) as e: AutoFix.get().exception(e) return False return True
def _create_image_library(self, tex0s): if not tex0s: return True converter = ImgConverter() if not converter: AutoFix.get().error('No image converter found!') return False converter.batch_decode(tex0s, self.image_dir) return True
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.getTexture(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.get().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.get().info('{}{}> {}'.format(start, self.name, key), 1)
def save_as_dialog(self): if self.brres: fname, filter = QFileDialog.getSaveFileName( self, 'Save as', self.cwd, 'Brres files (*.brres)') if fname: self.cwd = os.path.dirname(fname) self.brres.save(fname, overwrite=True) self.update_status('Wrote file {}'.format(fname)) else: AutoFix.get().error('No Brres file selected.')
def unpack_frames(self, pat0, binfile): # frame header size, _, scale_factor = binfile.read('2Hf', 8) frames = pat0.frames for i in range(size): frame_id, tex_id, plt_id = binfile.read('f2H', 8) if frame_id > pat0.framecount: AutoFix.get().warn('Unpacked Pat0 {} frame index out of range'.format(pat0.name), 1) break frames.append(pat0.Frame(frame_id, tex_id, plt_id))
def _try_import_textures(brres, image_paths): if len(image_paths): try: converter = ImgConverter() converter.batch_encode(image_paths.values(), brres, overwrite=converter.OVERWRITE_IMAGES) except EncodeError: AutoFix.get().warn('Failed to encode images') return image_paths
def _end_loading(self): mdl0 = self.mdl0 mdl0.rebuild_header() self.brres.add_mdl0(mdl0) if self.is_map: mdl0.add_map_bones() os.chdir(self.cwd) AutoFix.get().info('\t... finished in {} secs'.format( round(time.time() - self.start, 2))) return mdl0
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.get().info("{}\t{}:{}".format(trace, key, val), 1) else: AutoFix.get().info( "{}:\tScale:{} Rot:{} Trans:{}".format(trace, self.scale, self.rotation, self.translation), 1)
def enqueue(self, converter): if converter == self.item: AutoFix.get().error('Conversion already in progress!') return False for x in self.queue: if x == converter: AutoFix.get().error('Conversion already in progress!') return False self.queue.append(converter) return True
def set_convert(self, params): flags = 0 self.name = self.destination = self.model = None while len(params): param = params.pop(0) lower = param.lower() if lower == 'to': try: self.destination = os.path.normpath(params.pop(0)) except IndexError: raise ParsingException('Expected destination after "to"') elif lower == 'in': self.model = self.name try: self.name = os.path.normpath(params.pop(0)) except IndexError: raise ParsingException('Expected brres filename after keyword "in"') elif lower == 'no-normals': flags |= 1 elif lower == 'no-colors': flags |= 2 elif not self.name: self.name = os.path.normpath(param) else: raise ParsingException('Unknown parameter {}'.format(param)) self.ext = None supported_formats = ('.dae', '.obj') self.is_import = False if self.name: dir, filename = os.path.split(self.name) base_name, ext = os.path.splitext(filename) ext = ext.lower() if ext in supported_formats: self.is_import = True self.ext = ext if self.destination and self.is_import: dir, filename = os.path.split(self.destination) split = os.path.splitext(filename) try: ext = split[1] except IndexError: ext = None if ext is None or ext.lower() != '.brres': if ext: AutoFix.get().warn('Unsupported target extension {}, using .brres'.format(ext)) self.destination += '.brres' if not self.is_import: if not self.destination: raise ParsingException('Convert requires target!') dir, filename = os.path.split(self.destination) base_name, ext = os.path.splitext(filename) self.ext = ext.lower() if self.ext not in supported_formats: raise ParsingException('Unsupported export format {}'.format(self.ext)) self.flags = flags
def on_brres_update(self): self.materials = {} self.brres.register_observer(self) for model in self.brres.models: model.register_observer(self) for material in model.materials: material.register_observer(self) if material.name not in self.materials: self.materials[material.name] = material else: AutoFix.get().warn('Multiple materials named {} in material library'.format(material.name))
def get_index_type(self, index): """ Returns the INDEX_FORMAT """ if index < 0: return INDEX_FORMAT_NONE else: try: return INDEX_FORMAT_BYTE if self.encode_str[index + 1] == 'B' else INDEX_FORMAT_SHORT except IndexError: AutoFix.get().error(f'Polygon {self.name} in {self.parent.parent.name} tri index {index} out of range.')
def run_cmd(self): if self.hasSelection: if not self.updateSelection(self.file, self.model, self.name): AutoFix.get().warn('No selection found for "{}"'.format(self.txt)) return False elif self.cmd == 'select': return True elif not self.MATERIALS and self.cmd == 'info': if self.key == 'keys': ctype = self.type if self.type else self.SELECT_TYPE self.info_keys(ctype) return True # self.file = self.model = self.name = None # self.updateSelection(None) # reset selection if self.cmd == 'preset': return self.runPreset(self.key) elif self.cmd == 'convert': return self.run_convert() if not self.ACTIVE_FILES: raise RuntimeError('No file detected! ({})'.format(self.txt)) if self.cmd == 'save': self.run_save() return True self.updateTypeSelection() if not self.SELECTED: if self.cmd == 'info': AutoFix.get().info('No items in selection.') return True raise RuntimeError('No items found in selection! ({})'.format(self.txt)) if self.cmd == 'set': self.markModified() for x in self.SELECTED: x.set_str(self.key, self.value) elif self.cmd == 'info': if self.key == 'keys': self.info_keys(self.SELECT_TYPE) else: for x in self.SELECTED: x.info(self.key) # for y in self.ACTIVE_FILES: # print(y.name) elif self.cmd == 'add': self.markModified() self.add(self.SELECT_TYPE, self.SELECT_ID) elif self.cmd == 'remove': self.markModified() self.remove(self.SELECT_TYPE, self.SELECT_ID) elif self.cmd == 'copy': self.run_copy(self.SELECT_TYPE) elif self.cmd == 'paste': self.markModified() self.run_paste(self.SELECT_TYPE) return True
def run(self): try: AutoFix.get().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.get().exception(shutdown=True)
def info(self, key=None, indentation_level=0): AutoFix.get().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 info(self, key=None, indentation_level=0): trace = '>' + ' ' * indentation_level if indentation_level else '>' if not key: AutoFix.get().info( '{}(Shader){}'.format(trace, self.getMaterialName()), 1) indentation_level += 1 for x in self.stages: x.info(key, indentation_level) else: AutoFix.get().info( '{}(Shader){}: {}:{} '.format(trace, self.getMaterialName(), key, self[key]), 1)