[Bf-extensions-cvs] [dd32b1c] fbx_io_development: FBX export: add double-animation mess to shapes, this time they are read by Unity...

Bastien Montagne noreply at git.blender.org
Mon Jun 16 14:46:03 CEST 2014


Commit: dd32b1cdbddf87ef8b5722fe7c6a8968823e4e8b
Author: Bastien Montagne
Date:   Mon Jun 16 14:40:33 2014 +0200
https://developer.blender.org/rBAdd32b1cdbddf87ef8b5722fe7c6a8968823e4e8b

FBX export: add double-animation mess to shapes, this time they are read by Unity...

FBX makes me cry... :'(
I would not want my worst enemy to have to understand and follow that code.

===================================================================

M	io_scene_fbx/export_fbx_bin.py
M	io_scene_fbx/fbx_utils.py

===================================================================

diff --git a/io_scene_fbx/export_fbx_bin.py b/io_scene_fbx/export_fbx_bin.py
index 9eaf029..8c804ba 100644
--- a/io_scene_fbx/export_fbx_bin.py
+++ b/io_scene_fbx/export_fbx_bin.py
@@ -1721,7 +1721,10 @@ def fbx_animations_do(scene_data, ref_id, f_start, f_end, start_zero, objects=No
         if not me.shape_keys.use_relative:
             continue
         for shape, (channel_key, geom_key, _shape_verts_co, _shape_verts_idx) in shapes.items():
-            animdata_shapes[channel_key] = (AnimationCurveNodeWrapper(channel_key, 'SHAPE_KEY', (0.0,)), me, shape)
+            acnode = AnimationCurveNodeWrapper(channel_key, 'SHAPE_KEY', (0.0,))
+            # Sooooo happy to have to twist again like a mad snake... Yes, we need to write those curves twice. :/
+            acnode.add_group(me_key, shape.name, shape.name, (shape.name,))
+            animdata_shapes[channel_key] = (acnode, me, shape)
 
     p_rots = {}
 
@@ -1754,24 +1757,23 @@ def fbx_animations_do(scene_data, ref_id, f_start, f_end, start_zero, objects=No
     # And now, produce final data (usable by FBX export code)
     # Objects-like loc/rot/scale...
     for ob_obj, anims in animdata_ob.items():
-        final_keys = OrderedDict()
         for anim in anims:
             anim.simplfy(simplify_fac, bake_step)
             if anim:
-                group_key, group, fbx_group, fbx_gname = anim.get_final_data(scene, ref_id, force_keep)
-                final_keys[fbx_group] = (group_key, group, fbx_gname)
-        if final_keys:
-            #animations[ob_obj] = (get_blender_anim_layer_key(scene, ob_obj.bdata), final_keys)
-            animations[ob_obj.key] = ("dummy_unused_key", final_keys)
+                for obj_key, group_key, group, fbx_group, fbx_gname in anim.get_final_data(scene, ref_id, force_keep):
+                    if obj_key not in animations:
+                        animations[obj_key] = ("dummy_unused_key", OrderedDict())
+                    animations[obj_key][1][fbx_group] = (group_key, group, fbx_gname)
 
     # And meshes' shape keys.
     for channel_key, (anim_shape, me, shape) in animdata_shapes.items():
         final_keys = OrderedDict()
         anim_shape.simplfy(simplify_fac, bake_step)
         if anim_shape:
-            group_key, group, fbx_group, fbx_gname = anim_shape.get_final_data(scene, ref_id, force_keep)
-            final_keys[fbx_group] = (group_key, group, fbx_gname)
-            animations[channel_key] = ("dummy_unused_key", final_keys)
+            for elem_key, group_key, group, fbx_group, fbx_gname in anim_shape.get_final_data(scene, ref_id, force_keep):
+                if elem_key not in animations:
+                    animations[elem_key] = ("dummy_unused_key", OrderedDict())
+                animations[elem_key][1][fbx_group] = (group_key, group, fbx_gname)
 
     astack_key = get_blender_anim_stack_key(scene, ref_id)
     alayer_key = get_blender_anim_layer_key(scene, ref_id)
diff --git a/io_scene_fbx/fbx_utils.py b/io_scene_fbx/fbx_utils.py
index af5520b..4b477e8 100644
--- a/io_scene_fbx/fbx_utils.py
+++ b/io_scene_fbx/fbx_utils.py
@@ -614,13 +614,13 @@ class AnimationCurveNodeWrapper:
     This class provides a same common interface for all (FBX-wise) AnimationCurveNode and AnimationCurve elements,
     and easy API to handle those.
     """
-    __slots__ = ('elem_key', '_keys', 'default_values', 'fbx_group', 'fbx_gname', 'fbx_props')
+    __slots__ = ('elem_keys', '_keys', 'default_values', 'fbx_group', 'fbx_gname', 'fbx_props')
 
     kinds = {
         'LCL_TRANSLATION': ("Lcl Translation", "T", ("X", "Y", "Z")),
         'LCL_ROTATION': ("Lcl Rotation", "R", ("X", "Y", "Z")),
         'LCL_SCALING': ("Lcl Scaling", "S", ("X", "Y", "Z")),
-        'SHAPE_KEY': ("DeformPercent", "DeformPercent", ("DeformPercent",))
+        'SHAPE_KEY': ("DeformPercent", "DeformPercent", ("DeformPercent",)),
     }
 
     def __init__(self, elem_key, kind, default_values=...):
@@ -628,27 +628,38 @@ class AnimationCurveNodeWrapper:
         bdata might be an Object, DupliObject, Bone or PoseBone.
         If Bone or PoseBone, armature Object must be provided.
         """
-        self.elem_key = elem_key
+        self.elem_keys = [elem_key]
         assert(kind in self.kinds)
-        self.fbx_group = self.kinds[kind][0]
-        self.fbx_gname = self.kinds[kind][1]
-        self.fbx_props = self.kinds[kind][2]
+        self.fbx_group = [self.kinds[kind][0]]
+        self.fbx_gname = [self.kinds[kind][1]]
+        self.fbx_props = [self.kinds[kind][2]]
         self._keys = []  # (frame, values, write_flags)
         if default_values is not ...:
-            assert(len(default_values) == len(self.fbx_props))
+            assert(len(default_values) == len(self.fbx_props[0]))
             self.default_values = default_values
         else:
-            self.default_values = (0.0) * len(self.fbx_props)
+            self.default_values = (0.0) * len(self.fbx_props[0])
 
     def __bool__(self):
         # We are 'True' if we do have some validated keyframes...
         return self._keys and True in ((True in k[2]) for k in self._keys)
 
+    def add_group(self, elem_key, fbx_group, fbx_gname, fbx_props):
+        """
+        Add another whole group stuff (curvenode, animated item/prop + curvnode/curve identifiers).
+        E.g. Shapes animations is written twice, houra!
+        """
+        assert(len(fbx_props) == len(self.fbx_props[0]))
+        self.elem_keys.append(elem_key)
+        self.fbx_group.append(fbx_group)
+        self.fbx_gname.append(fbx_gname)
+        self.fbx_props.append(fbx_props)
+
     def add_keyframe(self, frame, values):
         """
         Add a new keyframe to all curves of the group.
         """
-        assert(len(values) == len(self.fbx_props))
+        assert(len(values) == len(self.fbx_props[0]))
         self._keys.append((frame, values, [True] * len(values)))  # write everything by default.
 
     def simplfy(self, fac, step):
@@ -705,7 +716,7 @@ class AnimationCurveNodeWrapper:
 
     def get_final_data(self, scene, ref_id, force_keep=False):
         """
-        Produce final anim data for this 'curvenode'.
+        Yield final anim data for this 'curvenode' (for all curvenodes defined).
         force_keep is to force to keep a curve even if it only has one valid keyframe.
         """
         curves = [[] for k in self._keys[0][1]]
@@ -714,15 +725,15 @@ class AnimationCurveNodeWrapper:
                 if wrt:
                     curve.append((currframe, val))
 
-        group_key = get_blender_anim_curve_node_key(scene, ref_id, self.elem_key, self.fbx_group)
-        group = OrderedDict()
-        for c, def_val, fbx_item in zip(curves, self.default_values, self.fbx_props):
-            fbx_item = FBX_ANIM_PROPSGROUP_NAME + "|" + fbx_item
-            curve_key = get_blender_anim_curve_key(scene, ref_id, self.elem_key, self.fbx_group, fbx_item)
-            # (curve key, default value, keyframes, write flag).
-            group[fbx_item] = (curve_key, def_val, c, True if (len(c) > 1 or (len(c) > 0 and force_keep)) else False)
-
-        return group_key, group, self.fbx_group, self.fbx_gname
+        for elem_key, fbx_group, fbx_gname, fbx_props in zip(self.elem_keys, self.fbx_group, self.fbx_gname, self.fbx_props):
+            group_key = get_blender_anim_curve_node_key(scene, ref_id, elem_key, fbx_group)
+            group = OrderedDict()
+            for c, def_val, fbx_item in zip(curves, self.default_values, fbx_props):
+                fbx_item = FBX_ANIM_PROPSGROUP_NAME + "|" + fbx_item
+                curve_key = get_blender_anim_curve_key(scene, ref_id, elem_key, fbx_group, fbx_item)
+                # (curve key, default value, keyframes, write flag).
+                group[fbx_item] = (curve_key, def_val, c, True if (len(c) > 1 or (len(c) > 0 and force_keep)) else False)
+            yield elem_key, group_key, group, fbx_group, fbx_gname
 
 
 ##### FBX objects generators. #####



More information about the Bf-extensions-cvs mailing list