diff --git a/.arcconfig b/.arcconfig
new file mode 100644
index 0000000000000000000000000000000000000000..b5d479dd7535026bfbcd341030417b1dfdfda5a4
--- /dev/null
+++ b/.arcconfig
@@ -0,0 +1,7 @@
+{
+	"project_id" : "Blender Addons Contrib",
+	"conduit_uri" : "https://developer.blender.org/",
+	"phabricator.uri" : "https://developer.blender.org/",
+	"git.default-relative-commit" : "origin/master",
+	"arc.land.update.default" : "rebase"
+}
diff --git a/.gitea/default_merge_message/REBASE_TEMPLATE.md b/.gitea/default_merge_message/REBASE_TEMPLATE.md
deleted file mode 100644
index 87a09370e270f126d99e81d1f74eea9371fd14b1..0000000000000000000000000000000000000000
--- a/.gitea/default_merge_message/REBASE_TEMPLATE.md
+++ /dev/null
@@ -1,5 +0,0 @@
-${CommitTitle}
-
-${CommitBody}
-
-Pull Request #${PullRequestIndex}
diff --git a/.gitea/default_merge_message/SQUASH_TEMPLATE.md b/.gitea/default_merge_message/SQUASH_TEMPLATE.md
deleted file mode 100644
index 36123d4d8ce23f55d1df1a86e13a851640fb8e09..0000000000000000000000000000000000000000
--- a/.gitea/default_merge_message/SQUASH_TEMPLATE.md
+++ /dev/null
@@ -1,3 +0,0 @@
-${PullRequestTitle}
-
-Pull Request #${PullRequestIndex}
diff --git a/.gitea/pull_request_template.yaml b/.gitea/pull_request_template.yaml
deleted file mode 100644
index 7ca55daf0ca14e77c239dbe6811832dacb040bcb..0000000000000000000000000000000000000000
--- a/.gitea/pull_request_template.yaml
+++ /dev/null
@@ -1,19 +0,0 @@
-name: Pull Request
-about: Contribute to add-ons bundled with Blender
-body:
-  - type: markdown
-    attributes:
-      value: |
-        ### Instructions
-
-        * [Contributing a new add-on](https://wiki.blender.org/wiki/Process/Addons)
-        * [Contributing code](https://wiki.blender.org/index.php/Dev:Doc/Process/Contributing_Code)
-        * [Effective code review](https://wiki.blender.org/index.php/Dev:Doc/Tools/Code_Review)
-
-        By submitting code here, you agree that the code is (compatible with) GNU GPL v2 or later.
-
-  - type: textarea
-    id: body
-    attributes:
-      label: "Description"
-      hide_label: true
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index 4b8e99e669aae89cd5ec21428391ad41ee188436..93a29565e542631d1fdd1748944ce39c5ba97ce4 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -1,4 +1,5 @@
-This repository is only used as a mirror. Blender development happens on projects.blender.org.
+This repository is only used as a mirror of git.blender.org. Blender development happens on
+https://developer.blender.org.
 
 To get started with contributing code, please see:
 https://wiki.blender.org/wiki/Process/Contributing_Code
diff --git a/.github/stale.yml b/.github/stale.yml
index db14bfd9d31d3cddddea7974cade7a1224fdef87..9c563f2dee008a93d6a01384accbb8a99728075b 100644
--- a/.github/stale.yml
+++ b/.github/stale.yml
@@ -15,7 +15,8 @@ staleLabel: stale
 # Comment to post when closing a stale Issue or Pull Request.
 closeComment: >
   This issue has been automatically closed, because this repository is only
-  used as a mirror. Blender development happens on projects.blender.org.
+  used as a mirror of git.blender.org. Blender development happens on
+  developer.blender.org.
 
   To get started contributing code, please read:
   https://wiki.blender.org/wiki/Process/Contributing_Code
diff --git a/animation_motion_trail.py b/animation_motion_trail.py
index d5b0bba729e75bd7db8b33c96417a6f0dd712db1..65be2db6bf2c2bfde0fb813a17e05802aeee9bf5 100644
--- a/animation_motion_trail.py
+++ b/animation_motion_trail.py
@@ -16,6 +16,8 @@
 #
 # ##### END GPL LICENSE BLOCK #####
 
+# <pep8 compliant>
+
 
 bl_info = {
     "name": "Motion Trail",
diff --git a/development_ui_classes.py b/development_ui_classes.py
index 24918c00c513e8b1951a0d8b60dd1e9ae9200cb6..65160980179c7760905414ce988b149dd52e04cf 100644
--- a/development_ui_classes.py
+++ b/development_ui_classes.py
@@ -16,6 +16,8 @@
 #
 # ##### END GPL LICENSE BLOCK #####
 
+# <pep8 compliant>
+
 bl_info = {
     "name": "UI Classes Overview",
     "author": "lijenstina",
diff --git a/io_export_after_effects.py b/io_export_after_effects.py
index 0db40e8b7daa6db9bf1b9b88b5650edda5224845..bca17f7bc2e5d33393daeb4c53a90dacf9ab3d4e 100644
--- a/io_export_after_effects.py
+++ b/io_export_after_effects.py
@@ -16,12 +16,14 @@
 #
 # ##### 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, Damien Picard (@pioverfour)",
-    "version": (0, 1, 3),
+    "author": "Bartek Skorupa",
+    "version": (0, 0, 69),
     "blender": (2, 80, 0),
     "location": "File > Export > Adobe After Effects (.jsx)",
     "warning": "",
@@ -34,350 +36,101 @@ bl_info = {
 import bpy
 import os
 import datetime
-from math import degrees
+from math import degrees, floor
 from mathutils import Matrix, Vector, Color
 
 
-def get_camera_frame_ranges(scene, start, end):
-    """Get frame ranges for each marker in the timeline
-
-    For this, start at the end of the timeline,
-    iterate through each camera-bound marker in reverse,
-    and get the range from this marker to the end of the previous range.
-    """
-    markers = sorted((m for m in scene.timeline_markers if m.camera is not None),
-                     key=lambda m:m.frame, reverse=True)
-
-    if len(markers) <= 1:
-        return [[[start, end], scene.camera],]
-
-    camera_frame_ranges = []
-    current_frame = end
-    for m in markers:
-        if m.frame < current_frame:
-            camera_frame_ranges.append([[m.frame, current_frame + 1], m.camera])
-            current_frame = m.frame - 1
-    camera_frame_ranges.reverse()
-    camera_frame_ranges[0][0][0] = start
-    return camera_frame_ranges
-
-
-class ObjectExport():
-    """Base exporter class
-
-    Collects data about an object and outputs the proper JSX script for AE.
-    """
-    def __init__(self, obj):
-        self.obj = obj
-        self.name_ae = convert_name(self.obj.name)
-        self.keyframes = {}
-
-    def get_prop_keyframe(self, prop_name, value, time):
-        """Get keyframe for given property, only if different from previous value"""
-        prop_keys = self.keyframes.setdefault(prop_name, [])
-        if len(prop_keys) == 0:
-            prop_keys.append([time, value, False])
-            return
-
-        if value != prop_keys[-1][1]:
-            prop_keys.append([time, value, False])
-        # Store which keys should hold, that is, which are
-        # the first in a series of identical values
-        else:
-            prop_keys[-1][2] = True
-
-    def get_keyframe(self, context, width, height, aspect, time, ae_size):
-        """Store animation for the current frame"""
-        ae_transform = convert_transform_matrix(self.obj.matrix_world,
-                                                width, height, aspect, ae_size)
+def get_comp_data(context):
+    """Create list of static blender's data"""
+    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,
+        }
+
+
+def get_active_cam_for_each_frame(scene, start, end):
+    """Create list of active camera for each frame in case active camera is set by markers"""
+    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 length 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)
+
+
+def get_selected(context):
+    """Create manageable list of selected objects"""
+    cameras = []  # List of selected cameras
+    solids = []   # List of selected meshes exported as AE solids
+    images = []   # List of selected meshes exported as AE AV layers
+    lights = []   # List of selected lights exported as AE lights
+    nulls = []    # List of selected objects except cameras (will be used to create nulls in AE)
+    obs = context.selected_objects
 
-        self.get_prop_keyframe('position', ae_transform[0:3], time)
-        self.get_prop_keyframe('orientation', ae_transform[3:6], time)
-        self.get_prop_keyframe('scale', ae_transform[6:9], time)
+    for ob in obs:
+        if ob.type == 'CAMERA':
+            cameras.append(ob)
 
-    def get_obj_script(self, include_animation):
-        """Get the JSX script for the object"""
-        return self.get_type_script() + self.get_anim_script(include_animation) + self.get_post_script()
+        elif is_image_plane(ob):
+            images.append(ob)
 
-    def get_type_script(self):
-        """Get the basic part of the JSX script"""
-        type_script = f'var {self.name_ae} = newComp.layers.addNull();\n'
-        type_script += f'{self.name_ae}.threeDLayer = true;\n'
-        type_script += f'{self.name_ae}.source.name = "{self.name_ae}";\n'
-        return type_script
+        elif is_plane(ob):
+            solids.append(ob)
 
-    def get_anim_script(self, include_animation):
-        """Get the part of the JSX script encoding animation"""
-        anim_script = ""
+        elif ob.type == 'LIGHT':
+            lights.append(ob)
 
-        # Set values of properties, add keyframes only where needed
-        for prop, keys in self.keyframes.items():
-            if include_animation and len(keys) > 1:
-                times = ",".join(str(k[0]) for k in keys)
-                values = ",".join(str(k[1]) for k in keys).replace(" ", "")
-                anim_script += (
-                    f'{self.name_ae}.property("{prop}").setValuesAtTimes([{times}],[{values}]);\n')
-
-                # Set to HOLD the frames after which animation is fixed
-                # for several frames, to avoid interpolation errors
-                if any(k[2] for k in keys):
-                    anim_script += (
-                        f'var hold_frames = {[i + 1 for i, k in enumerate(keys) if k[2]]};\n'
-                        'for (var i = 0; i < hold_frames.length; i++) {\n'
-                        f'  {self.name_ae}.property("{prop}").setInterpolationTypeAtKey(hold_frames[i], KeyframeInterpolationType.HOLD);\n'
-                        '}\n')
-
-            # No animation for this property
-            else:
-                value = str(keys[0][1]).replace(" ", "")
-                anim_script += (
-                    f'{self.name_ae}.property("{prop}").setValue({value});\n')
-
-        anim_script += '\n'
-
-        return anim_script
-
-    def get_post_script(self):
-        """This is only used in lights as a post-treatment after animation"""
-        return ""
-
-class CameraExport(ObjectExport):
-    def __init__(self, obj, start_time=None, end_time=None):
-        super().__init__(obj)
-        self.start_time = start_time
-        self.end_time = end_time
-
-    def get_keyframe(self, context, width, height, aspect, time, ae_size):
-        ae_transform = convert_transform_matrix(self.obj.matrix_world,
-                                                width, height, aspect, ae_size)
-        zoom = convert_lens(self.obj, width, height,
-                            aspect)
-
-        self.get_prop_keyframe('position', ae_transform[0:3], time)
-        self.get_prop_keyframe('orientation', ae_transform[3:6], time)
-        self.get_prop_keyframe('zoom', zoom, time)
-
-    def get_type_script(self):
-        type_script = f'var {self.name_ae} = newComp.layers.addCamera("{self.name_ae}",[0,0]);\n'
-        # Restrict time range when multiple cameras are used (markers)
-        if self.start_time is not None:
-            type_script += f'{self.name_ae}.inPoint = {self.start_time};\n'
-            type_script += f'{self.name_ae}.outPoint = {self.end_time};\n'
-        type_script += f'{self.name_ae}.autoOrient = AutoOrientType.NO_AUTO_ORIENT;\n'
-        return type_script
-
-
-class LightExport(ObjectExport):
-    def get_keyframe(self, context, width, height, aspect, time, ae_size):
-        ae_transform = convert_transform_matrix(self.obj.matrix_world,
-                                                width, height, aspect, ae_size)
-        self.type = self.obj.data.type
-        color = list(self.obj.data.color)
-        intensity = self.obj.data.energy * 10.0
-
-        self.get_prop_keyframe('position', ae_transform[0:3], time)
-        if self.type in {'SPOT', 'SUN'}:
-            self.get_prop_keyframe('orientation', ae_transform[3:6], time)
-        self.get_prop_keyframe('intensity', intensity, time)
-        self.get_prop_keyframe('Color', color, time)
-        if self.type == 'SPOT':
-            cone_angle = degrees(self.obj.data.spot_size)
-            self.get_prop_keyframe('Cone Angle', cone_angle, time)
-            cone_feather = self.obj.data.spot_blend * 100.0
-            self.get_prop_keyframe('Cone Feather', cone_feather, time)
-
-    def get_type_script(self):
-        type_script = f'var {self.name_ae} = newComp.layers.addLight("{self.name_ae}", [0.0, 0.0]);\n'
-        type_script += f'{self.name_ae}.autoOrient = AutoOrientType.NO_AUTO_ORIENT;\n'
-        type_script += f'{self.name_ae}.lightType = LightType.SPOT;\n'
-        return type_script
-
-    def get_post_script(self):
-        """Set light type _after_ the orientation, otherwise the property is hidden in AE..."""
-        if self.obj.data.type == 'SUN':
-            post_script = f'{self.name_ae}.lightType = LightType.PARALLEL;\n'
-        elif self.obj.data.type == 'SPOT':
-            post_script = f'{self.name_ae}.lightType = LightType.SPOT;\n'
         else:
-            post_script = f'{self.name_ae}.lightType = LightType.POINT;\n'
-        return post_script
-
-
-class ImageExport(ObjectExport):
-    def get_keyframe(self, context, width, height, aspect, time, ae_size):
-        # Convert obj transform properties to AE space
-        plane_matrix = get_image_plane_matrix(self.obj)
-        # Scale plane to account for AE's transforms
-        plane_matrix = plane_matrix @ Matrix.Scale(100.0 / width, 4)
-
-        ae_transform = convert_transform_matrix(plane_matrix,
-                                                width, height, aspect, ae_size)
-        opacity = 0.0 if self.obj.hide_render else 100.0
-
-        if not hasattr(self, 'filepath'):
-            self.filepath = get_image_filepath(self.obj)
-
-        image_width, image_height = get_image_size(self.obj)
-        ratio_to_comp = image_width / width
-        scale = ae_transform[6:9]
-        if image_height != 0.0:
-            scale[1] *= image_width / image_height
-        if ratio_to_comp != 0.0:
-            scale[0] /= ratio_to_comp
-            scale[1] /= ratio_to_comp
-
-        self.get_prop_keyframe('position', ae_transform[0:3], time)
-        self.get_prop_keyframe('orientation', ae_transform[3:6], time)
-        self.get_prop_keyframe('scale', scale, time)
-        self.get_prop_keyframe('opacity', opacity, time)
-
-    def get_type_script(self):
-        type_script = f'var newFootage = app.project.importFile(new ImportOptions(File("{self.filepath}")));\n'
-        type_script += 'newFootage.parentFolder = footageFolder;\n'
-        type_script += f'var {self.name_ae} = newComp.layers.add(newFootage);\n'
-        type_script += f'{self.name_ae}.threeDLayer = true;\n'
-        type_script += f'{self.name_ae}.source.name = "{self.name_ae}";\n'
-        return type_script
-
-
-class SolidExport(ObjectExport):
-    def get_keyframe(self, context, width, height, aspect, time, ae_size):
-        # Convert obj transform properties to AE space
-        plane_matrix = get_plane_matrix(self.obj)
-        # Scale plane to account for AE's transforms
-        plane_matrix = plane_matrix @ Matrix.Scale(100.0 / width, 4)
-
-        ae_transform = convert_transform_matrix(plane_matrix,
-                                                width, height, aspect, ae_size)
-        opacity = 0.0 if self.obj.hide_render else 100.0
-
-        if not hasattr(self, 'color'):
-            self.color = get_plane_color(self.obj)
-        if not hasattr(self, 'width'):
-            self.width = width
-        if not hasattr(self, 'height'):
-            self.height = height
-
-        scale = ae_transform[6:9]
-        scale[1] *= width / height
-
-        self.get_prop_keyframe('position', ae_transform[0:3], time)
-        self.get_prop_keyframe('orientation', ae_transform[3:6], time)
-        self.get_prop_keyframe('scale', scale, time)
-        self.get_prop_keyframe('opacity', opacity, time)
-
-    def get_type_script(self):
-        type_script = f'var {self.name_ae} = newComp.layers.addSolid({self.color},"{self.name_ae}",{self.width},{self.height},1.0);\n'
-        type_script += f'{self.name_ae}.source.name = "{self.name_ae}";\n'
-        type_script += f'{self.name_ae}.source.parentFolder = footageFolder;\n'
-        type_script += f'{self.name_ae}.threeDLayer = true;\n'
-        return type_script
-
-
-class CamBundleExport(ObjectExport):
-    def __init__(self, obj, track):
-        self.obj = obj
-        self.track = track
-        self.name_ae = convert_name(f'{obj.name}__{track.name}')
-        self.keyframes = {}
-
-    def get_keyframe(self, context, width, height, aspect, time, ae_size):
-        # Bundles are in camera space.
-        # Transpose to world space
-        matrix = self.obj.matrix_basis @ Matrix.Translation(self.track.bundle)
-        # Convert the position into AE space
-        ae_transform = convert_transform_matrix(matrix,
-                                                width, height, aspect, ae_size)
-
-        self.get_prop_keyframe('position', ae_transform[0:3], time)
-        self.get_prop_keyframe('orientation', ae_transform[3:6], time)
-
-    def get_type_script(self):
-        type_script = f'var {self.name_ae} = newComp.layers.addNull();\n'
-        type_script += f'{self.name_ae}.threeDLayer = true;\n'
-        type_script += f'{self.name_ae}.source.name = "{self.name_ae}";\n'
-        return type_script
-
-
-def get_camera_bundles(scene, camera):
-    cam_bundles = []
-
-    for constraint in camera.constraints:
-        if constraint.type == 'CAMERA_SOLVER':
-            # Which movie clip does it use
-            if constraint.use_active_clip:
-                clip = scene.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:
-                    cam_bundles.append(CamBundleExport(camera, track))
-
-    return cam_bundles
+            nulls.append(ob)
 
+    selection = {
+        'cameras': cameras,
+        'images': images,
+        'solids': solids,
+        'lights': lights,
+        'nulls': nulls,
+        }
 
-def get_selected(context, include_active_cam, include_selected_cams,
-                 include_selected_objects, include_cam_bundles,
-                 include_image_planes, include_solids):
-    """Create manageable list of selected objects"""
-    cameras = []
-    solids = []       # Meshes exported as AE solids
-    images = []       # Meshes exported as AE AV layers
-    lights = []       # Lights exported as AE lights
-    cam_bundles = []  # Camera trackers exported as AE nulls
-    nulls = []        # Remaining objects exported as AE nulls
-
-    scene = context.scene
-    fps = scene.render.fps / scene.render.fps_base
-
-    if context.scene.camera is not None:
-        if include_active_cam:
-            for frame_range, camera in get_camera_frame_ranges(
-                    context.scene,
-                    context.scene.frame_start, context.scene.frame_end):
-
-                if (include_cam_bundles
-                        and camera not in (cam.obj for cam in cameras)):
-                    cam_bundles.extend(
-                        get_camera_bundles(context.scene, camera))
-
-                cameras.append(
-                    CameraExport(camera,
-                                 (frame_range[0] - scene.frame_start) / fps,
-                                 (frame_range[1] - scene.frame_start) / fps))
-
-    for obj in context.selected_objects:
-        if obj.type == 'CAMERA':
-            # Ignore camera if already selected
-            if obj in (cam.obj for cam in cameras):
-                continue
-            if include_selected_cams:
-                cameras.append(CameraExport(obj))
-            if include_cam_bundles:
-                cam_bundles.extend(get_camera_bundles(context.scene, obj))
-
-        elif include_image_planes and is_image_plane(obj):
-            images.append(ImageExport(obj))
-
-        elif include_solids and is_plane(obj):
-            solids.append(SolidExport(obj))
-
-        elif include_selected_objects:
-            if obj.type == 'LIGHT':
-                lights.append(LightExport(obj))
-            else:
-                nulls.append(ObjectExport(obj))
-
-    return {'cameras': cameras,
-            'images': images,
-            'solids': solids,
-            'lights': lights,
-            'nulls': nulls,
-            'cam_bundles': cam_bundles}
+    return selection
 
 
 def get_first_material(obj):
@@ -401,7 +154,7 @@ def get_plane_color(obj):
         wrapper = node_shader_utils.PrincipledBSDFWrapper(obj.active_material)
         color = Color(wrapper.base_color[:3]) + wrapper.emission_color
 
-    return str(list(color))
+    return '[%f,%f,%f]' % (color[0], color[1], color[2])
 
 
 def is_plane(obj):
@@ -444,12 +197,11 @@ def is_image_plane(obj):
     - The mesh is a plane
     - The mesh has exactly one material
     - There is only one image in this material node tree
-    - The rectangle is UV unwrapped and its UV is occupying the whole space
     """
     if not is_plane(obj):
         return False
 
-    if len(obj.material_slots) == 0:
+    if not len(obj.material_slots):
         return False
 
     mat = get_first_material(obj)
@@ -460,13 +212,9 @@ def is_image_plane(obj):
     if img is None:
         return False
 
-    if len(obj.data.vertices) != 4:
-        return False
+    if len(obj.data.vertices) == 4:
+        return True
 
-    if not get_image_plane_matrix(obj):
-        return False
-
-    return True
 
 def get_image_filepath(obj):
     mat = get_first_material(obj)
@@ -504,7 +252,6 @@ def get_image_plane_matrix(obj):
 
     This will only work if uvs occupy all space, to get bounds
     """
-    p0, px, py = None, None, None
     for p_i, p in enumerate(obj.data.uv_layers.active.data):
         if p.uv == Vector((0, 0)):
             p0 = p_i
@@ -513,9 +260,6 @@ def get_image_plane_matrix(obj):
         elif p.uv == Vector((0, 1)):
             py = p_i
 
-    if None in (p0, px, py):
-        return False
-
     verts = obj.data.vertices
     loops = obj.data.loops
 
@@ -532,22 +276,31 @@ def get_image_plane_matrix(obj):
 
 def convert_name(name):
     """Convert names of objects to avoid errors in AE"""
-    if not name[0].isalpha():
+    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
 
 
-def convert_transform_matrix(matrix, width, height, aspect, ae_size=100.0):
+def convert_transform_matrix(matrix, width, height, aspect,
+                             x_rot_correction=False, ae_size=100.0):
     """Convert from Blender's Location, Rotation and Scale
     to AE's Position, Rotation/Orientation and Scale
 
     This function will be called for every object for every frame
     """
 
-    # Get blender transform data for object
+    scale_mat = Matrix.Scale(width, 4)
+
+    # 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()
@@ -561,19 +314,20 @@ def convert_transform_matrix(matrix, width, height, aspect, ae_size=100.0):
     z = (b_loc.y * 100.0) * ae_size / 100.0
 
     # Convert rotations to match AE's orientation.
-    # In Blender, object of zero rotation lays on floor.
-    # In AE, layer of zero orientation "stands", so subtract 90 degrees
-    rx =  degrees(b_rot.x) - 90.0  # AE's X orientation =  blender's X rotation if 'ZYX' euler.
+    # If not x_rot_correction
+    rx =  degrees(b_rot.x)  # AE's X orientation =  blender's X rotation if 'ZYX' euler.
     ry = -degrees(b_rot.y)  # AE's Y orientation = -blender's Y rotation if 'ZYX' euler
     rz = -degrees(b_rot.z)  # AE's Z orientation = -blender's Z rotation if 'ZYX' euler
-
+    if x_rot_correction:
+        # In Blender, ob of zero rotation lays on floor.
+        # In AE, layer of zero orientation "stands"
+        rx -= 90.0
     # Convert scale to AE scale. ae_size is a global multiplier.
     sx = b_scale.x * ae_size
     sy = b_scale.y * ae_size
     sz = b_scale.z * ae_size
 
-    return [x, y, z, rx, ry, rz, sx, sy, sz]
-
+    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
@@ -633,6 +387,7 @@ def convert_transform_matrix(matrix, width, height, aspect, ae_size=100.0):
 # 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
@@ -656,95 +411,639 @@ def convert_lens(camera, width, height, aspect):
 #    return matrix
 
 
-def write_jsx_file(context, file, selection, include_animation, ae_size):
+def write_jsx_file(file, data, selection, include_animation,
+                   include_active_cam, include_selected_cams,
+                   include_selected_objects, include_cam_bundles,
+                   include_image_planes, ae_size):
     """jsx script for AE creation"""
 
-    print("\n---------------------------\n"
-          "- Export to After Effects -\n"
-          "---------------------------")
-
-    # Create list of static blender data
-    scene = context.scene
-    width = scene.render.resolution_x
-    height = scene.render.resolution_y
-    aspect_x = scene.render.pixel_aspect_x
-    aspect_y = scene.render.pixel_aspect_y
-    aspect = aspect_x / aspect_y
+    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': {},
+        'images': {},
+        'solids': {},
+        '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 than one active cam exists
+        # (True if active cams set by markers)
+        if len(data['active_cam_frames']) == 1:
+            # Take name of the only active camera in scene
+            name_ae = convert_name(data['active_cam_frames'][0].name)
+        else:
+            name_ae = 'Active_Camera'
+        # Store name to be used when creating keyframes for active cam
+        active_cam_name = name_ae
+        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 obj in selection['cameras']:
+            # More than one camera can be selected
+            if convert_name(obj.name) != active_cam_name:
+                name_ae = convert_name(obj.name)
+                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
+    for obj in selection['solids']:
+        name_ae = convert_name(obj.name)
+        js_data['solids'][name_ae] = {
+            'position': '',
+            'position_static': '',
+            'position_anim': False,
+            'orientation': '',
+            'orientation_static': '',
+            'orientation_anim': False,
+            'scale': '',
+            'scale_static': '',
+            'scale_anim': False,
+            }
+
+    # Create structure for images
+    for obj in selection['images']:
+        name_ae = convert_name(obj.name)
+        js_data['images'][name_ae] = {
+            'position': '',
+            'position_static': '',
+            'position_anim': False,
+            'orientation': '',
+            'orientation_static': '',
+            'orientation_anim': False,
+            'scale': '',
+            'scale_static': '',
+            'scale_anim': False,
+            'filepath': '',
+        }
+
+    # Create structure for lights
+    for obj in selection['lights']:
+        if include_selected_objects:
+            name_ae = obj.data.type + convert_name(obj.name)
+            js_data['lights'][name_ae] = {
+                'type': obj.data.type,
+                'intensity': '',
+                'intensity_static': '',
+                'intensity_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
+    # nulls representing blender's obs except cameras, lights and solids
+    for obj in selection['nulls']:
+        if include_selected_objects:
+            name_ae = convert_name(obj.name)
+            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)
+        # 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:
-        frame_end = scene.frame_end + 1
+        end = data['end'] + 1
     else:
-        frame_end = scene.frame_start + 1
-    fps = scene.render.fps / scene.render.fps_base
-    duration = (frame_end - scene.frame_start) / fps
-
-    # Store the current frame to restore it at the end of export
-    frame_current = scene.frame_current
-
-    # Get all keyframes for each object
-    for frame in range(scene.frame_start, frame_end):
-        print("Working on frame: " + str(frame))
-        scene.frame_set(frame)
+        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
-        time = (frame - scene.frame_start) / fps
+        js_data['times'] += '%f,' % ((frame - data['start']) / data['fps'])
 
-        for obj_type in selection.values():
-            for obj in obj_type:
-                obj.get_keyframe(context, width, height, aspect, time, ae_size)
+        # 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_camera = js_data['cameras'][name_ae]
+            js_camera['position'] += position
+            js_camera['orientation'] += orientation
+            js_camera['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_camera['position_static']:
+                    js_camera['position_anim'] = True
+                if orientation != js_camera['orientation_static']:
+                    js_camera['orientation_anim'] = True
+                if zoom != js_camera['zoom_static']:
+                    js_camera['zoom_anim'] = True
+            js_camera['position_static'] = position
+            js_camera['orientation_static'] = orientation
+            js_camera['zoom_static'] = zoom
+
+        # Keyframes for selected cameras
+        if include_selected_cams:
+            for obj in selection['cameras']:
+                if convert_name(obj.name) != active_cam_name:
+                    # Get cam name
+                    name_ae = convert_name(obj.name)
+                    # Convert cam transform properties to AE space
+                    ae_transform = convert_transform_matrix(
+                        obj.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(obj, 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_camera = js_data['cameras'][name_ae]
+                    js_camera['position'] += position
+                    js_camera['orientation'] += orientation
+                    js_camera['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_camera['position_static']:
+                            js_camera['position_anim'] = True
+                        if orientation != js_camera['orientation_static']:
+                            js_camera['orientation_anim'] = True
+                        if zoom != js_camera['zoom_static']:
+                            js_camera['zoom_anim'] = True
+                    js_camera['position_static'] = position
+                    js_camera['orientation_static'] = orientation
+                    js_camera['zoom_static'] = zoom
+
+        # Keyframes for all solids.
+        if include_selected_objects:
+            for obj in selection['solids']:
+                # Get object name
+                name_ae = convert_name(obj.name)
+                # Convert obj transform properties to AE space
+                plane_matrix = get_plane_matrix(obj)
+                # Scale plane to account for AE's transforms
+                plane_matrix = plane_matrix @ Matrix.Scale(100.0 / data['width'], 4)
+                ae_transform = convert_transform_matrix(
+                    plane_matrix, 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])
+                # plane_width, plane_height, _ = plane_matrix.to_scale()
+                scale = '[%f,%f,%f],' % (ae_transform[6],
+                                         ae_transform[7] * data['width'] / data['height'],
+                                         ae_transform[8])
+                js_solid = js_data['solids'][name_ae]
+                js_solid['color'] = get_plane_color(obj)
+                js_solid['width'] = data['width']
+                js_solid['height'] = data['height']
+                js_solid['position'] += position
+                js_solid['orientation'] += orientation
+                js_solid['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_solid['position_static']:
+                        js_solid['position_anim'] = True
+                    if orientation != js_solid['orientation_static']:
+                        js_solid['orientation_anim'] = True
+                    if scale != js_solid['scale_static']:
+                        js_solid['scale_anim'] = True
+                js_solid['position_static'] = position
+                js_solid['orientation_static'] = orientation
+                js_solid['scale_static'] = scale
+
+        # Keyframes for all lights.
+        if include_selected_objects:
+            for obj in selection['lights']:
+                # Get object name
+                name_ae = obj.data.type + convert_name(obj.name)
+                type = obj.data.type
+                # Convert ob transform properties to AE space
+                ae_transform = convert_transform_matrix(
+                    obj.matrix_world.copy(), data['width'], data['height'],
+                    data['aspect'], True, ae_size)
+                color = obj.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],' % (obj.data.energy * 100.0)
+                color = '[%f,%f,%f],' % (color[0], color[1], color[2])
+                js_light = js_data['lights'][name_ae]
+                js_light['position'] += position
+                js_light['orientation'] += orientation
+                js_light['intensity'] += energy
+                js_light['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_light['position_static']:
+                        js_light['position_anim'] = True
+                    if orientation != js_light['orientation_static']:
+                        js_light['orientation_anim'] = True
+                    if energy != js_light['intensity_static']:
+                        js_light['intensity_anim'] = True
+                    if color != js_light['Color_static']:
+                        js_light['Color_anim'] = True
+                js_light['position_static'] = position
+                js_light['orientation_static'] = orientation
+                js_light['intensity_static'] = energy
+                js_light['Color_static'] = color
+                if type == 'SPOT':
+                    cone_angle = '[%f],' % (degrees(obj.data.spot_size))
+                    cone_feather = '[%f],' % (obj.data.spot_blend * 100.0)
+                    js_light['Cone Angle'] += cone_angle
+                    js_light['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_light['Cone Angle_static']:
+                            js_light['Cone Angle_anim'] = True
+                        if cone_feather != js_light['Cone Feather_static']:
+                            js_light['Cone Feather_anim'] = True
+                    js_light['Cone Angle_static'] = cone_angle
+                    js_light['Cone Feather_static'] = cone_feather
+
+        # Keyframes for all nulls
+        if include_selected_objects:
+            for obj in selection['nulls']:
+                # Get object name
+                name_ae = convert_name(obj.name)
+                # Convert obj transform properties to AE space
+                ae_transform = convert_transform_matrix(obj.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_null = js_data['nulls'][name_ae]
+                js_null['position'] += position
+                js_null['orientation'] += orientation
+                js_null['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_null['position_static']:
+                        js_null['position_anim'] = True
+                    if orientation != js_null['orientation_static']:
+                        js_null['orientation_anim'] = True
+                    if scale != js_null['scale_static']:
+                        js_null['scale_anim'] = True
+                js_null['position_static'] = position
+                js_null['orientation_static'] = orientation
+                js_null['scale_static'] = scale
+
+        # Keyframes for all images
+        if include_image_planes:
+            for obj in selection['images']:
+                # Get object name
+                name_ae = convert_name(obj.name)
+                # Convert obj transform properties to AE space
+                plane_matrix = get_image_plane_matrix(obj)
+                # Scale plane to account for AE's transforms
+                plane_matrix = plane_matrix @ Matrix.Scale(100.0 / data['width'], 4)
+                ae_transform = convert_transform_matrix(
+                    plane_matrix, 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])
+                image_width, image_height = get_image_size(obj)
+                ratio_to_comp = image_width / data['width']
+                scale = '[%f,%f,%f],' % (ae_transform[6] / ratio_to_comp,
+                                         ae_transform[7] / ratio_to_comp
+                                         * image_width / image_height,
+                                         ae_transform[8])
+                js_image = js_data['images'][name_ae]
+                js_image['position'] += position
+                js_image['orientation'] += orientation
+                js_image['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_image['position_static']:
+                        js_image['position_anim'] = True
+                    if orientation != js_image['orientation_static']:
+                        js_image['orientation_anim'] = True
+                    if scale != js_image['scale_static']:
+                        js_image['scale_anim'] = True
+                js_image['position_static'] = position
+                js_image['orientation_static'] = orientation
+                js_image['scale_static'] = scale
+                js_image['filepath'] = get_image_filepath(obj)
+
+        # keyframes for all object bundles. Not ready yet.
+        #
+        #
+        #
 
     # ---- write JSX file
-    with open(file, 'w') as jsx_file:
-        # 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(f'Scene : {scene.name}\n')
-        jsx_file.write(f'Resolution : {width} x {height}\n')
-        jsx_file.write(f'Duration : {duration}\n')
-        jsx_file.write(f'FPS : {fps}\n')
-        jsx_file.write(f'Date : {datetime.datetime.now()}\n')
-        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
-        if bpy.data.filepath:
-            comp_name = convert_name(
-                os.path.splitext(os.path.basename(bpy.data.filepath))[0])
-        else:
-            comp_name = "BlendComp"
-        jsx_file.write(f'\nvar compName = prompt("Blender Comp\'s Name \\nEnter Name of newly created Composition","{comp_name}","Composition\'s Name");\n')
-        jsx_file.write('if (compName){')
-        # Continue only if comp name is given. If not - terminate
+    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
+    if bpy.data.filepath:
+        comp_name = convert_name(
+            os.path.splitext(os.path.basename(bpy.data.filepath))[0])
+    else:
+        comp_name = "BlendComp"
+    jsx_file.write('\nvar compName = prompt("Blender Comp\'s Name \\nEnter Name of newly created Composition","%s","Composition\'s Name");\n' % comp_name)
+    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')
+    for name_ae, obj in js_data['bundles_cam'].items():
+        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'
+                       % (name_ae, obj['position']))
+    jsx_file.write('\n')
+
+    # Create object bundles (not ready yet)
+
+    # Create objects (nulls)
+    jsx_file.write('// **************  OBJECTS  **************\n\n')
+    for name_ae, obj in js_data['nulls'].items():
+        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 keyframes only where needed
+        for prop in ("position", "orientation", "scale"):
+            if include_animation and obj[prop + '_anim']:
+                jsx_file.write(
+                    '%s.property("%s").setValuesAtTimes([%s],[%s]);\n'
+                    % (name_ae, prop, js_data['times'], obj[prop]))
+            else:
+                jsx_file.write(
+                    '%s.property("%s").setValue(%s);\n'
+                    % (name_ae, prop, obj[prop + '_static']))
+        jsx_file.write('\n')
+    jsx_file.write('\n')
+
+    # Create solids
+    jsx_file.write('// **************  SOLIDS  **************\n\n')
+    for name_ae, obj in js_data['solids'].items():
+        jsx_file.write(
+            'var %s = newComp.layers.addSolid(%s,"%s",%i,%i,%f);\n' % (
+                name_ae,
+                obj['color'],
+                name_ae,
+                obj['width'],
+                obj['height'],
+                1.0))
+        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 keyframes only where needed
+        for prop in ("position", "orientation", "scale"):
+            if include_animation and obj[prop + '_anim']:
+                jsx_file.write(
+                    '%s.property("%s").setValuesAtTimes([%s],[%s]);\n'
+                    % (name_ae, prop, js_data['times'], obj[prop]))
+            else:
+                jsx_file.write(
+                    '%s.property("%s").setValue(%s);\n'
+                    % (name_ae, prop, obj[prop + '_static']))
+        jsx_file.write('\n')
+    jsx_file.write('\n')
+
+    # Create images
+    jsx_file.write('// **************  IMAGES  **************\n\n')
+    for name_ae, obj in js_data['images'].items():
+        jsx_file.write(
+            'var newFootage = app.project.importFile(new ImportOptions(File("%s")))\n'
+            % (obj['filepath']))
+        jsx_file.write(
+            'var %s = newComp.layers.add(newFootage);\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 keyframes only where needed
+        for prop in ("position", "orientation", "scale"):
+            if include_animation and obj[prop + '_anim']:
+                jsx_file.write(
+                    '%s.property("%s").setValuesAtTimes([%s],[%s]);\n'
+                    % (name_ae, prop, js_data['times'], obj[prop]))
+            else:
+                jsx_file.write(
+                    '%s.property("%s").setValue(%s);\n'
+                    % (name_ae, prop, obj[prop + '_static']))
+        jsx_file.write('\n')
+    jsx_file.write('\n')
+
+    # Create lights
+    jsx_file.write('// **************  LIGHTS  **************\n\n')
+    for name_ae, obj in js_data['lights'].items():
+        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 keyframes only where needed
+        props = ["position", "orientation", "intensity", "Color"]
+        if obj['type'] == 'SPOT':
+            props.extend(("Cone Angle", "Cone Feather"))
+        for prop in props:
+            if include_animation and obj[prop + '_anim']:
+                jsx_file.write(
+                    '%s.property("%s").setValuesAtTimes([%s],[%s]);\n'
+                    % (name_ae, prop, js_data['times'], obj[prop]))
+            else:
+                jsx_file.write(
+                    '%s.property("%s").setValue(%s);\n'
+                    % (name_ae, prop, obj[prop + '_static']))
+        jsx_file.write('\n')
+    jsx_file.write('\n')
+
+    # Create cameras
+    jsx_file.write('// **************  CAMERAS  **************\n\n')
+    for name_ae, obj in js_data['cameras'].items():
+        # More than one camera can be selected
         jsx_file.write(
-            f'\nvar newComp = app.project.items.addComp(compName, {width}, '
-            f'{height}, {aspect}, {duration}, {fps});')
-        jsx_file.write(f"\nnewComp.displayStartTime = {scene.frame_start / fps};\n\n")
-
-        jsx_file.write('var footageFolder = app.project.items.addFolder(compName + "_layers")\n\n\n')
-
-        # Write each object's creation script
-        for obj_type in ('cam_bundles', 'nulls', 'solids', 'images', 'lights', 'cameras'):
-            if len(selection[obj_type]):
-                type_name = 'CAMERA 3D MARKERS' if obj_type == 'cam_bundles' else obj_type.upper()
-                jsx_file.write(f'// **************  {type_name}  **************\n\n')
-                for obj in selection[obj_type]:
-                    jsx_file.write(obj.get_obj_script(include_animation))
-                jsx_file.write('\n')
-
-        # Exit import if no comp name given
-        jsx_file.write('\n}else{alert ("Exit Import Blender animation data \\nNo Comp 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')
-
-    # Restore current frame of animation in blender to state before export
-    scene.frame_set(frame_current)
+            '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 keyframes only where needed
+        for prop in ("position", "orientation", "zoom"):
+            if include_animation and obj[prop + '_anim']:
+                jsx_file.write(
+                    '%s.property("%s").setValuesAtTimes([%s],[%s]);\n'
+                    % (name_ae, prop, js_data['times'], obj[prop]))
+            else:
+                jsx_file.write(
+                    '%s.property("%s").setValue(%s);\n'
+                    % (name_ae, prop, obj[prop + '_static']))
+        jsx_file.write('\n')
+    jsx_file.write('\n')
+
+    # Exit import if no comp name given
+    jsx_file.write('\n}else{alert ("Exit Import Blender animation data \\nNo Comp 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()
+
+    # Set current frame of animation in blender to state before export
+    data['scn'].frame_set(curframe)
 
 
 ##########################################
@@ -794,11 +1093,6 @@ class ExportJsx(bpy.types.Operator, ExportHelper):
             description="Include image mesh objects",
             default=True,
             )
-    include_solids: BoolProperty(
-            name="Solids",
-            description="Include rectangles as solids",
-            default=True,
-            )
 #    include_ob_bundles = BoolProperty(
 #            name="Objects 3D Markers",
 #            description="Include 3D Markers of Object Motion Solution for selected cameras",
@@ -817,24 +1111,19 @@ class ExportJsx(bpy.types.Operator, ExportHelper):
 
         box = layout.box()
         box.label(text='Include Cameras and Objects')
-        col = box.column(align=True)
-        col.prop(self, 'include_active_cam')
-        col.prop(self, 'include_selected_cams')
-        col.prop(self, 'include_selected_objects')
-        col.prop(self, 'include_image_planes')
-        col.prop(self, 'include_solids')
-
-        box = layout.box()
-        box.label(text='Include Tracking Data')
-        box.prop(self, 'include_cam_bundles')
-#        box.prop(self, 'include_ob_bundles')
-
+        box.prop(self, 'include_active_cam')
+        box.prop(self, 'include_selected_cams')
+        box.prop(self, 'include_selected_objects')
+        box.prop(self, 'include_image_planes')
         box = layout.box()
         box.prop(self, 'include_animation')
-
         box = layout.box()
         box.label(text='Transform')
         box.prop(self, 'ae_size')
+        box = layout.box()
+        box.label(text='Include Tracking Data:')
+        box.prop(self, 'include_cam_bundles')
+#        box.prop(self, 'include_ob_bundles')
 
     @classmethod
     def poll(cls, context):
@@ -843,14 +1132,12 @@ class ExportJsx(bpy.types.Operator, ExportHelper):
         return selected or camera
 
     def execute(self, context):
-        selection = get_selected(context, self.include_active_cam,
-                                 self.include_selected_cams,
-                                 self.include_selected_objects,
-                                 self.include_cam_bundles,
-                                 self.include_image_planes,
-                                 self.include_solids)
-        write_jsx_file(context, self.filepath, selection,
-                       self.include_animation, self.ae_size)
+        data = get_comp_data(context)
+        selection = get_selected(context)
+        write_jsx_file(self.filepath, data, selection, self.include_animation,
+                       self.include_active_cam, self.include_selected_cams,
+                       self.include_selected_objects, self.include_cam_bundles,
+                       self.include_image_planes, self.ae_size)
         print("\nExport to After Effects Completed")
         return {'FINISHED'}
 
diff --git a/io_scene_3ds/__init__.py b/io_scene_3ds/__init__.py
index 3912ac147d814bd87de343dce6ba44db604c5ee8..0137dd222f5ad263adf7eaac0cf110c02008724d 100644
--- a/io_scene_3ds/__init__.py
+++ b/io_scene_3ds/__init__.py
@@ -16,6 +16,8 @@
 #
 # ##### END GPL LICENSE BLOCK #####
 
+# <pep8-80 compliant>
+
 from bpy_extras.io_utils import (
     ImportHelper,
     ExportHelper,
@@ -32,8 +34,8 @@ import bpy
 bl_info = {
     "name": "Autodesk 3DS format",
     "author": "Bob Holcomb, Campbell Barton, Andreas Atteneder, Sebastian Schrand",
-    "version": (2, 2, 0),
-    "blender": (3, 0, 0),
+    "version": (2, 1, 0),
+    "blender": (2, 82, 0),
     "location": "File > Import",
     "description": "Import 3DS, meshes, uvs, materials, textures, "
                    "cameras & lamps",
diff --git a/io_scene_3ds/export_3ds.py b/io_scene_3ds/export_3ds.py
index 2a22d742cfedc4b390c78994b53031614e361f8c..0ee332a03b6d180a13dcfdcfc273baac7e3152b1 100644
--- a/io_scene_3ds/export_3ds.py
+++ b/io_scene_3ds/export_3ds.py
@@ -16,6 +16,8 @@
 #
 # ##### END GPL LICENSE BLOCK #####
 
+# <pep8 compliant>
+
 # Script copyright (C) Bob Holcomb
 # Contributors: Campbell Barton, Bob Holcomb, Richard Lärkäng, Damien McGinnes, Mark Stijnman, Sebastian Sille
 
@@ -645,8 +647,8 @@ def make_material_chunk(material, image):
 
     name_str = material.name if material else "None"
 
-    #if image:
-    #    name_str += image.name
+    if image:
+        name_str += image.name
 
     name.add_variable("name", _3ds_string(sane_name(name_str)))
     material_chunk.add_subchunk(name)
@@ -670,7 +672,6 @@ def make_material_chunk(material, image):
         material_chunk.add_subchunk(make_percent_subchunk(MATSHIN2, wrap.specular))
         material_chunk.add_subchunk(make_percent_subchunk(MATSHIN3, wrap.metallic))
         material_chunk.add_subchunk(make_percent_subchunk(MATTRANS, 1 - wrap.alpha))
-        material_chunk.add_subchunk(make_percent_subchunk(MATSELFILPCT, wrap.emission_strength))
         material_chunk.add_subchunk(shading)
 
         if wrap.base_color_texture:
@@ -705,10 +706,13 @@ def make_material_chunk(material, image):
             normal = [wrap.normalmap_texture]
             bump = wrap.normalmap_strength
             b_pct = min(bump, 1)
+            bumpval = min(999, (bump * 100))  # 3ds max bump = 999
+            strength = _3ds_chunk(MAT_BUMP_PERCENT)
+            strength.add_variable("bump_pct", _3ds_ushort(int(bumpval)))
             matmap = make_material_texture_chunk(MAT_BUMPMAP, normal, b_pct)
             if matmap:
                 material_chunk.add_subchunk(matmap)
-                material_chunk.add_subchunk(make_percent_subchunk(MAT_BUMP_PERCENT, b_pct))
+                material_chunk.add_subchunk(strength)
 
         if wrap.roughness_texture:
             roughness = [wrap.roughness_texture]
@@ -718,7 +722,7 @@ def make_material_chunk(material, image):
                 material_chunk.add_subchunk(matmap)
 
         if wrap.emission_color_texture:
-            e_pct = wrap.emission_strength
+            e_pct = sum(wrap.emission_color[:]) * .25
             emission = [wrap.emission_color_texture]
             matmap = make_material_texture_chunk(MAT_SELFIMAP, emission, e_pct)
             if matmap:
@@ -905,8 +909,8 @@ def make_faces_chunk(tri_list, mesh, materialDict):
                 context_face_array = unique_mats[ma, img][1]
             except:
                 name_str = ma if ma else "None"
-                #if img:
-                #    name_str += img
+                if img:
+                    name_str += img
 
                 context_face_array = _3ds_array()
                 unique_mats[ma, img] = _3ds_string(sane_name(name_str)), context_face_array
@@ -1167,7 +1171,7 @@ def save(operator,
          ):
 
     import time
-    #from bpy_extras.io_utils import create_derived_objects, free_derived_objects
+    from bpy_extras.io_utils import create_derived_objects, free_derived_objects
 
     """Save the Blender scene to a 3ds file."""
 
@@ -1183,7 +1187,7 @@ def save(operator,
 
     scene = context.scene
     layer = context.view_layer
-    depsgraph = context.evaluated_depsgraph_get()
+    #depsgraph = context.evaluated_depsgraph_get()
 
     # Initialize the main chunk (primary):
     primary = _3ds_chunk(PRIMARY)
@@ -1231,9 +1235,7 @@ def save(operator,
 
     for ob in objects:
         # get derived objects
-        #free, derived = create_derived_objects(scene, ob)
-        derived_dict = bpy_extras.io_utils.create_derived_objects(depsgraph, [ob])
-        derived = derived_dict.get(ob)
+        free, derived = create_derived_objects(scene, ob)
 
         if derived is None:
             continue
@@ -1242,6 +1244,7 @@ def save(operator,
             if ob.type not in {'MESH', 'CURVE', 'SURFACE', 'FONT', 'META'}:
                 continue
 
+            #ob_derived_eval = ob_derived.evaluated_get(depsgraph)
             try:
                 data = ob_derived.to_mesh()
             except:
@@ -1285,8 +1288,8 @@ def save(operator,
 
                 # ob_derived_eval.to_mesh_clear()
 
-        #if free:
-        #    free_derived_objects(ob)
+        if free:
+            free_derived_objects(ob)
 
     # Make material chunks for all materials used in the meshes:
     for ma_image in materialDict.values():
diff --git a/io_scene_3ds/import_3ds.py b/io_scene_3ds/import_3ds.py
index 8dfa475e84f0265811340eed4df40ab818208067..193f53e71deaaa751a6ade7d4dd5d89d3545e4c7 100644
--- a/io_scene_3ds/import_3ds.py
+++ b/io_scene_3ds/import_3ds.py
@@ -16,6 +16,8 @@
 #
 # ##### END GPL LICENSE BLOCK #####
 
+# <pep8 compliant>
+
 # Script copyright (C) Bob Holcomb
 # Contributors: Bob Holcomb, Richard L?rk?ng, Damien McGinnes, Sebastian Sille
 # Campbell Barton, Mario Lapin, Dominique Lorre, Andreas Atteneder
@@ -63,7 +65,6 @@ MAT_SHIN2 = 0xA041  # Shininess of the object/material (percent)
 MAT_SHIN3 = 0xA042  # Reflection of the object/material (percent)
 MAT_TRANSPARENCY = 0xA050  # Transparency value of material (percent)
 MAT_SELF_ILLUM = 0xA080  # Self Illumination value of material
-MATSELFILPCT = 0xA084  # Self illumination strength (percent)
 MAT_WIRE = 0xA085  # Only render's wireframe
 
 MAT_TEXTURE_MAP = 0xA200  # This is a header for a new texture map
@@ -466,7 +467,6 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, IMAGE_SE
         pct = 50
 
         contextWrapper.emission_color = contextMaterial.line_color[:3]
-        contextWrapper.emission_strength = contextMaterial.line_priority / 100
         contextWrapper.base_color = contextMaterial.diffuse_color[:3]
         contextWrapper.specular = contextMaterial.specular_intensity
         contextWrapper.roughness = contextMaterial.roughness
@@ -669,18 +669,6 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, IMAGE_SE
                 print("Cannot read material transparency")
             new_chunk.bytes_read += temp_chunk.bytes_read
 
-        elif new_chunk.ID == MATSELFILPCT:
-            read_chunk(file, temp_chunk)
-            if temp_chunk.ID == PERCENTAGE_SHORT:
-                temp_data = file.read(SZ_U_SHORT)
-                temp_chunk.bytes_read += SZ_U_SHORT
-                contextMaterial.line_priority = int(struct.unpack('H', temp_data)[0])
-            elif temp_chunk.ID == PERCENTAGE_FLOAT:
-                temp_data = file.read(SZ_FLOAT)
-                temp_chunk.bytes_read += SZ_FLOAT
-                contextMaterial.line_priority = (float(struct.unpack('f', temp_data)[0]) * 100)
-            new_chunk.bytes_read += temp_chunk.bytes_read
-
         elif new_chunk.ID == MAT_TEXTURE_MAP:
             read_texture(new_chunk, temp_chunk, "Diffuse", "COLOR")
 
@@ -698,18 +686,11 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, IMAGE_SE
             read_texture(new_chunk, temp_chunk, "Bump", "NORMAL")
 
         elif new_chunk.ID == MAT_BUMP_PERCENT:
-            read_chunk(file, temp_chunk)
-            if temp_chunk.ID == PERCENTAGE_SHORT:
-                temp_data = file.read(SZ_U_SHORT)
-                temp_chunk.bytes_read += SZ_U_SHORT
-                contextWrapper.normalmap_strength = (float(struct.unpack('<H', temp_data)[0]) / 100)
-            elif temp_chunk.ID == PERCENTAGE_FLOAT:
-                temp_data = file.read(SZ_FLOAT)
-                temp_chunk.bytes_read += SZ_FLOAT
-                contextWrapper.normalmap_strength = float(struct.unpack('f', temp_data)[0])
+            temp_data = file.read(SZ_U_SHORT)
+            new_chunk.bytes_read += SZ_U_SHORT
+            contextWrapper.normalmap_strength = (float(struct.unpack('<H', temp_data)[0]) / 100)
             new_chunk.bytes_read += temp_chunk.bytes_read
 
-
         elif new_chunk.ID == MAT_SHIN_MAP:
             read_texture(new_chunk, temp_chunk, "Shininess", "ROUGHNESS")
 
diff --git a/io_scene_open_street_map.py b/io_scene_open_street_map.py
index 96136bf7027c45150f03c70907f19682657c0be2..204f41a5a83b43efe4154a13c942eec6f218f277 100644
--- a/io_scene_open_street_map.py
+++ b/io_scene_open_street_map.py
@@ -16,6 +16,8 @@
 #
 # ***** END GPL LICENCE BLOCK *****
 
+# <pep8 compliant>
+
 bl_info = {
     "name": "Open Street Map (.osm)",
     "author": "Michael Anthrax Schlachter, ideasman42, littleneo",
diff --git a/io_vector/__init__.py b/io_vector/__init__.py
index 6986b034b2426058442e7419054a39994af1609c..6abf2d503b243927e990886b4c550fc75e0e9184 100644
--- a/io_vector/__init__.py
+++ b/io_vector/__init__.py
@@ -16,6 +16,8 @@
 #
 # ##### END GPL LICENSE BLOCK #####
 
+# <pep8 compliant>
+
 bl_info = {
   "name": "Adobe Illustrator / PDF / SVG",
   "author": "Howard Trickey",
diff --git a/io_vector/art2polyarea.py b/io_vector/art2polyarea.py
index 27624e7b4f995ee335a7141400d2d25ef911973e..b49d3a2ecff0c8e21830176872ca2d91dfd28f44 100644
--- a/io_vector/art2polyarea.py
+++ b/io_vector/art2polyarea.py
@@ -16,6 +16,8 @@
 #
 # ##### END GPL LICENSE BLOCK #####
 
+# <pep8 compliant>
+
 """Convert an Art object to a list of PolyArea objects.
 """
 
diff --git a/io_vector/geom.py b/io_vector/geom.py
index c2f3366c6131e784e5f508914f70bc980c410612..a7eb4fedd139e65ffb754458a4ab3af47dd417bb 100644
--- a/io_vector/geom.py
+++ b/io_vector/geom.py
@@ -16,6 +16,8 @@
 #
 # ##### END GPL LICENSE BLOCK #####
 
+# <pep8 compliant>
+
 """Geometry classes and operations.
 Also, vector file representation (Art).
 """
diff --git a/io_vector/import_vecfile.py b/io_vector/import_vecfile.py
index db8674be5d501b76ec955231a957618cfae47e01..163eefce0e300b7a721b8c736788f07a3fa1965b 100644
--- a/io_vector/import_vecfile.py
+++ b/io_vector/import_vecfile.py
@@ -16,6 +16,8 @@
 #
 # ##### END GPL LICENSE BLOCK #####
 
+# <pep8 compliant>
+
 """Importing a vector file into Model format.
 """
 
diff --git a/io_vector/model.py b/io_vector/model.py
index a714e832ca73a37957aa668baf453a67e2bfe2ee..a3eb2aacc5d68141459a608a145e44612f4c6a2c 100644
--- a/io_vector/model.py
+++ b/io_vector/model.py
@@ -16,6 +16,8 @@
 #
 # ##### END GPL LICENSE BLOCK #####
 
+# <pep8 compliant>
+
 """Manipulations of Models.
 """
 
diff --git a/io_vector/offset.py b/io_vector/offset.py
index df04d2f05c31ab1eb687040cfffc9dfa0203016d..4e860b67ca382b5ab855b167043efadeda52591c 100644
--- a/io_vector/offset.py
+++ b/io_vector/offset.py
@@ -16,6 +16,8 @@
 #
 # ##### END GPL LICENSE BLOCK #####
 
+# <pep8 compliant>
+
 """Creating offset polygons inside faces."""
 
 __author__ = "howard.trickey@gmail.com"
diff --git a/io_vector/pdf.py b/io_vector/pdf.py
index 4e8f2f493bafb72805f5cdc3c00f3bc8e9d39833..e2e319917d81ab9e5ebb527b062268f3294a8ce2 100644
--- a/io_vector/pdf.py
+++ b/io_vector/pdf.py
@@ -16,6 +16,8 @@
 #
 # ##### END GPL LICENSE BLOCK #####
 
+# <pep8 compliant>
+
 """Functions for dealing with PDF files.
 """
 
diff --git a/io_vector/svg.py b/io_vector/svg.py
index 1ef5443a5d72ffe089cff8134cc0d372863ef6d8..4a2012b006c3a6085b299c0ae549b014ac974b4f 100644
--- a/io_vector/svg.py
+++ b/io_vector/svg.py
@@ -16,6 +16,8 @@
 #
 # ##### END GPL LICENSE BLOCK #####
 
+# <pep8 compliant>
+
 """Reading SVG file format.
 """
 
diff --git a/io_vector/triquad.py b/io_vector/triquad.py
index edced675c2b4daea5fd526d3d69b72de81a13aec..88affa8985e4b04f4f880da071ab81e7886b572b 100644
--- a/io_vector/triquad.py
+++ b/io_vector/triquad.py
@@ -16,6 +16,8 @@
 #
 # ##### END GPL LICENSE BLOCK #####
 
+# <pep8 compliant>
+
 
 from . import geom
 import math
diff --git a/io_vector/vecfile.py b/io_vector/vecfile.py
index 594255a83ae60e6d3074351fd5d0f85614f339c9..808a84e3f3f51ee42632e06d313e067f91055c6a 100644
--- a/io_vector/vecfile.py
+++ b/io_vector/vecfile.py
@@ -16,6 +16,8 @@
 #
 # ##### END GPL LICENSE BLOCK #####
 
+# <pep8 compliant>
+
 """Reading various vector file formats.
 
 Functions for classifying files, tokenizing, and parsing them.
diff --git a/mesh_show_vgroup_weights.py b/mesh_show_vgroup_weights.py
index ca603d11a77d00841c774979d6ad9facc03d98ba..f16adcd8b3fc0aa6d29e7623953f5d1c09ba31ad 100644
--- a/mesh_show_vgroup_weights.py
+++ b/mesh_show_vgroup_weights.py
@@ -17,6 +17,8 @@
 #
 # ***** END GPL LICENCE BLOCK *****
 
+# <pep8 compliant> (Thanks to CodemanX on IRC)
+
 bl_info = {
     "name": "Show Vertex Groups/Weights",
     "author": "Jason van Gumster (Fweeb), Bartius Crouch, CoDEmanX",
diff --git a/mocap/__init__.py b/mocap/__init__.py
index fecbf8c55ab3ead5416c3ac16b7e29cd4ab148ab..710db64011917d3c6fd1083dd6e2d88475a09b62 100644
--- a/mocap/__init__.py
+++ b/mocap/__init__.py
@@ -16,6 +16,8 @@
 #
 # ##### END GPL LICENSE BLOCK #####
 
+# <pep8 compliant>
+
 bl_info = {
     "name": "Motion Capture Tools",
     "author": "Benjy Cook",
diff --git a/mocap/mocap_constraints.py b/mocap/mocap_constraints.py
index 6d4a34cff604baba4236f4d090149ef4f6fac5c7..3d3e4a60cf653d2899fe08479915fe2ad3b6e71b 100644
--- a/mocap/mocap_constraints.py
+++ b/mocap/mocap_constraints.py
@@ -16,6 +16,8 @@
 #
 # ##### END GPL LICENSE BLOCK #####
 
+# <pep8 compliant>
+
 import bpy
 from mathutils import Vector
 from bpy_extras import anim_utils
diff --git a/mocap/mocap_tools.py b/mocap/mocap_tools.py
index 04a4261370d7814c770202ed75df902fc590f277..cc85529e9da4b4a26e4ea1b629b5883ac66aef9a 100644
--- a/mocap/mocap_tools.py
+++ b/mocap/mocap_tools.py
@@ -16,6 +16,8 @@
 #
 # ##### END GPL LICENSE BLOCK #####
 
+# <pep8 compliant>
+
 from math import sqrt, radians, floor, ceil
 import bpy
 import time
diff --git a/mocap/retarget.py b/mocap/retarget.py
index 5c963c056d01d267acaf77551977f84ebe9a665b..4fa5d2ce88de6ce642346a122935faa19a660e72 100644
--- a/mocap/retarget.py
+++ b/mocap/retarget.py
@@ -16,6 +16,8 @@
 #
 # ##### END GPL LICENSE BLOCK #####
 
+# <pep8 compliant>
+
 import bpy
 from mathutils import Vector, Matrix
 from math import radians
diff --git a/object_facemap_auto/__init__.py b/object_facemap_auto/__init__.py
index 1085633f9787ee7130863a4f20bef2d0e0cf3b46..0a309bc69803c3bb8353fbfcfbab03f80aff10d7 100644
--- a/object_facemap_auto/__init__.py
+++ b/object_facemap_auto/__init__.py
@@ -16,6 +16,8 @@
 #
 # ##### END GPL LICENSE BLOCK #####
 
+# <pep8 compliant>
+
 bl_info = {
     "name": "Auto Face Map Widgets",
     "author": "Campbell Barton",
diff --git a/object_facemap_auto/auto_fmap_ops.py b/object_facemap_auto/auto_fmap_ops.py
index 4ed3aef0c8099eb5a7884182217764bdcaa2e492..df2434fee972337ae07bb0d06349dd3e49649a1e 100644
--- a/object_facemap_auto/auto_fmap_ops.py
+++ b/object_facemap_auto/auto_fmap_ops.py
@@ -16,6 +16,8 @@
 #
 # ##### END GPL LICENSE BLOCK #####
 
+# <pep8 compliant>
+
 import bpy
 from bpy.types import (
     Operator,
diff --git a/object_facemap_auto/auto_fmap_utils.py b/object_facemap_auto/auto_fmap_utils.py
index ba825c0972528570de5b7fc8145180ee8a56331c..0a02907ffcfe2a92c68f1542fdfda6c4773d417a 100644
--- a/object_facemap_auto/auto_fmap_utils.py
+++ b/object_facemap_auto/auto_fmap_utils.py
@@ -16,6 +16,8 @@
 #
 # ##### END GPL LICENSE BLOCK #####
 
+# <pep8 compliant>
+
 
 # Use so we can develop modules without reloading the add-on.
 
diff --git a/object_facemap_auto/auto_fmap_widgets.py b/object_facemap_auto/auto_fmap_widgets.py
index 24ddf103229d8c25faaf6a98fd1c2456596c144e..6522eb42a88eaf1b571aed3f4b0edf8f645bc1b4 100644
--- a/object_facemap_auto/auto_fmap_widgets.py
+++ b/object_facemap_auto/auto_fmap_widgets.py
@@ -16,6 +16,8 @@
 #
 # ##### END GPL LICENSE BLOCK #####
 
+# <pep8 compliant>
+
 '''
 Face map manipulator:
 
diff --git a/object_facemap_auto/auto_fmap_widgets_xform.py b/object_facemap_auto/auto_fmap_widgets_xform.py
index 5b4ae1fecb128941d407f8bcd6c09e628b2ea669..71b99cf463c125d2888a733b49a17e3464dbfc8a 100644
--- a/object_facemap_auto/auto_fmap_widgets_xform.py
+++ b/object_facemap_auto/auto_fmap_widgets_xform.py
@@ -16,6 +16,8 @@
 #
 # ##### END GPL LICENSE BLOCK #####
 
+# <pep8 compliant>
+
 import bpy
 import math
 
diff --git a/object_fracture_crack/process/cell_calc.py b/object_fracture_crack/process/cell_calc.py
index 87fba051c56a5904e498fda92a6aef910ddeb1c8..2e47eaff16ecb1494421b9b0e731d9ad998422c1 100644
--- a/object_fracture_crack/process/cell_calc.py
+++ b/object_fracture_crack/process/cell_calc.py
@@ -16,6 +16,8 @@
 #
 # ##### END GPL LICENSE BLOCK #####
 
+# <pep8 compliant>
+
 # Script copyright (C) Blender Foundation 2012
 
 
diff --git a/render_cube_map.py b/render_cube_map.py
index 363bc02d40ca2d69d5e7427dae470bd60886fcc9..06417bab2bbf46210ea13e9be39472a5fe96aff1 100644
--- a/render_cube_map.py
+++ b/render_cube_map.py
@@ -16,6 +16,8 @@
 #
 # ======================= END GPL LICENSE BLOCK ========================
 
+# <pep8 compliant>
+
 # ########################################
 # Render Cube Map
 #
diff --git a/render_to_print.py b/render_to_print.py
index fdc54cd657fed96164464a1484bbfb64137add17..52d2fd5277d72bed36bbdd1cf475ae2502763e79 100644
--- a/render_to_print.py
+++ b/render_to_print.py
@@ -16,6 +16,8 @@
 #
 # ##### END GPL LICENSE BLOCK #####
 
+# <pep8 compliant>
+
 bl_info = {
     "name": "Render to Print",
     "author": "Marco Crippa <thekrypt77@tiscali.it>, Dealga McArdle, zebus3d",
diff --git a/system_keyboard_svg.py b/system_keyboard_svg.py
index db14916559dce927e7231205f9b870ac2b12ba15..bf6ab61c03ba907f7348fdbf225b409bb07d972a 100644
--- a/system_keyboard_svg.py
+++ b/system_keyboard_svg.py
@@ -16,6 +16,8 @@
 #
 # ##### END GPL LICENSE BLOCK #####
 
+# <pep8 compliant>
+
 # this script creates Keyboard layout images of the current keyboard configuration.
 # first implementation done by jbakker
 # version 0.2 - file manager directory on export, modified the SVG layout (lijenstina)