複数のマテリアルを1つのテクスチャ付マテリアルに置き換える

テクスチャペイント後に、複数のマテリアルを1つのテクスチャ付マテリアルに置き換えたい。

スクリプト

import bpy
import os
import re

#テクスチャフォルダの名前とテクスチャの拡張子を指定してもらう
folder_name = "Textures"
extension = ".png"

#テクスチャの一覧を取得する
current_folder = os.path.dirname(bpy.data.filepath)
texture_folder = current_folder + "\\" + folder_name
texture_list = os.listdir(texture_folder)
texture_name_list = [os.path.splitext(s)[0] for s in texture_list]

#対象オブジェクトの親オブジェクトを指定してもらう
parent_object = bpy.context.active_object
objects = parent_object.children

#対象オブジェクトをループする
for object in objects:

    #対象オブジェクトをアクティブにする
    bpy.context.view_layer.objects.active = object

    #現在あるマテリアルを全て削除する
    for i in range(len(object.material_slots)):
        bpy.ops.object.material_slot_remove()

    #オブジェクト名からマテリアル名を決定する
    material_name = object.name
    material_name = re.sub("\d{2}_", "", material_name)
    material_name = re.sub("_.*", "", material_name)

    #まだ他のオブジェクトで同じマテリアルを利用していない場合
    existing_material = bpy.data.materials.get(material_name)
    if existing_material is None:

        #空のマテリアルを作成して、オブジェクトに割り当てる
        material = bpy.data.materials.new(material_name)
        object.data.materials.append(material)

        #作成したマテリアルでノード利用をオンにする
        active_material = bpy.context.object.active_material
        active_material.use_nodes = True

        #Principled BSDFノードと出力ノードを作成する
        nodes = active_material.node_tree.nodes
        p_bsdf_node = nodes.new(type="ShaderNodeBsdfPrincipled")
        output_node = nodes.new(type="ShaderNodeOutputMaterial")

        #Principled BSDFノードと出力ノードを繋ぐ
        links = active_material.node_tree.links
        links.new(p_bsdf_node.outputs[0], output_node.inputs[0])

        #テクスチャフォルダにマテリアル名と同じテクスチャがある場合
        if material_name in texture_name_list:

            #テクスチャのファイルパスを変数に格納する
            file_path = texture_folder + "\\" + material_name + extension

            #画像ノードを作成して、テクスチャを割り当てる
            image_node = nodes.new(type="ShaderNodeTexImage")
            image_node.image = bpy.data.images.load(filepath=file_path)

            #画像ノードとPrincipled BSDFノードを繋ぐ
            links.new(image_node.outputs[0], principled_node.inputs[0])

    #既に他のオブジェクトで同じマテリアルを利用している場合
    else:

        #そのマテリアルをオブジェクトに割り当てる
        object.data.materials.append(existing_material)

#親オブジェクトをアクティブに戻しておく
bpy.context.view_layer.objects.active = parent_object

オブジェクトの命名ルール

オブジェクトは以下の命名ルールを守るようにする。
2桁の数字の直後のアンダースコアで囲まれた文字列をマテリアルおよびテクスチャの名前とする。

手順

  1. Scripting という Workspace を選択する
  2. 上記のスクリプトをコピペする
  3. テクスチャフォルダの名前を指定する
  4. テクスチャの拡張子を指定する
  5. 親オブジェクトを選択する
  6. 実行する

所感

  • スクリプトには必要最低限のコードしか書いていないので、適宜修正して使ってほしい。
  • Copilot がスクリプトの8割を書いてくれたので、わざわざ記事にする必要が無いのではと思った。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です