import bpy from os import path import os from dataclasses import dataclass import shutil @dataclass class OBJMetadata: materials: list[str] objects: list[str] D = bpy.data C = bpy.context def select_one_object(obj): bpy.ops.object.select_all(action='DESELECT') bpy.context.view_layer.objects.active = obj # type: ignore obj.select_set(True) def iter_buttons(): object_names = D.objects.keys() assert object_names for name in object_names: print(name) if name.startswith("Buttons "): yield D.objects[name] def extract_metadata(obj_path): mtl_filename = None objects = [] with open(obj_path, "r") as f: for line in f.readlines(): if line.startswith("mtllib"): mtl_filename = line.removeprefix("mtllib ") elif line.startswith("o"): object_name = line.strip().removeprefix("o ") objects.append(object_name) materials = [] if mtl_filename: mtl_path = path.join(path.dirname(obj_path), mtl_filename).strip() with open(mtl_path, "r") as f: for line in f.readlines(): if not line.startswith("newmtl"): continue material_name = line.strip().removeprefix("newmtl ") materials.append(material_name) return OBJMetadata(materials, objects) def write_list_to_file(filename, values): with open(filename, "w") as f: for i in range(len(values)): if i > 0: f.write("\n") f.writelines(values[i]) export_options = { "use_triangles": True, "use_materials": True, "use_normals": True, "use_vertex_groups": True, "path_mode": "RELATIVE", } bpy.ops.object.select_all(action="SELECT") for btn in iter_buttons(): btn.select_set(False) bpy.ops.export_scene.obj( filepath="emulator.obj", use_selection=True, **export_options ) metadata = extract_metadata("emulator.obj") write_list_to_file("emulator.mtls.txt", metadata.materials) write_list_to_file("emulator.objs.txt", metadata.objects) object_names = D.objects.keys() assert object_names for name in object_names: if name.startswith("Buttons "): button_name = name.removeprefix("Buttons ") button_obj_path = f"buttons/Button {button_name}.obj" button_mtl_path = f"buttons/Button {button_name}.mtl" select_one_object(D.objects[name]) bpy.ops.export_scene.obj( filepath=button_obj_path, use_selection=True, **export_options ) tmp_file = "/tmp/blender_export" with open(button_obj_path, "r") as src: with open(tmp_file, "w") as dst: for line in src.readlines(): if line.startswith("mtllib"): dst.write("mtllib Button.mtl\n") else: dst.write(line) os.remove(button_obj_path) shutil.move(tmp_file, button_obj_path) if button_name == "0": os.rename("buttons/Button 0.mtl", "buttons/Button.mtl") else: os.remove(button_mtl_path)