# How to stack nodes using a loop?

This is a followup to my previous question. While that answer tells me how to stack all nodes along the x axis, I now need to stack certain nodes along the y axis, at the same x axis point.

My code right now uses this loop:

for i in node_names:
print(i)
nodes[i].location.x = locx
locx += nodes[i].width + 50
nodes[i].location.y = 0
if nodes[i].type == "TEX_IMAGE":
nodes[i].location.y = locy
locy += nodes[i].height + 200
newlocx = nodes[i].location.x
nodes[i].location.x = newlocx


This gives me a result where the nodes "staircase" up the graph.

I think what I want is to remember the x value of the first image node, but only the first one, and save it to a variable. That way I can just pass that coord as the x value for the rest of them.

I have tried setting the image nodes as their own array and looping through it, but that throws an error because the blender's method doesn't process lists, it processes strings or ints.

I can provide more context if need be.

• The main question is how dynamic you want your script to be. Do you have a list of the nodes in the correct order, or do you want the script to generate the order along x axis automatically (which will be much more complicated)? – Dimali Aug 24 '17 at 17:53
• In my script, the order is generated correctly; although I use reversed() when it is called so that it writes it out in the correct order. – Rug Aug 24 '17 at 19:23

import bpy

node_names = ['Texture Coordinate', 'Mapping', 'Image Texture','Image Texture 2','Diffuse BSDF','Material Output']
nodes = bpy.data.materials['Material'].node_tree.nodes
startlocy = 0
startlocx = 0

locx = startlocx
locy = startlocy
# Set the first node's X and y coords to 0,0
nodes[node_names[0]].location.x = locx
nodes[node_names[0]].location.y = locy
# For index, node in the list 'node_names'
for i, node in enumerate(node_names[1:]):
# Set the last used node
lastnode = node_names[i]
#if the last node AND the current node are texture images
if nodes[lastnode].type == "TEX_IMAGE" and nodes[node].type == "TEX_IMAGE":
# Set current node to the height of the last one plus 200px
locy += nodes[lastnode].height + 200
else:
# Otherwise, set the y to the default (0)
locy = startlocy
# Set the x to the width of the node plus 50px
locx += nodes[lastnode].width + 50
nodes[node].location.x = locx
nodes[node].location.y = locy


This seems to work if your texture nodes have the same width, else only the highest node influences the next x position. You need to write the node names in the right order in the list node_names.