import bpy
import random
import math
def action_z_spin():
"""
:return: the action for spinning on the Z axis with a period of 30 frames
"""
rval = bpy.data.actions.get("z spin")
if rval is None:
rval = bpy.data.actions.new("z spin")
curve = rval.fcurves.new("rotation_euler", 2)
curve.extrapolation = 'LINEAR'
curve.keyframe_points.add(2)
p0 = curve.keyframe_points[0]
p1 = curve.keyframe_points[1]
p0.interpolation = 'LINEAR'
p0.co = (1, 0)
p1.co = (31, math.pi*2)
return rval
def many_spinning_frogs(template, bounds, count, name, group):
"""
return a list of 'count' objects (not yet linked to the scene).
Each object is an empty rigged to duplicate the group 'template'.
Each object also has an NLA track which references the "z spin" action with a random time scale.
Each object is added to 'group'.
:param template: a group of objects for each empty to duplicate
:param bounds: a list of the form [xmin, xmax, ymin, ymax, zmin, zmax]
:param count: how many objects to create and return
:param name: the name for newly created objects
:param group: the group to which all newly created objects will be added
"""
rval = []
for i in range(count):
# pick a random coordinate in the bounds
x = random.uniform(bounds[0], bounds[1])
y = random.uniform(bounds[2], bounds[3])
z = random.uniform(bounds[4], bounds[5])
obj = bpy.data.objects.new(name, None)
obj.location = (x, y, z)
# rig the Empty to duplicate the template group
obj.dupli_type = 'GROUP'
obj.dupli_group = template
# brand new objects don't have any animation_data, so we create it
obj.animation_data_create()
# create an NLA track
track = obj.animation_data.nla_tracks.new()
track.name = "spin"
# create a new strip in that track with the z_spin() action
strip = track.strips.new("spin", 1, action_z_spin())
# The strip will pull values from the z_spin() action covering 20 to 100 seconds (random)
strip.action_frame_start = 1
freq = random.randrange(20, 100)
if random.randrange(2) > 0:
# this is a little trick to make half the frogs spin the opposite direction,
# since you can't run NLAs in reverse.
obj.rotation_euler[1] = math.pi
obj.rotation_mode = 'ZXY'
strip.action_frame_end = freq*30
# the strip will scale that random span of time to 200 seconds
strip.frame_end = 1+30*200
# the order in which you set action_frame_end and frame_end are important.
# Setting them in the "wrong" order can cause a recalculation
# of the other value to something you don't want.
# stuff the newly created object in the group
if not group is None:
group.objects.link(obj)
rval.append(obj)
return rval
#
#
#
frog = bpy.data.groups['frog']
group = bpy.data.groups.get("stars")
if group is None:
group = bpy.data.groups.new("stars")
frogs = many_spinning_frogs(frog, [-15, 15, -10, 10, -20, -40], 100, "star", group)
for obj in frogs:
bpy.context.scene.objects.link(obj)
|
Blender python API quick-start
Syntax highlighting by Pygments.