Material Nodes Not Connecting Properly

When linking a vector math node and a math node together, using the code below, the nodes are never linked.

        # Add nodes.
        nodes = bake_material.node_tree.nodes

        bsdf_node = nodes.get("Principled BSDF")
        if bsdf_node != None:
            nodes.remove(bsdf_node)

        material_output_node = nodes.get("Material Output")
        image_node = nodes.new(type='ShaderNodeTexImage')
        emission_node = nodes.new(type='ShaderNodeEmission')
        vector_math_node = nodes.new(type='ShaderNodeVectorMath')
        math_node = nodes.new(type='ShaderNodeMath')
        geometry_node = nodes.new(type='ShaderNodeNewGeometry')
        invert_node = nodes.new(type='ShaderNodeInvert')
        bevel_node = nodes.new(type='ShaderNodeBevel')

        # Set node values.
        bevel_node.inputs[0].default_value = 0.001
        image_node.image = bpy.data.images[bake_image_name]
        math_node.operation = 'MULTIPLY'
        math_node.inputs[1].default_value = 1.0
        vector_math_node.operation = 'DOT_PRODUCT'

        # Link Nodes
        links = bake_material.node_tree.links
        links.new(bevel_node.outputs[0], vector_math_node.inputs[0])
        links.new(geometry_node.outputs[1], vector_math_node.inputs[1])
        links.new(vector_math_node.outputs[0], math_node.inputs[0])
        links.new(math_node.outputs[0], invert_node.inputs[1])
        links.new(invert_node.outputs[0], emission_node.inputs[0])
        links.new(emission_node.outputs[0], material_output_node.inputs[0])

your inputs/outputs are reversed (unless you’re trying to connect the vector_math to the math node? maybe you can describe what the desired node tree should look like).

links.new(to_node.inputs[to_socket], from_node.outputs[from_socket])

https://docs.blender.org/api/current/bpy.types.NodeLinks.html?highlight=links%20new#bpy.types.NodeLinks.new

I reversed the inputs and outputs to match the API, this didn’t make any differences unfortunately.

Only the vectormath node doesn’t link to the math node.

I believe this is because the output socket is changing from vector to a float socket when the operation is changed.

        links = bake_material.node_tree.links

        links.new(material_output_node.inputs[0], emission_node.outputs[0])
        links.new(emission_node.inputs[0], invert_node.outputs[0])
        links.new(invert_node.inputs[1], math_node.outputs[0])

        # This node never links to math node.
        vector_math_node.operation = 'DOT_PRODUCT'
        vector_math_node.update()
        vector_math_node.socket_value_update(context)
        links.new(math_node.inputs[1], vector_math_node.outputs[0])


        links.new(vector_math_node.inputs[1], geometry_node.outputs[1])
        links.new(vector_math_node.inputs[0], bevel_node.outputs[0])

I thought the socket value or node wasn’t updating so I’ve been trying to force the node to update using update() and socket_value_update().

Neither of these seem to have any effect, as I believe this are actually getting called automatically anyways.

SOLUTION: I found that connecting the second (outputs[1]) vector math node output works, which is very strange because the vector math node doesn’t visually have a second output node.

        vector_math_node.operation = 'DOT_PRODUCT'
        links.new(math_node.inputs[1], vector_math_node.outputs[1])

FYI: you can actually access socket names by their dictionary name to avoid this problem in the future.

ie) inputs['Color'], outputs['Value'] etc

1 Like

Ahh, that’s very helpful. Thank you!

Hi,

I’m having similar problem but inside the geometry nodes editor, for some reason there are two node links which wont execute, I’ve tried to use the socket name and reverse the linking in the code but with no success, any ideas? here is the code:

def create_MMC_Spline():
    if not "MMC_Spline_Nodetree" in bpy.data.node_groups.keys():
        spline_group = bpy.data.node_groups.new("MMC_Spline_Nodetree", 'GeometryNodeTree')
        
        spline_group.inputs.new("NodeSocketGeometry", "Geometry")
        spline_group.inputs.new("NodeSocketInt", "ID")
        input_node = spline_group.nodes.new("NodeGroupInput")
        input_node.location = (0, 0)
        
        spline_group.outputs.new("NodeSocketGeometry", "Geometry")
        output_node = spline_group.nodes.new("NodeGroupOutput")
        output_node.location = (800, 0)
        
        CaptureAttribute = spline_group.nodes.new('GeometryNodeCaptureAttribute')
        CaptureAttribute.domain = 'CURVE'
        CaptureAttribute.data_type = 'INT'
        CaptureAttribute.location = (200, 0)
        
        CompareFloats = spline_group.nodes.new('FunctionNodeCompareFloats')
        CompareFloats.operation = 'EQUAL'
        CompareFloats.location = (400, -50)
        
        SeparateGeometry = spline_group.nodes.new('GeometryNodeSeparateGeometry')
        SeparateGeometry.domain = 'POINT'
        SeparateGeometry.location = (600, 50)
        
        ##### LINKING NODES ########
        spline_group.links.new(input_node.outputs["Geometry"], CaptureAttribute.inputs["Geometry"])
        spline_group.links.new(input_node.outputs[1], CaptureAttribute.inputs[1]) ##### Link not being executed ########
        spline_group.links.new(CaptureAttribute.outputs[0], SeparateGeometry.inputs[0])
        spline_group.links.new(CaptureAttribute.outputs[1], CompareFloats.inputs[0]) ##### Link not being executed ########
        spline_group.links.new(CompareFloats.outputs[0], SeparateGeometry.inputs[1])
        spline_group.links.new(SeparateGeometry.outputs[0], output_node.inputs[0])
                
    else:
        spline_group = bpy.data.node_groups["MMC_Spline_Nodetree"]
        
    return spline_group

And the resulting nodetree with the missing links:

generally this happens because the indices are not what you expect. a node is like any other UI element, such as a panel- and some of them have their own draw() routine with custom logic. For example, if you change a math node from “addition” to “power” you’ll get different inputs. Under the hood, all of these inputs are just properties and they all exist simultaneously, changing the dropdown does not re-index everything to what is visible. So what you are thinking is at index 1 might actually be at index 5 or 99.

TLDR: try using the key name instead.

spline_group.links.new(input_node.outputs['ID'], CaptureAttribute.inputs['Value'])

If that doesn’t work, try listing out the available inputs and outputs of a node and find the one you’re looking for.

for o in input_node.outputs:
    print(o.name)

I tried to use the socket name but strangely the captureAttribute node has 4 sockets named ‘Value’ so it didn’t work, what it did worked is to use the last socket [-1]

spline_group.links.new(input_node.outputs['ID'], CaptureAttribute.inputs[-1])

thanks