Created
February 4, 2016 19:10
-
-
Save cdbfoster/ee55590c7759d534cad9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# shift_object_animation_into_armature.py | |
# Chris Foster <cdbfoster@gmail.com> | |
# | |
# Creates a single armature containing a bone for every selected object and | |
# copies the movement of the selected objects into the bones. Sets up proper | |
# Armature modifiers for each affected object and clears its action. | |
# To use, select all desired objects and run the script. | |
from math import radians | |
import bpy | |
from mathutils import Matrix, Vector | |
def snap_cursor_to_selected(): | |
bpy.context.area.type = 'VIEW_3D' | |
bpy.ops.view3d.snap_cursor_to_selected() | |
bpy.context.area.type = 'TEXT_EDITOR' | |
def snap_cursor_to_center(): | |
bpy.context.area.type = 'VIEW_3D' | |
bpy.ops.view3d.snap_cursor_to_center() | |
bpy.context.area.type = 'TEXT_EDITOR' | |
def select_mesh(object): | |
for p in object.data.polygons: | |
p.select = True | |
mesh_objects = [object for object in bpy.context.selected_objects if object.type == 'MESH'] | |
snap_cursor_to_center() | |
bpy.ops.object.add(type='ARMATURE') | |
armature = bpy.context.active_object | |
def select_all_bones(deselect=False): | |
global armature | |
for bone in armature.pose.bones: | |
bone.bone.select = not deselect | |
bone.bone.select_head = not deselect | |
bone.bone.select_tail = not deselect | |
for mesh_object in mesh_objects: | |
bpy.ops.object.select_all(action='DESELECT') | |
mesh_object.select = True | |
snap_cursor_to_selected() | |
bone_name = mesh_object.name + "_arm" | |
# Create a bone at the mesh object's location that's an appropriate size | |
bpy.ops.object.select_all(action='DESELECT') | |
bpy.context.scene.objects.active = armature | |
bpy.ops.object.mode_set(mode='EDIT') | |
bpy.ops.armature.bone_primitive_add(name=bone_name) | |
bone = armature.data.edit_bones[bone_name] | |
bone.tail = bone.head + Vector((0.0, 0.0, mesh_object.dimensions.z / 2.0)) | |
bpy.ops.object.mode_set(mode='OBJECT') | |
# Add all vertices of the mesh object into the bone's vertex group | |
bpy.context.scene.objects.active = mesh_object | |
if bone_name in mesh_object.vertex_groups: | |
mesh_object.vertex_groups.active = mesh_object.vertex_groups[bone_name] | |
else: | |
bpy.ops.object.vertex_group_add() | |
vertex_group = mesh_object.vertex_groups.active | |
vertex_group.name = bone_name | |
select_mesh(mesh_object) | |
bpy.ops.object.mode_set(mode='EDIT') | |
bpy.ops.object.vertex_group_assign() | |
bpy.ops.object.mode_set(mode='OBJECT') | |
# Key the bones at the positions/rotations of the mesh objects at each frame | |
bpy.context.scene.objects.active = armature | |
bpy.ops.object.mode_set(mode='POSE') | |
select_all_bones() | |
for frame in range(bpy.context.scene.frame_start, bpy.context.scene.frame_end + 1): | |
bpy.context.scene.frame_set(frame) | |
for mesh_object in mesh_objects: | |
bone = armature.pose.bones[mesh_object.name + "_arm"] | |
bone.matrix = mesh_object.matrix_world * Matrix.Rotation(radians(90), 4, 'X') | |
bpy.ops.anim.keyframe_insert(type='BUILTIN_KSI_LocRot') | |
bpy.ops.object.mode_set(mode='OBJECT') | |
# Add Armature modifiers to the mesh objects and clear their actions | |
bpy.context.scene.frame_set(bpy.context.scene.frame_start) | |
for mesh_object in mesh_objects: | |
mesh_object.animation_data.action = None | |
bpy.context.scene.objects.active = mesh_object | |
bpy.ops.object.modifier_add(type='ARMATURE') | |
mesh_object.modifiers[-1].object = armature |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment