Blenderのアニメーション情報は、アクション > Fカーブ > キーフレームのようになっている。
まずキーを入れるFカーブを作る必要があり、Fカーブは各トランスフォームごとの各軸ごとに作る必要がある。
もくじ
Fカーブ
Fカーブの識別は、data_path(属性の文字列)とarray_index(軸指定)で指定できる。
data_pathは、'pose.bones["ぼーん"].location'のように、固有アイテム名(例:ぼーん)を含む文字列となっている。
固有アイテム名と属性名が一緒になっているので扱いづらい。
%sを活用して、文字列を作るとよい。
注意点
そのオブジェクトにアニメーションデータがない場合は、animation_dataの中身が無いので注意。
一括処理する際は事前に作成するか、アニメーションデータを持っていないオブジェクトをcontinueで除外する処理が必要。
obj = bpy.context.object
obj.animation_data
for obj in bpy.context.selected_objects:
if not obj.animation_data:
obj.animation_data_create()
if not obj.animation_data.action:
obj.animation_data.action = bpy.data.actions.new(name="Action")
for fc in obj.animation_data.action.fcurves:
# 処理...
例
位置回転スケールで3、XYZ軸で3の、計9こ作る必要があるため、それぞれのリストを用意して、下記のように多重のfor文で回す必要がある。
for bone in ボーン:
for trans in トランスフォーム:
dp_name = 'pose.bones["%s"].%s' % (bone.name,trans)
for axis in 軸:
# 新規Fカーブ作成
tgt_fc = ~~.fcurves.new(data_path=dp_name, index=axis, action_group=bone.name)
# キーフレーム作成
tgt_fc.keyframe_points.insert(frame=指定のフレーム, value= getattr(bone, trans)[axis])
サンプル
下記は自作アドオンから抜粋したものであり、コピペしただけでは動きはしないので注意。
あくまでこんなかんじになる程度に。
data_path
# data_path
def get_target_data_path(bone):
sc = bpy.context.scene
props = sc.lazy_shapekeys
p_sync = props.synckey
d_path_l = []
if p_sync.location:
d_path_l += [('pose.bones["%s"].location',"location")]
if p_sync.rotation:
if bone.rotation_mode == 'QUATERNION':
d_path_l += [('pose.bones["%s"].rotation_quaternion',"rotation_quaternion")]
else:
d_path_l += [('pose.bones["%s"].rotation_euler',"rotation_euler")]
if p_sync.scale:
d_path_l += [('pose.bones["%s"].scale',"scale")]
return d_path_l
array_index
クォータニオン回転だけは他と違いWXYZの4つなので、リストを作成する際に分岐を用意する必要がある。
# array_index def get_array_index(trs_name, bone): sc = bpy.context.scene props = sc.lazy_shapekeys p_sync = props.synckey arry_index_l = [] if trs_name == "rotation_quaternion" and bone.rotation_mode == 'QUATERNION': arry_index_l += [0] if p_sync.axis_x: arry_index_l += [1] if p_sync.axis_y: arry_index_l += [2] if p_sync.axis_z: arry_index_l += [3] else: if p_sync.axis_x: arry_index_l += [0] if p_sync.axis_y: arry_index_l += [1] if p_sync.axis_z: arry_index_l += [2] return arry_index_l
キー挿入
# insert def key_insert_bone(self, p_sync, obj, sel_bone_l, cur_f, dp_name): for bone in sel_bone_l: # 対象ボーン d_path_l = get_target_data_path(bone) for dp, trs_name in d_path_l: # data_path dp_name = dp % bone.name # 作っておいたデータパス文字列にボーン名を入れる for id in get_array_index(trs_name, bone): # array_index # 対象Fカーブを探す tgt_fc = None for fc in obj.animation_data.action.fcurves: if fc.data_path == dp_name and fc.array_index == id: tgt_fc = fc break # なければ新規作成 if not tgt_fc: tgt_fc = obj.animation_data.action.fcurves.new(data_path=dp_name, index=id, action_group=bone.name) # 新規キー挿入 key = tgt_fc.keyframe_points.insert(frame=cur_f, value= getattr(bone,trs_name)[id]) if not p_sync.interpolation == "NONE": key.interpolation = p_sync.interpolation