MRが楽しい

MRやVRについて学習したことを書き残す

Blender3.0で利用可能なpythonスクリプトを作る その117(現在のポーズからループアクションを作成する)

本日は Blender の技術調査枠です。
Blender3.0で利用可能なpythonスクリプトを作ります。

現在のポーズからループアクションを作成する

アクションの開始と終了のポーズを同じに、中間フレームに左右反転のポーズを設定することで簡易なループアクションが作成可能です。
今回は以下のフレーム移動、ポーズの反転コピー、キーフレームの登録を利用しました。
docs.blender.org
docs.blender.org
docs.blender.org

サンプルスクリプト

アーマチュアオブジェクト、アクション、フレーム数を指定することで現在のポーズを左右反転で繰り返すループアクションを作成します。
スクリプトはポーズモードでのみ動作します。
・Script_make_loopaction.py

# bpyインポート
import bpy

# 現在のポーズからボーン位置と回転をキーフレームに登録してループアクションを作成する
def make_loopaction(
    arg_targetobject:bpy.types.Object,
    arg_targetaction:bpy.types.Action,
    arg_framecount:int) -> bool:
    """現在のポーズからボーン位置と回転をキーフレームに登録してループアクションを作成する

    Keyword Arguments:
        arg_targetobject {bpy.types.Object} -- 対象オブジェクト
        arg_targetaction {bpy.types.Action} -- 対象アクションデータ
        arg_framecount {int} -- アクションのフレーム数

    Returns:
        bool -- 実行の正否
    """

    # 引数のNoneチェック
    if arg_targetobject == None:
        return False
    if arg_targetaction == None:
        return False

    # 指定オブジェクトがアーマチュアか確認する
    # オブジェクトタイプの一覧
    # (https://docs.blender.org/api/current/bpy.types.Object.html#bpy.types.Object.type)
    if arg_targetobject.type != 'ARMATURE':
        # アーマチュアでない場合はボーンを選択しない
        return False

    # アクションデータを現在のアーマチュアに設定する
    arg_targetobject.animation_data.action = arg_targetaction

    # 現在のモードがポーズモードかチェックする(反転には bpy.ops.pose 関数を利用するため)
    is_posemode = is_posemode_object(arg_targetobject)
    if not is_posemode:
        # ポーズモードでない場合はボーンを反転しない
        return False
    
    # アーマチュア内の全ボーンを選択状態にする(有効状態のレイヤー内のボーンのみ対象)
    # アーマチュア操作のマニュアル
    # (https://docs.blender.org/api/current/bpy.types.Armature.html#bpy.types.Armature.bones)
    for bone in arg_targetobject.data.bones:
        # 選択状態に設定する
        # ボーン操作のマニュアル
        # (https://docs.blender.org/api/current/bpy.types.Bone.html)
        bone.select = True

    # 0 のフレーム番号を設定する
    bpy.context.scene.frame_set(0)

    # 選択中のボーンの位置・回転をキーフレームに挿入する
    bpy.ops.anim.keyframe_insert_menu(type='BUILTIN_KSI_LocRot')

    # 0 のフレームのポーズのコピーを行う
    bpy.ops.pose.copy()

    # 中間のフレーム番号を設定する
    bpy.context.scene.frame_set(arg_framecount / 2)

    # ポーズを反転して貼り付けを行う
    bpy.ops.pose.paste(flipped=True)

    # 選択中のボーンの位置・回転をキーフレームに挿入する
    bpy.ops.anim.keyframe_insert_menu(type='BUILTIN_KSI_LocRot')

    # 指定の最終フレーム番号を設定する
    bpy.context.scene.frame_set(arg_framecount)

    # ポーズを反転せず貼り付けを行う
    bpy.ops.pose.paste(flipped=False)

    # 選択中のボーンの位置・回転をキーフレームに挿入する
    bpy.ops.anim.keyframe_insert_menu(type='BUILTIN_KSI_LocRot')

    return True

# 指定のオブジェクトがポーズモードかチェックする
def is_posemode_object(arg_checkobject:bpy.types.Object) -> bool:
    """指定のオブジェクトがポーズモードかチェックする
    
    Keyword Arguments:
        arg_checkobject {bpy.types.Object} -- チェック対象オブジェクト

    Returns:
        bool -- ポーズモードか否か
    """

    # オブジェクト毎のモードをチェックする
    # (https://docs.blender.org/api/current/bpy.types.Object.html#bpy.types.Object.mode)
    return ('POSE' == arg_checkobject.mode)


# 関数の実行例
# 現在のポーズからボーン位置と回転をキーフレームに登録してループアクションを作成する
make_loopaction(
    arg_targetobject=bpy.data.objects.get("metarig"),
    arg_targetaction=bpy.data.actions.get("NewAction"),
    arg_framecount=48
    )

f:id:bluebirdofoz:20220325230800j:plain
f:id:bluebirdofoz:20220325230809j:plain
f:id:bluebirdofoz:20220325230818j:plain