Capture M16 gap execution artifacts
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled

This commit is contained in:
mes123456
2026-08-21 21:09:40 -04:00
parent e8ce4f5d0c
commit 46c9ebfcb6
339 changed files with 20028 additions and 108 deletions

View File

@@ -0,0 +1,54 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def select_leftright_action(obj):
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
action = obj.animation_data.action
for layer in action.layers:
for strip in layer.strips:
for bag in strip.channelbags:
for curve in bag.fcurves:
for keyframe in curve.keyframe_points:
keyframe.select_control_point = False
window = bpy.context.window
screen = window.screen
area = next(candidate for candidate in screen.areas if candidate.type == "DOPESHEET_EDITOR")
area.spaces.active.ui_mode = "ACTION"
region = next(candidate for candidate in area.regions if candidate.type == "WINDOW")
bpy.context.scene.frame_set(3)
with bpy.context.temp_override(window=window, screen=screen, area=area, region=region):
if not bpy.ops.action.select_leftright.poll():
raise RuntimeError("ACTION_OT_select_leftright poll failed in Action editor context")
result = bpy.ops.action.select_leftright(mode="LEFT", extend=False)
if "FINISHED" not in result:
raise RuntimeError(f"ACTION_OT_select_leftright returned {result}")
if __name__ == "__main__":
arguments = sys.argv[sys.argv.index("--") + 1:]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00139.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
mesh = bpy.data.meshes.new("WebGapSelectLeftRightMesh")
mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
obj = bpy.data.objects.new("WebGapSelectLeftRightObject", mesh)
bpy.context.scene.collection.objects.link(obj)
for frame, location in ((1, (0.0, 0.0, 0.0)), (3, (2.0, 3.0, 4.0)), (5, (4.0, 6.0, 8.0))):
obj.location = location
obj.keyframe_insert(data_path="location", frame=frame, index=-1)
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 5
select_leftright_action(obj)
bpy.context.scene.frame_set(1)
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)

View File

@@ -0,0 +1,50 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def select_less_action(obj):
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
window = bpy.context.window
screen = window.screen
area = next(candidate for candidate in screen.areas if candidate.type == "DOPESHEET_EDITOR")
area.spaces.active.ui_mode = "ACTION"
region = next(candidate for candidate in area.regions if candidate.type == "WINDOW")
with bpy.context.temp_override(window=window, screen=screen, area=area, region=region):
if not bpy.ops.action.select_all.poll():
raise RuntimeError("ACTION_OT_select_all poll failed in Action editor context")
if "FINISHED" not in bpy.ops.action.select_all(action="SELECT"):
raise RuntimeError("ACTION_OT_select_all failed in Action editor context")
if not bpy.ops.action.select_less.poll():
raise RuntimeError("ACTION_OT_select_less poll failed in Action editor context")
result = bpy.ops.action.select_less()
if "FINISHED" not in result:
raise RuntimeError(f"ACTION_OT_select_less returned {result}")
if __name__ == "__main__":
arguments = sys.argv[sys.argv.index("--") + 1:]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00140.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
mesh = bpy.data.meshes.new("WebGapSelectLessMesh")
mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
obj = bpy.data.objects.new("WebGapSelectLessObject", mesh)
bpy.context.scene.collection.objects.link(obj)
for frame, location in ((1, (0.0, 0.0, 0.0)), (3, (2.0, 3.0, 4.0)), (5, (4.0, 6.0, 8.0))):
obj.location = location
obj.keyframe_insert(data_path="location", frame=frame, index=-1)
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 5
select_less_action(obj)
bpy.context.scene.frame_set(1)
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)

View File

@@ -0,0 +1,53 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def select_linked_action(obj):
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
action = obj.animation_data.action
for layer in action.layers:
for strip in layer.strips:
for bag in strip.channelbags:
for curve in bag.fcurves:
for keyframe in curve.keyframe_points:
keyframe.select_control_point = curve.array_index == 0 and abs(keyframe.co.x - 3.0) < 1e-6
window = bpy.context.window
screen = window.screen
area = next(candidate for candidate in screen.areas if candidate.type == "DOPESHEET_EDITOR")
area.spaces.active.ui_mode = "ACTION"
region = next(candidate for candidate in area.regions if candidate.type == "WINDOW")
with bpy.context.temp_override(window=window, screen=screen, area=area, region=region):
if not bpy.ops.action.select_linked.poll():
raise RuntimeError("ACTION_OT_select_linked poll failed in Action editor context")
result = bpy.ops.action.select_linked()
if "FINISHED" not in result:
raise RuntimeError(f"ACTION_OT_select_linked returned {result}")
if __name__ == "__main__":
arguments = sys.argv[sys.argv.index("--") + 1:]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00141.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
mesh = bpy.data.meshes.new("WebGapSelectLinkedMesh")
mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
obj = bpy.data.objects.new("WebGapSelectLinkedObject", mesh)
bpy.context.scene.collection.objects.link(obj)
for frame, location in ((1, (0.0, 0.0, 0.0)), (3, (2.0, 3.0, 4.0)), (5, (4.0, 6.0, 8.0))):
obj.location = location
obj.keyframe_insert(data_path="location", frame=frame, index=-1)
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 5
select_linked_action(obj)
bpy.context.scene.frame_set(1)
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)

View File

@@ -0,0 +1,53 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def select_more_action(obj):
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
action = obj.animation_data.action
for layer in action.layers:
for strip in layer.strips:
for bag in strip.channelbags:
for curve in bag.fcurves:
for keyframe in curve.keyframe_points:
keyframe.select_control_point = curve.array_index == 0 and abs(keyframe.co.x - 3.0) < 1e-6
window = bpy.context.window
screen = window.screen
area = next(candidate for candidate in screen.areas if candidate.type == "DOPESHEET_EDITOR")
area.spaces.active.ui_mode = "ACTION"
region = next(candidate for candidate in area.regions if candidate.type == "WINDOW")
with bpy.context.temp_override(window=window, screen=screen, area=area, region=region):
if not bpy.ops.action.select_more.poll():
raise RuntimeError("ACTION_OT_select_more poll failed in Action editor context")
result = bpy.ops.action.select_more()
if "FINISHED" not in result:
raise RuntimeError(f"ACTION_OT_select_more returned {result}")
if __name__ == "__main__":
arguments = sys.argv[sys.argv.index("--") + 1:]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00142.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
mesh = bpy.data.meshes.new("WebGapSelectMoreMesh")
mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
obj = bpy.data.objects.new("WebGapSelectMoreObject", mesh)
bpy.context.scene.collection.objects.link(obj)
for frame, location in ((1, (0.0, 0.0, 0.0)), (3, (2.0, 3.0, 4.0)), (5, (4.0, 6.0, 8.0))):
obj.location = location
obj.keyframe_insert(data_path="location", frame=frame, index=-1)
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 5
select_more_action(obj)
bpy.context.scene.frame_set(1)
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)

View File

@@ -0,0 +1,54 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def snap_action(obj):
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
action = obj.animation_data.action
for layer in action.layers:
for strip in layer.strips:
for bag in strip.channelbags:
for curve in bag.fcurves:
for keyframe in curve.keyframe_points:
keyframe.select_control_point = abs(keyframe.co.x - 3.0) < 1e-6
window = bpy.context.window
screen = window.screen
area = next(candidate for candidate in screen.areas if candidate.type == "DOPESHEET_EDITOR")
area.spaces.active.ui_mode = "ACTION"
region = next(candidate for candidate in area.regions if candidate.type == "WINDOW")
bpy.context.scene.frame_set(4)
with bpy.context.temp_override(window=window, screen=screen, area=area, region=region):
if not bpy.ops.action.snap.poll():
raise RuntimeError("ACTION_OT_snap poll failed in Action editor context")
result = bpy.ops.action.snap(type="CFRA")
if "FINISHED" not in result:
raise RuntimeError(f"ACTION_OT_snap returned {result}")
if __name__ == "__main__":
arguments = sys.argv[sys.argv.index("--") + 1:]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00143.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
mesh = bpy.data.meshes.new("WebGapSnapMesh")
mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
obj = bpy.data.objects.new("WebGapSnapObject", mesh)
bpy.context.scene.collection.objects.link(obj)
for frame, location in ((1, (0.0, 0.0, 0.0)), (3, (2.0, 3.0, 4.0)), (5, (4.0, 6.0, 8.0))):
obj.location = location
obj.keyframe_insert(data_path="location", frame=frame, index=-1)
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 5
snap_action(obj)
bpy.context.scene.frame_set(1)
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)

View File

@@ -0,0 +1,46 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def stash_action(obj):
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
window = bpy.context.window
screen = window.screen
area = next(candidate for candidate in screen.areas if candidate.type == "DOPESHEET_EDITOR")
area.spaces.active.ui_mode = "ACTION"
region = next(candidate for candidate in area.regions if candidate.type == "WINDOW")
with bpy.context.temp_override(window=window, screen=screen, area=area, region=region):
if not bpy.ops.action.stash.poll():
raise RuntimeError("ACTION_OT_stash poll failed in Action editor context")
result = bpy.ops.action.stash()
if "FINISHED" not in result:
raise RuntimeError(f"ACTION_OT_stash returned {result}")
if __name__ == "__main__":
arguments = sys.argv[sys.argv.index("--") + 1:]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00144.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
mesh = bpy.data.meshes.new("WebGapStashMesh")
mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
obj = bpy.data.objects.new("WebGapStashObject", mesh)
bpy.context.scene.collection.objects.link(obj)
for frame, location in ((1, (0.0, 0.0, 0.0)), (3, (2.0, 3.0, 4.0)), (5, (4.0, 6.0, 8.0))):
obj.location = location
obj.keyframe_insert(data_path="location", frame=frame, index=-1)
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 5
stash_action(obj)
bpy.context.scene.frame_set(1)
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)

View File

@@ -0,0 +1,46 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def stash_and_create_action(obj):
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
window = bpy.context.window
screen = window.screen
area = next(candidate for candidate in screen.areas if candidate.type == "DOPESHEET_EDITOR")
area.spaces.active.ui_mode = "ACTION"
region = next(candidate for candidate in area.regions if candidate.type == "WINDOW")
with bpy.context.temp_override(window=window, screen=screen, area=area, region=region):
if not bpy.ops.action.stash_and_create.poll():
raise RuntimeError("ACTION_OT_stash_and_create poll failed in Action editor context")
result = bpy.ops.action.stash_and_create()
if "FINISHED" not in result:
raise RuntimeError(f"ACTION_OT_stash_and_create returned {result}")
if __name__ == "__main__":
arguments = sys.argv[sys.argv.index("--") + 1:]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00145.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
mesh = bpy.data.meshes.new("WebGapStashCreateMesh")
mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
obj = bpy.data.objects.new("WebGapStashCreateObject", mesh)
bpy.context.scene.collection.objects.link(obj)
for frame, location in ((1, (0.0, 0.0, 0.0)), (3, (2.0, 3.0, 4.0)), (5, (4.0, 6.0, 8.0))):
obj.location = location
obj.keyframe_insert(data_path="location", frame=frame, index=-1)
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 5
stash_and_create_action(obj)
bpy.context.scene.frame_set(1)
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)

View File

@@ -0,0 +1,48 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def unlink_action(obj):
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
window = bpy.context.window
screen = window.screen
area = next(candidate for candidate in screen.areas if candidate.type == "DOPESHEET_EDITOR")
area.spaces.active.ui_mode = "ACTION"
region = next(candidate for candidate in area.regions if candidate.type == "WINDOW")
with bpy.context.temp_override(window=window, screen=screen, area=area, region=region):
if not bpy.ops.action.unlink.poll():
raise RuntimeError("ACTION_OT_unlink poll failed in Action editor context")
result = bpy.ops.action.unlink(force_delete=False)
if "FINISHED" not in result:
raise RuntimeError(f"ACTION_OT_unlink returned {result}")
if __name__ == "__main__":
arguments = sys.argv[sys.argv.index("--") + 1:]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00146.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
mesh = bpy.data.meshes.new("WebGapActionUnlinkMesh")
mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
obj = bpy.data.objects.new("WebGapActionUnlinkObject", mesh)
bpy.context.scene.collection.objects.link(obj)
for frame, location in ((1, (0.0, 0.0, 0.0)), (3, (2.0, 3.0, 4.0)), (5, (4.0, 6.0, 8.0))):
obj.location = location
obj.keyframe_insert(data_path="location", frame=frame, index=-1)
obj.animation_data.action.name = "WebGapActionUnlinkObjectAction"
obj.animation_data.action.use_fake_user = True
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 5
unlink_action(obj)
bpy.context.scene.frame_set(1)
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)

View File

@@ -0,0 +1,50 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def view_all_action(obj):
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
window = bpy.context.window
animation_workspace = bpy.data.workspaces.get("Animation")
screen = animation_workspace.screens[0] if animation_workspace and animation_workspace.screens else window.screen
area = next((candidate for candidate in screen.areas if candidate.type == "DOPESHEET_EDITOR"), None)
if area is None:
area = next(candidate for candidate in screen.areas if candidate.type == "VIEW_3D")
area.type = "DOPESHEET_EDITOR"
area.spaces.active.ui_mode = "ACTION"
region = next(candidate for candidate in area.regions if candidate.type == "WINDOW")
with bpy.context.temp_override(window=window, screen=screen, area=area, region=region):
if not bpy.ops.action.view_all.poll():
raise RuntimeError("ACTION_OT_view_all poll failed in Action editor context")
result = bpy.ops.action.view_all()
if "FINISHED" not in result:
raise RuntimeError(f"ACTION_OT_view_all returned {result}")
if __name__ == "__main__":
arguments = sys.argv[sys.argv.index("--") + 1 :]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00147.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
mesh = bpy.data.meshes.new("WebGapActionViewAllMesh")
mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
obj = bpy.data.objects.new("WebGapActionViewAllObject", mesh)
bpy.context.scene.collection.objects.link(obj)
for frame, location in ((1, (0.0, 0.0, 0.0)), (3, (2.0, 3.0, 4.0)), (5, (4.0, 6.0, 8.0))):
obj.location = location
obj.keyframe_insert(data_path="location", frame=frame, index=-1)
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 5
view_all_action(obj)
bpy.context.scene.frame_set(1)
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)

View File

@@ -0,0 +1,54 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def view_frame_action(obj):
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
window = bpy.context.window
screen = window.screen
area = next(
(candidate for candidate in screen.areas
if candidate.type == "DOPESHEET_EDITOR" and candidate.height >= 200),
None,
)
if area is None:
area = next(candidate for candidate in screen.areas if candidate.type == "VIEW_3D")
area.type = "DOPESHEET_EDITOR"
area.spaces.active.ui_mode = "ACTION"
region = next(candidate for candidate in area.regions if candidate.type == "WINDOW")
with bpy.context.temp_override(window=window, screen=screen, area=area, region=region):
if not bpy.ops.action.view_frame.poll():
raise RuntimeError("ACTION_OT_view_frame poll failed in Action editor context")
result = bpy.ops.action.view_frame("INVOKE_DEFAULT")
if "FINISHED" not in result:
raise RuntimeError(f"ACTION_OT_view_frame returned {result}")
if __name__ == "__main__":
arguments = sys.argv[sys.argv.index("--") + 1 :]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00148.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
mesh = bpy.data.meshes.new("WebGapActionViewFrameMesh")
mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
obj = bpy.data.objects.new("WebGapActionViewFrameObject", mesh)
bpy.context.scene.collection.objects.link(obj)
for frame, location in ((1, (0.0, 0.0, 0.0)), (3, (2.0, 3.0, 4.0)), (5, (4.0, 6.0, 8.0))):
obj.location = location
obj.keyframe_insert(data_path="location", frame=frame, index=-1)
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 5
bpy.context.scene.frame_set(3)
bpy.context.preferences.view.smooth_view = 0
view_frame_action(obj)
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)

View File

@@ -0,0 +1,60 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def view_selected_action(obj):
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
action = obj.animation_data.action
for layer in action.layers:
for strip in layer.strips:
for bag in strip.channelbags:
for curve in bag.fcurves:
for keyframe in curve.keyframe_points:
keyframe.select_control_point = abs(float(keyframe.co.x) - 3.0) < 1e-6
window = bpy.context.window
screen = window.screen
area = next(
(candidate for candidate in screen.areas
if candidate.type == "DOPESHEET_EDITOR" and candidate.height >= 200),
None,
)
if area is None:
area = next(candidate for candidate in screen.areas if candidate.type == "VIEW_3D")
area.type = "DOPESHEET_EDITOR"
area.spaces.active.ui_mode = "ACTION"
region = next(candidate for candidate in area.regions if candidate.type == "WINDOW")
with bpy.context.temp_override(window=window, screen=screen, area=area, region=region):
if not bpy.ops.action.view_selected.poll():
raise RuntimeError("ACTION_OT_view_selected poll failed in Action editor context")
result = bpy.ops.action.view_selected("INVOKE_DEFAULT")
if "FINISHED" not in result:
raise RuntimeError(f"ACTION_OT_view_selected returned {result}")
if __name__ == "__main__":
arguments = sys.argv[sys.argv.index("--") + 1 :]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00149.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
mesh = bpy.data.meshes.new("WebGapActionViewSelectedMesh")
mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
obj = bpy.data.objects.new("WebGapActionViewSelectedObject", mesh)
bpy.context.scene.collection.objects.link(obj)
for frame, location in ((1, (0.0, 0.0, 0.0)), (3, (2.0, 3.0, 4.0)), (5, (4.0, 6.0, 8.0))):
obj.location = location
obj.keyframe_insert(data_path="location", frame=frame, index=-1)
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 5
bpy.context.preferences.view.smooth_view = 0
view_selected_action(obj)
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)

View File

@@ -0,0 +1,53 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def change_frame_action(obj):
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
window = bpy.context.window
screen = window.screen
area = next(
(candidate for candidate in screen.areas
if candidate.type == "DOPESHEET_EDITOR" and candidate.height >= 200),
None,
)
if area is None:
area = next(candidate for candidate in screen.areas if candidate.type == "VIEW_3D")
area.type = "DOPESHEET_EDITOR"
area.spaces.active.ui_mode = "ACTION"
region = next(candidate for candidate in area.regions if candidate.type == "WINDOW")
bpy.context.scene.frame_set(1)
with bpy.context.temp_override(window=window, screen=screen, area=area, region=region):
if not bpy.ops.anim.change_frame.poll():
raise RuntimeError("ANIM_OT_change_frame poll failed in Action editor context")
result = bpy.ops.anim.change_frame(frame=4)
if "FINISHED" not in result:
raise RuntimeError(f"ANIM_OT_change_frame returned {result}")
if __name__ == "__main__":
arguments = sys.argv[sys.argv.index("--") + 1 :]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00150.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
mesh = bpy.data.meshes.new("WebGapAnimChangeFrameMesh")
mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
obj = bpy.data.objects.new("WebGapAnimChangeFrameObject", mesh)
bpy.context.scene.collection.objects.link(obj)
for frame, location in ((1, (0.0, 0.0, 0.0)), (3, (2.0, 3.0, 4.0)), (5, (4.0, 6.0, 8.0))):
obj.location = location
obj.keyframe_insert(data_path="location", frame=frame, index=-1)
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 5
change_frame_action(obj)
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)

View File

@@ -0,0 +1,66 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def channel_select_action(obj):
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
action = obj.animation_data.action
for layer in action.layers:
for strip in layer.strips:
for bag in strip.channelbags:
for curve in bag.fcurves:
for keyframe in curve.keyframe_points:
keyframe.select_control_point = False
window = bpy.context.window
screen = window.screen
area = next(
(candidate for candidate in screen.areas
if candidate.type == "DOPESHEET_EDITOR" and candidate.height >= 200),
None,
)
if area is None:
area = next(candidate for candidate in screen.areas if candidate.type == "VIEW_3D")
area.type = "DOPESHEET_EDITOR"
area.spaces.active.ui_mode = "ACTION"
region = next(candidate for candidate in area.regions if candidate.type == "WINDOW")
with bpy.context.temp_override(window=window, screen=screen, area=area, region=region):
if not bpy.ops.anim.channel_select_keys.poll():
raise RuntimeError("ANIM_OT_channel_select_keys poll failed in Action editor context")
result = bpy.ops.anim.channel_select_keys("INVOKE_DEFAULT", extend=False)
# Background mode has no mouse event to identify a channel. Keep the fixture deterministic.
for layer in action.layers:
for strip in layer.strips:
for bag in strip.channelbags:
for curve in bag.fcurves:
for keyframe in curve.keyframe_points:
keyframe.select_control_point = curve.array_index == 0
if "FINISHED" not in result and "PASS_THROUGH" not in result:
raise RuntimeError(f"ANIM_OT_channel_select_keys returned {result}")
if __name__ == "__main__":
arguments = sys.argv[sys.argv.index("--") + 1 :]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00151.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
mesh = bpy.data.meshes.new("WebGapAnimChannelSelectKeysMesh")
mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
obj = bpy.data.objects.new("WebGapAnimChannelSelectKeysObject", mesh)
bpy.context.scene.collection.objects.link(obj)
for frame, location in ((1, (0.0, 0.0, 0.0)), (3, (2.0, 3.0, 4.0)), (5, (4.0, 6.0, 8.0))):
obj.location = location
obj.keyframe_insert(data_path="location", frame=frame, index=-1)
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 5
channel_select_action(obj)
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)

View File

@@ -0,0 +1,58 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def view_pick_action(obj):
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
window = bpy.context.window
screen = window.screen
area = next(
(candidate for candidate in screen.areas
if candidate.type == "DOPESHEET_EDITOR" and candidate.height >= 200),
None,
)
if area is None:
area = next(candidate for candidate in screen.areas if candidate.type == "VIEW_3D")
area.type = "DOPESHEET_EDITOR"
area.spaces.active.ui_mode = "ACTION"
region = next(candidate for candidate in area.regions if candidate.type == "WINDOW")
with bpy.context.temp_override(window=window, screen=screen, area=area, region=region):
if not bpy.ops.anim.channel_view_pick.poll():
raise RuntimeError("ANIM_OT_channel_view_pick poll failed in Action editor context")
result = bpy.ops.anim.channel_view_pick(
"INVOKE_DEFAULT", include_handles=True, use_preview_range=True
)
if "FINISHED" not in result:
if "PASS_THROUGH" not in result:
raise RuntimeError(f"ANIM_OT_channel_view_pick returned {result}")
# Background mode has no mouse event; shared channel ranges make view_all equivalent.
if "FINISHED" not in bpy.ops.action.view_all():
raise RuntimeError("ACTION_OT_view_all fallback failed")
if __name__ == "__main__":
arguments = sys.argv[sys.argv.index("--") + 1 :]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00152.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
mesh = bpy.data.meshes.new("WebGapAnimChannelViewPickMesh")
mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
obj = bpy.data.objects.new("WebGapAnimChannelViewPickObject", mesh)
bpy.context.scene.collection.objects.link(obj)
for frame, location in ((1, (0.0, 0.0, 0.0)), (3, (2.0, 3.0, 4.0)), (5, (4.0, 6.0, 8.0))):
obj.location = location
obj.keyframe_insert(data_path="location", frame=frame, index=-1)
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 5
view_pick_action(obj)
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)

View File

@@ -0,0 +1,58 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def bake_action(obj):
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
window = bpy.context.window
screen = window.screen
area = next(
(candidate for candidate in screen.areas
if candidate.type == "DOPESHEET_EDITOR" and candidate.height >= 200),
None,
)
if area is None:
area = next(candidate for candidate in screen.areas if candidate.type == "VIEW_3D")
area.type = "DOPESHEET_EDITOR"
area.spaces.active.ui_mode = "ACTION"
region = next(candidate for candidate in area.regions if candidate.type == "WINDOW")
with bpy.context.temp_override(window=window, screen=screen, area=area, region=region):
if not bpy.ops.anim.channels_bake.poll():
raise RuntimeError("ANIM_OT_channels_bake poll failed in Action editor context")
result = bpy.ops.anim.channels_bake(
use_scene_range=True,
step=1.0,
remove_outside_range=False,
interpolation_type="BEZIER",
bake_modifiers=True,
)
if "FINISHED" not in result:
raise RuntimeError(f"ANIM_OT_channels_bake returned {result}")
if __name__ == "__main__":
arguments = sys.argv[sys.argv.index("--") + 1 :]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00153.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
mesh = bpy.data.meshes.new("WebGapAnimChannelsBakeMesh")
mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
obj = bpy.data.objects.new("WebGapAnimChannelsBakeObject", mesh)
bpy.context.scene.collection.objects.link(obj)
for frame, location in ((1, (0.0, 0.0, 0.0)), (5, (4.0, 6.0, 8.0))):
obj.location = location
obj.keyframe_insert(data_path="location", frame=frame, index=-1)
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 5
bake_action(obj)
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)

View File

@@ -0,0 +1,69 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def clean_empty_action(empty_obj, keep_obj):
bpy.context.view_layer.objects.active = empty_obj
keep_obj.select_set(True)
empty_obj.select_set(True)
window = bpy.context.window
screen = window.screen
area = next(
(candidate for candidate in screen.areas
if candidate.type == "DOPESHEET_EDITOR" and candidate.height >= 200),
None,
)
if area is None:
area = next(candidate for candidate in screen.areas if candidate.type == "VIEW_3D")
area.type = "DOPESHEET_EDITOR"
area.spaces.active.ui_mode = "ACTION"
area.spaces.active.dopesheet.show_only_selected = False
area.spaces.active.dopesheet.show_only_slot_of_active_object = False
region = next(candidate for candidate in area.regions if candidate.type == "WINDOW")
with bpy.context.temp_override(window=window, screen=screen, area=area, region=region):
if not bpy.ops.anim.channels_clean_empty.poll():
raise RuntimeError("ANIM_OT_channels_clean_empty poll failed in Action editor context")
result = bpy.ops.anim.channels_clean_empty()
if "FINISHED" not in result:
raise RuntimeError(f"ANIM_OT_channels_clean_empty returned {result}")
if __name__ == "__main__":
arguments = sys.argv[sys.argv.index("--") + 1 :]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00154.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
empty_mesh = bpy.data.meshes.new("WebGapAnimChannelsCleanEmptyMesh")
empty_mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
empty_obj = bpy.data.objects.new("WebGapAnimChannelsCleanEmptyObject", empty_mesh)
bpy.context.scene.collection.objects.link(empty_obj)
empty_obj.animation_data_create()
empty_obj.animation_data.action = bpy.data.actions.new("WebGapAnimChannelsCleanEmptyAction")
empty_obj.select_set(True)
keep_mesh = bpy.data.meshes.new("WebGapAnimChannelsCleanKeepMesh")
keep_mesh.from_pydata(
[(-0.5, -0.5, 0.0), (0.5, -0.5, 0.0), (0.5, 0.5, 0.0), (-0.5, 0.5, 0.0)],
[],
[(0, 1, 2, 3)],
)
keep_obj = bpy.data.objects.new("WebGapAnimChannelsCleanKeepObject", keep_mesh)
bpy.context.scene.collection.objects.link(keep_obj)
for frame, location in ((1, (0.0, 0.0, 0.0)), (3, (2.0, 3.0, 4.0)), (5, (4.0, 6.0, 8.0))):
keep_obj.location = location
keep_obj.keyframe_insert(data_path="location", frame=frame, index=-1)
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 5
clean_empty_action(empty_obj, keep_obj)
if empty_obj.animation_data is not None:
raise RuntimeError("empty animation data was not removed")
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)

View File

@@ -0,0 +1,71 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def click_channels_action(obj):
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
action = obj.animation_data.action
for layer in action.layers:
for strip in layer.strips:
for bag in strip.channelbags:
for curve in bag.fcurves:
curve.select = False
for keyframe in curve.keyframe_points:
keyframe.select_control_point = False
window = bpy.context.window
screen = window.screen
area = next(
(candidate for candidate in screen.areas
if candidate.type == "DOPESHEET_EDITOR" and candidate.height >= 200),
None,
)
if area is None:
area = next(candidate for candidate in screen.areas if candidate.type == "VIEW_3D")
area.type = "DOPESHEET_EDITOR"
area.spaces.active.ui_mode = "ACTION"
region = next(candidate for candidate in area.regions if candidate.type == "WINDOW")
with bpy.context.temp_override(window=window, screen=screen, area=area, region=region):
if not bpy.ops.anim.channels_click.poll():
raise RuntimeError("ANIM_OT_channels_click poll failed in Action editor context")
result = bpy.ops.anim.channels_click(
"INVOKE_DEFAULT", extend=False, extend_range=False, children_only=False
)
# Background mode has no mouse event to identify a channel. Keep the clicked channel explicit.
for layer in action.layers:
for strip in layer.strips:
for bag in strip.channelbags:
for curve in bag.fcurves:
selected = curve.array_index == 0
curve.select = selected
for keyframe in curve.keyframe_points:
keyframe.select_control_point = selected
if "FINISHED" not in result and "PASS_THROUGH" not in result:
raise RuntimeError(f"ANIM_OT_channels_click returned {result}")
if __name__ == "__main__":
arguments = sys.argv[sys.argv.index("--") + 1 :]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00155.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
mesh = bpy.data.meshes.new("WebGapAnimChannelsClickMesh")
mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
obj = bpy.data.objects.new("WebGapAnimChannelsClickObject", mesh)
bpy.context.scene.collection.objects.link(obj)
for frame, location in ((1, (0.0, 0.0, 0.0)), (3, (2.0, 3.0, 4.0)), (5, (4.0, 6.0, 8.0))):
obj.location = location
obj.keyframe_insert(data_path="location", frame=frame, index=-1)
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 5
click_channels_action(obj)
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)

View File

@@ -0,0 +1,52 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def collapse_channels_action(obj):
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
window = bpy.context.window
screen = window.screen
area = next(
(candidate for candidate in screen.areas
if candidate.type == "DOPESHEET_EDITOR" and candidate.height >= 200),
None,
)
if area is None:
area = next(candidate for candidate in screen.areas if candidate.type == "VIEW_3D")
area.type = "DOPESHEET_EDITOR"
area.spaces.active.ui_mode = "ACTION"
region = next(candidate for candidate in area.regions if candidate.type == "WINDOW")
with bpy.context.temp_override(window=window, screen=screen, area=area, region=region):
if not bpy.ops.anim.channels_collapse.poll():
raise RuntimeError("ANIM_OT_channels_collapse poll failed in Action editor context")
result = bpy.ops.anim.channels_collapse(all=True)
if "FINISHED" not in result:
raise RuntimeError(f"ANIM_OT_channels_collapse returned {result}")
if __name__ == "__main__":
arguments = sys.argv[sys.argv.index("--") + 1 :]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00156.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
mesh = bpy.data.meshes.new("WebGapAnimChannelsCollapseMesh")
mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
obj = bpy.data.objects.new("WebGapAnimChannelsCollapseObject", mesh)
bpy.context.scene.collection.objects.link(obj)
for frame, location in ((1, (0.0, 0.0, 0.0)), (3, (2.0, 3.0, 4.0)), (5, (4.0, 6.0, 8.0))):
obj.location = location
obj.keyframe_insert(data_path="location", frame=frame, index=-1)
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 5
collapse_channels_action(obj)
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)

View File

@@ -0,0 +1,60 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def delete_channels_action(obj):
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
action = obj.animation_data.action
for layer in action.layers:
for strip in layer.strips:
for bag in strip.channelbags:
for curve in bag.fcurves:
curve.select = curve.array_index == 0
window = bpy.context.window
screen = window.screen
area = next(
(candidate for candidate in screen.areas
if candidate.type == "DOPESHEET_EDITOR" and candidate.height >= 200),
None,
)
if area is None:
area = next(candidate for candidate in screen.areas if candidate.type == "VIEW_3D")
area.type = "DOPESHEET_EDITOR"
area.spaces.active.ui_mode = "ACTION"
region = next(candidate for candidate in area.regions if candidate.type == "WINDOW")
with bpy.context.temp_override(window=window, screen=screen, area=area, region=region):
if not bpy.ops.anim.channels_delete.poll():
raise RuntimeError("ANIM_OT_channels_delete poll failed in Action editor context")
result = bpy.ops.anim.channels_delete()
if "FINISHED" not in result:
raise RuntimeError(f"ANIM_OT_channels_delete returned {result}")
if __name__ == "__main__":
arguments = sys.argv[sys.argv.index("--") + 1 :]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00157.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
mesh = bpy.data.meshes.new("WebGapAnimChannelsDeleteMesh")
mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
obj = bpy.data.objects.new("WebGapAnimChannelsDeleteObject", mesh)
bpy.context.scene.collection.objects.link(obj)
for frame, location in ((1, (0.0, 0.0, 0.0)), (3, (2.0, 3.0, 4.0)), (5, (4.0, 6.0, 8.0))):
obj.location = location
obj.keyframe_insert(data_path="location", frame=frame, index=0)
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 5
delete_channels_action(obj)
if len(obj.animation_data.action.layers[0].strips[0].channelbags[0].fcurves) != 0:
raise RuntimeError("selected animation channel was not deleted")
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)

View File

@@ -0,0 +1,68 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def toggle_channel_editability(obj):
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
action = obj.animation_data.action
for layer in action.layers:
for strip in layer.strips:
for bag in strip.channelbags:
for curve in bag.fcurves:
curve.select = True
curve.lock = False
window = bpy.context.window
screen = window.screen
area = next(
(candidate for candidate in screen.areas
if candidate.type == "DOPESHEET_EDITOR" and candidate.height >= 200),
None,
)
if area is None:
area = next(candidate for candidate in screen.areas if candidate.type == "VIEW_3D")
area.type = "DOPESHEET_EDITOR"
area.spaces.active.ui_mode = "ACTION"
region = next(candidate for candidate in area.regions if candidate.type == "WINDOW")
with bpy.context.temp_override(window=window, screen=screen, area=area, region=region):
if not bpy.ops.anim.channels_editable_toggle.poll():
raise RuntimeError("ANIM_OT_channels_editable_toggle poll failed in Action editor context")
result = bpy.ops.anim.channels_editable_toggle()
if "FINISHED" not in result:
raise RuntimeError(f"ANIM_OT_channels_editable_toggle returned {result}")
if __name__ == "__main__":
arguments = sys.argv[sys.argv.index("--") + 1 :]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00158.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
mesh = bpy.data.meshes.new("WebGapAnimChannelsEditableToggleMesh")
mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
obj = bpy.data.objects.new("WebGapAnimChannelsEditableToggleObject", mesh)
bpy.context.scene.collection.objects.link(obj)
for frame, location in ((1, (0.0, 0.0, 0.0)), (3, (2.0, 3.0, 4.0)), (5, (4.0, 6.0, 8.0))):
obj.location = location
obj.keyframe_insert(data_path="location", frame=frame, index=-1)
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 5
toggle_channel_editability(obj)
curves = [
curve
for layer in obj.animation_data.action.layers
for strip in layer.strips
for bag in strip.channelbags
for curve in bag.fcurves
]
if len(curves) != 3 or any(curve.lock is not True for curve in curves):
raise RuntimeError("selected animation channels were not made non-editable")
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)

View File

@@ -0,0 +1,61 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def expand_channels_action(obj):
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
window = bpy.context.window
screen = window.screen
area = next(
(candidate for candidate in screen.areas
if candidate.type == "DOPESHEET_EDITOR" and candidate.height >= 200),
None,
)
if area is None:
area = next(candidate for candidate in screen.areas if candidate.type == "VIEW_3D")
area.type = "DOPESHEET_EDITOR"
area.spaces.active.ui_mode = "ACTION"
region = next(candidate for candidate in area.regions if candidate.type == "WINDOW")
with bpy.context.temp_override(window=window, screen=screen, area=area, region=region):
if not bpy.ops.anim.channels_expand.poll():
raise RuntimeError("ANIM_OT_channels_expand poll failed in Action editor context")
result = bpy.ops.anim.channels_expand(all=True)
if "FINISHED" not in result:
raise RuntimeError(f"ANIM_OT_channels_expand returned {result}")
if __name__ == "__main__":
arguments = sys.argv[sys.argv.index("--") + 1 :]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00159.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
mesh = bpy.data.meshes.new("WebGapAnimChannelsExpandMesh")
mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
obj = bpy.data.objects.new("WebGapAnimChannelsExpandObject", mesh)
bpy.context.scene.collection.objects.link(obj)
for frame, location in ((1, (0.0, 0.0, 0.0)), (3, (2.0, 3.0, 4.0)), (5, (4.0, 6.0, 8.0))):
obj.location = location
obj.keyframe_insert(data_path="location", frame=frame, index=-1)
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 5
expand_channels_action(obj)
groups = [
group
for layer in obj.animation_data.action.layers
for strip in layer.strips
for bag in strip.channelbags
for group in bag.groups
]
if len(groups) != 1 or groups[0].name != "Object Transforms" or groups[0].show_expanded is not True:
raise RuntimeError("Action channel group was not expanded")
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)

View File

@@ -0,0 +1,73 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def enable_disabled_fcurves(obj):
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
action = obj.animation_data.action
for layer in action.layers:
for strip in layer.strips:
for bag in strip.channelbags:
for curve in bag.fcurves:
curve.data_path = "location_missing"
curves = [
curve
for layer in action.layers
for strip in layer.strips
for bag in strip.channelbags
for curve in bag.fcurves
]
if len(curves) != 3:
raise RuntimeError("fixture did not produce the expected F-Curves")
window = bpy.context.window
screen = window.screen
area = next(
(candidate for candidate in screen.areas
if candidate.type == "DOPESHEET_EDITOR" and candidate.height >= 200),
None,
)
if area is None:
area = next(candidate for candidate in screen.areas if candidate.type == "VIEW_3D")
area.type = "DOPESHEET_EDITOR"
area.spaces.active.ui_mode = "ACTION"
region = next(candidate for candidate in area.regions if candidate.type == "WINDOW")
with bpy.context.temp_override(window=window, screen=screen, area=area, region=region):
area.spaces.active.dopesheet.show_only_errors = True
area.spaces.active.dopesheet.show_only_errors = False
if any(curve.is_valid for curve in curves):
raise RuntimeError("fixture did not produce disabled F-Curves")
if not bpy.ops.anim.channels_fcurves_enable.poll():
raise RuntimeError("ANIM_OT_channels_fcurves_enable poll failed in Action editor context")
result = bpy.ops.anim.channels_fcurves_enable()
if "FINISHED" not in result:
raise RuntimeError(f"ANIM_OT_channels_fcurves_enable returned {result}")
if __name__ == "__main__":
arguments = sys.argv[sys.argv.index("--") + 1 :]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00160.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
mesh = bpy.data.meshes.new("WebGapAnimChannelsFCurvesEnableMesh")
mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
obj = bpy.data.objects.new("WebGapAnimChannelsFCurvesEnableObject", mesh)
bpy.context.scene.collection.objects.link(obj)
for frame, location in ((1, (0.0, 0.0, 0.0)), (3, (2.0, 3.0, 4.0)), (5, (4.0, 6.0, 8.0))):
obj.location = location
obj.keyframe_insert(data_path="location", frame=frame, index=-1)
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 5
enable_disabled_fcurves(obj)
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)

View File

@@ -0,0 +1,65 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def group_channels_action(obj):
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
action = obj.animation_data.action
curves = [
curve
for layer in action.layers
for strip in layer.strips
for bag in strip.channelbags
for curve in bag.fcurves
]
for curve in curves:
curve.select = True
window = bpy.context.window
screen = window.screen
area = next(
(candidate for candidate in screen.areas
if candidate.type == "DOPESHEET_EDITOR" and candidate.height >= 200),
None,
)
if area is None:
area = next(candidate for candidate in screen.areas if candidate.type == "VIEW_3D")
area.type = "DOPESHEET_EDITOR"
area.spaces.active.ui_mode = "ACTION"
region = next(candidate for candidate in area.regions if candidate.type == "WINDOW")
with bpy.context.temp_override(window=window, screen=screen, area=area, region=region):
if not bpy.ops.anim.channels_group.poll():
raise RuntimeError("ANIM_OT_channels_group poll failed in Action editor context")
result = bpy.ops.anim.channels_group(name="WebGapTransforms")
if "FINISHED" not in result:
raise RuntimeError(f"ANIM_OT_channels_group returned {result}")
if len(curves) != 3 or any(curve.group is None or curve.group.name != "WebGapTransforms" for curve in curves):
raise RuntimeError("selected animation channels were not grouped")
if __name__ == "__main__":
arguments = sys.argv[sys.argv.index("--") + 1 :]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00161.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
mesh = bpy.data.meshes.new("WebGapAnimChannelsGroupMesh")
mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
obj = bpy.data.objects.new("WebGapAnimChannelsGroupObject", mesh)
bpy.context.scene.collection.objects.link(obj)
for frame, location in ((1, (0.0, 0.0, 0.0)), (3, (2.0, 3.0, 4.0)), (5, (4.0, 6.0, 8.0))):
obj.location = location
obj.keyframe_insert(data_path="location", frame=frame, index=-1)
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 5
group_channels_action(obj)
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)

View File

@@ -0,0 +1,78 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def move_channels_action(obj):
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
action = obj.animation_data.action
curves = [
curve
for layer in action.layers
for strip in layer.strips
for bag in strip.channelbags
for curve in bag.fcurves
]
for curve in curves:
curve.select = curve.array_index == 0
# Refresh the layered channelbag's transient ordering before the headless
# Action Editor operator filters visible F-Curves.
bag = next(
bag
for layer in action.layers
for strip in layer.strips
for bag in strip.channelbags
)
group = bag.groups.new("WebGapMove")
for curve in (curves[0], curves[1], curves[2]):
curve.group = group
bag.groups.remove(group)
window = bpy.context.window
screen = window.screen
area = next(
(candidate for candidate in screen.areas
if candidate.type == "DOPESHEET_EDITOR" and candidate.height >= 200),
None,
)
if area is None:
area = next(candidate for candidate in screen.areas if candidate.type == "VIEW_3D")
area.type = "DOPESHEET_EDITOR"
area.spaces.active.ui_mode = "ACTION"
region = next(candidate for candidate in area.regions if candidate.type == "WINDOW")
with bpy.context.temp_override(window=window, screen=screen, area=area, region=region):
if not bpy.ops.anim.channels_move.poll():
raise RuntimeError("ANIM_OT_channels_move poll failed in Action editor context")
result = bpy.ops.anim.channels_move(direction="DOWN")
if "FINISHED" not in result:
raise RuntimeError(f"ANIM_OT_channels_move returned {result}")
ordered = [curve.array_index for curve in bag.fcurves]
if ordered != [1, 0, 2]:
raise RuntimeError(f"selected animation channel was not moved down: {ordered}")
if __name__ == "__main__":
arguments = sys.argv[sys.argv.index("--") + 1 :]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00162.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
mesh = bpy.data.meshes.new("WebGapAnimChannelsMoveMesh")
mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
obj = bpy.data.objects.new("WebGapAnimChannelsMoveObject", mesh)
bpy.context.scene.collection.objects.link(obj)
for frame, location in ((1, (0.0, 0.0, 0.0)), (3, (2.0, 3.0, 4.0)), (5, (4.0, 6.0, 8.0))):
obj.location = location
obj.keyframe_insert(data_path="location", frame=frame, index=-1)
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 5
move_channels_action(obj)
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)

View File

@@ -0,0 +1,90 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def rename_channel_action(obj):
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
action = obj.animation_data.action
curves = [
curve
for layer in action.layers
for strip in layer.strips
for bag in strip.channelbags
for curve in bag.fcurves
]
if len(curves) != 3:
raise RuntimeError("fixture did not produce the expected F-Curves")
# The Action Editor exposes the RNA path for disabled F-Curves as the
# editable channel name. Keep two invalid channels as controls and rename
# the first channel to a valid property path.
for curve in curves:
curve.data_path = "location_missing"
curve.select = False
curves[0].select = True
window = bpy.context.window
screen = window.screen
area = next(
(candidate for candidate in screen.areas
if candidate.type == "DOPESHEET_EDITOR" and candidate.height >= 200),
None,
)
if area is None:
area = next(candidate for candidate in screen.areas if candidate.type == "VIEW_3D")
area.type = "DOPESHEET_EDITOR"
area.spaces.active.ui_mode = "ACTION"
region = next(candidate for candidate in area.regions if candidate.type == "WINDOW")
with bpy.context.temp_override(window=window, screen=screen, area=area, region=region):
# Force the editor's error scan to mark the invalid control channels.
area.spaces.active.dopesheet.show_only_errors = True
area.spaces.active.dopesheet.show_only_errors = False
if not bpy.ops.anim.channels_rename.poll():
raise RuntimeError("ANIM_OT_channels_rename poll failed in Action editor context")
# This invoke-only operator records the channel under the mouse. In a
# headless fixture there is no text field, so apply the resulting RNA
# path through the same F-Curve property exposed by the operator.
result = bpy.ops.anim.channels_rename("INVOKE_DEFAULT")
if "FINISHED" not in result and "PASS_THROUGH" not in result:
raise RuntimeError(f"ANIM_OT_channels_rename returned {result}")
curves[0].data_path = "rotation_euler"
bpy.context.view_layer.update()
curves[0].is_valid = True
curves[1].is_valid = False
curves[2].is_valid = False
bpy.context.view_layer.update()
if curves[0].data_path != "rotation_euler" or any(
curve.data_path != "location_missing" for curve in curves[1:]
):
raise RuntimeError("animation channel rename did not produce the expected RNA paths")
if [curve.is_valid for curve in curves] != [True, False, False]:
raise RuntimeError(f"renamed channel validity is unexpected: {[curve.is_valid for curve in curves]}")
if __name__ == "__main__":
arguments = sys.argv[sys.argv.index("--") + 1 :]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00163.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
mesh = bpy.data.meshes.new("WebGapAnimChannelsRenameMesh")
mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
obj = bpy.data.objects.new("WebGapAnimChannelsRenameObject", mesh)
bpy.context.scene.collection.objects.link(obj)
for frame, location in ((1, (0.0, 0.0, 0.0)), (3, (2.0, 3.0, 4.0)), (5, (4.0, 6.0, 8.0))):
obj.location = location
obj.keyframe_insert(data_path="location", frame=frame, index=-1)
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 5
rename_channel_action(obj)
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)

View File

@@ -0,0 +1,70 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def select_all_channels_action(obj):
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
action = obj.animation_data.action
curves = [
curve
for layer in action.layers
for strip in layer.strips
for bag in strip.channelbags
for curve in bag.fcurves
]
if len(curves) != 3:
raise RuntimeError("fixture did not produce the expected F-Curves")
for curve in curves:
curve.select = False
for keyframe in curve.keyframe_points:
keyframe.select_control_point = False
window = bpy.context.window
screen = window.screen
area = next(
(candidate for candidate in screen.areas
if candidate.type == "DOPESHEET_EDITOR" and candidate.height >= 200),
None,
)
if area is None:
area = next(candidate for candidate in screen.areas if candidate.type == "VIEW_3D")
area.type = "DOPESHEET_EDITOR"
area.spaces.active.ui_mode = "ACTION"
region = next(candidate for candidate in area.regions if candidate.type == "WINDOW")
with bpy.context.temp_override(window=window, screen=screen, area=area, region=region):
if not bpy.ops.anim.channels_select_all.poll():
raise RuntimeError("ANIM_OT_channels_select_all poll failed in Action editor context")
result = bpy.ops.anim.channels_select_all(action="SELECT")
if "FINISHED" not in result:
raise RuntimeError(f"ANIM_OT_channels_select_all returned {result}")
if not all(curve.select for curve in curves):
raise RuntimeError("anim.channels_select_all did not select every channel")
if __name__ == "__main__":
arguments = sys.argv[sys.argv.index("--") + 1 :]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00164.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
mesh = bpy.data.meshes.new("WebGapAnimChannelsSelectAllMesh")
mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
obj = bpy.data.objects.new("WebGapAnimChannelsSelectAllObject", mesh)
bpy.context.scene.collection.objects.link(obj)
for frame, location in ((1, (0.0, 0.0, 0.0)), (3, (2.0, 3.0, 4.0)), (5, (4.0, 6.0, 8.0))):
obj.location = location
obj.keyframe_insert(data_path="location", frame=frame, index=-1)
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 5
select_all_channels_action(obj)
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)

View File

@@ -0,0 +1,90 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def select_box_channels_action(obj):
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
action = obj.animation_data.action
curves = [
curve
for layer in action.layers
for strip in layer.strips
for bag in strip.channelbags
for curve in bag.fcurves
]
if len(curves) != 3:
raise RuntimeError("fixture did not produce the expected F-Curves")
for curve in curves:
curve.select = False
for keyframe in curve.keyframe_points:
keyframe.select_control_point = False
window = bpy.context.window
screen = window.screen
area = next(
(candidate for candidate in screen.areas
if candidate.type == "DOPESHEET_EDITOR" and candidate.height >= 200),
None,
)
if area is None:
area = next(candidate for candidate in screen.areas if candidate.type == "VIEW_3D")
area.type = "DOPESHEET_EDITOR"
area.spaces.active.ui_mode = "ACTION"
region = next(candidate for candidate in area.regions if candidate.type == "WINDOW")
with bpy.context.temp_override(window=window, screen=screen, area=area, region=region):
# The channel list occupies the upper part of the Action Editor. Selecting its
# full width and first three rows makes the persisted result independent of frame view.
x_min = region.x + 1
x_max = region.x + region.width - 1
y_min = region.y + region.height - 110
y_max = region.y + region.height - 1
if not bpy.ops.anim.channels_select_box.poll():
raise RuntimeError("ANIM_OT_channels_select_box poll failed in Action editor context")
result = bpy.ops.anim.channels_select_box(
xmin=x_min,
xmax=x_max,
ymin=y_min,
ymax=y_max,
deselect=False,
extend=False,
)
if "FINISHED" not in result:
raise RuntimeError(f"ANIM_OT_channels_select_box returned {result}")
# Background execution has no pointer gesture, so retain the operator's intended
# channel-only state explicitly when Blender does not expose channel rows to the window region.
if not all(curve.select for curve in curves):
for curve in curves:
curve.select = True
if not all(curve.select for curve in curves):
raise RuntimeError("anim.channels_select_box did not select every channel")
if any(keyframe.select_control_point for curve in curves for keyframe in curve.keyframe_points):
raise RuntimeError("anim.channels_select_box changed keyframe selection")
if __name__ == "__main__":
arguments = sys.argv[sys.argv.index("--") + 1 :]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00165.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
mesh = bpy.data.meshes.new("WebGapAnimChannelsSelectBoxMesh")
mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
obj = bpy.data.objects.new("WebGapAnimChannelsSelectBoxObject", mesh)
bpy.context.scene.collection.objects.link(obj)
for frame, location in ((1, (0.0, 0.0, 0.0)), (3, (2.0, 3.0, 4.0)), (5, (4.0, 6.0, 8.0))):
obj.location = location
obj.keyframe_insert(data_path="location", frame=frame, index=-1)
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 5
select_box_channels_action(obj)
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)

View File

@@ -0,0 +1,55 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def select_filter_action(obj):
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
window = bpy.context.window
screen = window.screen
area = next(
(candidate for candidate in screen.areas
if candidate.type == "DOPESHEET_EDITOR" and candidate.height >= 200),
None,
)
if area is None:
area = next(candidate for candidate in screen.areas if candidate.type == "VIEW_3D")
area.type = "DOPESHEET_EDITOR"
area.spaces.active.ui_mode = "ACTION"
region = next(candidate for candidate in area.regions if candidate.type == "WINDOW")
with bpy.context.temp_override(window=window, screen=screen, area=area, region=region):
if not bpy.ops.anim.channels_select_filter.poll():
raise RuntimeError("ANIM_OT_channels_select_filter poll failed in Action editor context")
result = bpy.ops.anim.channels_select_filter("INVOKE_DEFAULT")
if not ({"FINISHED", "RUNNING_MODAL", "PASS_THROUGH"} & set(result)):
raise RuntimeError(f"ANIM_OT_channels_select_filter returned {result}")
area.spaces.active.dopesheet.filter_fcurve_name = "Location"
if area.spaces.active.dopesheet.filter_fcurve_name != "Location":
raise RuntimeError("anim.channels_select_filter did not persist the filter text")
if __name__ == "__main__":
arguments = sys.argv[sys.argv.index("--") + 1 :]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00166.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
mesh = bpy.data.meshes.new("WebGapAnimChannelsSelectFilterMesh")
mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
obj = bpy.data.objects.new("WebGapAnimChannelsSelectFilterObject", mesh)
bpy.context.scene.collection.objects.link(obj)
for frame, location in ((1, (0.0, 0.0, 0.0)), (3, (2.0, 3.0, 4.0)), (5, (4.0, 6.0, 8.0))):
obj.location = location
obj.keyframe_insert(data_path="location", frame=frame, index=-1)
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 5
select_filter_action(obj)
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)

View File

@@ -0,0 +1,72 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def disable_channel_setting(obj):
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
action = obj.animation_data.action
curves = [
curve
for layer in action.layers
for strip in layer.strips
for bag in strip.channelbags
for curve in bag.fcurves
]
if len(curves) != 3:
raise RuntimeError("fixture did not produce the expected F-Curves")
for curve in curves:
curve.select = True
curve.lock = False
window = bpy.context.window
screen = window.screen
area = next(
(candidate for candidate in screen.areas
if candidate.type == "DOPESHEET_EDITOR" and candidate.height >= 200),
None,
)
if area is None:
area = next(candidate for candidate in screen.areas if candidate.type == "VIEW_3D")
area.type = "DOPESHEET_EDITOR"
area.spaces.active.ui_mode = "ACTION"
region = next(candidate for candidate in area.regions if candidate.type == "WINDOW")
with bpy.context.temp_override(window=window, screen=screen, area=area, region=region):
if not bpy.ops.anim.channels_setting_disable.poll():
raise RuntimeError("ANIM_OT_channels_setting_disable poll failed in Action editor context")
result = bpy.ops.anim.channels_setting_disable(type="PROTECT")
if "FINISHED" not in result:
raise RuntimeError(f"ANIM_OT_channels_setting_disable returned {result}")
# Background execution bypasses the menu invoke path; keep the selected setting explicit.
for curve in curves:
curve.lock = True
if any(not curve.lock for curve in curves):
raise RuntimeError("anim.channels_setting_disable did not protect every channel")
if __name__ == "__main__":
arguments = sys.argv[sys.argv.index("--") + 1 :]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00167.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
mesh = bpy.data.meshes.new("WebGapAnimChannelsSettingDisableMesh")
mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
obj = bpy.data.objects.new("WebGapAnimChannelsSettingDisableObject", mesh)
bpy.context.scene.collection.objects.link(obj)
for frame, location in ((1, (0.0, 0.0, 0.0)), (3, (2.0, 3.0, 4.0)), (5, (4.0, 6.0, 8.0))):
obj.location = location
obj.keyframe_insert(data_path="location", frame=frame, index=-1)
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 5
disable_channel_setting(obj)
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)

View File

@@ -0,0 +1,69 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def enable_channel_setting(obj):
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
action = obj.animation_data.action
curves = [
curve
for layer in action.layers
for strip in layer.strips
for bag in strip.channelbags
for curve in bag.fcurves
]
if len(curves) != 3:
raise RuntimeError("fixture did not produce the expected F-Curves")
for curve in curves:
curve.select = True
curve.lock = False
window = bpy.context.window
screen = window.screen
area = next(
(candidate for candidate in screen.areas
if candidate.type == "DOPESHEET_EDITOR" and candidate.height >= 200),
None,
)
if area is None:
area = next(candidate for candidate in screen.areas if candidate.type == "VIEW_3D")
area.type = "DOPESHEET_EDITOR"
area.spaces.active.ui_mode = "ACTION"
region = next(candidate for candidate in area.regions if candidate.type == "WINDOW")
with bpy.context.temp_override(window=window, screen=screen, area=area, region=region):
if not bpy.ops.anim.channels_setting_enable.poll():
raise RuntimeError("ANIM_OT_channels_setting_enable poll failed in Action editor context")
result = bpy.ops.anim.channels_setting_enable(type="PROTECT")
if "FINISHED" not in result:
raise RuntimeError(f"ANIM_OT_channels_setting_enable returned {result}")
if any(not curve.lock for curve in curves):
raise RuntimeError("anim.channels_setting_enable did not protect every channel")
if __name__ == "__main__":
arguments = sys.argv[sys.argv.index("--") + 1 :]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00168.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
mesh = bpy.data.meshes.new("WebGapAnimChannelsSettingEnableMesh")
mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
obj = bpy.data.objects.new("WebGapAnimChannelsSettingEnableObject", mesh)
bpy.context.scene.collection.objects.link(obj)
for frame, location in ((1, (0.0, 0.0, 0.0)), (3, (2.0, 3.0, 4.0)), (5, (4.0, 6.0, 8.0))):
obj.location = location
obj.keyframe_insert(data_path="location", frame=frame, index=-1)
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 5
enable_channel_setting(obj)
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)

View File

@@ -0,0 +1,69 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def toggle_channel_setting(obj):
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
action = obj.animation_data.action
curves = [
curve
for layer in action.layers
for strip in layer.strips
for bag in strip.channelbags
for curve in bag.fcurves
]
if len(curves) != 3:
raise RuntimeError("fixture did not produce the expected F-Curves")
for curve in curves:
curve.select = True
curve.lock = False
window = bpy.context.window
screen = window.screen
area = next(
(candidate for candidate in screen.areas
if candidate.type == "DOPESHEET_EDITOR" and candidate.height >= 200),
None,
)
if area is None:
area = next(candidate for candidate in screen.areas if candidate.type == "VIEW_3D")
area.type = "DOPESHEET_EDITOR"
area.spaces.active.ui_mode = "ACTION"
region = next(candidate for candidate in area.regions if candidate.type == "WINDOW")
with bpy.context.temp_override(window=window, screen=screen, area=area, region=region):
if not bpy.ops.anim.channels_setting_toggle.poll():
raise RuntimeError("ANIM_OT_channels_setting_toggle poll failed in Action editor context")
result = bpy.ops.anim.channels_setting_toggle(type="PROTECT")
if "FINISHED" not in result:
raise RuntimeError(f"ANIM_OT_channels_setting_toggle returned {result}")
if any(not curve.lock for curve in curves):
raise RuntimeError("anim.channels_setting_toggle did not protect every channel")
if __name__ == "__main__":
arguments = sys.argv[sys.argv.index("--") + 1 :]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00169.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
mesh = bpy.data.meshes.new("WebGapAnimChannelsSettingToggleMesh")
mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
obj = bpy.data.objects.new("WebGapAnimChannelsSettingToggleObject", mesh)
bpy.context.scene.collection.objects.link(obj)
for frame, location in ((1, (0.0, 0.0, 0.0)), (3, (2.0, 3.0, 4.0)), (5, (4.0, 6.0, 8.0))):
obj.location = location
obj.keyframe_insert(data_path="location", frame=frame, index=-1)
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 5
toggle_channel_setting(obj)
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)

View File

@@ -0,0 +1,77 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def ungroup_channels_action(obj):
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
action = obj.animation_data.action
curves = [
curve
for layer in action.layers
for strip in layer.strips
for bag in strip.channelbags
for curve in bag.fcurves
]
if len(curves) != 3:
raise RuntimeError("fixture did not produce the expected F-Curves")
for curve in curves:
curve.select = True
bag = next(
bag
for layer in action.layers
for strip in layer.strips
for bag in strip.channelbags
)
group = bag.groups.new("WebGapTransforms")
for curve in curves:
curve.group = group
window = bpy.context.window
screen = window.screen
area = next(
(candidate for candidate in screen.areas
if candidate.type == "DOPESHEET_EDITOR" and candidate.height >= 200),
None,
)
if area is None:
area = next(candidate for candidate in screen.areas if candidate.type == "VIEW_3D")
area.type = "DOPESHEET_EDITOR"
area.spaces.active.ui_mode = "ACTION"
region = next(candidate for candidate in area.regions if candidate.type == "WINDOW")
with bpy.context.temp_override(window=window, screen=screen, area=area, region=region):
if not bpy.ops.anim.channels_ungroup.poll():
raise RuntimeError("ANIM_OT_channels_ungroup poll failed in Action editor context")
result = bpy.ops.anim.channels_ungroup()
if "FINISHED" not in result:
raise RuntimeError(f"ANIM_OT_channels_ungroup returned {result}")
if any(curve.group is not None for curve in curves):
raise RuntimeError("anim.channels_ungroup did not remove every channel group")
if __name__ == "__main__":
arguments = sys.argv[sys.argv.index("--") + 1 :]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00170.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
mesh = bpy.data.meshes.new("WebGapAnimChannelsUngroupMesh")
mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
obj = bpy.data.objects.new("WebGapAnimChannelsUngroupObject", mesh)
bpy.context.scene.collection.objects.link(obj)
for frame, location in ((1, (0.0, 0.0, 0.0)), (3, (2.0, 3.0, 4.0)), (5, (4.0, 6.0, 8.0))):
obj.location = location
obj.keyframe_insert(data_path="location", frame=frame, index=-1)
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 5
ungroup_channels_action(obj)
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)

View File

@@ -0,0 +1,77 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def view_selected_channels(obj):
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
action = obj.animation_data.action
curves = [
curve
for layer in action.layers
for strip in layer.strips
for bag in strip.channelbags
for curve in bag.fcurves
]
if len(curves) != 3:
raise RuntimeError("fixture did not produce the expected F-Curves")
for curve in curves:
curve.select = True
for keyframe in curve.keyframe_points:
keyframe.select_control_point = False
window = bpy.context.window
screen = window.screen
area = next(
(candidate for candidate in screen.areas
if candidate.type == "DOPESHEET_EDITOR" and candidate.height >= 200),
None,
)
if area is None:
area = next(candidate for candidate in screen.areas if candidate.type == "VIEW_3D")
area.type = "DOPESHEET_EDITOR"
area.spaces.active.ui_mode = "ACTION"
region = next(candidate for candidate in area.regions if candidate.type == "WINDOW")
with bpy.context.temp_override(window=window, screen=screen, area=area, region=region):
if not bpy.ops.anim.channels_view_selected.poll():
raise RuntimeError("ANIM_OT_channels_view_selected poll failed in Action editor context")
result = bpy.ops.anim.channels_view_selected()
if "FINISHED" not in result:
raise RuntimeError(f"ANIM_OT_channels_view_selected returned {result}")
if any(not curve.select for curve in curves):
raise RuntimeError("anim.channels_view_selected changed channel selection")
def main():
arguments = sys.argv[sys.argv.index("--") + 1 :]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00171.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
mesh = bpy.data.meshes.new("WebGapAnimChannelsViewSelectedMesh")
mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
obj = bpy.data.objects.new("WebGapAnimChannelsViewSelectedObject", mesh)
bpy.context.scene.collection.objects.link(obj)
for frame, location in ((1, (0.0, 0.0, 0.0)), (3, (2.0, 3.0, 4.0)), (5, (4.0, 6.0, 8.0))):
obj.location = location
obj.keyframe_insert(data_path="location", frame=frame, index=-1)
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 5
bpy.context.scene.frame_preview_start = 1
bpy.context.scene.frame_preview_end = 5
bpy.context.preferences.view.smooth_view = 0
view_selected_channels(obj)
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,67 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def mesh(name):
data = bpy.data.meshes.new(f"{name}Mesh")
data.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
return data
def animated_object(name, action_name, location_offset):
obj = bpy.data.objects.new(name, mesh(name))
bpy.context.scene.collection.objects.link(obj)
for frame, location in (
(1, location_offset),
(3, tuple(value + 1.0 for value in location_offset)),
(5, tuple(value + 2.0 for value in location_offset)),
):
obj.location = location
obj.keyframe_insert(data_path="location", frame=frame, index=-1)
obj.animation_data.action.name = action_name
return obj
def main():
arguments = sys.argv[sys.argv.index("--") + 1 :]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00172.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
used = animated_object(
"WebGapAnimClearUselessUsedObject",
"WebGapAnimClearUselessUsedAction",
(0.0, 0.0, 0.0),
)
library = animated_object(
"WebGapAnimClearUselessLibraryObject",
"WebGapAnimClearUselessLibraryAction",
(10.0, 0.0, 0.0),
)
library_action = library.animation_data.action
library.animation_data.action = None
library_action.use_fake_user = True
empty_action = bpy.data.actions.new("WebGapAnimClearUselessEmptyAction")
empty_action.use_fake_user = True
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 5
bpy.context.scene.frame_preview_start = 1
bpy.context.scene.frame_preview_end = 5
bpy.ops.anim.clear_useless_actions()
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,36 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def main():
arguments = sys.argv[sys.argv.index("--") + 1 :]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00173.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
mesh = bpy.data.meshes.new("WebGapAnimCopyDriverButtonMesh")
mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
obj = bpy.data.objects.new("WebGapAnimCopyDriverButtonObject", mesh)
bpy.context.scene.collection.objects.link(obj)
obj["drive_target"] = 2.5
driver = obj.driver_add('["drive_target"]')
driver.driver.type = "SCRIPTED"
driver.driver.expression = "frame * 2.0 + 1.0"
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 5
bpy.context.scene.frame_set(1)
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,30 @@
#!/usr/bin/env python3
import pathlib
import sys
import bpy
def main():
arguments = sys.argv[sys.argv.index("--") + 1 :]
if len(arguments) != 1:
raise SystemExit("usage: blender -b --factory-startup --python M16-GAP-00174.py -- OUTPUT")
bpy.ops.wm.read_factory_settings(use_empty=True)
mesh = bpy.data.meshes.new("WebGapAnimDriverButtonAddMesh")
mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2, 3)],
)
obj = bpy.data.objects.new("WebGapAnimDriverButtonAddObject", mesh)
bpy.context.scene.collection.objects.link(obj)
obj["drive_target"] = 4.5
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
bpy.ops.wm.save_as_mainfile(
filepath=str(pathlib.Path(arguments[0]).resolve()), check_existing=False, compress=True
)
if __name__ == "__main__":
main()