diff --git a/io_scene_fbx/export_fbx_bin.py b/io_scene_fbx/export_fbx_bin.py
index be5776a5877802bd68ee2127d8a295d7068d58fa..dad89f1158f33de3e009f6d7d5e24f7986e840f2 100644
--- a/io_scene_fbx/export_fbx_bin.py
+++ b/io_scene_fbx/export_fbx_bin.py
@@ -442,23 +442,57 @@ def elem_props_compound(elem, cmpd_name, custom=False):
     return _setter
 
 
+def elem_props_template_init(templates, template_type):
+    """
+    Init a writing template of given type, for *one* element's properties.
+    """
+    ret = None
+    if template_type in templates:
+        tmpl = templates[template_type]
+        written = tmpl.written[0]
+        print(template_type, written)
+        props = tmpl.properties
+        ret = OrderedDict((name, [val, ptype, anim, written]) for name, (val, ptype, anim) in props.items())
+    return ret or OrderedDict()
+
+
 def elem_props_template_set(template, elem, ptype_name, name, value, animatable=False):
     """
     Only add a prop if the same value is not already defined in given template.
     Note it is important to not give iterators as value, here!
     """
     ptype = FBX_PROPERTIES_DEFINITIONS[ptype_name]
-    tmpl_val, tmpl_ptype, tmpl_animatable = template.properties.get(name, (None, None, False))
+    if len(ptype) > 3:
+        value = tuple(value)
+    tmpl_val, tmpl_ptype, tmpl_animatable, tmpl_written = template.get(name, (None, None, False, False))
     # Note animatable flag from template takes precedence over given one, if applicable.
     if tmpl_ptype is not None:
-        if ((len(ptype) == 3 and (tmpl_val, tmpl_ptype) == (value, ptype_name)) or
-                (len(ptype) > 3 and (tuple(tmpl_val), tmpl_ptype) == (tuple(value), ptype_name))):
+        if (tmpl_written and
+            ((len(ptype) == 3 and (tmpl_val, tmpl_ptype) == (value, ptype_name)) or
+             (len(ptype) > 3 and (tuple(tmpl_val), tmpl_ptype) == (value, ptype_name)))):
             return  # Already in template and same value.
         _elem_props_set(elem, ptype, name, value, _elem_props_flags(tmpl_animatable, False))
+        template[name][3] = True
     else:
         _elem_props_set(elem, ptype, name, value, _elem_props_flags(animatable, False))
 
 
+def elem_props_template_finalize(template, elem):
+    """
+    Finalize one element's template/props.
+    Issue is, some templates might be "needed" by different types (e.g. NodeAttribute is for lights, cameras, etc.),
+    but values for only *one* subtype can be written as template. So we have to be sure we write those for ths other
+    subtypes in each and every elements, if they are not overriden by that element.
+    Yes, hairy, FBX that is to say. When they could easily support several subtypes per template... :(
+    """
+    for name, (value, ptype_name, animatable, written) in template.items():
+        if written:
+            continue
+        ptype = FBX_PROPERTIES_DEFINITIONS[ptype_name]
+        print(elem, ptype, name, value, _elem_props_flags(animatable, False))
+        _elem_props_set(elem, ptype, name, value, _elem_props_flags(animatable, False))
+
+
 ##### Generators for connection elements. #####
 
 def elem_connection(elem, c_type, uid_src, uid_dst, prop_dst=None):
@@ -472,37 +506,55 @@ def elem_connection(elem, c_type, uid_src, uid_dst, prop_dst=None):
 ##### Templates #####
 # TODO: check all those "default" values, they should match Blender's default as much as possible, I guess?
 
-FBXTemplate = namedtuple("FBXTemplate", ("type_name", "prop_type_name", "properties", "nbr_users"))
+FBXTemplate = namedtuple("FBXTemplate", ("type_name", "prop_type_name", "properties", "nbr_users", "written"))
 
 
 def fbx_templates_generate(root, fbx_templates):
     # We may have to gather different templates in the same node (e.g. NodeAttribute template gathers properties
     # for Lights, Cameras, LibNodes, etc.).
+    ref_templates = {(tmpl.type_name, tmpl.prop_type_name) : tmpl for tmpl in fbx_templates.values()}
+
     templates = OrderedDict()
-    for type_name, prop_type_name, properties, nbr_users in fbx_templates.values():
+    for type_name, prop_type_name, properties, nbr_users, _written in fbx_templates.values():
         if type_name not in templates:
-            templates[type_name] = [OrderedDict(((prop_type_name, properties),)), nbr_users]
+            templates[type_name] = [OrderedDict(((prop_type_name, (properties, nbr_users)),)), nbr_users]
         else:
-            templates[type_name][0][prop_type_name] = properties
+            templates[type_name][0][prop_type_name] = (properties, nbr_users)
             templates[type_name][1] += nbr_users
 
     for type_name, (subprops, nbr_users) in templates.items():
         template = elem_data_single_string(root, b"ObjectType", type_name)
         elem_data_single_int32(template, b"Count", nbr_users)
 
-        for prop_type_name, properties in subprops.items():
-            if prop_type_name and properties:
-                elem = elem_data_single_string(template, b"PropertyTemplate", prop_type_name)
-                props = elem_properties(elem)
-                for name, (value, ptype, animatable) in properties.items():
-                    elem_props_set(props, ptype, name, value, animatable=animatable)
+        if len(subprops) == 1:
+            prop_type_name, (properties, _nbr_sub_type_users) = next(iter(subprops.items()))
+            subprops = (prop_type_name, properties)
+            ref_templates[(type_name, prop_type_name)].written[0] = True
+        else:
+            # Ack! Even though this could/should work, looks like it is not supported. So we have to chose one. :|
+            max_users = max_props = -1
+            written_prop_type_name = None
+            for prop_type_name, (properties, nbr_sub_type_users) in subprops.items():
+                if nbr_sub_type_users > max_users or (nbr_sub_type_users == max_users and len(properties) > max_props):
+                    max_users = nbr_sub_type_users
+                    max_props = len(properties)
+                    written_prop_type_name = prop_type_name
+            subprops = (written_prop_type_name, properties)
+            ref_templates[(type_name, written_prop_type_name)].written[0] = True
+
+        prop_type_name, properties = subprops
+        if prop_type_name and properties:
+            elem = elem_data_single_string(template, b"PropertyTemplate", prop_type_name)
+            props = elem_properties(elem)
+            for name, (value, ptype, animatable) in properties.items():
+                elem_props_set(props, ptype, name, value, animatable=animatable)
 
 
 def fbx_template_def_globalsettings(scene, settings, override_defaults=None, nbr_users=0):
     props = OrderedDict()
     if override_defaults is not None:
         props.update(override_defaults)
-    return FBXTemplate(b"GlobalSettings", b"", props, nbr_users)
+    return FBXTemplate(b"GlobalSettings", b"", props, nbr_users, [False])
 
 
 def fbx_template_def_model(scene, settings, override_defaults=None, nbr_users=0):
@@ -583,7 +635,7 @@ def fbx_template_def_model(scene, settings, override_defaults=None, nbr_users=0)
     ))
     if override_defaults is not None:
         props.update(override_defaults)
-    return FBXTemplate(b"Model", b"FbxNode", props, nbr_users)
+    return FBXTemplate(b"Model", b"FbxNode", props, nbr_users, [False])
 
 
 def fbx_template_def_null(scene, settings, override_defaults=None, nbr_users=0):
@@ -594,7 +646,7 @@ def fbx_template_def_null(scene, settings, override_defaults=None, nbr_users=0):
     ))
     if override_defaults is not None:
         props.update(override_defaults)
-    return FBXTemplate(b"NodeAttribute", b"FbxNull", props, nbr_users)
+    return FBXTemplate(b"NodeAttribute", b"FbxNull", props, nbr_users, [False])
 
 
 def fbx_template_def_light(scene, settings, override_defaults=None, nbr_users=0):
@@ -612,7 +664,7 @@ def fbx_template_def_light(scene, settings, override_defaults=None, nbr_users=0)
     ))
     if override_defaults is not None:
         props.update(override_defaults)
-    return FBXTemplate(b"NodeAttribute", b"FbxLight", props, nbr_users)
+    return FBXTemplate(b"NodeAttribute", b"FbxLight", props, nbr_users, [False])
 
 
 def fbx_template_def_camera(scene, settings, override_defaults=None, nbr_users=0):
@@ -727,14 +779,14 @@ def fbx_template_def_camera(scene, settings, override_defaults=None, nbr_users=0
     ))
     if override_defaults is not None:
         props.update(override_defaults)
-    return FBXTemplate(b"NodeAttribute", b"FbxCamera", props, nbr_users)
+    return FBXTemplate(b"NodeAttribute", b"FbxCamera", props, nbr_users, [False])
 
 
 def fbx_template_def_bone(scene, settings, override_defaults=None, nbr_users=0):
     props = OrderedDict()
     if override_defaults is not None:
         props.update(override_defaults)
-    return FBXTemplate(b"NodeAttribute", b"LimbNode", props, nbr_users)
+    return FBXTemplate(b"NodeAttribute", b"LimbNode", props, nbr_users, [False])
 
 
 def fbx_template_def_geometry(scene, settings, override_defaults=None, nbr_users=0):
@@ -748,7 +800,7 @@ def fbx_template_def_geometry(scene, settings, override_defaults=None, nbr_users
     ))
     if override_defaults is not None:
         props.update(override_defaults)
-    return FBXTemplate(b"Geometry", b"FbxMesh", props, nbr_users)
+    return FBXTemplate(b"Geometry", b"FbxMesh", props, nbr_users, [False])
 
 
 def fbx_template_def_material(scene, settings, override_defaults=None, nbr_users=0):
@@ -786,7 +838,7 @@ def fbx_template_def_material(scene, settings, override_defaults=None, nbr_users
     ))
     if override_defaults is not None:
         props.update(override_defaults)
-    return FBXTemplate(b"Material", b"FbxSurfacePhong", props, nbr_users)
+    return FBXTemplate(b"Material", b"FbxSurfacePhong", props, nbr_users, [False])
 
 
 def fbx_template_def_texture_file(scene, settings, override_defaults=None, nbr_users=0):
@@ -813,7 +865,7 @@ def fbx_template_def_texture_file(scene, settings, override_defaults=None, nbr_u
     ))
     if override_defaults is not None:
         props.update(override_defaults)
-    return FBXTemplate(b"Texture", b"FbxFileTexture", props, nbr_users)
+    return FBXTemplate(b"Texture", b"FbxFileTexture", props, nbr_users, [False])
 
 
 def fbx_template_def_video(scene, settings, override_defaults=None, nbr_users=0):
@@ -840,21 +892,21 @@ def fbx_template_def_video(scene, settings, override_defaults=None, nbr_users=0)
     ))
     if override_defaults is not None:
         props.update(override_defaults)
-    return FBXTemplate(b"Video", b"FbxVideo", props, nbr_users)
+    return FBXTemplate(b"Video", b"FbxVideo", props, nbr_users, [False])
 
 
 def fbx_template_def_pose(scene, settings, override_defaults=None, nbr_users=0):
     props = OrderedDict()
     if override_defaults is not None:
         props.update(override_defaults)
-    return FBXTemplate(b"Pose", b"", props, nbr_users)
+    return FBXTemplate(b"Pose", b"", props, nbr_users, [False])
 
 
 def fbx_template_def_deformer(scene, settings, override_defaults=None, nbr_users=0):
     props = OrderedDict()
     if override_defaults is not None:
         props.update(override_defaults)
-    return FBXTemplate(b"Deformer", b"", props, nbr_users)
+    return FBXTemplate(b"Deformer", b"", props, nbr_users, [False])
 
 
 def fbx_template_def_animstack(scene, settings, override_defaults=None, nbr_users=0):
@@ -867,7 +919,7 @@ def fbx_template_def_animstack(scene, settings, override_defaults=None, nbr_user
     ))
     if override_defaults is not None:
         props.update(override_defaults)
-    return FBXTemplate(b"AnimationStack", b"FbxAnimStack", props, nbr_users)
+    return FBXTemplate(b"AnimationStack", b"FbxAnimStack", props, nbr_users, [False])
 
 
 def fbx_template_def_animlayer(scene, settings, override_defaults=None, nbr_users=0):
@@ -884,7 +936,7 @@ def fbx_template_def_animlayer(scene, settings, override_defaults=None, nbr_user
     ))
     if override_defaults is not None:
         props.update(override_defaults)
-    return FBXTemplate(b"AnimationLayer", b"FbxAnimLayer", props, nbr_users)
+    return FBXTemplate(b"AnimationLayer", b"FbxAnimLayer", props, nbr_users, [False])
 
 
 def fbx_template_def_animcurvenode(scene, settings, override_defaults=None, nbr_users=0):
@@ -893,14 +945,14 @@ def fbx_template_def_animcurvenode(scene, settings, override_defaults=None, nbr_
     ))
     if override_defaults is not None:
         props.update(override_defaults)
-    return FBXTemplate(b"AnimationCurveNode", b"FbxAnimCurveNode", props, nbr_users)
+    return FBXTemplate(b"AnimationCurveNode", b"FbxAnimCurveNode", props, nbr_users, [False])
 
 
 def fbx_template_def_animcurve(scene, settings, override_defaults=None, nbr_users=0):
     props = OrderedDict()
     if override_defaults is not None:
         props.update(override_defaults)
-    return FBXTemplate(b"AnimationCurve", b"", props, nbr_users)
+    return FBXTemplate(b"AnimationCurve", b"", props, nbr_users, [False])
 
 
 ##### FBX objects generators. #####
@@ -1017,8 +1069,9 @@ def fbx_data_empty_elements(root, empty, scene_data):
 
     elem_data_single_string(null, b"TypeFlags", b"Null")
 
-    tmpl = scene_data.templates[b"Null"]
+    tmpl = elem_props_template_init(scene_data.templates, b"Null")
     props = elem_properties(null)
+    elem_props_template_finalize(tmpl, props)
 
     # No custom properties, already saved with object (Model).
 
@@ -1047,7 +1100,7 @@ def fbx_data_lamp_elements(root, lamp, scene_data):
 
     elem_data_single_int32(light, b"GeometryVersion", FBX_GEOMETRY_VERSION)  # Sic...
 
-    tmpl = scene_data.templates[b"Light"]
+    tmpl = elem_props_template_init(scene_data.templates, b"Light")
     props = elem_properties(light)
     elem_props_template_set(tmpl, props, "p_enum", b"LightType", FBX_LIGHT_TYPES[lamp.type])
     elem_props_template_set(tmpl, props, "p_bool", b"CastLight", do_light)
@@ -1061,6 +1114,7 @@ def fbx_data_lamp_elements(root, lamp, scene_data):
         elem_props_template_set(tmpl, props, "p_double", b"OuterAngle", math.degrees(lamp.spot_size))
         elem_props_template_set(tmpl, props, "p_double", b"InnerAngle",
                                 math.degrees(lamp.spot_size * (1.0 - lamp.spot_blend)))
+    elem_props_template_finalize(tmpl, props)
 
     # Custom properties.
     if scene_data.settings.use_custom_properties:
@@ -1099,8 +1153,9 @@ def fbx_data_camera_elements(root, cam_obj, scene_data):
     cam.add_string(fbx_name_class(cam_data.name.encode(), b"NodeAttribute"))
     cam.add_string(b"Camera")
 
-    tmpl = scene_data.templates[b"Camera"]
+    tmpl = elem_props_template_init(scene_data.templates, b"Camera")
     props = elem_properties(cam)
+
     elem_props_template_set(tmpl, props, "p_vector", b"Position", loc)
     elem_props_template_set(tmpl, props, "p_vector", b"UpVector", up)
     elem_props_template_set(tmpl, props, "p_vector", b"InterestPosition", loc + to)  # Point, not vector!
@@ -1128,6 +1183,8 @@ def fbx_data_camera_elements(root, cam_obj, scene_data):
     elem_props_template_set(tmpl, props, "p_enum", b"BackPlaneDistanceMode", 1)  # RelativeToCamera.
     elem_props_template_set(tmpl, props, "p_double", b"BackPlaneDistance", cam_data.clip_end * gscale)
 
+    elem_props_template_finalize(tmpl, props)
+
     # Custom properties.
     if scene_data.settings.use_custom_properties:
         fbx_data_element_custom_properties(props, cam_data)
@@ -1529,8 +1586,9 @@ def fbx_data_material_elements(root, mat, scene_data):
     elem_data_single_string(fbx_mat, b"ShadingModel", mat_type)
     elem_data_single_int32(fbx_mat, b"MultiLayer", 0)  # Should be bool...
 
-    tmpl = scene_data.templates[b"Material"]
+    tmpl = elem_props_template_init(scene_data.templates, b"Material")
     props = elem_properties(fbx_mat)
+
     elem_props_template_set(tmpl, props, "p_string", b"ShadingModel", mat_type.decode())
     elem_props_template_set(tmpl, props, "p_color", b"EmissiveColor", mat.diffuse_color)
     elem_props_template_set(tmpl, props, "p_number", b"EmissiveFactor", mat.emit)
@@ -1561,6 +1619,8 @@ def fbx_data_material_elements(root, mat, scene_data):
         elem_props_template_set(tmpl, props, "p_number", b"ReflectionFactor",
                                 mat.raytrace_mirror.reflect_factor if mat.raytrace_mirror.use else 0.0)
 
+    elem_props_template_finalize(tmpl, props)
+
     # Custom properties.
     if scene_data.settings.use_custom_properties:
         fbx_data_element_custom_properties(props, mat)
@@ -1621,7 +1681,7 @@ def fbx_data_texture_file_elements(root, tex, scene_data):
     if tex.texture.extension in {'REPEAT'}:
         wrap_mode = 0  # Repeat
 
-    tmpl = scene_data.templates[b"TextureFile"]
+    tmpl = elem_props_template_init(scene_data.templates, b"TextureFile")
     props = elem_properties(fbx_tex)
     elem_props_template_set(tmpl, props, "p_enum", b"AlphaSource", alpha_source)
     elem_props_template_set(tmpl, props, "p_bool", b"PremultiplyAlpha",
@@ -1632,6 +1692,7 @@ def fbx_data_texture_file_elements(root, tex, scene_data):
     elem_props_template_set(tmpl, props, "p_vector_3d", b"Translation", tex.offset)
     elem_props_template_set(tmpl, props, "p_vector_3d", b"Scaling", tex.scale)
     elem_props_template_set(tmpl, props, "p_bool", b"UseMipMap", tex.texture.use_mipmap)
+    elem_props_template_finalize(tmpl, props)
 
     # Custom properties.
     if scene_data.settings.use_custom_properties:
@@ -1676,7 +1737,6 @@ def fbx_data_armature_elements(root, armature, scene_data):
     """
 
     # Bones "data".
-    tmpl = scene_data.templates[b"Bone"]
     for bo in armature.data.bones:
         _bo_key, bo_data_key, _arm = scene_data.data_bones[bo]
         fbx_bo = elem_data_single_int64(root, b"NodeAttribute", get_fbxuid_from_key(bo_data_key))
@@ -1684,8 +1744,10 @@ def fbx_data_armature_elements(root, armature, scene_data):
         fbx_bo.add_string(b"LimbNode")
         elem_data_single_string(fbx_bo, b"TypeFlags", b"Skeleton")
 
+        tmpl = elem_props_template_init(scene_data.templates, b"Bone")
         props = elem_properties(fbx_bo)
         elem_props_template_set(tmpl, props, "p_double", b"Size", (bo.tail_local - bo.head_local).length)
+        elem_props_template_finalize(tmpl, props)
 
         # Custom properties.
         if scene_data.settings.use_custom_properties:
@@ -1790,15 +1852,13 @@ def fbx_data_object_elements(root, obj, scene_data):
     loc, rot, scale, matrix, matrix_rot = fbx_object_tx(scene_data, obj)
     rot = tuple(units_convert_iter(rot, "radian", "degree"))
 
-    tmpl = scene_data.templates[b"Model"]
+    tmpl = elem_props_template_init(scene_data.templates, b"Model")
     # For now add only loc/rot/scale...
     props = elem_properties(model)
     elem_props_template_set(tmpl, props, "p_lcl_translation", b"Lcl Translation", loc)
     elem_props_template_set(tmpl, props, "p_lcl_rotation", b"Lcl Rotation", rot)
     elem_props_template_set(tmpl, props, "p_lcl_scaling", b"Lcl Scaling", scale)
 
-    # TODO: "constraints" (limit loc/rot/scale, and target-to-object).
-
     # Custom properties.
     if scene_data.settings.use_custom_properties:
         fbx_data_element_custom_properties(props, obj)
@@ -1823,6 +1883,8 @@ def fbx_data_object_elements(root, obj, scene_data):
         elem_props_template_set(tmpl, props, "p_enum", b"BackgroundMode", 0)  # Don't know what it means
         elem_props_template_set(tmpl, props, "p_bool", b"ForegroundTransparent", True)
 
+    elem_props_template_finalize(tmpl, props)
+
 
 def fbx_data_animation_elements(root, scene_data):
     """
@@ -1838,23 +1900,23 @@ def fbx_data_animation_elements(root, scene_data):
         return (int(v) for v in units_convert_iter((f / fps for f, _v in keys), "second", "ktime"))
 
     astack_key, alayers = animations
-    astack_tmpl = scene_data.templates[b"AnimationStack"]
-    acn_tmpl = scene_data.templates[b"AnimationCurveNode"]
 
     # Animation stack.
     astack = elem_data_single_int64(root, b"AnimationStack", get_fbxuid_from_key(astack_key))
     astack.add_string(fbx_name_class(scene.name.encode(), b"AnimStack"))
     astack.add_string(b"")
 
+    astack_tmpl = elem_props_template_init(scene_data.templates, b"AnimationStack")
     astack_props = elem_properties(astack)
     r = scene_data.scene.render
     fps = r.fps / r.fps_base
     f_start = int(units_convert(scene_data.scene.frame_start / fps, "second", "ktime"))
     f_end = int(units_convert(scene_data.scene.frame_end / fps, "second", "ktime"))
-    elem_props_set(astack_props, "p_timestamp", b"LocalStart", f_start)
-    elem_props_set(astack_props, "p_timestamp", b"LocalStop", f_end)
-    elem_props_set(astack_props, "p_timestamp", b"ReferenceStart", f_start)
-    elem_props_set(astack_props, "p_timestamp", b"ReferenceStop", f_end)
+    elem_props_template_set(astack_tmpl, astack_props, "p_timestamp", b"LocalStart", f_start)
+    elem_props_template_set(astack_tmpl, astack_props, "p_timestamp", b"LocalStop", f_end)
+    elem_props_template_set(astack_tmpl, astack_props, "p_timestamp", b"ReferenceStart", f_start)
+    elem_props_template_set(astack_tmpl, astack_props, "p_timestamp", b"ReferenceStop", f_end)
+    elem_props_template_finalize(astack_tmpl, astack_props)
 
     for obj, (alayer_key, acurvenodes) in alayers.items():
         # Animation layer.
@@ -1868,6 +1930,7 @@ def fbx_data_animation_elements(root, scene_data):
             acurvenode.add_string(fbx_name_class(acurvenode_name.encode(), b"AnimCurveNode"))
             acurvenode.add_string(b"")
 
+            acn_tmpl = elem_props_template_init(scene_data.templates, b"AnimationCurveNode")
             acn_props = elem_properties(acurvenode)
 
             for fbx_item, (acurve_key, def_value, keys, _acurve_valid) in acurves.items():
@@ -1900,6 +1963,8 @@ def fbx_data_animation_elements(root, scene_data):
                     elem_data_single_float32_array(acurve, b"KeyAttrDataFloat", keyattr_datafloat)
                     elem_data_single_int32_array(acurve, b"KeyAttrRefCount", (nbr_keys,))
 
+            elem_props_template_finalize(acn_tmpl, acn_props)
+
 
 ##### Top-level FBX data container. #####
 
@@ -2228,8 +2293,6 @@ def fbx_data_from_scene(scene, settings):
     templates = OrderedDict()
     templates[b"GlobalSettings"] = fbx_template_def_globalsettings(scene, settings, nbr_users=1)
 
-    # XXX Looks like there can only be one NodeAttribute template? At lest, never found more than one
-    #     (null/light/camera) template in one file... :/
     if data_empties:
         templates[b"Null"] = fbx_template_def_null(scene, settings, nbr_users=len(data_empties))