The Animation Replicator with Offset - Part 2

Finally, I managed to complete the second part of the ARewO tutorial. It can now distribute objects along a path and include armatures.

If you haven't watched the first part, I strongly recommend you to do so.


So here is the script:
[code:python]import bpy
import math

loops = 30
distanceX = 0
distanceY = 0.4
distanceZ = 0
offset = 6
offset_extra = 0

arm = bpy.context.active_object
kinder = bpy.context.selected_objects
placer = bpy.data.objects['Placer']

for i in range(loops):
    print(str(i))
    bpy.ops.object.duplicate_move(OBJECT_OT_duplicate={"linked":True})
    bpy.context.scene.frame_set(i)
    bpy.ops.object.make_single_user(type = 'SELECTED_OBJECTS', object = False, obdata = False, material = False, texture = False, animation = True)
    bpy.ops.object.select_all(action = 'DESELECT')
    for j in range(3):
        arm.location[j] = placer.matrix_world[j][3]
    animData = arm.animation_data
    action = animData.action
    fcurves = action.fcurves
    for k in range(len(kinder)):
        kinder[k].select = True
    for curve in fcurves:     
        keyframePoints = curve.keyframe_points
        for keyframe in keyframePoints:
            keyframe.co[0] += offset #verschieben
            keyframe.handle_left[0] += offset
            keyframe.handle_right[0] += offset
print("done")[/code]

And here the explanation:
[code:python]arm = bpy.context.active_object
kinder = bpy.context.selected_objects
placer = bpy.data.objects['Placer']
[/code]These are the important variables. Arm is the armature you want to include, notice that it has to be the active object in your bunch. Kinder are all selected objects and placer is an object that flies anywhere it wants, but it needs to exist with the name "Placer".

[code:python]for i in range(loops):
    print(str(i))
    bpy.ops.object.duplicate_move(OBJECT_OT_duplicate={"linked":True})
    bpy.context.scene.frame_set(i)[/code]This calls a for loop that will execute as many times as you specified with the "loops" variable.
We want a linked copy of our object, in case we want to change something later and also linked objects render faster.
[code:python]    bpy.ops.object.make_single_user(type = 'SELECTED_OBJECTS', object = False, obdata = False, material = False, texture = False, animation = True)[/code]But we cannot have the animation linked, because we want to offset it in time, and if we wouldn't make it a single user, our offset would go into all our armatures, thus synchronizing them.

[code:python]    for j in range(3):
        arm.location[j] = placer.matrix_world[j][3]][/code]Now this is a tricky one, try parenting an object to an empty, then remember its location displayed in the "n" menu. then move only the empty, you'll see, even though your object has moved in space, its location is the same. Same for pathes, so we need to find the absolute location of our placer object, in order to be able to make our armature copy its position. If you type in C.active_object.matrix_world in the console, you'll see that it's a 2 dimensional array, thus requiring 2 indices, I picked out the right ones for you, they result in the world x, y and z location.

[code:python]    animData = arm.animation_data
    action = animData.action
    fcurves = action.fcurves[/code]Those are just variables that make it a little easier for someone else to follow the code.
[code:python]    for k in range(len(kinder)):
        kinder[k].select = True[/code]Kinder is german for children. I don't like to use reserved terms for variables like "children". But the code is supposed to select all children, so I chose the German word for it, feel free to change it.
Oh, right, the actual explanation: it will reselect all objects that were selected when we pressed "run script".

[code:python]    for curve in fcurves:     
        keyframePoints = curve.keyframe_points
        for keyframe in keyframePoints:
            keyframe.co[0] += offset #verschieben
            keyframe.handle_left[0] += offset
            keyframe.handle_right[0] += offset[/code]            
This part looks through all f-curves and then trough all keyframes in each f-curve. It then moves them in x (time) by the offset we specified.

[code:python]print("done")[/code]This indicates that the script worked with surgical precision.

Download the finished .blend here!