import sys import bpy def mesh_object(name: str): mesh = bpy.data.meshes.new(f"{name}Mesh") mesh.from_pydata( [(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (0.0, 1.0, 0.0)], [], [(0, 1, 2)], ) mesh.update() obj = bpy.data.objects.new(name, mesh) bpy.context.collection.objects.link(obj) return obj def location_action(name: str, axis: int): action = bpy.data.actions.new(name) slot = action.slots.new("OBJECT", "M10NlaTimeMapping") layer = action.layers.new("M10 NLA Keys") keyframe_strip = layer.strips.new(type="KEYFRAME") channelbag = keyframe_strip.channelbags.new(slot) curve = channelbag.fcurves.new(data_path="location", index=axis) curve.keyframe_points.add(2) curve.keyframe_points[0].co = (1.0, 0.0) curve.keyframe_points[1].co = (11.0, 10.0) for keyframe in curve.keyframe_points: keyframe.interpolation = "LINEAR" action.frame_start = 1.0 action.frame_end = 11.0 return action, slot def configure_strip(strip, slot, *, frame_start, frame_end, scale, repeat, reverse): strip.action_slot = slot strip.action_frame_start = 1.0 strip.action_frame_end = 11.0 strip.frame_start = frame_start strip.frame_end = frame_end strip.scale = scale strip.repeat = repeat strip.blend_type = "REPLACE" strip.extrapolation = "NOTHING" strip.use_reverse = reverse strip.influence = 1.0 strip.blend_in = 0.0 strip.blend_out = 0.0 def main(output_path: str) -> None: bpy.ops.wm.read_factory_settings(use_empty=True) scene = bpy.context.scene scene.frame_start = 1 scene.frame_end = 70 obj = mesh_object("M10_NLA_TimeMapping") animation_data = obj.animation_data_create() track = animation_data.nla_tracks.new() track.name = "M10 Time Mapping" scaled_action, scaled_slot = location_action("M10_NLA_Scaled_X", 0) scaled_strip = track.strips.new("M10 Scaled Clip", 20, scaled_action) configure_strip( scaled_strip, scaled_slot, frame_start=20.0, frame_end=40.0, scale=2.0, repeat=1.0, reverse=False, ) reverse_repeat_action, reverse_repeat_slot = location_action("M10_NLA_ReverseRepeat_Y", 1) reverse_repeat_strip = track.strips.new("M10 Reverse Repeat Clip", 45, reverse_repeat_action) configure_strip( reverse_repeat_strip, reverse_repeat_slot, frame_start=45.0, frame_end=65.0, scale=1.0, repeat=2.0, reverse=True, ) scene.frame_set(1) bpy.ops.wm.save_as_mainfile(filepath=output_path, compress=True) if __name__ == "__main__": if "--" not in sys.argv or len(sys.argv) <= sys.argv.index("--") + 1: raise SystemExit("usage: blender -b --python generate-nla-evaluation-fixture.py -- output.blend") main(sys.argv[sys.argv.index("--") + 1])