From dda5658325f247c4773ce43721d6a522b11d3048 Mon Sep 17 00:00:00 2001
From: Bastien Montagne <montagne29@wanadoo.fr>
Date: Sat, 6 Oct 2012 13:24:08 +0000
Subject: [PATCH] Fix for [#32792] BVH exporter crashes on rigs with multiple
 roots.

In this situation, the script creates a dummy root bone... But code was buggy (and import of non-rotating bones was too).
---
 io_anim_bvh/export_bvh.py | 16 ++++++++++++----
 io_anim_bvh/import_bvh.py |  5 +++--
 2 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/io_anim_bvh/export_bvh.py b/io_anim_bvh/export_bvh.py
index fcddb63cf..4d7f0b093 100644
--- a/io_anim_bvh/export_bvh.py
+++ b/io_anim_bvh/export_bvh.py
@@ -99,7 +99,7 @@ def write_armature(context,
 
         if my_children:
             # store the location for the children
-            # to het their relative offset
+            # to get their relative offset
 
             # Write children
             for child_bone in my_children:
@@ -124,15 +124,23 @@ def write_armature(context,
         write_recursive_nodes(key, indent)
 
     else:
-        # Write a dummy parent node
+        # Write a dummy parent node, with a dummy key name
+        # Just be sure it's not used by another bone!
+        i = 0
+        key = "__%d" % i
+        while key in children:
+            i += 1
+            key = "__%d" % i
         file.write("ROOT %s\n" % key)
         file.write("{\n")
         file.write("\tOFFSET 0.0 0.0 0.0\n")
         file.write("\tCHANNELS 0\n")  # Xposition Yposition Zposition Xrotation Yrotation Zrotation
-        key = None
         indent = 1
 
-        write_recursive_nodes(key, indent)
+        # Write children
+        for child_bone in children[None]:
+            serialized_names.append(child_bone)
+            write_recursive_nodes(child_bone, indent)
 
         file.write("}\n")
 
diff --git a/io_anim_bvh/import_bvh.py b/io_anim_bvh/import_bvh.py
index a19b39dbf..fc3aebd1a 100644
--- a/io_anim_bvh/import_bvh.py
+++ b/io_anim_bvh/import_bvh.py
@@ -35,7 +35,7 @@ class BVH_Node(object):
         'rest_head_local',  # localspace rest location for the head of this node
         'rest_tail_world',  # worldspace rest location for the tail of this node
         'rest_tail_local',  # worldspace rest location for the tail of this node
-        'channels',  # list of 6 ints, -1 for an unused channel, otherwise an index for the BVH motion data lines, lock triple then rot triple
+        'channels',  # list of 6 ints, -1 for an unused channel, otherwise an index for the BVH motion data lines, loc triple then rot triple
         'rot_order',  # a triple of indices as to the order rotation is applied. [0,1,2] is x/y/z - [None, None, None] if no rotation.
         'rot_order_str',  # same as above but a string 'XYZ' format.
         'anim_data',  # a list one tuple's one for each frame. (locx, locy, locz, rotx, roty, rotz), euler rotation ALWAYS stored xyz order, even when native used.
@@ -45,7 +45,8 @@ class BVH_Node(object):
         'temp',  # use this for whatever you want
         )
 
-    _eul_order_lookup = {(0, 1, 2): 'XYZ',
+    _eul_order_lookup = {(None, None, None): 'XYZ', # XXX Dummy one, no rotation anyway!
+                         (0, 1, 2): 'XYZ',
                          (0, 2, 1): 'XZY',
                          (1, 0, 2): 'YXZ',
                          (1, 2, 0): 'YZX',
-- 
GitLab