Skip to content
This repository was archived by the owner on May 9, 2025. It is now read-only.

Commit 61efd17

Browse files
committed
After Effects export: export multiple cameras when using markers
In previous versions, when using markers to switch between cameras, a single animated camera would be exported. This would cause motion blur issues when the camera would jump quickly and unexpectedly between two positions. Instead, we now export all marker cameras, but restrict their time range to switch between them. If a camera is used multiple times through a shot, as many cameras with the same name will be exported.
1 parent e45c150 commit 61efd17

File tree

1 file changed

+28
-7
lines changed

1 file changed

+28
-7
lines changed

io_export_after_effects.py

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"description": "Export cameras, selected objects & camera solution "
2424
"3D Markers to Adobe After Effects CS3 and above",
2525
"author": "Bartek Skorupa, Damien Picard (@pioverfour)",
26-
"version": (0, 1, 1),
26+
"version": (0, 1, 2),
2727
"blender": (2, 80, 0),
2828
"location": "File > Export > Adobe After Effects (.jsx)",
2929
"warning": "",
@@ -144,6 +144,11 @@ def get_post_script(self):
144144
return ""
145145

146146
class CameraExport(ObjectExport):
147+
def __init__(self, obj, start_time=None, end_time=None):
148+
super().__init__(obj)
149+
self.start_time = start_time
150+
self.end_time = end_time
151+
147152
def get_keyframe(self, context, width, height, aspect, time, ae_size):
148153
ae_transform = convert_transform_matrix(self.obj.matrix_world,
149154
width, height, aspect, ae_size)
@@ -156,6 +161,10 @@ def get_keyframe(self, context, width, height, aspect, time, ae_size):
156161

157162
def get_type_script(self):
158163
type_script = f'var {self.name_ae} = newComp.layers.addCamera("{self.name_ae}",[0,0]);\n'
164+
# Restrict time range when multiple cameras are used (markers)
165+
if self.start_time is not None:
166+
type_script += f'{self.name_ae}.inPoint = {self.start_time};\n'
167+
type_script += f'{self.name_ae}.outPoint = {self.end_time};\n'
159168
type_script += f'{self.name_ae}.autoOrient = AutoOrientType.NO_AUTO_ORIENT;\n'
160169
return type_script
161170

@@ -324,17 +333,29 @@ def get_selected(context, include_active_cam, include_selected_cams,
324333
cam_bundles = [] # Camera trackers exported as AE nulls
325334
nulls = [] # Remaining objects exported as AE nulls
326335

336+
scene = context.scene
337+
fps = scene.render.fps / scene.render.fps_base
338+
327339
if context.scene.camera is not None:
328340
if include_active_cam:
329-
cameras.append(CameraExport(context.scene.camera))
330-
if include_cam_bundles:
331-
cam_bundles.extend(get_camera_bundles(context.scene, context.scene.camera))
341+
for frame_range, camera in get_camera_frame_ranges(
342+
context.scene,
343+
context.scene.frame_start, context.scene.frame_end):
344+
345+
if (include_cam_bundles
346+
and camera not in (cam.obj for cam in cameras)):
347+
cam_bundles.extend(
348+
get_camera_bundles(context.scene, camera))
349+
350+
cameras.append(
351+
CameraExport(camera,
352+
(frame_range[0] - scene.frame_start) / fps,
353+
(frame_range[1] - scene.frame_start) / fps))
332354

333355
for obj in context.selected_objects:
334356
if obj.type == 'CAMERA':
335-
if (include_active_cam
336-
and obj is context.scene.camera):
337-
# Ignore active camera if already selected
357+
# Ignore camera if already selected
358+
if obj in (cam.obj for cam in cameras):
338359
continue
339360
if include_selected_cams:
340361
cameras.append(CameraExport(obj))

0 commit comments

Comments
 (0)