MRが楽しい

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

Blender3.0で利用可能なpythonスクリプトを作る その99(編集モード中の全オブジェクトに対して選択中の頂点から頂点グループを作成する)

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

編集モード中の全オブジェクトに対して選択中の頂点から頂点グループを作成する

本記事では以下の2つの記事の技術を組み合わせて利用します。
bluebirdofoz.hatenablog.com
bluebirdofoz.hatenablog.com

Blender2.8 以降では複数のオブジェクトを同時に編集モードで編集可能です。
スクリプトでは各オブジェクトのモードを判定して、編集モード中のオブジェクトに対して選択中の頂点から頂点グループの作成を行います。

サンプルスクリプト

編集モード中の全オブジェクトで選択中の頂点から新規頂点グループを作成するサンプルスクリプトです。
編集モードでないオブジェクトまたは選択中の頂点がないオブジェクトに対しては頂点グループの作成は実行されません。
また誤操作を防ぐため、編集モードでのみ動作します。
・Script_make_vertexgroup.py

# bpyインポート
import bpy

# 現在編集モードで選択中の頂点から各オブジェクトに新規頂点グループを作成する
def make_vertexgroup_byselectvert_forallobject() -> bool:
    """現在編集モードで選択中の頂点から各オブジェクトに新規頂点グループを作成する
    頂点を選択していないオブジェクトまたは編集モードでないオブジェクトに頂点グループは作成しない

    Keyword Arguments:

    Returns:
        bpy.types.VertexGroup -- 新規頂点グループ
    """
    
    # 現在のモードが編集モードかチェックする
    # (誤操作を防ぐため)
    if is_editmode() == False:
        return False

    # 編集対象のオブジェクトリストを作成する
    targetobject_list = []

    # シーン内の全オブジェクトを走査する
    for check_obj in bpy.context.scene.objects:
        # 編集モード中のオブジェクトを対象とする
        if is_editmode_object(check_obj) == True:
            # 編集モード中であれば頂点グループ作成の対象とする
            targetobject_list.append(check_obj)

    # 対象のオブジェクトがあったか
    if len(targetobject_list) <= 0:
        # 対象のオブジェクトが無かった場合、頂点グループは作成しない
        return True

    # オブジェクトモードに移行する
    set_objectmode()

    # 対象のオブジェクトを全て処理する
    for target_obj in targetobject_list:
        # 選択中の頂点があれば頂点グループを作成する
        make_vertexgroup_byselectvert(target_obj)

    # 編集モードに戻す
    set_editmode()

    return True

# 選択中の頂点から新規頂点グループを作成して頂点グループを取得する
def make_vertexgroup_byselectvert(arg_object:bpy.types.Object) -> bpy.types.VertexGroup:
    """選択中の頂点から新規頂点グループを作成して頂点グループを取得する

    Keyword Arguments:
        arg_object {bpy.types.Object} -- 対象オブジェクト

    Returns:
        bpy.types.VertexGroup -- 新規頂点グループ
    """

    # 現在のモードがオブジェクトモードかチェックする
    # (VertexGroupのAddは編集モードで実行不可のため)
    if is_objectmode() == False :
        return None

    # 指定オブジェクトがメッシュか確認する
    if arg_object.type != 'MESH':
        # メッシュでない場合は処理しない
        return None

    # インデックスリストを作成する
    index_list = []

    # 全ての頂点を走査する
    # 頂点操作のマニュアル
    # (https://docs.blender.org/api/current/bpy.types.MeshVertex.html)
    for vert in arg_object.data.vertices:
        # 選択状態か否か
        if vert.select:
            # 選択中の頂点のインデックスをリストに追加する
            index_list.append(vert.index)

    # 選択中の頂点があったか
    if len(index_list) <= 0:
        # 選択中の頂点が無かった場合、頂点グループは作成しない
        return None

    # オブジェクトに新規頂点グループを追加する
    # VertexGroupsアクセスのマニュアル
    # (https://docs.blender.org/api/current/bpy.types.VertexGroups.html)
    vertexgroup = arg_object.vertex_groups.new()

    # 選択中の頂点のインデックスを頂点グループに設定する
    # VertexGroupアクセスのマニュアル
    # (https://docs.blender.org/api/current/bpy.types.VertexGroup.html#bpy.types.VertexGroup)
    vertexgroup.add(index_list, 1.0, 'REPLACE')

    # 作成した頂点グループを返却する
    return vertexgroup

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

    Returns:
        bool -- 編集モードか否か
    """

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

# オブジェクトモードに移行する
def set_objectmode():
    """オブジェクトモードに移行する

    Keyword Arguments:

    Returns:
    """

    # オブジェクトモードに移行する
    # モード切替のマニュアル
    # (https://docs.blender.org/api/current/bpy.ops.object.html#bpy.ops.object.mode_set)
    bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
    return

# 現在のモードがオブジェクトモードかチェックする
def is_objectmode() -> bool:
    """現在のモードがオブジェクトモードかチェックする

    Keyword Arguments:

    Returns:
        bool -- オブジェクトモードか否か
    """

    # 現在のモードをチェックする
    # (https://docs.blender.org/api/current/bpy.context.html#bpy.context.mode)
    return ('OBJECT' == bpy.context.mode)

# 編集モードに移行する
def set_editmode():
    """編集モードに移行する

    Keyword Arguments:

    Returns:
    """

    # 編集モードに移行する
    # モード切替のマニュアル
    # (https://docs.blender.org/api/current/bpy.ops.object.html#bpy.ops.object.mode_set)
    bpy.ops.object.mode_set(mode='EDIT', toggle=False)
    return

# 現在のモードが編集モードかチェックする
def is_editmode() -> bool:
    """現在のモードが編集モードかチェックする

    Keyword Arguments:

    Returns:
        bool -- 編集モードか否か
    """

    # 現在のモードをチェックする
    # (https://docs.blender.org/api/current/bpy.context.html#bpy.context.mode)
    return ('EDIT_MESH' == bpy.context.mode)

# 関数の実行例
# 編集モード中の全てのオブジェクトに対して選択中の頂点から新規頂点グループを作成する
make_vertexgroup_byselectvert_forallobject()

・実行前
f:id:bluebirdofoz:20220210232847j:plain
・実行後
f:id:bluebirdofoz:20220210232924j:plain
f:id:bluebirdofoz:20220210232933j:plain
f:id:bluebirdofoz:20220210232942j:plain
f:id:bluebirdofoz:20220210232951j:plain
f:id:bluebirdofoz:20220210232959j:plain
f:id:bluebirdofoz:20220210233008j:plain
f:id:bluebirdofoz:20220210233018j:plain

選択中の頂点がないオブジェクトがあるパターン

・実行前
f:id:bluebirdofoz:20220210233028j:plain
・実行後
f:id:bluebirdofoz:20220210233038j:plain