mirror of
https://github.com/blender/blender
synced 2026-09-29 04:37:17 +03:00
Alembic: support camera and visibility animation via FCurves
This adds support to import animations on the various camera properties and on object visibilities via FCurves for non-sequence Alembic files. This adds a single routine `create_keyframes` to create FCurves for all objects which need some for the entire duration of the animation in the archive. The FCurves creation and key frame addition are done via some newly added `FCurveCreationHelper` objects which are created and gathered during object creation if need be. For camera data animation, as Alembic does not separate the various properties into separate sample arrays, we initially create FCurves for all properties and remove the ones which were unnecessary at the end. Ref: #69191 Ref: #54050 See PR for video examples. Pull Request: https://projects.blender.org/blender/blender/pulls/158321
This commit is contained in:
parent
0972fef660
commit
fab51c3e35
11 changed files with 504 additions and 7 deletions
|
|
@ -499,6 +499,83 @@ class AlembicVisibilityImportTests(AbstractAlembicTest):
|
|||
self.assertObjectVisible('HIDDEN')
|
||||
|
||||
|
||||
class AlembicAnimatedVisibilityImportTests(AbstractAlembicTest):
|
||||
def test_import_visibility_animated(self):
|
||||
res = bpy.ops.wm.alembic_import(
|
||||
filepath=str(self.testdir / "visibility-animated.abc"),
|
||||
as_background_job=False)
|
||||
self.assertEqual({'FINISHED'}, res)
|
||||
|
||||
view_layer = bpy.context.view_layer
|
||||
|
||||
# The object was written to be visible on frames following the Fibonacci sequence
|
||||
a = 0
|
||||
b = 1
|
||||
next_fib = a + b
|
||||
|
||||
# Compare visibility against the expected value for every frame
|
||||
for frame in range(1, 25):
|
||||
bpy.context.scene.frame_set(frame)
|
||||
depsgraph = bpy.context.evaluated_depsgraph_get()
|
||||
point_object = bpy.data.objects["ANIMATED"].evaluated_get(depsgraph)
|
||||
|
||||
is_hidden = True
|
||||
|
||||
if frame == next_fib:
|
||||
a = b
|
||||
b = next_fib
|
||||
next_fib = a + b
|
||||
is_hidden = False
|
||||
|
||||
# Unlike static visibility, animated visibility by default should not set the visibility on the `Base`
|
||||
self.assertEqual(point_object.hide_get(view_layer=view_layer), False)
|
||||
self.assertEqual(point_object.hide_viewport, is_hidden)
|
||||
self.assertEqual(point_object.hide_render, is_hidden)
|
||||
|
||||
|
||||
class AlembicAnimatedCameraImportTests(AbstractAlembicTest):
|
||||
def test_import_camera_data_animation(self):
|
||||
res = bpy.ops.wm.alembic_import(
|
||||
filepath=str(self.testdir / "camera-data-animated.abc"),
|
||||
as_background_job=False)
|
||||
self.assertEqual({'FINISHED'}, res)
|
||||
|
||||
view_layer = bpy.context.view_layer
|
||||
|
||||
# Compare Blender data against the expected value for every frame
|
||||
for frame in range(1, 26):
|
||||
bpy.context.scene.frame_set(frame)
|
||||
depsgraph = bpy.context.evaluated_depsgraph_get()
|
||||
camera_object = bpy.data.objects["Camera"].evaluated_get(depsgraph)
|
||||
camera = camera_object.data
|
||||
|
||||
lens = 50.0 + frame
|
||||
shift = (frame - 1) * (1.0 / 24.0)
|
||||
clip = frame
|
||||
|
||||
self.assertEqual(
|
||||
lens,
|
||||
camera.lens,
|
||||
f"Frame {frame}: {camera_object.name} lens values do not match")
|
||||
|
||||
self.assertAlmostEqual(
|
||||
shift,
|
||||
camera.shift_x,
|
||||
places=6,
|
||||
msg=f"Frame {frame}: {camera_object.name} shift_x values do not match")
|
||||
|
||||
self.assertAlmostEqual(
|
||||
shift,
|
||||
camera.shift_y,
|
||||
places=6,
|
||||
msg=f"Frame {frame}: {camera_object.name} shift_y values do not match")
|
||||
|
||||
self.assertEqual(
|
||||
clip,
|
||||
camera.clip_start,
|
||||
f"Frame {frame}: {camera_object.name} clip_start values do not match")
|
||||
|
||||
|
||||
class AlembicImportComparisonTests(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue