忘却まとめ

Blenderの中級者・上級者向けの踏み込んだ情報や、アドオン・3DCGに関する情報を記事にします

【ドライバー・アクション・NLAトラック】アニメーションデータへのアクセス【Blender / Python】

Python

更新日:

基本

ドライバー・アクション・NLAトラックなどのアニメーションデータへは、オブジェクトごとにアクセスできる。


アクションは bpy.data.actions から直接アクセスできる。

obj = bpy.context.object
obj.animation_data

# アクションデータ
bpy.data.actions

注意点

そのオブジェクトにアニメーションデータがない場合は、animation_dataの中身が無いので注意。
一括処理する際は事前にアニメーションデータを持っていないオブジェクトを除外する処理が必要。

obj = bpy.context.object
obj.animation_data
for obj in bpy.context.selected_objects:
    if obj.animation_data is None:
        continue
    if obj.animation_data.action is None:
        continue
    for fc in obj.animation_data.action.fcurves:
        # 処理...

contextでのアクセス

アニメーションデータへはcontextを使えば簡単にアクセスすることができる。
実行した際のグラフエディターやドープシートの状態に依存するので注意。エディターはそれぞれ選択状態を

# 表示中のFカーブ
bpy.context.visible_fcurves
# 編集中のFカーブ
bpy.context.editable_fcurves
# 選択中のFカーブ
bpy.context.selected_visible_fcurves
# 選択中の編集中のFカーブ
bpy.context.selected_editable_fcurves
# アクティブFカーブ
bpy.context.active_editable_fcurve
# 選択中のキーフレーム
bpy.context.selected_editable_keyframes
# 選択中のNLAストリップ
bpy.context.selected_nla_strips

他のエディターからFカーブ関連のcontextを使う方法

これらのcontextはドープシートやグラフエディターでないとアクセスできない。
そのため、それ以外のエディターのメニューボタンからこのcontextを使いたいという場合は、一旦グラフエディターに変えてから処理して、元のエディターに戻すということが必要。

ただし、コンソールエディターで利用しようとすると、エリアタイプを戻す際にクラッシュする模様。

old_area_type = bpy.context.area.type
bpy.context.area.type = 'GRAPH_EDITOR'
bpy.context.area.ui_type = 'FCURVES' # ドライバーなら'DRIVERS'

bpy.context.selected_visible_fcurves

bpy.context.area.type = old_area_type

以下はオブジェクトからアニメーションデータにアクセスする方法を紹介する。

アクション

  • オブジェクト > アニメーションデータ
    > アクション > 位置[0]など > Fカーブ> キーフレーム

位置を変えたい場合は、ポイント・ハンドルの左・ハンドルの右の3つを動かす必要がある。

obj = bpy.context.object
# アクション
for fc in obj.animation_data.action.fcurves:
    for p in fc.keyframe_points:
        # ポイントの位置
        p.co.x
        p.handle_left[0]
        p.handle_right[0]

特定のFカーブにアクセスする場合

下記は、選択ボーンのZ位置のキーフレームの位置を表示するサンプル。

アニメーションのデータは、実際にはオブジェクトやボーンなどとは直接関連付けられていない。
data_path というFカーブの名前と、同じデータに関連付けられるようになっている。
このため、別のオブジェクトやボーンなどにも名前さえ同じなら関連付けることができる。

data_pathは単なる文字列であるため、確実に同じデータにアクセスするにはボーン名を検索して対応するFカーブを見つける必要がある。

array_indexは、XYZなどの配列の番号がどれなのかが登録されている。

import re
obj = bpy.context.object

for bone in obj.data.bones:
    if bone.select:
        fcurves_l = obj.animation_data.action.fcurves
        for fcurve in fcurves_l:
            if re.findall("pose\.bones\[\"(%s)\"]" % bone.name,fcurve.data_path):
                if fcurve.array_index == 2:
                    if "location" in fcurve.data_path :
                        for p in fcurve.keyframe_points:
                            p.co

下記は、data_pathからボーン名を取得するサンプル。

import re
t = 'pose.bones["bone_hoge.L"].rotation_euler'
re.findall("pose\.bones\[\"(.+)\"]",t)
# > bone_hoge.L

ドライバー

  • オブジェクト > アニメーションデータ
    > ドライバー> 入力値

設定済みのドライバにアクセス

obj = bpy.context.object
for div in obj.animation_data.drivers:
    div

ドライバを追加

下記はZ位置(つまりlocation[2])にドライバーを追加するサンプル。

追加したい属性の親データに、driver_add()で属性を指定して新しいドライバーを作成する。
ドライバの中には入力値(variables)があり、この入力値にターゲットにしたいボーン位置などを設定する。

obj = bpy.context.object
# ドライバー
fc = obj.driver_add("location", 2)
div = fc.driver
div.expression = "var + 1"
var = div.variables.new()
var.type = 'TRANSFORMS'
var.targets[0].id = bpy.data.objects["hoge"]
var.targets[0].bone_target = "Bone"
var.targets[0].transform_type = "LOC_Y"
var.targets[0].transform_space = 'LOCAL_SPACE'

NLAトラック

  • オブジェクト > アニメーションデータ > NLAトラック > ストリップ

ストリップの位置を動かしたい場合は、frame_startとframe_endに同じ値を加算して動かす。

obj = bpy.context.object
# NLAトラック
for track in obj.animation_data.nla_tracks:
    for strip in track.strips
        strip.frame_start
        strip.frame_end

参考

ソースコードの参考となる自作アドオンはこちら。

_

アドオンの制作依頼はこちら

-Python

Copyright© 忘却まとめ , 2021 All Rights Reserved Powered by STINGER.