7
$\begingroup$

I'am beginner at python and blender. I' am trying to create simple addon for myself as part of learning process. I want to achieve that, if i run the script, mixrgb node is added to node tree and link to shader, and if i run script again another mixrgb node is added and linked to shader instead of previous one and previous one link to new one input. Here is the code

import bpy
nodes = bpy.context.active_object.active_material.node_tree.nodes
links = bpy.context.active_object.active_material.node_tree.links
mix = nodes.new('ShaderNodeMixRGB')


mix.location = (-300, -200)
mix.label = "mix"

for n in nodes :
    if n.label == "mix" :
    n.location.y -= 200
links.new(mix.outputs[0], nodes['Principled BSDF'].inputs[0])

Node is created and linked to shader, if i run the script again , new node is created and conected to shader ,previous one change its y location , and here i would like to link old node output to new node input.

I tried

links.new(mix.outputs[0] , mix.inputs[1])

But it conects to itself. I dont want to make separate nodes like mixrgb2 mixrgb3, because i would like to be able to add infinite number of nodes , which are linked to previous.

If somebody can show me the correct way or creating that, iam stuck in that point for few days already. I was searching for solution here and every other forum, but no success, that 's why i decided to make a post.

$\endgroup$

2 Answers 2

5
$\begingroup$

Look for the link.

enter image description here Each run of script, offsetting old mix node 's location.x

  • Put all current mix nodes into a list.
  • Find any links between a mix node and the principle shader
  • Make a new mix node.
  • If there's a link attach the from node (a mix node) output to the input of new mix node
  • Make link new mix node to principled shader
  • Move the old mix nodes. Could do this prior... sometimes handy to post-process incase a prior step is aborted.)

Test script

import bpy
context = bpy.context
nodes = context.active_object.active_material.node_tree.nodes
links = context.active_object.active_material.node_tree.links
ps = nodes.get('Principled BSDF')


mixnodes = [n for n in nodes if n.label == "mix"]
mix_ps_links = [l for l in links if l.from_node.label == "mix" and l.to_node == ps]

# add new mix node
mix = nodes.new('ShaderNodeMixRGB')
mix.location = (-300, -200)
mix.label = "mix"

if mix_ps_links:
    link = mix_ps_links.pop()
    links.new(link.from_node.outputs[0], mix.inputs[0])

links.new(mix.outputs[0], ps.inputs[0])

for mix in mixnodes:
    mix.location.y -= 200

Note: I use the line in test code context = bpy.context to make it cut and paste directly into methods where context is passed, eg def execute(self, context):

$\endgroup$
3
  • 2
    $\begingroup$ That was very fast and good answer. Your solution is perfect for my little project, i managed to make all of the linking and creating nodes. Still have a lot to learn and a lot of questions. $\endgroup$
    – fyf
    Commented Jul 20, 2019 at 18:11
  • $\begingroup$ well done batFinger!!! But...i wanna complain ...your code does not fit to your animation. In reality the mixnodes are arranged under each other, not to the left side ;) ...sorry, could not resist. Of course you got an upvote from me! $\endgroup$
    – Chris
    Commented Apr 14, 2021 at 6:33
  • $\begingroup$ and i have a little "improvement" ;) hope you don't mind: mix.location = (ps.location.x - ps.width - 100, ps.location.y). would give a better positioning, independent from the "real" location of the bsdf ;) $\endgroup$
    – Chris
    Commented Apr 14, 2021 at 6:40
0
$\begingroup$

You need to store a reference to the previously created node and pass it on to the next iteration of the loop. See the sample code below:

import bpy
nodes = bpy.context.active_object.active_material.node_tree.nodes
links = bpy.context.active_object.active_material.node_tree.links
principled = nodes.get('Principled BSDF')

number_of_mix_nodes = 5
previous_mix = None

for n in range(number_of_mix_nodes):
    mix = nodes.new('ShaderNodeMixRGB')
    mix.location = ((number_of_mix_nodes - n) * -300 + principled.location.x, principled.location.y)
    mix.label = f"mix_number_{n}"

    if previous_mix:
        # only if previous_mix is not None, try to connect it
        # to the new mix node
        links.new(previous_mix.outputs[0], mix.inputs[0])

    # let previous_mix point to this mix, so it will be connected
    # the next time the loop is executed
    previous_mix = mix

links.new(mix.outputs[0], principled.inputs[0])

Aside from arranging the nodes relative to the current location of the Principled node, the key here is to introduce the previous_mix variable. In the beginning it is set to None, so the if previous_mix statement will be skipped. Right after that, I re-hook previous_mix to mix. Next time the loop is run, previous_mix contains the first created node, and a second (new) mix node is created. This game can be repeated as many times as you want, just change the number_of_mix_nodes variable.

$\endgroup$

You must log in to answer this question.

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