Skip to content

Commit

Permalink
Make bones included in xmot export configurable
Browse files Browse the repository at this point in the history
  • Loading branch information
georgeto committed Mar 24, 2024
1 parent 5d05d21 commit 463e3e4
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 7 deletions.
21 changes: 20 additions & 1 deletion g3blend/operators/io_export_xmot.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,16 @@

logger = logging.getLogger(__name__)

# These are the only slots commonly used animations.
COMMONLY_USED_SLOTS = {
'Slot_LeftHand_Weapon', # relevant for everything except faces
'Slot_RightHand_Weapon', # relevant for everything except faces
'Slot_Beard', # relevant for faces
}


def save_xmot(context: bpy.types.Context, filepath: str, arm_obj: bpy.types.Object, global_scale: float,
global_matrix: Matrix, ignore_transform: bool, use_selection: bool):
global_matrix: Matrix, ignore_transform: bool, bone_filter: str):
xmot = Xmot()
xmot.resource_size = 0
xmot.resource_priority = 0.0
Expand All @@ -33,6 +40,10 @@ def save_xmot(context: bpy.types.Context, filepath: str, arm_obj: bpy.types.Obje
if arm_obj is None:
raise ValueError('No armature was selected.')

use_selection = bone_filter in ['SELECTED', 'SELECTED_WITH_SLOTS']
with_keysframes = bone_filter == 'WITH_KEYFRAMES'
filter_slots = not with_keysframes and bone_filter not in ['ALL_WITH_SLOTS', 'SELECTED_WITH_SLOTS']

# 2. Figure out keyframe/animation data for each bone
action = arm_obj.animation_data.action

Expand Down Expand Up @@ -92,9 +103,17 @@ def save_xmot(context: bpy.types.Context, filepath: str, arm_obj: bpy.types.Obje
# 3. Collect all bones in armature
selected_pose_bones = context.selected_pose_bones
for pose_bone in reversed(arm_obj.pose.bones):
# Filter by selection.
if use_selection and pose_bone not in selected_pose_bones:
continue

# Filter by keyframes.
if with_keysframes and not any(True for bone_name, _ in frames_per_bone.keys() if bone_name == pose_bone.name):
continue

if filter_slots and pose_bone.name.startswith('Slot_') and pose_bone.name not in COMMONLY_USED_SLOTS:
continue

bone = pose_bone.bone

rest_matrix = bone.matrix_local
Expand Down
34 changes: 28 additions & 6 deletions g3blend/ui/io_export_xmot.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,32 @@ def _get_target_armature(self):
get=_get_target_armature,
)

use_selection: BoolProperty(
name='Selection Only',
description='Export selected objects only',
default=False,
# Overlay / Normal / Interactive
# All Bones
# Bones with Keyframes
# Selected Bones
# TODO: <Groups>
# All Bones (including unused slots)
# Selected Bones (including unused slots)
bone_filter: EnumProperty(
name='Bones',
description='Bones that shall be included in the exported animation',
items=[
('ALL', 'All', 'Include all bones (slots not commonly used in animations are filtered out)'),
('WITH_KEYFRAMES', 'With Keyframes',
'Include only bones that have keyframe data assigned. '
'Especially useful when re-exporting a modified animation, because for example overlay animations'
'(recognizable by their _O_ infix) only apply to a part of the skeleton. '
'In such an xmot, only a subset of bones is contained and on import keyframe data is only created for these bones.'
"When re-exporting later with 'With Keyframes' ensures that only this subset of bones is included."),
('SELECTED', 'Selected',
'Include only selected bones (slots not commonly used in animations are filtered out)'),
('ALL_WITH_SLOTS', 'All (including uncommon slots)',
'Include all bones (including slots not commonly used in animations)'),
('SELECTED_WITH_SLOTS', 'Selected (including uncommon slots)',
'Include only selected bones (including slots not commonly used in animations)'),
],
default='WITH_KEYFRAMES',
)

ignore_transform: BoolProperty(
Expand All @@ -58,7 +80,7 @@ def execute(self, context):
global_scale, global_matrix = self._global_transform(context)
target_armature = get_object_for_armature_item(context, self.target_armature)
save_xmot(context, self.filepath, target_armature, global_scale, global_matrix, self.ignore_transform,
self.use_selection)
self.bone_filter)
self.target_armature_index = 0
except Exception as e:
self.report({'ERROR'}, f'Error while exporting {self.filepath}: {e}')
Expand All @@ -77,7 +99,7 @@ def _draw(self, context: bpy.types.Context, layout: bpy.types.UILayout, operator
target_armature = get_object_for_armature_item(context, operator.target_armature)
sub = layout.row()
sub.enabled = target_armature is not None
sub.prop(operator, "use_selection")
sub.prop(operator, "bone_filter")


class G3BLEND_PT_export_xmot_transform(AbstractFileTransformPanel):
Expand Down

0 comments on commit 463e3e4

Please sign in to comment.