Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormeta-androcto <meta.androcto1@gmail.com>2019-05-24 04:34:21 +0300
committermeta-androcto <meta.androcto1@gmail.com>2019-05-24 04:34:21 +0300
commit4e7735c70026b0a1d55d2e6e1cb445f83be8b05e (patch)
tree120d8c2f8edeecc9eae3140f189f5738ec56430e /io_export_after_effects.py
parent0704ebc48b4762a4f3c6b4a1252abb514d7f21db (diff)
io_export_after_effects: move to contrib: T63750
Diffstat (limited to 'io_export_after_effects.py')
-rw-r--r--io_export_after_effects.py779
1 files changed, 0 insertions, 779 deletions
diff --git a/io_export_after_effects.py b/io_export_after_effects.py
deleted file mode 100644
index c0afe51f..00000000
--- a/io_export_after_effects.py
+++ /dev/null
@@ -1,779 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-# <pep8 compliant>
-
-bl_info = {
- "name": "Export: Adobe After Effects (.jsx)",
- "description": "Export cameras, selected objects & camera solution "
- "3D Markers to Adobe After Effects CS3 and above",
- "author": "Bartek Skorupa",
- "version": (0, 65),
- "blender": (2, 79, 0),
- "location": "File > Export > Adobe After Effects (.jsx)",
- "warning": "",
- "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/"
- "Scripts/Import-Export/Adobe_After_Effects",
- "category": "Import-Export",
-}
-
-
-import bpy
-import datetime
-from math import degrees, floor
-from mathutils import Matrix
-
-
-# create list of static blender's data
-def get_comp_data(context):
- scene = context.scene
- aspect_x = scene.render.pixel_aspect_x
- aspect_y = scene.render.pixel_aspect_y
- aspect = aspect_x / aspect_y
- start = scene.frame_start
- end = scene.frame_end
- active_cam_frames = get_active_cam_for_each_frame(scene, start, end)
- fps = floor(scene.render.fps / (scene.render.fps_base) * 1000.0) / 1000.0
-
- return {
- 'scn': scene,
- 'width': scene.render.resolution_x,
- 'height': scene.render.resolution_y,
- 'aspect': aspect,
- 'fps': fps,
- 'start': start,
- 'end': end,
- 'duration': (end - start + 1.0) / fps,
- 'active_cam_frames': active_cam_frames,
- 'curframe': scene.frame_current,
- }
-
-
-# create list of active camera for each frame in case active camera is set by markers
-def get_active_cam_for_each_frame(scene, start, end):
- active_cam_frames = []
- sorted_markers = []
- markers = scene.timeline_markers
- if markers:
- for marker in markers:
- if marker.camera:
- sorted_markers.append([marker.frame, marker])
- sorted_markers = sorted(sorted_markers)
-
- if sorted_markers:
- for frame in range(start, end + 1):
- for m, marker in enumerate(sorted_markers):
- if marker[0] > frame:
- if m != 0:
- active_cam_frames.append(sorted_markers[m - 1][1].camera)
- else:
- active_cam_frames.append(marker[1].camera)
- break
- elif m == len(sorted_markers) - 1:
- active_cam_frames.append(marker[1].camera)
- if not active_cam_frames:
- if scene.camera:
- # in this case active_cam_frames array will have legth of 1. This will indicate that there is only one active cam in all frames
- active_cam_frames.append(scene.camera)
-
- return(active_cam_frames)
-
-
-# create manageable list of selected objects
-def get_selected(context):
- cameras = [] # list of selected cameras
- solids = [] # list of all selected meshes that can be exported as AE's solids
- lights = [] # list of all selected lamps that can be exported as AE's lights
- nulls = [] # list of all selected objects except cameras (will be used to create nulls in AE)
- obs = context.selected_objects
-
- for ob in obs:
- if ob.type == 'CAMERA':
- cameras.append([ob, convert_name(ob.name)])
-
- elif is_plane(ob):
- # not ready yet. is_plane(object) returns False in all cases. This is temporary
- solids.append([ob, convert_name(ob.name)])
-
- elif ob.type == 'LIGHT':
- lights.append([ob, ob.data.type + convert_name(ob.name)]) # Type of lamp added to name
-
- else:
- nulls.append([ob, convert_name(ob.name)])
-
- selection = {
- 'cameras': cameras,
- 'solids': solids,
- 'lights': lights,
- 'nulls': nulls,
- }
-
- return selection
-
-
-# check if object is plane and can be exported as AE's solid
-def is_plane(object):
- # work in progress. Not ready yet
- return False
-
-
-# convert names of objects to avoid errors in AE.
-def convert_name(name):
- name = "_" + name
- '''
- # Digits are not allowed at beginning of AE vars names.
- # This section is commented, as "_" is added at beginning of names anyway.
- # Placeholder for this name modification is left so that it's not ignored if needed
- if name[0].isdigit():
- name = "_" + name
- '''
- name = bpy.path.clean_name(name)
- name = name.replace("-", "_")
-
- return name
-
-
-# get object's blender's location rotation and scale and return AE's Position, Rotation/Orientation and scale
-# this function will be called for every object for every frame
-def convert_transform_matrix(matrix, width, height, aspect, x_rot_correction=False, ae_size=100.0):
-
- # get blender transform data for ob
- b_loc = matrix.to_translation()
- b_rot = matrix.to_euler('ZYX') # ZYX euler matches AE's orientation and allows to use x_rot_correction
- b_scale = matrix.to_scale()
-
- # convert to AE Position Rotation and Scale
- # Axes in AE are different. AE's X is blender's X, AE's Y is negative Blender's Z, AE's Z is Blender's Y
- x = (b_loc.x * ae_size) / aspect + width / 2.0 # calculate AE's X position
- y = (-b_loc.z * ae_size) + (height / 2.0) # calculate AE's Y position
- z = b_loc.y * ae_size # calculate AE's Z position
- # Convert rotations to match AE's orientation.
- rx = degrees(b_rot.x) # if not x_rot_correction - AE's X orientation = blender's X rotation if 'ZYX' euler.
- ry = -degrees(b_rot.y) # AE's Y orientation is negative blender's Y rotation if 'ZYX' euler
- rz = -degrees(b_rot.z) # AE's Z orientation is negative blender's Z rotation if 'ZYX' euler
- if x_rot_correction:
- rx -= 90.0 # In blender - ob of zero rotation lay on floor. In AE layer of zero orientation "stands"
- # Convert scale to AE scale
- sx = b_scale.x * 100.0 # scale of 1.0 is 100% in AE
- sy = b_scale.z * 100.0 # scale of 1.0 is 100% in AE
- sz = b_scale.y * 100.0 # scale of 1.0 is 100% in AE
-
- return x, y, z, rx, ry, rz, sx, sy, sz
-
-# get camera's lens and convert to AE's "zoom" value in pixels
-# this function will be called for every camera for every frame
-#
-#
-# AE's lens is defined by "zoom" in pixels. Zoom determines focal angle or focal length.
-#
-# ZOOM VALUE CALCULATIONS:
-#
-# Given values:
-# - sensor width (camera.data.sensor_width)
-# - sensor height (camera.data.sensor_height)
-# - sensor fit (camera.data.sensor_fit)
-# - lens (blender's lens in mm)
-# - width (width of the composition/scene in pixels)
-# - height (height of the composition/scene in pixels)
-# - PAR (pixel aspect ratio)
-#
-# Calculations are made using sensor's size and scene/comp dimension (width or height).
-# If camera.sensor_fit is set to 'AUTO' or 'HORIZONTAL' - sensor = camera.data.sensor_width, dimension = width.
-# If camera.sensor_fit is set to 'VERTICAL' - sensor = camera.data.sensor_height, dimension = height
-#
-# zoom can be calculated using simple proportions.
-#
-# |
-# / |
-# / |
-# / | d
-# s |\ / | i
-# e | \ / | m
-# n | \ / | e
-# s | / \ | n
-# o | / \ | s
-# r |/ \ | i
-# \ | o
-# | | \ | n
-# | | \ |
-# | | |
-# lens | zoom
-#
-# zoom / dimension = lens / sensor =>
-# zoom = lens * dimension / sensor
-#
-# above is true if square pixels are used. If not - aspect compensation is needed, so final formula is:
-# zoom = lens * dimension / sensor * aspect
-
-
-def convert_lens(camera, width, height, aspect):
- if camera.data.sensor_fit == 'VERTICAL':
- sensor = camera.data.sensor_height
- dimension = height
- else:
- sensor = camera.data.sensor_width
- dimension = width
-
- zoom = camera.data.lens * dimension / sensor * aspect
-
- return zoom
-
-# convert object bundle's matrix. Not ready yet. Temporarily not active
-#def get_ob_bundle_matrix_world(cam_matrix_world, bundle_matrix):
-# matrix = cam_matrix_basis
-# return matrix
-
-
-# jsx script for AE creation
-def write_jsx_file(file, data, selection, include_animation, include_active_cam, include_selected_cams, include_selected_objects, include_cam_bundles, ae_size):
-
- print("\n---------------------------\n- Export to After Effects -\n---------------------------")
- # store the current frame to restore it at the end of export
- curframe = data['curframe']
- # create array which will contain all keyframes values
- js_data = {
- 'times': '',
- 'cameras': {},
- 'solids': {}, # not ready yet
- 'lights': {},
- 'nulls': {},
- 'bundles_cam': {},
- 'bundles_ob': {}, # not ready yet
- }
-
- # create structure for active camera/cameras
- active_cam_name = ''
- if include_active_cam and data['active_cam_frames'] != []:
- # check if more that one active cam exist (true if active cams set by markers)
- if len(data['active_cam_frames']) is 1:
- name_ae = convert_name(data['active_cam_frames'][0].name) # take name of the only active camera in scene
- else:
- name_ae = 'Active_Camera'
- active_cam_name = name_ae # store name to be used when creating keyframes for active cam.
- js_data['cameras'][name_ae] = {
- 'position': '',
- 'position_static': '',
- 'position_anim': False,
- 'orientation': '',
- 'orientation_static': '',
- 'orientation_anim': False,
- 'zoom': '',
- 'zoom_static': '',
- 'zoom_anim': False,
- }
-
- # create camera structure for selected cameras
- if include_selected_cams:
- for i, cam in enumerate(selection['cameras']): # more than one camera can be selected
- if cam[1] != active_cam_name:
- name_ae = selection['cameras'][i][1]
- js_data['cameras'][name_ae] = {
- 'position': '',
- 'position_static': '',
- 'position_anim': False,
- 'orientation': '',
- 'orientation_static': '',
- 'orientation_anim': False,
- 'zoom': '',
- 'zoom_static': '',
- 'zoom_anim': False,
- }
- '''
- # create structure for solids. Not ready yet. Temporarily not active
- for i, obj in enumerate(selection['solids']):
- name_ae = selection['solids'][i][1]
- js_data['solids'][name_ae] = {
- 'position': '',
- 'orientation': '',
- 'rotationX': '',
- 'scale': '',
- }
- '''
- # create structure for lights
- for i, obj in enumerate(selection['lights']):
- if include_selected_objects:
- name_ae = selection['lights'][i][1]
- js_data['lights'][name_ae] = {
- 'type': selection['lights'][i][0].data.type,
- 'energy': '',
- 'energy_static': '',
- 'energy_anim': False,
- 'cone_angle': '',
- 'cone_angle_static': '',
- 'cone_angle_anim': False,
- 'cone_feather': '',
- 'cone_feather_static': '',
- 'cone_feather_anim': False,
- 'color': '',
- 'color_static': '',
- 'color_anim': False,
- 'position': '',
- 'position_static': '',
- 'position_anim': False,
- 'orientation': '',
- 'orientation_static': '',
- 'orientation_anim': False,
- }
-
- # create structure for nulls
- for i, obj in enumerate(selection['nulls']): # nulls representing blender's obs except cameras, lamps and solids
- if include_selected_objects:
- name_ae = selection['nulls'][i][1]
- js_data['nulls'][name_ae] = {
- 'position': '',
- 'position_static': '',
- 'position_anim': False,
- 'orientation': '',
- 'orientation_static': '',
- 'orientation_anim': False,
- 'scale': '',
- 'scale_static': '',
- 'scale_anim': False,
- }
-
- # create structure for cam bundles including positions (cam bundles don't move)
- if include_cam_bundles:
- # go through each selected camera and active cameras
- selected_cams = []
- active_cams = []
- if include_active_cam:
- active_cams = data['active_cam_frames']
- if include_selected_cams:
- for cam in selection['cameras']:
- selected_cams.append(cam[0])
- # list of cameras that will be checked for 'CAMERA SOLVER'
- cams = list(set.union(set(selected_cams), set(active_cams)))
-
- for cam in cams:
- # go through each constraints of this camera
- for constraint in cam.constraints:
- # does the camera have a Camera Solver constraint
- if constraint.type == 'CAMERA_SOLVER':
- # Which movie clip does it use
- if constraint.use_active_clip:
- clip = data['scn'].active_clip
- else:
- clip = constraint.clip
-
- # go through each tracking point
- for track in clip.tracking.tracks:
- # Does this tracking point have a bundle (has its 3D position been solved)
- if track.has_bundle:
- # get the name of the tracker
- name_ae = convert_name(str(cam.name) + '__' + str(track.name))
- js_data['bundles_cam'][name_ae] = {
- 'position': '',
- }
- # bundles are in camera space. Transpose to world space
- matrix = Matrix.Translation(cam.matrix_basis.copy() * track.bundle)
- # convert the position into AE space
- ae_transform = convert_transform_matrix(matrix, data['width'], data['height'], data['aspect'], False, ae_size)
- js_data['bundles_cam'][name_ae]['position'] += '[%f,%f,%f],' % (ae_transform[0], ae_transform[1], ae_transform[2])
-
- # get all keyframes for each object and store in dico
- if include_animation:
- end = data['end'] + 1
- else:
- end = data['start'] + 1
- for frame in range(data['start'], end):
- print("working on frame: " + str(frame))
- data['scn'].frame_set(frame)
-
- # get time for this loop
- js_data['times'] += '%f ,' % ((frame - data['start']) / data['fps'])
-
- # keyframes for active camera/cameras
- if include_active_cam and data['active_cam_frames'] != []:
- if len(data['active_cam_frames']) == 1:
- cur_cam_index = 0
- else:
- cur_cam_index = frame - data['start']
- active_cam = data['active_cam_frames'][cur_cam_index]
- # get cam name
- name_ae = active_cam_name
- # convert cam transform properties to AE space
- ae_transform = convert_transform_matrix(active_cam.matrix_world.copy(), data['width'], data['height'], data['aspect'], True, ae_size)
- # convert Blender's lens to AE's zoom in pixels
- zoom = convert_lens(active_cam, data['width'], data['height'], data['aspect'])
- # store all values in dico
- position = '[%f,%f,%f],' % (ae_transform[0], ae_transform[1], ae_transform[2])
- orientation = '[%f,%f,%f],' % (ae_transform[3], ae_transform[4], ae_transform[5])
- zoom = '%f,' % (zoom)
- js_data['cameras'][name_ae]['position'] += position
- js_data['cameras'][name_ae]['orientation'] += orientation
- js_data['cameras'][name_ae]['zoom'] += zoom
- # Check if properties change values compared to previous frame
- # If property don't change through out the whole animation - keyframes won't be added
- if frame != data['start']:
- if position != js_data['cameras'][name_ae]['position_static']:
- js_data['cameras'][name_ae]['position_anim'] = True
- if orientation != js_data['cameras'][name_ae]['orientation_static']:
- js_data['cameras'][name_ae]['orientation_anim'] = True
- if zoom != js_data['cameras'][name_ae]['zoom_static']:
- js_data['cameras'][name_ae]['zoom_anim'] = True
- js_data['cameras'][name_ae]['position_static'] = position
- js_data['cameras'][name_ae]['orientation_static'] = orientation
- js_data['cameras'][name_ae]['zoom_static'] = zoom
-
- # keyframes for selected cameras
- if include_selected_cams:
- for i, cam in enumerate(selection['cameras']):
- if cam[1] != active_cam_name:
- # get cam name
- name_ae = selection['cameras'][i][1]
- # convert cam transform properties to AE space
- ae_transform = convert_transform_matrix(cam[0].matrix_world.copy(), data['width'], data['height'], data['aspect'], True, ae_size)
- # convert Blender's lens to AE's zoom in pixels
- zoom = convert_lens(cam[0], data['width'], data['height'], data['aspect'])
- # store all values in dico
- position = '[%f,%f,%f],' % (ae_transform[0], ae_transform[1], ae_transform[2])
- orientation = '[%f,%f,%f],' % (ae_transform[3], ae_transform[4], ae_transform[5])
- zoom = '%f,' % (zoom)
- js_data['cameras'][name_ae]['position'] += position
- js_data['cameras'][name_ae]['orientation'] += orientation
- js_data['cameras'][name_ae]['zoom'] += zoom
- # Check if properties change values compared to previous frame
- # If property don't change through out the whole animation - keyframes won't be added
- if frame != data['start']:
- if position != js_data['cameras'][name_ae]['position_static']:
- js_data['cameras'][name_ae]['position_anim'] = True
- if orientation != js_data['cameras'][name_ae]['orientation_static']:
- js_data['cameras'][name_ae]['orientation_anim'] = True
- if zoom != js_data['cameras'][name_ae]['zoom_static']:
- js_data['cameras'][name_ae]['zoom_anim'] = True
- js_data['cameras'][name_ae]['position_static'] = position
- js_data['cameras'][name_ae]['orientation_static'] = orientation
- js_data['cameras'][name_ae]['zoom_static'] = zoom
-
- '''
- # keyframes for all solids. Not ready yet. Temporarily not active
- for i, ob in enumerate(selection['solids']):
- #get object name
- name_ae = selection['solids'][i][1]
- #convert ob position to AE space
- '''
-
- # keyframes for all lights.
- if include_selected_objects:
- for i, ob in enumerate(selection['lights']):
- #get object name
- name_ae = selection['lights'][i][1]
- type = selection['lights'][i][0].data.type
- # convert ob transform properties to AE space
- ae_transform = convert_transform_matrix(ob[0].matrix_world.copy(), data['width'], data['height'], data['aspect'], True, ae_size)
- color = ob[0].data.color
- # store all values in dico
- position = '[%f,%f,%f],' % (ae_transform[0], ae_transform[1], ae_transform[2])
- orientation = '[%f,%f,%f],' % (ae_transform[3], ae_transform[4], ae_transform[5])
- energy = '[%f],' % (ob[0].data.energy * 100.0)
- color = '[%f,%f,%f],' % (color[0], color[1], color[2])
- js_data['lights'][name_ae]['position'] += position
- js_data['lights'][name_ae]['orientation'] += orientation
- js_data['lights'][name_ae]['energy'] += energy
- js_data['lights'][name_ae]['color'] += color
- # Check if properties change values compared to previous frame
- # If property don't change through out the whole animation - keyframes won't be added
- if frame != data['start']:
- if position != js_data['lights'][name_ae]['position_static']:
- js_data['lights'][name_ae]['position_anim'] = True
- if orientation != js_data['lights'][name_ae]['orientation_static']:
- js_data['lights'][name_ae]['orientation_anim'] = True
- if energy != js_data['lights'][name_ae]['energy_static']:
- js_data['lights'][name_ae]['energy_anim'] = True
- if color != js_data['lights'][name_ae]['color_static']:
- js_data['lights'][name_ae]['color_anim'] = True
- js_data['lights'][name_ae]['position_static'] = position
- js_data['lights'][name_ae]['orientation_static'] = orientation
- js_data['lights'][name_ae]['energy_static'] = energy
- js_data['lights'][name_ae]['color_static'] = color
- if type == 'SPOT':
- cone_angle = '[%f],' % (degrees(ob[0].data.spot_size))
- cone_feather = '[%f],' % (ob[0].data.spot_blend * 100.0)
- js_data['lights'][name_ae]['cone_angle'] += cone_angle
- js_data['lights'][name_ae]['cone_feather'] += cone_feather
- # Check if properties change values compared to previous frame
- # If property don't change through out the whole animation - keyframes won't be added
- if frame != data['start']:
- if cone_angle != js_data['lights'][name_ae]['cone_angle_static']:
- js_data['lights'][name_ae]['cone_angle_anim'] = True
- if orientation != js_data['lights'][name_ae]['cone_feather_static']:
- js_data['lights'][name_ae]['cone_feather_anim'] = True
- js_data['lights'][name_ae]['cone_angle_static'] = cone_angle
- js_data['lights'][name_ae]['cone_feather_static'] = cone_feather
-
- # keyframes for all nulls
- if include_selected_objects:
- for i, ob in enumerate(selection['nulls']):
- # get object name
- name_ae = selection['nulls'][i][1]
- # convert ob transform properties to AE space
- ae_transform = convert_transform_matrix(ob[0].matrix_world.copy(), data['width'], data['height'], data['aspect'], True, ae_size)
- # store all values in dico
- position = '[%f,%f,%f],' % (ae_transform[0], ae_transform[1], ae_transform[2])
- orientation = '[%f,%f,%f],' % (ae_transform[3], ae_transform[4], ae_transform[5])
- scale = '[%f,%f,%f],' % (ae_transform[6], ae_transform[7], ae_transform[8])
- js_data['nulls'][name_ae]['position'] += position
- js_data['nulls'][name_ae]['orientation'] += orientation
- js_data['nulls'][name_ae]['scale'] += scale
- # Check if properties change values compared to previous frame
- # If property don't change through out the whole animation - keyframes won't be added
- if frame != data['start']:
- if position != js_data['nulls'][name_ae]['position_static']:
- js_data['nulls'][name_ae]['position_anim'] = True
- if orientation != js_data['nulls'][name_ae]['orientation_static']:
- js_data['nulls'][name_ae]['orientation_anim'] = True
- if scale != js_data['nulls'][name_ae]['scale_static']:
- js_data['nulls'][name_ae]['scale_anim'] = True
- js_data['nulls'][name_ae]['position_static'] = position
- js_data['nulls'][name_ae]['orientation_static'] = orientation
- js_data['nulls'][name_ae]['scale_static'] = scale
-
- # keyframes for all object bundles. Not ready yet.
- #
- #
- #
-
- # ---- write JSX file
- jsx_file = open(file, 'w')
-
- # make the jsx executable in After Effects (enable double click on jsx)
- jsx_file.write('#target AfterEffects\n\n')
- # Script's header
- jsx_file.write('/**************************************\n')
- jsx_file.write('Scene : %s\n' % data['scn'].name)
- jsx_file.write('Resolution : %i x %i\n' % (data['width'], data['height']))
- jsx_file.write('Duration : %f\n' % (data['duration']))
- jsx_file.write('FPS : %f\n' % (data['fps']))
- jsx_file.write('Date : %s\n' % datetime.datetime.now())
- jsx_file.write('Exported with io_export_after_effects.py\n')
- jsx_file.write('**************************************/\n\n\n\n')
-
- # wrap in function
- jsx_file.write("function compFromBlender(){\n")
- # create new comp
- jsx_file.write('\nvar compName = prompt("Blender Comp\'s Name \\nEnter Name of newly created Composition","BlendComp","Composition\'s Name");\n')
- jsx_file.write('if (compName){') # Continue only if comp name is given. If not - terminate
- jsx_file.write('\nvar newComp = app.project.items.addComp(compName, %i, %i, %f, %f, %f);' %
- (data['width'], data['height'], data['aspect'], data['duration'], data['fps']))
- jsx_file.write('\nnewComp.displayStartTime = %f;\n\n\n' % ((data['start'] + 1.0) / data['fps']))
-
- # create camera bundles (nulls)
- jsx_file.write('// ************** CAMERA 3D MARKERS **************\n\n\n')
- for i, obj in enumerate(js_data['bundles_cam']):
- name_ae = obj
- jsx_file.write('var %s = newComp.layers.addNull();\n' % (name_ae))
- jsx_file.write('%s.threeDLayer = true;\n' % name_ae)
- jsx_file.write('%s.source.name = "%s";\n' % (name_ae, name_ae))
- jsx_file.write('%s.property("position").setValue(%s);\n\n\n' % (name_ae, js_data['bundles_cam'][obj]['position']))
-
- # create object bundles (not ready yet)
-
- # create objects (nulls)
- jsx_file.write('// ************** OBJECTS **************\n\n\n')
- for i, obj in enumerate(js_data['nulls']):
- name_ae = obj
- jsx_file.write('var %s = newComp.layers.addNull();\n' % (name_ae))
- jsx_file.write('%s.threeDLayer = true;\n' % name_ae)
- jsx_file.write('%s.source.name = "%s";\n' % (name_ae, name_ae))
- # Set values of properties, add kyeframes only where needed
- if include_animation and js_data['nulls'][name_ae]['position_anim']:
- jsx_file.write('%s.property("position").setValuesAtTimes([%s],[%s]);\n' % (name_ae, js_data['times'], js_data['nulls'][obj]['position']))
- else:
- jsx_file.write('%s.property("position").setValue(%s);\n' % (name_ae, js_data['nulls'][obj]['position_static']))
- if include_animation and js_data['nulls'][name_ae]['orientation_anim']:
- jsx_file.write('%s.property("orientation").setValuesAtTimes([%s],[%s]);\n' % (name_ae, js_data['times'], js_data['nulls'][obj]['orientation']))
- else:
- jsx_file.write('%s.property("orientation").setValue(%s);\n' % (name_ae, js_data['nulls'][obj]['orientation_static']))
- if include_animation and js_data['nulls'][name_ae]['scale_anim']:
- jsx_file.write('%s.property("scale").setValuesAtTimes([%s],[%s]);\n\n\n' % (name_ae, js_data['times'], js_data['nulls'][obj]['scale']))
- else:
- jsx_file.write('%s.property("scale").setValue(%s);\n\n\n' % (name_ae, js_data['nulls'][obj]['scale_static']))
- # create solids (not ready yet)
-
- # create lights
- jsx_file.write('// ************** LIGHTS **************\n\n\n')
- for i, obj in enumerate(js_data['lights']):
- name_ae = obj
- jsx_file.write('var %s = newComp.layers.addLight("%s", [0.0, 0.0]);\n' % (name_ae, name_ae))
- jsx_file.write('%s.autoOrient = AutoOrientType.NO_AUTO_ORIENT;\n' % name_ae)
- # Set values of properties, add kyeframes only where needed
- if include_animation and js_data['lights'][name_ae]['position_anim']:
- jsx_file.write('%s.property("position").setValuesAtTimes([%s],[%s]);\n' % (name_ae, js_data['times'], js_data['lights'][obj]['position']))
- else:
- jsx_file.write('%s.property("position").setValue(%s);\n' % (name_ae, js_data['lights'][obj]['position_static']))
- if include_animation and js_data['lights'][name_ae]['orientation_anim']:
- jsx_file.write('%s.property("orientation").setValuesAtTimes([%s],[%s]);\n' % (name_ae, js_data['times'], js_data['lights'][obj]['orientation']))
- else:
- jsx_file.write('%s.property("orientation").setValue(%s);\n' % (name_ae, js_data['lights'][obj]['orientation_static']))
- if include_animation and js_data['lights'][name_ae]['energy_anim']:
- jsx_file.write('%s.property("intensity").setValuesAtTimes([%s],[%s]);\n' % (name_ae, js_data['times'], js_data['lights'][obj]['energy']))
- else:
- jsx_file.write('%s.property("intensity").setValue(%s);\n' % (name_ae, js_data['lights'][obj]['energy_static']))
- if include_animation and js_data['lights'][name_ae]['color_anim']:
- jsx_file.write('%s.property("Color").setValuesAtTimes([%s],[%s]);\n' % (name_ae, js_data['times'], js_data['lights'][obj]['color']))
- else:
- jsx_file.write('%s.property("Color").setValue(%s);\n' % (name_ae, js_data['lights'][obj]['color_static']))
- if js_data['lights'][obj]['type'] == 'SPOT':
- if include_animation and js_data['lights'][name_ae]['cone_angle_anim']:
- jsx_file.write('%s.property("Cone Angle").setValuesAtTimes([%s],[%s]);\n' % (name_ae, js_data['times'], js_data['lights'][obj]['cone_angle']))
- else:
- jsx_file.write('%s.property("Cone Angle").setValue(%s);\n' % (name_ae, js_data['lights'][obj]['cone_angle_static']))
- if include_animation and js_data['lights'][name_ae]['cone_feather_anim']:
- jsx_file.write('%s.property("Cone Feather").setValuesAtTimes([%s],[%s]);\n' % (name_ae, js_data['times'], js_data['lights'][obj]['cone_feather']))
- else:
- jsx_file.write('%s.property("Cone Feather").setValue(%s);\n' % (name_ae, js_data['lights'][obj]['cone_feather_static']))
- jsx_file.write('\n\n')
-
- # create cameras
- jsx_file.write('// ************** CAMERAS **************\n\n\n')
- for i, cam in enumerate(js_data['cameras']): # more than one camera can be selected
- name_ae = cam
- jsx_file.write('var %s = newComp.layers.addCamera("%s",[0,0]);\n' % (name_ae, name_ae))
- jsx_file.write('%s.autoOrient = AutoOrientType.NO_AUTO_ORIENT;\n' % name_ae)
- # Set values of properties, add kyeframes only where needed
- if include_animation and js_data['cameras'][name_ae]['position_anim']:
- jsx_file.write('%s.property("position").setValuesAtTimes([%s],[%s]);\n' % (name_ae, js_data['times'], js_data['cameras'][cam]['position']))
- else:
- jsx_file.write('%s.property("position").setValue(%s);\n' % (name_ae, js_data['cameras'][cam]['position_static']))
- if include_animation and js_data['cameras'][name_ae]['orientation_anim']:
- jsx_file.write('%s.property("orientation").setValuesAtTimes([%s],[%s]);\n' % (name_ae, js_data['times'], js_data['cameras'][cam]['orientation']))
- else:
- jsx_file.write('%s.property("orientation").setValue(%s);\n' % (name_ae, js_data['cameras'][cam]['orientation_static']))
- if include_animation and js_data['cameras'][name_ae]['zoom_anim']:
- jsx_file.write('%s.property("zoom").setValuesAtTimes([%s],[%s]);\n\n\n' % (name_ae, js_data['times'], js_data['cameras'][cam]['zoom']))
- else:
- jsx_file.write('%s.property("zoom").setValue(%s);\n\n\n' % (name_ae, js_data['cameras'][cam]['zoom_static']))
-
- # Exit import if no comp name given
- jsx_file.write('\n}else{alert ("Exit Import Blender animation data \\nNo Comp\'s name has been chosen","EXIT")};')
- # Close function
- jsx_file.write("}\n\n\n")
- # Execute function. Wrap in "undo group" for easy undoing import process
- jsx_file.write('app.beginUndoGroup("Import Blender animation data");\n')
- jsx_file.write('compFromBlender();\n') # execute function
- jsx_file.write('app.endUndoGroup();\n\n\n')
- jsx_file.close()
-
- data['scn'].frame_set(curframe) # set current frame of animation in blender to state before export
-
-##########################################
-# DO IT
-##########################################
-
-
-def main(file, context, include_animation, include_active_cam, include_selected_cams, include_selected_objects, include_cam_bundles, ae_size):
- data = get_comp_data(context)
- selection = get_selected(context)
- write_jsx_file(file, data, selection, include_animation, include_active_cam, include_selected_cams, include_selected_objects, include_cam_bundles, ae_size)
- print ("\nExport to After Effects Completed")
- return {'FINISHED'}
-
-##########################################
-# ExportJsx class register/unregister
-##########################################
-
-from bpy_extras.io_utils import ExportHelper
-from bpy.props import StringProperty, BoolProperty, FloatProperty
-
-
-class ExportJsx(bpy.types.Operator, ExportHelper):
- """Export selected cameras and objects animation to After Effects"""
- bl_idname = "export.jsx"
- bl_label = "Export to Adobe After Effects"
- filename_ext = ".jsx"
- filter_glob: StringProperty(default="*.jsx", options={'HIDDEN'})
-
- include_animation: BoolProperty(
- name="Animation",
- description="Animate Exported Cameras and Objects",
- default=True,
- )
- include_active_cam: BoolProperty(
- name="Active Camera",
- description="Include Active Camera",
- default=True,
- )
- include_selected_cams: BoolProperty(
- name="Selected Cameras",
- description="Add Selected Cameras",
- default=True,
- )
- include_selected_objects: BoolProperty(
- name="Selected Objects",
- description="Export Selected Objects",
- default=True,
- )
- include_cam_bundles: BoolProperty(
- name="Camera 3D Markers",
- description="Include 3D Markers of Camera Motion Solution for selected cameras",
- default=True,
- )
-# include_ob_bundles = BoolProperty(
-# name="Objects 3D Markers",
-# description="Include 3D Markers of Object Motion Solution for selected cameras",
-# default=True,
-# )
- ae_size: FloatProperty(
- name="AE Size",
- description="Size of AE Composition (pixels per 1BU)",
- default=100.0,
- )
-
- def draw(self, context):
- layout = self.layout
-
- box = layout.box()
- box.label(text='Size fo AE Comp (pixels per 1 BU)')
- box.prop(self, 'ae_size')
- box.label(text='Animation:')
- box.prop(self, 'include_animation')
- box.label(text='Include Cameras and Objects:')
- box.prop(self, 'include_active_cam')
- box.prop(self, 'include_selected_cams')
- box.prop(self, 'include_selected_objects')
- box.label(text="Include Tracking Data:")
- box.prop(self, 'include_cam_bundles')
-# box.prop(self, 'include_ob_bundles')
-
- @classmethod
- def poll(cls, context):
- active = context.active_object
- selected = context.selected_objects
- camera = context.scene.camera
- ok = selected or camera
- return ok
-
- def execute(self, context):
- return main(self.filepath, context, self.include_animation, self.include_active_cam, self.include_selected_cams, self.include_selected_objects, self.include_cam_bundles, self.ae_size)
-
-
-def menu_func(self, context):
- self.layout.operator(ExportJsx.bl_idname, text="Adobe After Effects (.jsx)")
-
-
-def register():
- bpy.utils.register_class(ExportJsx)
- bpy.types.TOPBAR_MT_file_export.append(menu_func)
-
-
-def unregister():
- bpy.utils.unregister_class(ExportJsx)
- bpy.types.TOPBAR_MT_file_export.remove(menu_func)
-
-if __name__ == "__main__":
- register()