1
$\begingroup$

I want to ask a solution for blender scipt for principled. I have imported about 50 characters in FBX format, problem is that every one of them have about 10-15 materials with principled but they are wrong. I never scripted in python so Im in the dark right now. What I want to do I want create script for selected material that use Principled to set:

Specular and Metallic

to 0.0

and disconnect(clear)

Alpha and Normal

I found here this script and I try to recreate that but I'm afraid im too green to do that right. If anyone will be able to help it would be great!

import bpy

# I separated the creation of nodes to a function so it's easier 
# to edit later if needed
def create_nodes(mat): 
    mat.use_nodes = True
    nodes = mat.node_tree.nodes
    for every_node in nodes: # this removes all existing nodes
        nodes.remove(every_node)

    # creating Principled node and moving it:
    node = nodes.new('ShaderNodeBsdfPrincipled')
    node.location = (-190,100)

    # creating Output node and moving it:
    output_node = nodes.new('ShaderNodeOutputMaterial')
    output_node.location = (40,100)

    # creating the link between the two nodes:
    links = mat.node_tree.links
    link = links.new(node.outputs[0], output_node.inputs[0])

# this saves the currently active object so it can be restored later
active = bpy.context.object 

# let's loop through all selected objects
for every_object in bpy.context.selected_objects: 
    # I only want to work with objects capable of having a material
    if every_object.type in {'MESH','CURVE', 'SURFACE','META', 'FONT'}: 
        if every_object.name not in bpy.data.materials:
        # if there is no material named after the object yet let's make one
            mat = bpy.data.materials.new(every_object.name)
            # and let's create the nodes for it
            create_nodes(mat)
        else:
            # if the material already exists let's just use it
            mat = bpy.data.materials.get(every_object.name)
        if len(every_object.material_slots) == 0: # if there are no material slots
            # let's make the current object active and create a material slot
            bpy.context.scene.objects.active = every_object
            bpy.ops.object.material_slot_add() 
            # let's leave the active object as it was
            bpy.context.scene.objects.active = active

        # The only thing left now is to assign the material to 
        # all material slots. We probably do not want to loose the info
        # about how the object is divided into separate materials
        for every_slot in every_object.material_slots:
            every_slot.material = mat  
$\endgroup$
2
  • $\begingroup$ I will post a solution in about an hour. $\endgroup$
    – Robert Gützkow
    Nov 22, 2019 at 16:14
  • $\begingroup$ I will appreciate your help with this situation, I made mistake in main post, I meant for selected obj, not material. Sorry for mistake. $\endgroup$
    – Lathiel
    Nov 22, 2019 at 16:51

1 Answer 1

2
$\begingroup$

The following code iterates through all selected objects and their respective materials found in the material slots. If a Principled BSDF node is found in the material, the Specular and Metallic properties are set to zero and links to Alpha and Normal are removed.

Be aware that every material will be fixed that is present in the selected objects' material slots. If that includes a material that is also assigned to an unselected object, that change will affect the unselected object as well.

import bpy


def remove_links(socket: bpy.types.NodeSocket, node_tree: bpy.types.NodeTree):
    """Remove all links from or to the given socket"""
    for link in socket.links:
        node_tree.links.remove(link)


def fix_node(node: bpy.types.Node, node_tree: bpy.types.NodeTree):
    """Adjust the properties if the node is a Principled BSDF"""
    if node.type == 'BSDF_PRINCIPLED':
        node.inputs['Specular'].default_value = 0.0
        node.inputs['Metallic'].default_value = 0.0
        remove_links(node.inputs['Alpha'], node_tree)
        remove_links(node.inputs['Normal'], node_tree)


def fix_material(material: bpy.types.Material):
    """Fix the nodes of the given material"""
    for node in material.node_tree.nodes:
        fix_node(node, material.node_tree)


def fix_selected():
    """Fix the materials of the selected objects"""
    for object in bpy.context.selected_objects:
        for material_slot in object.material_slots:
            fix_material(material_slot.material)

if __name__ == "__main__":
    fix_selected()
$\endgroup$
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .