def _create_blender_textures_from_mod(mod, base_dir): textures = [None] # materials refer to textures in index-1 # TODO: check why in Arc.header.file_entries[n].file_path it returns a bytes, and # here the whole array of chars for i, texture_path in enumerate(mod.textures_array): path = texture_path[:].decode('ascii').partition('\x00')[0] folder = ntpath.dirname(path) path = os.path.join(base_dir, *path.split(ntpath.sep)) path = '.'.join((path, 'tex')) if not os.path.isfile(path): # TODO: log warnings, figure out 'rtex' format continue tex = Tex112(path) try: dds = tex.to_dds() except TextureError as err: # TODO: log this instead of printing it print('Error converting "{}"to dds: {}'.format(path, err)) textures.append(None) continue dds_path = path.replace('.tex', '.dds') with open(dds_path, 'wb') as w: w.write(dds) image = bpy.data.images.load(dds_path) texture = bpy.data.textures.new(os.path.basename(path), type='IMAGE') texture.image = image textures.append(texture) # saving meta data for export texture.albam_imported_texture_folder = folder texture.albam_imported_texture_value_1 = tex.unk_float_1 texture.albam_imported_texture_value_2 = tex.unk_float_2 texture.albam_imported_texture_value_3 = tex.unk_float_3 texture.albam_imported_texture_value_4 = tex.unk_float_4 return textures
def test_tex_calculate_mipmap_count(tex_file): tex = Tex112(file_path=tex_file) mipmap_count_from_file = tex.mipmap_count mipmap_calculated = DDS.calculate_mipmap_count(tex.width, tex.height) # There might be cases where tex don't have mipmaps? assert mipmap_count_from_file == mipmap_calculated
def test_tex_from_dds(dds_path_1, tmpdir): tex_1 = Tex112.from_dds(file_path=dds_path_1) tex_1_name = os.path.basename(dds_path_1).replace('.dds', '.tex') tex_1_path = os.path.join(str(tmpdir), tex_1_name) with open(tex_1_path, 'wb') as w: w.write(tex_1) tex_2 = Tex112(file_path=tex_1_path) tex_2_name = tex_1_name.replace('.tex', '1.tex') tex_2_path = os.path.join(str(tmpdir), tex_2_name) with open(tex_2_path, 'wb') as w2: w2.write(tex_2) with open(tex_1_path, 'rb') as w, open(tex_2_path, 'rb') as w2: c1 = w.read() c2 = w2.read() assert sha1(c1).hexdigest() == sha1(c2).hexdigest()
def test_tex_112(tex_file, tmpdir): tex = Tex112(file_path=tex_file) out = os.path.join(str(tmpdir), 'test.tex') with open(out, 'wb') as w: w.write(tex) with open(tex_file, 'rb') as f, open(out, 'rb') as f2: s1 = sha1(f.read()).hexdigest() s2 = sha1(f2.read()).hexdigest() assert s1 == s2 assert os.path.getsize(out) == os.path.getsize(tex_file)
def test_tex112_to_dds(tmpdir, tex_file): tex = Tex112(file_path=tex_file) dds = tex.to_dds() tex_name = os.path.basename(tex_file) dds_name = tex_name.replace('.tex', '.dds') out = os.path.join(str(tmpdir), dds_name) with open(out, 'wb') as w: w.write(dds) assert dds.header.id_magic == b'DDS ' assert os.path.getsize(out) == sizeof(DDSHeader) + len(tex.dds_data)
def test_tex112_calculate_mipmap_offsets(tex_file): tex = Tex112(file_path=tex_file) offsets_from_file = list(tex.mipmap_offsets) w = tex.width h = tex.height mc = tex.mipmap_count fmt = tex.compression_format fixed_size_of_header = 40 # mmm... start_offset = fixed_size_of_header + (mc * 4) calculated_offsets = tex.calculate_mipmap_offsets(mc, w, h, fmt, start_offset) assert offsets_from_file == calculated_offsets
def export_arc(blender_object): '''Exports an arc file containing mod and tex files, among others from a previously imported arc.''' mods = {} try: saved_arc = Arc( file_path=BytesIO(blender_object.albam_imported_item.data)) except AttributeError: raise ExportError( 'Object {0} did not come from the original arc'.format( blender_object.name)) for child in blender_object.children: try: basename = posixpath.basename(child.name) folder = child.albam_imported_item.folder if os.sep == ntpath.sep: # Windows mod_filepath = ntpath.join(ensure_ntpath(folder), basename) else: mod_filepath = os.path.join(folder, basename) except AttributeError: raise ExportError( 'Object {0} did not come from the original arc'.format( child.name)) assert child.albam_imported_item.file_type == 'mtframework.mod' mod, textures = export_mod156(child) mods[mod_filepath] = (mod, textures) with tempfile.TemporaryDirectory() as tmpdir: tmpdir_slash_ending = tmpdir + os.sep if not tmpdir.endswith( os.sep) else tmpdir saved_arc.unpack(tmpdir) mod_files = [ os.path.join(root, f) for root, _, files in os.walk(tmpdir) for f in files if f.endswith('.mod') ] # tex_files = {os.path.join(root, f) for root, _, files in os.walk(tmpdir) # for f in files if f.endswith('.tex')} new_tex_files = set() for modf in mod_files: rel_path = modf.split(tmpdir_slash_ending)[1] try: new_mod = mods[rel_path] except KeyError: raise ExportError( "Can't export to arc, a mod file is missing: {}".format( rel_path)) with open(modf, 'wb') as w: w.write(new_mod[0]) mod_textures = new_mod[1] for texture in mod_textures: tex = Tex112.from_dds( file_path=bpy.path.abspath(texture.image.filepath)) try: tex.unk_float_1 = texture.albam_imported_texture_value_1 tex.unk_float_2 = texture.albam_imported_texture_value_2 tex.unk_float_3 = texture.albam_imported_texture_value_3 tex.unk_float_4 = texture.albam_imported_texture_value_4 except AttributeError: pass tex_name = os.path.basename(texture.image.filepath) tex_filepath = os.path.join(os.path.dirname(modf), tex_name.replace('.dds', '.tex')) new_tex_files.add(tex_filepath) with open(tex_filepath, 'wb') as w: w.write(tex) # probably other files can reference textures besides mod, this is in case # textures applied have other names. # TODO: delete only textures referenced from saved_mods at import time # unused_tex_files = tex_files - new_tex_files # for utex in unused_tex_files: # os.unlink(utex) new_arc = Arc.from_dir(tmpdir) return new_arc
def export_arc(blender_object): '''Exports an arc file containing mod and tex files, among others from a previously imported arc.''' mods = {} try: saved_arc = Arc(file_path=BytesIO(blender_object.albam_imported_item.data)) except AttributeError: raise ExportError('Object {0} did not come from the original arc'.format(blender_object.name)) for child in blender_object.children: try: basename = posixpath.basename(child.name) folder = child.albam_imported_item.folder if os.sep == ntpath.sep: # Windows mod_filepath = ntpath.join(ensure_ntpath(folder), basename) else: mod_filepath = os.path.join(folder, basename) except AttributeError: raise ExportError('Object {0} did not come from the original arc'.format(child.name)) assert child.albam_imported_item.file_type == 'mtframework.mod' mod, textures = export_mod156(child) mods[mod_filepath] = (mod, textures) with tempfile.TemporaryDirectory() as tmpdir: tmpdir_slash_ending = tmpdir + os.sep if not tmpdir.endswith(os.sep) else tmpdir saved_arc.unpack(tmpdir) mod_files = [os.path.join(root, f) for root, _, files in os.walk(tmpdir) for f in files if f.endswith('.mod')] # tex_files = {os.path.join(root, f) for root, _, files in os.walk(tmpdir) # for f in files if f.endswith('.tex')} new_tex_files = set() for modf in mod_files: rel_path = modf.split(tmpdir_slash_ending)[1] try: new_mod = mods[rel_path] except KeyError: raise ExportError("Can't export to arc, a mod file is missing: {}".format(rel_path)) with open(modf, 'wb') as w: w.write(new_mod[0]) mod_textures = new_mod[1] for texture in mod_textures: tex = Tex112.from_dds(file_path=bpy.path.abspath(texture.image.filepath)) try: tex.unk_float_1 = texture.albam_imported_texture_value_1 tex.unk_float_2 = texture.albam_imported_texture_value_2 tex.unk_float_3 = texture.albam_imported_texture_value_3 tex.unk_float_4 = texture.albam_imported_texture_value_4 except AttributeError: pass tex_name = os.path.basename(texture.image.filepath) tex_filepath = os.path.join(os.path.dirname(modf), tex_name.replace('.dds', '.tex')) new_tex_files.add(tex_filepath) with open(tex_filepath, 'wb') as w: w.write(tex) # probably other files can reference textures besides mod, this is in case # textures applied have other names. # TODO: delete only textures referenced from saved_mods at import time # unused_tex_files = tex_files - new_tex_files # for utex in unused_tex_files: # os.unlink(utex) new_arc = Arc.from_dir(tmpdir) return new_arc