diff --git a/io_scene_dae/__init__.py b/io_scene_dae/__init__.py index 5090605..10120c4 100644 --- a/io_scene_dae/__init__.py +++ b/io_scene_dae/__init__.py @@ -99,6 +99,11 @@ class ExportDAE(bpy.types.Operator, ExportHelper): description="Export only objects on the active layers.", default=True, ) + use_exclude_ctrl_bones = BoolProperty( + name="Exclude Control Bones", + description="Exclude skeleton bones with names that begin with 'ctrl'.", + default=True, + ) use_anim = BoolProperty( name="Export Animation", description="Export keyframe animation", diff --git a/io_scene_dae/export_dae.py b/io_scene_dae/export_dae.py index 0087b2a..d201639 100644 --- a/io_scene_dae/export_dae.py +++ b/io_scene_dae/export_dae.py @@ -1093,38 +1093,52 @@ class DaeExporter: self.writel(S_NODES, il, '') def export_armature_bone(self, bone, il, si): - boneid = self.new_id("bone") - boneidx = si["bone_count"] - si["bone_count"] += 1 - bonesid = "{}-{}".format(si["id"], boneidx) - if (bone.name in self.used_bones): - if (self.config["use_anim_action_all"]): - self.operator.report({"WARNING"}, - "Bone name \"{}\" used in more than one skeleton. "\ - "Actions might export wrong.".format(bone.name)) - else: - self.used_bones.append(bone.name) + is_ctrl_bone = (bone.name.startswith("ctrl") and self.config["use_exclude_ctrl_bones"]) + if (bone.parent is None and is_ctrl_bone is True): + self.operator.report({'WARNING'},'Root bone cannot be a control bone.') + is_ctrl_bone = False + + if (is_ctrl_bone is False): + boneid = self.new_id("bone") + boneidx = si["bone_count"] + si["bone_count"] += 1 + bonesid = si["id"] + "-" + str(boneidx) + if (bone.name in self.used_bones): + if (self.config["use_anim_action_all"]): + self.operator.report({'WARNING'}, 'Bone name "' + bone.name + + '" used in more than one skeleton. ' + 'Actions might export wrong.') + else: + self.used_bones.append(bone.name) + + si["bone_index"][bone.name] = boneidx + si["bone_ids"][bone] = boneid + si["bone_names"].append(bonesid) + self.writel(S_NODES, il, '') + + if (is_ctrl_bone is False): + il += 1 - si["bone_index"][bone.name] = boneidx - si["bone_ids"][bone] = boneid - si["bone_names"].append(bonesid) - self.writel(S_NODES, il, '') - il += 1 xform = bone.matrix_local - si["bone_bind_poses"].append((si["armature_xform"] * xform).inverted()) + if (is_ctrl_bone is False): + si["bone_bind_poses"].append((si["armature_xform"] * xform).inverted_safe()) if (bone.parent is not None): - xform = bone.parent.matrix_local.inverted() * xform + xform = bone.parent.matrix_local.inverted_safe() * xform else: si["skeleton_nodes"].append(boneid) - self.writel(S_NODES, il, '' + - strmtx(xform) + '') + if (is_ctrl_bone is False): + self.writel(S_NODES, il, '' + + strmtx(xform) + '') + for c in bone.children: self.export_armature_bone(c, il, si) - il -= 1 - self.writel(S_NODES, il, '') + + if (is_ctrl_bone is False): + il -= 1 + self.writel(S_NODES, il, '') def export_armature_node(self, node, il): if (node.data is None): @@ -1682,7 +1696,7 @@ class DaeExporter: mtx = node.matrix_world.copy() if (node.parent): - mtx = node.parent.matrix_world.inverted() * mtx + mtx = node.parent.matrix_world.inverted_safe() * mtx xform_cache[name].append((key, mtx)) @@ -1690,7 +1704,9 @@ class DaeExporter: # All bones exported for now for bone in node.data.bones: - + if((bone.name.startswith("ctrl") and self.config["use_exclude_ctrl_bones"])): + continue + bone_name = self.skeleton_info[node]["bone_ids"][bone] if (not (bone_name in xform_cache)): @@ -1702,7 +1718,13 @@ class DaeExporter: mtx = posebone.matrix.copy() if (bone.parent): - parent_posebone = node.pose.bones[bone.parent.name] + if (self.config["use_exclude_ctrl_bones"]): + current_parent_posebone = bone.parent + while (current_parent_posebone.name.startswith("ctrl") and current_parent_posebone.parent): + current_parent_posebone = current_parent_posebone.parent + parent_posebone = node.pose.bones[current_parent_posebone.name] + else: + parent_posebone = node.pose.bones[bone.parent.name] parent_invisible = False for i in range(3): @@ -1710,7 +1732,7 @@ class DaeExporter: parent_invisible = True if (not parent_invisible): - mtx = parent_posebone.matrix.inverted() * mtx + mtx = parent_posebone.matrix.inverted_safe() * mtx xform_cache[bone_name].append((key, mtx))