import json from pathlib import Path import sys import bpy def curves_of(action): curves = [] if hasattr(action, "fcurves"): curves.extend(action.fcurves) for layer in action.layers: for strip in layer.strips: for bag in getattr(strip, "channelbags", []): curves.extend(bag.fcurves) return curves def curve_data(curve): driver = curve.driver return { "path": curve.data_path, "index": curve.array_index, "group": curve.group.name if curve.group else None, "driver": None if driver is None else { "type": driver.type, "expression": driver.expression, "variables": [variable.name for variable in driver.variables], }, "keys": [{ "co": list(key.co), "left": list(key.handle_left), "right": list(key.handle_right), "leftType": key.handle_left_type, "rightType": key.handle_right_type, "interpolation": key.interpolation, } for key in curve.keyframe_points], } def snapshot(): result = { "actions": [{ "name": action.name, "curves": sorted([curve_data(curve) for curve in curves_of(action)], key=lambda curve: (curve["path"], curve["index"])), "legacyGroups": [group.name for group in getattr(action, "groups", [])], "slotGroups": [{ "slot": bag.slot_handle, "groups": [group.name for group in bag.groups], } for layer in action.layers for strip in layer.strips for bag in getattr(strip, "channelbags", [])], } for action in sorted(bpy.data.actions, key=lambda item: item.name)], "objects": [{ "name": obj.name, "action": obj.animation_data.action.name if obj.animation_data and obj.animation_data.action else None, "drivers": [curve_data(curve) for curve in obj.animation_data.drivers] if obj.animation_data else [], "location": list(obj.location), } for obj in sorted(bpy.data.objects, key=lambda item: item.name)], "scenes": [{ "name": scene.name, "frame": scene.frame_current, "activeKeyingSet": scene.keying_sets.active.bl_label if scene.keying_sets.active else None, "keyingSets": [{ "name": keying_set.bl_label, "idname": keying_set.bl_idname, "isPathAbsolute": keying_set.is_path_absolute, "paths": [{ "path": item.data_path, "arrayIndex": item.array_index, "id": item.id.name if item.id else None, "idType": item.id_type, } for item in keying_set.paths], } for keying_set in scene.keying_sets], } for scene in sorted(bpy.data.scenes, key=lambda item: item.name)], } frames = [] scene = bpy.context.scene original_frame = scene.frame_current for frame in [1, 3, 5]: scene.frame_set(frame) evaluated = bpy.context.evaluated_depsgraph_get() frames.append({ "frame": frame, "objects": [{ "name": obj.name, "location": list(obj.evaluated_get(evaluated).location), "rotation": list(obj.evaluated_get(evaluated).rotation_euler), "scale": list(obj.evaluated_get(evaluated).scale), } for obj in sorted(bpy.data.objects, key=lambda item: item.name)], }) scene.frame_set(original_frame) result["evaluatedSamples"] = frames return result request_path = Path(sys.argv[sys.argv.index("--") + 1]) request = json.loads(request_path.read_text()) result = {} for label, filename in request["files"].items(): bpy.ops.wm.open_mainfile(filepath=str(Path(filename).resolve())) result[label] = snapshot() Path(request["output"]).write_text(json.dumps(result, sort_keys=True, indent=2) + "\n")