import bpy from bpy.types import Context, Object, Scene, Collection def get_first_collection_sharing_scene(scene: Scene, obj: Object): def collection_in_scene(collection: Collection, tree: Collection): if collection == tree: return True return any(collection_in_scene(collection, child) for child in tree.children) return next(candidate for candidate in obj.users_collection if collection_in_scene(candidate, scene.collection)) def is_pc2_enabled(): return hasattr(bpy.ops, "export_shape") and hasattr(bpy.ops.export_shape, "pc2") def export_pc2_filepath(obj: Object, absolute=False): path = f"//{obj.name}.pc2" return bpy.path.abspath(path) if absolute else path def export_pc2(scene: Scene, obj: Object): path = export_pc2_filepath(obj, absolute=True) frame_start = scene.frame_start scene.frame_set(frame_start) frame_end = scene.frame_end bpy.context.view_layer.objects.active = obj bpy.context.view_layer.update() bpy.ops.export_shape.pc2(filepath=path, check_existing=False, rot_x90=False, world_space=False, apply_modifiers=True, range_start=frame_start, range_end=frame_end, sampling='1') bpy.context.view_layer.update() frame_end = scene.frame_end scene.frame_set(frame_start) bpy.context.view_layer.update() for modifier in obj.modifiers: bpy.ops.object.modifier_apply(modifier=modifier.name) bpy.context.view_layer.update() def create_proxy(scene: Scene, obj: Object): copy = obj.copy() copy.name = f"{obj.name}Bake" copy.data = copy.data.copy() copy.constraints.clear() c = get_first_collection_sharing_scene(scene, obj) c.objects.link(copy) export_pc2(scene, copy) mod = copy.modifiers.new("Mesh Bake", "MESH_CACHE") mod.cache_format = "PC2" mod.filepath = export_pc2_filepath(obj) class BakeMeshOperator(bpy.types.Operator): bl_idname = "object.bakemesh" bl_label = "Bake Mesh to PC2" @classmethod def poll(Cls, context: Context): return context.active_object is not None def execute(self, context: Context): if not is_pc2_enabled(): self.report({"ERROR"}, "PC2 export addon must be enabled") return {'FINISHED'} scene = context.scene obj = context.active_object create_proxy(scene, obj) return {'FINISHED'} def BakeMeshOperator_menu_func(self, context: Context): return self.layout.operator(BakeMeshOperator.bl_idname) def register(): bpy.types.VIEW3D_MT_object.append(BakeMeshOperator_menu_func) def unregister(): bpy.types.VIEW3D_MT_object.remove(BakeMeshOperator_menu_func)