Skip to content

Instantly share code, notes, and snippets.

@cdbfoster
Created February 4, 2016 19:10
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cdbfoster/ee55590c7759d534cad9 to your computer and use it in GitHub Desktop.
Save cdbfoster/ee55590c7759d534cad9 to your computer and use it in GitHub Desktop.
# 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