__author__ = 'thoth'
import bpy
from mathutils import *
movies = {
"bbb1080.mp4": {
"img": "bbb1080.mp4",
"base_frame":1000
},
"redline.mp4": {
"img": "redline.mp4",
"base_frame": 2593
},
"redline A": {
"img": "redline.mp4",
"base_frame": 2593
},
"redline B": {
"img": "redline.mp4",
"base_frame": 5838
}
}
def material_for(image_movie, offset):
name = "%s o=%d" % (image_movie.name, offset)
mat = bpy.data.materials.get(name)
if mat is None:
mat = bpy.data.materials.new(name)
mat.texture_slots.add()
ts0 = mat.texture_slots[0]
ts0.texture_coords = 'UV'
ts0.uv_layer = 'UVMap'
ts0.texture = bpy.data.textures.new(name, 'IMAGE')
else:
ts0 = mat.texture_slots[0]
mat.specular_intensity = 0
t1 = ts0.texture
t1.image = image_movie
t1.image_user.frame_duration = 1
t1.image_user.frame_offset = offset
return mat
def action_card_start():
return bpy.data.actions.get("card start")
def action_card_pick_up():
return bpy.data.actions.get("card parenting")
def action_card_release():
return bpy.data.actions.get("card release")
def rig_child_animation(obj, pick_up, release):
if obj.animation_data is None:
obj.animation_data_create()
track = obj.animation_data.nla_tracks.new()
track.new("pick up", pick_up, action_card_pick_up())
track.new("release", release, action_card_release())
def cardbot_for(num, loc=None):
""" get or create the cardbot object and armature with the requested number. Then set the location
"""
rval = None
scn = bpy.context.scene
for obj in scn.objects:
if obj.get("bot.number") == num and obj.data.name == "cardbot":
# print(obj)
if not hasattr(obj.data, "bones"):
rval = obj
ao = rval.parent
if rval is None:
# hmm, doesn't exist yet
mesh = bpy.data.meshes["cardbot"]
rval = bpy.data.objects.new("cardbot", mesh)
rval["bot.number"] = num
arm = bpy.data.armatures["cardbot"]
ao = bpy.data.objects.new("cardbot armature", arm)
ao["bot.number"] = num
mod = rval.modifiers.new("armature", "ARMATURE")
mod.object = ao
clone_vertex_groups(bpy.data.objects["transmit bot"], rval)
rval.parent = ao
try:
scn.objects.link(rval)
except:
pass
try:
scn.objects.link(ao)
except:
pass
if loc is not None:
ao.location = loc
# and now comes the part I hate:
bpy.context.scene.objects.active = ao
bpy.ops.object.mode_set(mode='POSE')
for bone in ao.pose.bones:
bone.rotation_mode = 'XYZ'
bpy.ops.object.mode_set(mode='OBJECT')
return [rval, ao]
def add_child_constraint(obj, name, target, bone_name=None, use_location=True, use_rotation=True):
cns = obj.constraints.new('CHILD_OF')
cns.name = name
cns.target = target
cns.use_location_x = use_location
cns.use_location_y = use_location
cns.use_location_z = use_location
cns.use_rotation_x = use_rotation
cns.use_rotation_y = use_rotation
cns.use_rotation_z = use_rotation
if bone_name is not None:
cns.subtarget = bone_name
def make_card_animated(armature, movie_id, pickup, release, num):
name = "movie card"
mesh = bpy.data.meshes["movie card"]
obj = bpy.data.objects.new(name, mesh)
ms0 = obj.material_slots[0]
ms0.link = 'OBJECT'
image_movie = bpy.data.images[movies[movie_id]["img"]]
movie_base = movies[movie_id]["base_frame"]
ms0.material = material_for(image_movie, pickup+movie_base)
obj["card.number"] = num
obj["bot.number"] = armature["bot.number"]
scn = bpy.context.scene
scn.objects.link(obj)
obj.animation_data_create()
track = obj.animation_data.nla_tracks.new()
track.strips.new("pick up", pickup-49, action_card_pick_up())
track.strips.new("release", release, action_card_release())
try:
track.strips.new("start", min(1, pickup-51), action_card_start())
except:
# the pickup happened so early we don't even need a start strip
pass
add_child_constraint(obj, "prelude rotation", armature, "card pre", False, True)
add_child_constraint(obj, "prelude", armature, "card pre", True, False)
add_child_constraint(obj, "ready", armature, "card lift", True, False)
add_child_constraint(obj, "on arm", armature, "card anchor")
add_child_constraint(obj, "sky", get_card_destination())
add_child_constraint(obj, "up", armature, "card release")
obj.layers = [i==1 or i==5 for i in range(20)]
return obj
def get_card_destination():
return bpy.data.objects.get("card destination")
def make_phantom_animated(armature, pickup, release, num):
name = "phantom"
mesh = bpy.data.meshes["phantom"]
obj = bpy.data.objects.new(name, mesh)
obj.scale = [0.25, 0.25, 0.25]
obj["card.number"] = num
obj["bot.number"] = armature["bot.number"]
scn = bpy.context.scene
scn.objects.link(obj)
obj.animation_data_create()
track = obj.animation_data.nla_tracks.new()
track.strips.new("pick up", pickup-49, action_card_pick_up())
track.strips.new("release", release, action_card_release())
try:
track.strips.new("start", min(1, pickup-51), action_card_start())
except:
# the pickup happened so early we don't even need a start strip
pass
obj.animation_data.action = action = bpy.data.actions.new("phantom action")
fc = find_or_create_fcurve(action, "hide_render")
for kp in add_keyframe_points(fc, [ [1, True],
[pickup+19, False]]):
kp.interpolation = 'CONSTANT'
add_child_constraint(obj, "prelude", armature, "card pre", True, False)
add_child_constraint(obj, "ready", armature, "card lift", True, False)
add_child_constraint(obj, "on arm", armature, "card anchor", True, False)
add_child_constraint(obj, "sky", get_card_destination(), None, True, False)
add_child_constraint(obj, "up", armature, "card release", True, False)
obj.layers = [i==15 for i in range(20)]
return obj
def clone_vertex_groups(src, dst):
""" this is NOT general purpose. It doesn't copy weights. """
for vg1 in src.vertex_groups:
vg = dst.vertex_groups.new(vg1.name)
print(vg)
def find_or_create_track(animation_data, name):
for track in animation_data.nla_tracks:
print (track)
if track.name == name:
return track
track = animation_data.nla_tracks.new()
print(track)
track.name = name
return track
def destroy_all_nla_strips(strips):
""" remove all the strips from an NLA track
:param strips: something like data_block.animation_data.nla_tracks[i].strips
"""
while len(strips) >0:
strips.remove(strips[-1])
def wipe_fcurves(action):
print("wipe fcurves %s"%action.name)
while len(action.fcurves)>0:
action.fcurves.remove(action.fcurves[-1])
def find_constraint_track_to(obj, armature, subtarget=None):
cns_name = "look at %s" % armature.name
for cns in obj.constraints:
if cns.type == 'TRACK_TO' and cns.target == armature and cns.subtarget == subtarget:
return cns
cns = obj.constraints.new('TRACK_TO')
cns.name = cns_name
cns.target = armature
cns.subtarget = subtarget
cns.track_axis = 'TRACK_Z'
cns.up_axis = 'UP_X'
return cns
def find_or_create_fcurve(action, data_path, array_index= -1):
for fc in action.fcurves:
if fc.data_path == data_path and ( array_index<0 or fc.array_index==array_index):
return fc
fc = action.fcurves.new(data_path, array_index)
return fc
def get_object(prefix, scene=bpy.context.scene):
for obj in scene.objects:
if obj.name[:len(prefix)] == prefix:
return obj
return None
def get_eyeball():
prefix = "eyeball"
return get_object("eyeball")
def get_laser_end():
return get_object("laser end")
def get_laser():
return get_object("laser beam")
def make_eyeball_look_at(armature, frame):
eyeball = get_eyeball()
cns = find_constraint_track_to(eyeball, armature, "card release")
data_path = 'constraints["%s"].influence' % cns.name
fc = find_or_create_fcurve(eyeball.animation_data.action, data_path)
i0 = len(fc.keyframe_points)
fc.keyframe_points.add(4)
kp0 = fc.keyframe_points[i0]
kp1 = fc.keyframe_points[i0 + 1]
kp2 = fc.keyframe_points[i0 + 2]
kp3 = fc.keyframe_points[i0 + 3]
kp0.handle_left = [frame - 7, 0]
kp0.co = [frame - 6, 0]
kp0.handle_right = [frame - 5, 0]
kp1.handle_left = [frame - 4, 1]
kp1.co = [frame - 3, 1]
kp1.handle_right = [frame - 2, 1]
kp2.handle_left = [frame + 2, 1]
kp2.co = [frame + 3, 1]
kp2.handle_right = [frame + 4, 1]
kp3.handle_left = [frame + 5, 0]
kp3.co = [frame + 6, 0]
kp3.handle_right = [frame + 7, 0]
def add_keyframe_points(fcurve, kps):
idx0 = len(fcurve.keyframe_points)
fcurve.keyframe_points.add(len(kps))
rval = []
for i in range(len(kps)):
kp = fcurve.keyframe_points[idx0 + i]
kp.co = kps[i]
rval.append(kp)
return rval
def find_or_create_child_constraint(obj, cns_name, target, subtarget=None):
for cns in obj.constraints:
if cns.type == 'CHILD_OF' and cns.target==target and (subtarget is None or cns.subtarget==subtarget):
return cns
cns = obj.constraints.new('CHILD_OF')
cns.name =cns_name
cns.target = target
if subtarget is not None:
cns.subtarget = subtarget
return cns
def make_laser_blast(frame, armature):
laser = get_laser()
fc = find_or_create_fcurve(laser.animation_data.action, "hide_render")
if len(fc.keyframe_points) < 1:
# start off hidden
fc.keyframe_points.add(1)
fc.keyframe_points[0].co = [1, 1]
fc.keyframe_points[0].interpolation = 'CONSTANT'
idx0 = len(fc.keyframe_points)
fc.keyframe_points.add(2)
kp0 = fc.keyframe_points[idx0]
kp1 = fc.keyframe_points[idx0 + 1]
kp0.co = [frame - 2, 0]
kp0.interpolation = 'CONSTANT'
kp1.co = [frame + 3, 1]
kp1.interpolation = 'CONSTANT'
#
laser_end = get_laser_end()
cns = find_or_create_child_constraint(laser_end, "be at %s"%armature.name, armature, "card release")
fc = find_or_create_fcurve(laser_end.animation_data.action, 'constraints["%s"].influence'%cns.name)
if len(fc.keyframe_points) < 1:
# start off hidden
fc.keyframe_points.add(1)
fc.keyframe_points[0].co = [1, 0]
fc.keyframe_points[0].interpolation = 'CONSTANT'
kps = [ [frame-4,1],
[frame+5,0]]
for kp in add_keyframe_points(fc, kps):
kp.interpolation = 'CONSTANT'
def card_approval_event(armature, movie_id, old, frame, num):
"""
:param armature: the armature handling the card
:param movie_image: the movie that our cards come from
:param old: the frame number of the previous card approval on this specific robot
:param frame: the frame number of this specific card approval event
:param num: card number
:return:
"""
make_card_animated(armature, movie_id, old, frame, num)
track = find_or_create_track(armature.animation_data, "robot grabbing")
track.strips.new("catch and release", frame, bpy.data.actions["robot grabbing"])
make_eyeball_look_at(armature, frame)
make_laser_blast(frame, armature)
def phantom_event(armature, movie_id, old, frame, num):
make_phantom_animated(armature, old, frame, num)
track = find_or_create_track(armature.animation_data, "robot grabbing")
track.strips.new("catch and release", frame, bpy.data.actions["robot grabbing"])
make_eyeball_look_at(armature, frame)
make_laser_blast(frame, armature)
def set_empty_action(laser, action_name):
if laser.animation_data is None:
laser.animation_data_create()
if laser.animation_data.action is None:
laser.animation_data.action = bpy.data.actions.new(action_name)
else:
wipe_fcurves(laser.animation_data.action)
def blast_old_cards():
scn = bpy.context.scene
for obj in scn.objects:
if obj.name[:10] == "movie card" and obj.layers[5] or obj.name[:7]=="phantom" and obj.layers[15]:
scn.objects.unlink(obj)
def reinitialize_actors(robots):
eyeball = get_eyeball()
set_empty_action(eyeball, "eyeball look at")
#
#
laser = get_laser()
print ("laser is %s"% laser.name)
set_empty_action(laser, "laser flash")
#
#
set_empty_action(get_laser_end(), "laser end")
#
#
for robot in robots:
(bot, arm) = cardbot_for(robot[0], robot[1])
bot["movie"] = robot[2]
if arm.animation_data is None:
arm.animation_data_create()
track = find_or_create_track(arm.animation_data, "robot grabbing")
destroy_all_nla_strips(track.strips)
#
#
blast_old_cards()
def go():
reinitialize_actors([
[7, [0, 2, 0], 'bbb1080.mp4'],
[3, [0, -2, 0], 'redline.mp4']
])
#
#
(b1, a1) = cardbot_for(7, [0, 2, 0])
num = 1
events = [ [7,15], [3,45], [7,75, phantom_event], [7,100], [3,130], [7,165] ]
animate_for_events(events, 1)
def events_1_1_2():
frame = 15
events = []
for i in range(7):
for suffix in [ "a", "b", "a", "c"]:
bot = "112 "+suffix
evt = [ bot, frame]
events.append(evt)
frame = frame + 30
return events
def animate_for_events(events, num):
old_per_bot = {}
for event in events:
bot_num = event[0]
frame = event[1]
event_actor = None
if len(event) > 2:
event_actor = event[2]
if event_actor is None:
event_actor = card_approval_event
old = old_per_bot.get(bot_num) or -15
(b1, a1) = cardbot_for(bot_num)
event_actor(a1, b1["movie"], old, frame, num)
num += 1
old_per_bot[bot_num] = frame
bpy.context.scene.objects.active = a1
# print(a1)
def scene_1_1_2():
reinitialize_actors([
["112 a", [0, 2, 0], 'bbb1080.mp4'],
["112 b", [0, 0, 0], 'redline A'],
["112 c", [0, -2, 0], 'redline B']
])
#
#
num = 1
events = events_1_1_2()
animate_for_events(events, num)
#
#
#
scn = bpy.context.scene
if scn.name == "weight 1 1 2":
scene_1_1_2()
else:
go()
|
Blender python API quick-start
Syntax highlighting by Pygments.