0

Does anyone have a clue how to do this? In python code i have a button that selects all my objects in the scene except 1 object named ‘PLANE’. Those objects have all a material (Principled BSDF and Material Output). When this button is pushed, the operator selects all the objects except the PLANE and adds a Groupnode to those materials of thos objects (in between the Princepled BSDF and the Material Output). This works, links the nodes and all. But my problem is that even when the PLANE is not selected and has also a specific other material, it also recieves the Groupnode. And that is just what i do not want. The PLANE must keep its own material. Anyone knows how to fix it? Thanks

this is the code.

class SETACTIVEMATERIAL_OT_operator(bpy.types.Operator):
    bl_idname = "object.section_material"
    bl_label = "Set color to all"
    bl_description = ""

this gives the RGB controller in the panel

col:bpy.props.FloatVectorProperty(name= "pick color", subtype= 'COLOR_GAMMA' , size=4, default= (0,1,0,1), min=0.0, max=1.0) 

def execute(self, context):


# selects all objects in the outliner that are a MESH, except a specific one called Section Plane A
    for collection in bpy.data.collections:
        bpy.data.collections.get("")  # between brackets is name of choice of the collection
        if collection:
           for obj in collection.objects:
               obj.select_set(True)
               obj.select_set(obj.type == "MESH")
        for obj in bpy.context.scene.objects:

            if obj.name.startswith("Sec"):   # even the beginletters are sufficiant
                obj.select_set(False)
            else:

                  bpy.context.view_layer.objects.active=obj








        group_name = "GlobalMixer"
        mixer_name = "Overrider"
        MixerGlobalGroup = bpy.data.node_groups.get(group_name)
        # create a group
        if MixerGlobalGroup == None :
            test_group = bpy.data.node_groups.new(group_name, 'ShaderNodeTree')
            # create group inputs
            group_inputs = test_group.nodes.new('NodeGroupInput')
            group_inputs.location = (-200,0)
            test_group.inputs.new('NodeSocketShader','MainShader')
            # create group outputs
            group_outputs = test_group.nodes.new('NodeGroupOutput')
            group_outputs.location = (400,0)
            test_group.outputs.new('NodeSocketShader','MixedShader')
            # create three math nodes in a group
            node = test_group.nodes.new('ShaderNodeMixShader')
            node.location = (-200,-200)
            node.inputs[0].default_value = 1
            node2 = test_group.nodes.new('ShaderNodeBsdfDiffuse')
            node2.inputs[0].default_value = self.col ########

            node.location = (200,100)
            # link inputs
            test_group.links.new(group_inputs.outputs['MainShader'], node.inputs[1])
            #link output
            test_group.links.new(node.outputs[0], group_outputs.inputs['MixedShader'])
            test_group.links.new(node2.outputs[0], node.inputs[2])
            MixerGlobalGroup = test_group
            print('Global MIxer Created:', MixerGlobalGroup)
        else:
            test_group = bpy.data.node_groups[group_name]
            print('Global MIxer Exists: ', test_group)
            diffuse = test_group.nodes.get('Diffuse BSDF')  ##########
            diffuse.inputs[0].default_value = self.col      #########
        #####################################################################################
        # ADD A MIXER GROUP
        #####################################################################################


        for mat in bpy.data.materials:

            nodes = mat.node_tree.nodes
            if nodes.get(mixer_name) == None:
                mixer = nodes.new(type="ShaderNodeGroup")
                mixer.node_tree  = MixerGlobalGroup
                mixer.name = mixer_name
                mixer.location = (200,200)
                print(mixer_name," [created] ", mixer)
            else:
                print("....overrider already exists")
            mylinks = mat.node_tree.links
            matOut = nodes.get("Material Output")
            matInput = matOut.inputs
            mixerOut = nodes.get(mixer_name).outputs
            mixerIn = nodes.get(mixer_name).inputs
            old_link = matInput['Surface'].links[0].from_node
            if old_link.name != mixer_name:
                print("conected to: ",old_link.name)
                mylinks.new(mixerOut[0], matInput[0])
                old_link = mylinks.new(mixerIn[0], old_link.outputs[0])

        return {"FINISHED"}

to change it from an operator to a dialog box:

def invoke(self, context, event):
    return context.window_manager.invoke_props_dialog(self) 



class RESTOREMATERIAL_OT_operator(bpy.types.Operator): bl_idname = "object.restore_material" bl_label = "restore material" bl_description = "" bl_options = {"REGISTER", "UNDO"}

def execute(self, context):
    for mat in bpy.data.materials:

        node_tree = mat.node_tree
        nodes = mat.node_tree.nodes

        #Get the node / GroupNode in its node tree (replace the name below)
        node_to_delete =  mat.node_tree.nodes['Overrider']

        #Remove the node / GroupNode
        mat.node_tree.nodes.remove( node_to_delete )
        mainShader = nodes.get("Principled BSDF") 
        material_output = nodes.get("Material Output") 


        # Update the links. The current links will get overwritten
        links = node_tree.links
        links.new(mainShader.outputs[0], material_output.inputs[0])  





    return {"FINISHED"} 

K VDAM
  • 1
  • 2
  • Hi, so i have to remove that line of code?Sorry for the indentation, i copied my code from my phone. – K VDAM Jan 26 '22 at 08:21

1 Answers1

1

Instead of running through all materials in your blend, filter the materials from the desired objects by using Object.material_slots and add the node group to these materials only: https://docs.blender.org/api/current/bpy.types.Object.html#bpy.types.Object.material_slots

import bpy

C = bpy.context

Filter the materials from all objects in selection

mats_filter = set(slot.material for o in C.selected_objects for slot in o.material_slots)

Loop through all materials of objects in selection

for material in mats_filter: custom_group = bpy.data.node_groups.get("NodeGroup") # Add the node group to each material if custom_group: new_node = material.node_tree.nodes.new(type='ShaderNodeGroup') new_node.node_tree = custom_group

How to iterate over material index using Python

How do I iterate over all selected objects and change a property on their materials?

pyCod3R
  • 1,926
  • 4
  • 15
  • Thank you for this info. I understand what you mean, but i do not know where to put those lines in the code above and what lines i have to remove. I keep messing up the code. The line custom_group = bpy.data.node_groups.get("NodeGroup") is where the NodeGroup name will be replaced by Override because that is the name of the Nodegroup i want to add i suppose. I am new to all the python coding stuff. It is cool to learn and i am learning every day. – K VDAM Jan 26 '22 at 10:51
  • @KVDAM -> https://www.codepile.net/pile/EgWBmDRk replace bpy.data.materials as mentioned in my very first comment. – pyCod3R Jan 26 '22 at 11:34
  • Thank you for helping. I followed your instructions and it seems to be working. By it seems i mean that when i for example have 1 object selected or active, that object also does not get that groupnode added. If i select the plane the groupnode gets added to all the objects like it supposed to be. I tried to copy my code into here but the indentation gets messed up. – K VDAM Jan 26 '22 at 13:22