import bpy
import math
def maybeDispose(name):
obj = bpy.data.objects.get(name)
if not obj is None:
obj.name = "discard"
bpy.context.scene.objects.unlink(obj)
def fakeData():
rval = []
for x in range(100+1):
y = (x*x)/100 + 4*math.sin(x/2)
rval.append( [ x,y] )
return rval
def makeCurve(name, data):
curve = bpy.data.curves.new(name, 'CURVE')
spline = curve.splines.new('BEZIER')
spline.bezier_points.add(len(data) - 1)
for i,xy in enumerate(data):
xyz = [ xy[0], xy[1], 0 ]
spline.bezier_points[i].co = xyz
spline.bezier_points[i].handle_left = xyz
spline.bezier_points[i].handle_right = xyz
curve.bevel_object = bpy.data.objects["line"]
return curve
def animateCurveBevel(obj, f1, f2):
obj.data.keyframe_insert(data_path="bevel_factor_end", frame=f2)
obj.data.bevel_factor_end = 0
obj.data.keyframe_insert(data_path="bevel_factor_end", frame=f1)
anim = obj.data.animation_data.action.fcurves[0]
anim.keyframe_points[0].interpolation = 'LINEAR'
def animateCurveBevelBad(obj, f1, f2):
obj.keyframe_insert(data_path="data.bevel_factor_end", frame=f2)
obj.data.bevel_factor_end = 0
obj.keyframe_insert(data_path="data.bevel_factor_end", frame=f1)
anim = obj.animation_data.action.fcurves[0]
anim.keyframe_points[0].interpolation = 'LINEAR'
def frameForX(idx, nPoints, f0, f9):
return f0 + (f9-f0) *idx/(nPoints-1)
def setVisibility(obj, f1, f2):
if not f2 is None:
obj.keyframe_insert(data_path='hide', frame= bpy.context.scene.frame_end+10)
obj.keyframe_insert(data_path='hide_render', frame=f1)
obj.keyframe_insert(data_path='hide', frame=f1)
obj.hide = True
obj.hide_render = True
obj.keyframe_insert(data_path='hide', frame=0)
obj.keyframe_insert(data_path='hide_render', frame=0)
if not f2 is None:
obj.keyframe_insert(data_path='hide', frame=f2)
obj.keyframe_insert(data_path='hide_render', frame=f2)
def makeText(text, loc, f1, f2):
curve = bpy.data.curves.new("label", 'FONT')
curve.body = text
o1 = bpy.data.objects.new("label", curve)
bpy.context.scene.objects.link(o1)
o1.location = loc
if not f1 is None:
setVisibility(o1, f1, f2)
o1.parent = bpy.data.objects["font folder"]
curve.materials.append(bpy.data.materials["text"])
return o1
def make2Text(text1, text2, loc, f1, f2):
o1 = makeText(text1, loc, f1, f2)
o2 = makeText(text2, loc, f1, f2)
o1.data.align = 'RIGHT'
return (o1, o2)
def lookUp(data, f0, f9, frame):
f1 = -1
for i,xy in enumerate(data):
f2 = frameForX(i, len(data), f0, f9)
f3 = frameForX(i+1, len(data), f0, f9)
if frame<f3:
return xy
f1 = f2
return data[-1]
#
#
name = "graph"
for obj in bpy.data.objects:
if obj.name[:5] == "label":
obj.name = "discard"
bpy.context.scene.objects.unlink(obj)
maybeDispose(name)
data = fakeData()
obj = bpy.data.objects.new(name, makeCurve(name, data))
obj.scale = (0.1,0.1,0.1)
bpy.context.scene.objects.link(obj)
bpy.context.scene.objects.active = obj
obj.select = True
obj.data.materials.append(bpy.data.materials["graph"])
f0 = 31
f9 = f0+ 5*bpy.context.scene.render.fps
animateCurveBevel(obj, 31, f9)
if False:
# animating text by creating hundreds of individual text objects that pop in and out
f1 = -1
for i,xy in enumerate(data):
f2 = frameForX(i, len(data), f0, f9)
f3 = frameForX(i+1, len(data), f0, f9)
if (i+1 >= len(data)):
f3 = None
if (f2>f1):
make2Text("x=%d,"%xy[0], "y=%.1f"%xy[1], [4,6,1], f2, f3)
f1 = f2
else:
# animating text by hooking into the frame_change_pre callback.
# Thanks: http://blender.stackexchange.com/questions/7904/dynamic-text-in-animation
# wipe out any preexisting handlers. Hope that doesn't ruin anyone's day.
bpy.app.handlers.frame_change_pre.clear()
# make the two text objects.
(t1, t2) = make2Text("x=?,", "y=?", [4,6,1], None, None)
tdata1 = t1.data
tdata2 = t2.data
def adjustText(scene):
"""
Update the body on the text labels to be correct for each frame.
"""
xy = lookUp(data, f0, f9, scene.frame_current)
tdata1.body = "x=%d,"%xy[0]
tdata2.body = "y=%.1f"%xy[1]
bpy.app.handlers.frame_change_pre.append(adjustText)
#
|
Blender python API quick-start
Syntax highlighting by Pygments.