diff --git a/pype/plugins/blender/create/create_animation.py b/pype/plugins/blender/create/create_animation.py index b40a456c8f..6b7616bbfd 100644 --- a/pype/plugins/blender/create/create_animation.py +++ b/pype/plugins/blender/create/create_animation.py @@ -25,8 +25,28 @@ class CreateAnimation(Creator): self.data['task'] = api.Session.get('AVALON_TASK') lib.imprint(collection, self.data) + # Add the rig object and all the children meshes to + # a set and link them all at the end to avoid duplicates. + # Blender crashes if trying to link an object that is already linked. + # This links automatically the children meshes if they were not + # selected, and doesn't link them twice if they, insted, + # were manually selected by the user. + objects_to_link = set() + if (self.options or {}).get("useSelection"): + for obj in lib.get_selection(): - collection.objects.link(obj) + + objects_to_link.add( obj ) + + if obj.type == 'ARMATURE': + + for subobj in obj.children: + + objects_to_link.add(subobj) + + for obj in objects_to_link: + + collection.objects.link(obj) return collection diff --git a/pype/plugins/blender/publish/extract_fbx_animation.py b/pype/plugins/blender/publish/extract_fbx_animation.py index bc088f8bb7..4b1fe98c2f 100644 --- a/pype/plugins/blender/publish/extract_fbx_animation.py +++ b/pype/plugins/blender/publish/extract_fbx_animation.py @@ -47,8 +47,7 @@ class ExtractAnimationFBX(pype.api.Extractor): # We set the scale of the scene for the export bpy.context.scene.unit_settings.scale_length = 0.01 - # We export all the objects in the collection - objects_to_export = collections[0].objects + armatures = [obj for obj in collections[0].objects if obj.type == 'ARMATURE'] object_action_pairs = [] original_actions = [] @@ -56,20 +55,25 @@ class ExtractAnimationFBX(pype.api.Extractor): starting_frames = [] ending_frames = [] - # For each object, we make a copy of the current action - for obj in objects_to_export: + # For each armature, we make a copy of the current action + for obj in armatures: - curr_action = obj.animation_data.action - copy_action = curr_action.copy() + curr_action = None + copy_action = None + + if obj.animation_data and obj.animation_data.action: + + curr_action = obj.animation_data.action + copy_action = curr_action.copy() + + curr_frame_range = curr_action.frame_range + + starting_frames.append( curr_frame_range[0] ) + ending_frames.append( curr_frame_range[1] ) object_action_pairs.append((obj, copy_action)) original_actions.append(curr_action) - curr_frame_range = curr_action.frame_range - - starting_frames.append( curr_frame_range[0] ) - ending_frames.append( curr_frame_range[1] ) - # We compute the starting and ending frames max_frame = min( starting_frames ) min_frame = max( ending_frames ) @@ -98,10 +102,14 @@ class ExtractAnimationFBX(pype.api.Extractor): # We delete the baked action and set the original one back for i in range(0, len(object_action_pairs)): - object_action_pairs[i][0].animation_data.action = original_actions[i] + if original_actions[i]: - object_action_pairs[i][1].user_clear() - bpy.data.actions.remove(object_action_pairs[i][1]) + object_action_pairs[i][0].animation_data.action = original_actions[i] + + if object_action_pairs[i][1]: + + object_action_pairs[i][1].user_clear() + bpy.data.actions.remove(object_action_pairs[i][1]) if "representations" not in instance.data: instance.data["representations"] = []