# Creating objects with a 'for loop' and setting each new one a keyframe within the 'for loop'

So I wish to have a script which creates an object then set's it keyframe at a frame, 'f', before creating another object and setting a keyframe at a new frame, say f+1. However it always sets the keyframe to the first object created and not to the newer ones and using bpy.ops.data.object['Wave'].select = True doesn't work as it just selects the first plane created and not the others (due to the fact the others are named Wave.001 for example. I thought about turning the name into a string but that seemed like an improbable solution. When I ran this script with a more simple example of a plane it seemed to work... Here's the script I'm using for the wave:

import bpy
import math
scn = bpy.context.scene

numY = 10
freq = 1
amp = 1
scale = 1

for numX in range (2, 20):
scn.frame_current = numX - 2
verts = []
faces = []

for i in range (0, numX):
for j in range (0, numY):
x = scale * i
y = scale * j
z = scale*((amp*math.cos(i*freq))+(amp*math.sin(j*freq)))

vert = (x,y,z)
verts.append(vert)

count = 0
for i in range (0, numY*(numX-1)):
if count < numY-1:
A = i
B = i+1
C = (i+numY)+1
D = (i+numY)

face = (A,B,C,D)
faces.append(face)
count = count + 1
else:
count = 0

mesh = bpy.data.meshes.new("Wave")
object = bpy.data.objects.new("Wave",mesh)

object.location = (0,0,0)

mesh.from_pydata(verts, [],faces)
mesh.update(calc_edges=True)
bpy.ops.data.object['Wave'].select = True


The strange thing was that without the bpy.ops.data.object['Wave'].select = True the script fails with it outlining bpy.ops.anim.keyframe_insert_menu(type='Location') as the issue. I don't see a difference between this and the simpler cube example though - which works fine without the need of selecting the Plane. Here's the code for the plane example :

import bpy
from mathutils import Vector

scn = bpy.context.scene
scn.frame_start = 0
scn.frame_end = 20
scn.frame_current = 0
for f in range (0, 20):
Plane = bpy.context.object
Plane.name = "Plane"
PlaneMesh = Plane.data

verts = [(0,0,0), (0,5,0), (0,5,5), (0,0,5)]
faces = [(0,1,2,3)]

PlaneMesh.from_pydata(verts, [], faces)
PlaneMesh.update()
scn.frame_current = f

scn.frame_current = 0


• – Ray Mairlot Oct 4 '17 at 16:49
• @RayMairlot I now see its impracticality but what else would be a solution to insert keyframes then? – CooperCape Oct 4 '17 at 17:10
• In this instance, I don't actually think that's the issue, just something to note, but it's hard to tell if I've got the script working because I'm not sure what it's meant to do. The error in the line where you are selecting your object is because bpy.ops does not store the list of objects (the error was trying to tell you this), the correct command is bpy.data.objects['objectName']. But you can just do object.select = True anyway. – Ray Mairlot Oct 4 '17 at 17:26
• @batFINGER Okay thanks... I've changed all names from object now. By using context.object != context.selected_objects[0] is this deselecting all selected objects? And from that I can select the new object and edit thus? – CooperCape Oct 4 '17 at 18:22
• To make an object the context object need to use scene.objects.active = obj. before calling an operator that works on context object. Anyway, don't use bpy.ops.anim.keyframe_insert use obj.keyframe_insert(data_path, frame=frame) Can be done without any need to set scene frame also. Can write up as answer if you prefer. – batFINGER Oct 4 '17 at 18:23

Here is your script (a) doing what I think you want it to do. It makes a mesh object at each frame, and adds a location keyframe at the frame it was created in script.

If you are using an operator, need to be in, or set the context it requires. Make a new object obj context with context.scene.objects.active = obj. If it works on selected objects, like say join, need to make sure other objects are (de)selected correctly by setting obj.select accordingly on each.

Going to use bpy_struct.keyframe_insert(...) rather than the operator. This will be quicker, especially for high numbers.

import bpy
from math import sin, cos
scn = bpy.context.scene

numY = 10
freq = 1
amp = 1
scale = 1

for numX in range (2, 20):
verts = []
faces = []

for i in range (0, numX):
x = scale * i
for j in range (0, numY):
y = scale * j
z = scale * amp * (cos(i * freq) + sin(j * freq))
vert = (x, y, z)
verts.append(vert)

count = 0
for i in range (0, numY * (numX - 1)):
if count < numY - 1:
A = i
B = i + 1
C = (i + numY) + 1
D = (i + numY)

face = (A, B, C, D)
faces.append(face)
count = count + 1
else:
count = 0

mesh = bpy.data.meshes.new("Wave")

mesh.from_pydata(verts, [], faces)
mesh.update(calc_edges = True)

obj = bpy.data.objects.new("Wave", mesh)

obj.location = (0, 0, 0)
obj.keyframe_insert("location", frame=numX, group="Location")

• Thanks! Works exactly how I wanted it to (even if I didn't explain that very well oops...) – CooperCape Oct 4 '17 at 18:50
• Just so I know what's going on what's happening with the last two lines? – CooperCape Oct 4 '17 at 18:51