MRが楽しい

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

Blender2.8で利用可能なpythonスクリプトを作る その51(マテリアルスロットの作成と削除)

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

空のマテリアルスロットの作成

指定オブジェクトに空のマテリアルスロットを作成します。
マテリアルスロットは new では作成できないため、append 関数を利用しています。
append 関数を用いることで Operator を利用せずにスロットを作成できます。
・Script_add_materialslot_empty.py

# bpyインポート
import bpy

# 指定オブジェクトに空のマテリアルスロットを作成する
# (オブジェクト名指定)
def add_materialslot_empty_checker(arg_objectname="Default") -> bool:
    """指定オブジェクトに空のマテリアルスロットを作成する

    Args:
        arg_objectname (str, optional): 指定オブジェクト名. Defaults to "Default".

    Returns:
        bool: 実行正否
    """

    # 指定オブジェクトを取得する
    # (get関数は対象が存在しない場合 None が返る)
    selectob = bpy.data.objects.get(arg_objectname)

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

    # 指定オブジェクトに空ノードの新規マテリアルを参照するマテリアルスロットを作成する
    add_materialslot_empty(arg_object=selectob)

    return True

# 指定オブジェクトに空のマテリアルスロットを作成する
def add_materialslot_empty(arg_object:bpy.types.Object) -> bool:
    """指定オブジェクトに空のマテリアルスロットを作成する

    Args:
        arg_object (bpy.types.Object): 指定オブジェクト
        arg_materialname (str, optional): 作成マテリアル名. Defaults to "DefaultMaterial".

    Returns:
        bool: 実行正否
    """

    # 指定オブジェクトがメッシュオブジェクトか確認する
    if arg_object.type != 'MESH':
        # メッシュオブジェクトでない場合は処理しない
        return False
    
    # メッシュデータの参照を取得する
    mesh = arg_object.data

    # メッシュのマテリアルにNoneを追加する
    # (空のマテリアルスロットを作成する)
    mesh.materials.append(None)

    return True


# 関数の実行例
add_materialslot_empty_checker(arg_objectname = "Cube")

f:id:bluebirdofoz:20200716231414j:plain

参照付きマテリアルスロットの作成

指定オブジェクトに指定のマテリアルを参照するマテリアルスロットを作成します。
マテリアルは指定した名前で空のノードのマテリアルを作成します
・Script_add_materialslot_emptynodematerial.py

# bpyインポート
import bpy

# 指定オブジェクトに空ノードの新規マテリアルを参照するマテリアルスロットを作成する
# (オブジェクト名指定)
def add_materialslot_emptynodematerial_checker(arg_objectname="Default", arg_materialname="DefaultMaterial") -> bool:
    """指定オブジェクトに空ノードの新規マテリアルを参照するマテリアルスロットを作成する

    Args:
        arg_objectname (str, optional): 指定オブジェクト名. Defaults to "Default".
        arg_materialname (str, optional): 作成マテリアル名. Defaults to "DefaultMaterial".

    Returns:
        bool: 実行正否
    """

    # 指定オブジェクトを取得する
    # (get関数は対象が存在しない場合 None が返る)
    selectob = bpy.data.objects.get(arg_objectname)

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

    # 指定オブジェクトに空ノードの新規マテリアルを参照するマテリアルスロットを作成する
    add_materialslot_emptynodematerial(arg_object=selectob, arg_materialname=arg_materialname)

    return True

# 指定オブジェクトに空ノードの新規マテリアルを参照するマテリアルスロットを作成する
def add_materialslot_emptynodematerial(arg_object:bpy.types.Object, arg_materialname="DefaultMaterial") -> bool:
    """指定オブジェクトに空ノードの新規マテリアルを参照するマテリアルスロットを作成する

    Args:
        arg_object (bpy.types.Object): 指定オブジェクト
        arg_materialname (str, optional): 作成マテリアル名. Defaults to "DefaultMaterial".

    Returns:
        bool: 実行正否
    """

    # 空のノードの新規マテリアルを作成する
    makemat = new_material_emptynode(arg_materialname=arg_materialname)

    # 作成したマテリアルをオブジェクトのマテリアルスロットに追加する
    add_materialslot_target(arg_object=arg_object, arg_material=makemat)

    return True

# 空ノードの新規マテリアルを作成する
def new_material_emptynode(arg_materialname:str="EmptyNodeMaterial") -> bpy.types.Material:
    """空ノードの新規マテリアルを作成する

    Args:
        arg_materialname (str, optional): 作成マテリアル名. Defaults to "EmptyNodeMaterial".

    Returns:
        bpy.types.Material: 作成マテリアルの参照
    """

    # 新規マテリアルを作成する
    newmaterial = bpy.data.materials.new(arg_materialname)

    # ノードを使用する
    newmaterial.use_nodes = True

    # 新規マテリアルのノード参照を取得する
    mat_nodes = newmaterial.node_tree.nodes

    # マテリアル内の全ノードを走査する
    for delete_node in mat_nodes:
        # ノードを削除する
        mat_nodes.remove(delete_node)

    return newmaterial

# 指定オブジェクトのマテリアルスロットに指定マテリアルを追加する
def add_materialslot_target(arg_object:bpy.types.Object, arg_material:bpy.types.Material):
    """指定オブジェクトのマテリアルスロットに指定マテリアルを追加する

    Args:
        arg_object (bpy.types.Object): 指定オブジェクト
        arg_material (bpy.types.Material): 指定マテリアル

    Returns:
        [type]: [description]
    """

    # 指定オブジェクトがメッシュオブジェクトか確認する
    if arg_object.type != 'MESH':
        # メッシュオブジェクトでない場合は処理しない
        return False
    
    # メッシュデータの参照を取得する
    mesh = arg_object.data

    # メッシュのマテリアルを追加する
    mesh.materials.append(arg_material)

    return


# 関数の実行例
add_materialslot_emptynodematerial_checker(arg_objectname = "Cube", arg_materialname = "TestMaterial")

f:id:bluebirdofoz:20200716231432j:plain

マテリアルスロットの削除

指定オブジェクトにマテリアルスロットを全て削除します。
pop 関数を用いることで Operator を利用せずにスロットを削除できます。
・Script_delete_materialslot_all.py

# bpyインポート
import bpy

# 指定オブジェクトのマテリアルスロットを全て削除する
# (オブジェクト名指定)
def delete_materialslot_all_checker(arg_objectname="Default") -> bool:
    """指定オブジェクトのマテリアルスロットを全て削除する

    Args:
        arg_objectname (str, optional): 指定オブジェクト名. Defaults to "Default".

    Returns:
        bool: 実行正否
    """

    # 指定オブジェクトを取得する
    # (get関数は対象が存在しない場合 None が返る)
    selectob = bpy.data.objects.get(arg_objectname)

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

    # 指定オブジェクトのマテリアルスロットを全て削除する
    delete_materialslot_all(arg_object=selectob)

    return True

# 指定オブジェクトのマテリアルスロットを全て削除する
def delete_materialslot_all(arg_object:bpy.types.Object) -> bool:
    """指定オブジェクトのマテリアルスロットを全て削除する

    Args:
        arg_object (bpy.types.Object): 指定オブジェクト
        arg_materialname (str, optional): 作成マテリアル名. Defaults to "DefaultMaterial".

    Returns:
        bool: 実行正否
    """

    # 指定オブジェクトがメッシュオブジェクトか確認する
    if arg_object.type != 'MESH':
        # メッシュオブジェクトでない場合は処理しない
        return False
    
    # メッシュデータの参照を取得する
    mesh = arg_object.data

    # メッシュのマテリアルを全て削除する
    while len(mesh.materials) > 0:

        # IDMaterial操作のマニュアル
        # (https://docs.blender.org/api/current/bpy.types.IDMaterials.html)
        mesh.materials.pop(index=-1)

    return True


# 関数の実行例
delete_materialslot_all_checker(arg_objectname = "Cube")

f:id:bluebirdofoz:20200718025935j:plain

マテリアルスロットの削除(指定)

指定オブジェクトの指定マテリアルスロットを削除します。
指定マテリアルがスロットに含まれない場合は削除を行いません。
・Script_delete_materialslot_target.py

# bpyインポート
import bpy

# 指定オブジェクトの指定マテリアルスロットを削除する
# (オブジェクト名、マテリアル名指定)
def delete_materialslot_target_checker(arg_objectname="Default", arg_materialname="DefaultMat") -> bool:
    """指定オブジェクトの指定マテリアルスロットを削除する

    Args:
        arg_objectname (str, optional): 指定オブジェクト名. Defaults to "Default".
        arg_materialname (str, optional): 指定マテリアル名. Defaults to "DefaultMat".

    Returns:
        bool: 実行正否
    """

    # 指定オブジェクトを取得する
    # (get関数は対象が存在しない場合 None が返る)
    selectob = bpy.data.objects.get(arg_objectname)

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

    # 指定マテリアルを取得する
    # (get関数は対象が存在しない場合 None が返る)
    selectmat = bpy.data.materials.get(arg_materialname)

    # 指定マテリアルが存在するか確認する
    if selectmat == None:
        # 指定オブジェクトが存在しない場合は処理しない
        return False
    
    # 指定オブジェクトのマテリアルスロットを全て削除する
    delete_materialslot_target(arg_object=selectob, arg_material=selectmat)

    return True

# 指定オブジェクトの指定マテリアルスロットを削除する
def delete_materialslot_target(arg_object:bpy.types.Object, arg_material:bpy.types.Material) -> bool:
    """指定オブジェクトの指定マテリアルスロットを削除する

    Args:
        arg_object (bpy.types.Object): 指定オブジェクト
        arg_material (bpy.types.Material): 指定マテリアル

    Returns:
        bool: 実行正否
    """

    # 指定オブジェクトがメッシュオブジェクトか確認する
    if arg_object.type != 'MESH':
        # メッシュオブジェクトでない場合は処理しない
        return False
    
    # メッシュデータの参照を取得する
    mesh = arg_object.data

    # 削除対象マテリアルのインデックス番号を取得する
    # Collection操作のマニュアル
    # (https://docs.blender.org/api/current/bpy.types.bpy_prop_collection.html)
    pop_index = mesh.materials.find(arg_material.name)

    # 戻り値が-1の場合は対象が見つからなかった
    if pop_index == -1:
        # 削除処理をせず終了する
        return False

    # 指定マテリアルスロットを削除する
    # IDMaterial操作のマニュアル
    # (https://docs.blender.org/api/current/bpy.types.IDMaterials.html)
    mesh.materials.pop(index=pop_index)

    return True


# 関数の実行例
delete_materialslot_target_checker(arg_objectname = "Cube", arg_materialname="DefaultMat")

f:id:bluebirdofoz:20200822181027j:plain