MRが楽しい

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

Blender2.8で利用可能なpythonスクリプトを作る その69(プリンシプルBSDFのベースカラー端子の情報)

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

プリンシプルBSDFのベースカラー端子の情報

プリンシプルBSDFのベースカラー端子の情報をチェックし、デフォルト値が有効な場合はベースカラー端子のデフォルト値を取得します。
スクリプトは以下のチェックを行います。
1.指定マテリアルのアクティブな出力ノードにノードが接続されているか
2.アクティブな出力ノードに接続されたノードはプリンシプルBSDFか
3.プリンシプルBSDFのベースカラー端子にリンクが貼られておらず、デフォルト値が有効か
これらのチェックが通った場合、ベースカラー端子のデフォルト値を取得します。
・Script_get_basecolor_bsdf.py

# bpyインポート
import bpy

# 指定マテリアルのアクティブな出力ノードに接続されたプリンシプルBSDFのベースカラーを取得する
def get_basecolor_bsdf(arg_material:bpy.types.Material) -> bpy.types.NodeSocketColor:
    """指定マテリアルのアクティブな出力ノードに接続されたプリンシプルBSDFのベースカラーを取得する

    Args:
        arg_material (bpy.types.Material): 指定マテリアル

    Returns:
        bpy.types.NodeSocketColor: ベースカラー(取得失敗時 None)
    """

    # カラーの取得変数を初期化する
    getBaseColor = None

    # マテリアルのノードを有効化する
    use_material_node(arg_material=arg_material)

    # アクティブな出力ノードに接続されたノードを取得する
    get_node = get_node_linkoutput(arg_material=arg_material)

    # ノードが取得できたか確認する
    if get_node == None:
        # サーフェスノードが存在しない場合はFalseを返す
        return False

    # ノードの種類がプリンシプルBSDFかチェックして結果を返す
    isBSDF = check_isnode_bsdf(get_node)

    # プリンスプルBSDFか確認する
    if isBSDF == True:
        # プリンシプルBSDFならベースカラーにリンクが貼られているかチェックする
        isCheckedLink = check_link_bsdf_basecolor(get_node)

        # リンクが貼られていたか確認する
        if isCheckedLink == False:
            # リンクが貼られていないならベースカラー値を取得する
            getBaseColor = get_value_bsdf_basecolor(get_node)

    return getBaseColor

# アクティブな出力ノードに接続されたノードを取得する
def get_node_linkoutput(arg_material:bpy.types.Material) -> bpy.types.Node:
    """アクティブな出力ノードに接続されたノードを取得する

    Args:
        arg_material (bpy.types.Material): 指定マテリアル

    Returns:
        bpy.types.Node: アクティブな出力ノードに接続されたノード
    """

    # 参照の保存用変数
    name_mapping = {}

    # ノード操作のマニュアル
    # (https://docs.blender.org/api/current/bpy.types.Node.html)
    # ノードリスト操作のマニュアル
    # (https://docs.blender.org/api/current/bpy.types.Nodes.html)
    # ノードツリー操作のマニュアル
    # (https://docs.blender.org/api/current/bpy.types.NodeTree.html)

    # ターゲットマテリアルのノード参照を取得する
    mat_nodes = arg_material.node_tree.nodes

    # 出力ノードを取得する変数
    output_node = None

    # 出力ノードの操作マニュアル
    # (https://docs.blender.org/api/current/bpy.types.ShaderNodeOutputMaterial.html)

    # 全ノードを走査する
    for check_node in mat_nodes:
        # ノードタイプを取得する
        node_idname = check_node.bl_idname

        # ノードタイプが出力ノードか確認する
        if node_idname == 'ShaderNodeOutputMaterial':
            # アクティブな出力ノードのフラグを取得する
            is_activeoutput = check_node.is_active_output

            # アクティブな出力ノードかチェックする
            if is_activeoutput == True:
                # アクティブな出力ノードなら保持する
                output_node = check_node

    # 出力ノードが取得できたか確認する
    if output_node == None:
        # 出力ノードが存在しない場合は処理しない
        return None
    
    # ノードソケット操作のマニュアル
    # (https://docs.blender.org/api/current/bpy.types.NodeSocket.html)

    # 出力ノードのサーフェス入力(1番目の入力)のリンクを確認する
    surface_input = output_node.inputs[0]

    # リンクが接続されているか確認する
    if surface_input.is_linked == False:
        # 出力ノードにサーフェスノードが接続されていない場合は処理しない
        return None

    # リンク操作のマニュアル
    # (https://docs.blender.org/api/current/bpy.types.NodeLink.html#bpy.types.NodeLink)

    # リンクの一覧を取得する
    mat_links = arg_material.node_tree.links

    # 接続元ノードを取得する変数
    surface_node = None

    # リンクを走査する
    for check_link in mat_links:
        # 接続先が出力ノードのサーフェス入力か確認する
        if check_link.to_socket == surface_input:
            # リンクの接続元ノードを取得する
            surface_node = check_link.from_node
    
    # 接続元ノードが取得できたか確認する
    if surface_node == None:
        # 接続元ノードが存在しない場合は処理しない
        return None
    
    # 接続元となっているサーフェスノードを返却する
    return_node = surface_node

    return return_node

# 対象マテリアルのノードを有効化する
def use_material_node(arg_material:bpy.types.Material):
    """対象マテリアルのノードを有効化する

    Args:
        arg_material (bpy.types.Material): 対象マテリアル
    """

    # マテリアル操作のマニュアル
    # (https://docs.blender.org/api/current/bpy.types.Material.html)

    # ノードが無効な場合、有効化する
    if arg_material.use_nodes == False:
        arg_material.use_nodes = True

    return

# 指定ノードがプリンシプルBSDFかチェックする
def check_isnode_bsdf(arg_node:bpy.types.Node) -> bool:
    """指定ノードがプリンシプルBSDFかチェックする

    Args:
        arg_node (bpy.types.Node): 指定ノード

    Returns:
        bool: プリンシプルBSDFか否か
    """

    # チェック結果
    isBSDF = False

    # ノードタイプを取得する
    node_idname = arg_node.bl_idname

    # ノードタイプがプリンシプルBSDFノードか確認する
    if node_idname == 'ShaderNodeBsdfPrincipled':
        # プリンシプルBSDFならTrueを返す
        isBSDF = True

    return isBSDF


# 指定ノードのプリンシプルBSDFのベースカラーにリンクが設定されているかチェックする
def check_link_bsdf_basecolor(arg_node:bpy.types.Node) -> bool:
    """指定ノードのプリンシプルBSDFのベースカラーにリンクが設定されているかチェックする

    Args:
        arg_node (bpy.types.Node): 指定ノード

    Returns:
        bool: リンクの有無
    """

    # チェック結果
    isLinked = False

    # ベースカラーのリンクが接続されているか確認する
    if arg_node.inputs["Base Color"].is_linked == True:
        # リンクが設定されていればTrueを返す
        isLinked = True
    
    return isLinked

# 指定ノードのプリンシプルBSDFのベースカラー値を取得する
def get_value_bsdf_basecolor(arg_node:bpy.types.Node) -> bpy.types.NodeSocketColor:
    """指定ノードのプリンシプルBSDFのベースカラー値を取得する

    Args:
        arg_node (bpy.types.Node): 指定ノード

    Returns:
        bpy.types.NodeSocketColor: ベースカラー値
    """

    # ベースカラーのデフォルトカラーを取得する
    # ノードソケットカラー操作のマニュアル
    # (https://docs.blender.org/api/current/bpy.types.NodeSocketColor.html)
    basecolor_value = arg_node.inputs["Base Color"].default_value

    return basecolor_value


# 関数の実行例
target_mat = bpy.data.materials.get("Red")
mat_color = get_basecolor_bsdf(target_mat)
if mat_color != None:
    print("Red:" + str(mat_color[0]) + ",Green:" + str(mat_color[1])
      + ",Blue:" + str(mat_color[2]) + ",Alpha:" + str(mat_color[3]))
else:
    print("None")

・ベースカラー有効時
f:id:bluebirdofoz:20201019231838j:plain
・デフォルト値が無効な場合
f:id:bluebirdofoz:20201019231848j:plain
・プリンシプルBSDF以外の場合
f:id:bluebirdofoz:20201019231859j:plain