Blender Python のボーンアクセスチートシート
注意点
グローバル変数に Blender オブジェクトをキャッシュしてはならない
Undo したときにそのオブジェクトは無効化される。
# 以下の amt オブジェクトは Undo 時に無効化され、アクセスすると EXCEPTION_ACCESS_VIOLOATION を出して Blender がクラッシュする amt = bpy.data.objects['Armature'] # Blender オブジェクトが必要な場所で取得するようにする armature_name = 'Armature' # 文字列は Undo でも無効化されない def some_method(): amt = bpy.data.objects[armature_name] # もしくはメソッドでオブジェクトを取得する def get_armature(): return bpy.data.objects['Armature']
ボーンの位置が更新されない
値を更新してすぐその値を読みだしても更新後の値が得られないことがある。このようなときは bpy.context.scene.update() を呼び出した後、値を読みだすようにする。
このような動作になっているのは、あるプロパティの更新は animation function curve、driver、expression、constraint、child object 等の更新を引き起こすかもしれないからだ。値が更新されるたびこれらも更新すると実行速度が遅くなる。
ボーンの種類
data.bones
変形などのプロパティパネルで設定する項目にアクセスできる。
data.edit_bones
ボーンのポーズ位置などの、エディットモードで設定する項目にアクセスできる。編集するのにエディットモードへ移行する必要がある。ボーンの追加等はここからできる。
pose.bones
主にコンストレイントの追加を行う。コンストレイントの編集ならばポーズモードへ移行する必要はない。
アーマチュアへのアクセス
スクリプトにする場合 import bpy が必要になる。
アーマチュアの作成
bpy.ops.object.add(type='ARMATURE', enter_editmode=True, location=(0,0,0))
作成したアーマチュアの取得
enter_editmode=True の場合は以下の方法が使える。
amt = bpy.context.object
名前の変更
amt.name = 'myArmature'
エディットモードでボーンにアクセスする
アーマチュアの edit_bones はエディットモードの時にしかアクセスできないことに注意する。
ボーンの作成
head と tail とを設定するとボーンが作成される。
bpy.ops.object.mode_set(mode='EDIT') b = amt.data.edit_bones.new('Bone') b.head = (0,0,0) b.tail = (0,0,1)
デフォームの設定
b.use_deform = False # メッシュをデフォームしない
親子関係の設定
b2 = amt.data.edit_bones.new('Bone2') b2.haed = b.tail b2.tail = (0,0,2) b2.parent = b
座標軸の設定
calculate_roll はボーンの Z 軸の向きを引数で指定した軸と一致させる。この例ではグローバル Z 方向にボーンを伸ばしているので、ボーンのローカル Z を グローバル -Y に向けるとローカル X とグローバル X とが一致する。
for b in amt.data.edit_bones: b.select = True # すべてのボーンを選択 bpy.ops.armature.calculate_roll(type='GLOBAL_NEG_Y')
bpy.ops.pose.select_all(action="SELECT") でもすべてのボーンを選択できる。
個別に計算するときには roll に回転量を設定する。
import math b.roll = math.radians(90) # 90°回転
ポーズモードでボーンにアクセスする
ポーズボーンのローカル座標の取得
bpy.ops.object.mode_set(mode='POSE') loc = amt.pose.bones['Bone'].location
ポーズボーンの回転モードと回転量の取得
回転モードは AXIS_ANGLE、QUATERNION、XYZ... がある。
if amt.pose.bones['Bone'].rotation_mode == 'QUATERNION': rot = amt.pose.bones['Bone'].rotation_quaternion elif amt.pose.bones['Bone'].rotation_mode == 'AXIS_ANGLE': rot = amt.pose.bones['Bone'].rotation_axis_angle else: rot = amt.pose.bones['Bone'].rotation_euler
ポーズボーンのアーマチュア座標の取得
アーマチュア座標はアーマチュアの位置から見たボーンの座標だ。アーマチュアの座標が (0, 0, 0) で回転が0でスケールが1のとき、ボーンのアーマチュア座標とグローバル座標とは一致する。
amt.pose.bones['Bone'].head
ポーズボーンのグローバル座標の取得
amt.matrix_world @ amt.pose.bones['Bone'].head
ポーズボーンを隠す
amt.pose.bones['Bone'].bone.hide = True
ポーズボーンの選択
amt.pose.bones['Bone'].bone.select = True
最後に選択されたポーズボーンの取得
amt.pose.bones['Bone'].data.bones.active
選択されているポーズボーンをすべて取得
bpy.context.selected_pose_bones
位置回転スケールのロック
pose_bone = amt.pose.bones['Bone'] pose_bone.lock_location = [True]*3 pose_bone.lock_scale = [True]*3 pose_bone.lock_rotation = [True]*3 pose_bone.lock_rotation_w = True
モディフィア
IK の設定
c = amt.pose.bones['Bone2'].constraints.new('IK') c.name = 'IK' c.target = amt c.subtarget = 'ik' # ik という名前のボーンを先に作成しておく c.chain_count = 2
回転コピーの設定
c = amt.pose.bones['Bone2'].constraints.new('COPY_ROTATION') c.name = 'Copy_Rotation' c.target = amt c.subtarget = 'Bone' c.owner_space = 'LOCAL' c.target_space = 'LOCAL'
ボーンにキーを打つ
group があると位置回転スケールなどの複数のキーを折りたたんで表示できる。
b = amt.pose.bones['Bone'] b.keyframe_insert(data_path='location',group='Bone') b.keyframe_insert(data_path='scale',group='Bone') if b.rotation_mode == 'QUATERNION': b.keyframe_insert(data_path='rotation_quaternion',group='Bone') elif b.rotation_mode == 'AXIS_ANGLE': b.keyframe_insert(data_path='rotation_axis_angle',group='Bone') else: b.keyframe_insert(data_path='rotation_euler',group='Bone')
def_ で始まるボーンの変形にチェックを入れる
import bpy bones = bpy.context.active_object.data.bones for b in bones: b.use_deform = b.name.startswith('def_')
関連記事
Blender PythonのMeshデータアクセスのチートシート