I just lost 10 minutes because a colleague shared a geometry nodes graph, where they had hidden one node underneath the other in the node editor. I am talking just about the simple act of dragging a node so that it makes it impossible to see another node. They had on top it all, moved it so that the connecting noodle was occluded as well.

I wonder if there is some way to avoid this automatically. Either by enabling some feature in Blender, by installing some addon, or by having some kind of automatic layout. Perhaps with alpha layer on the nodes, or by red markings of the outline of the back node or similar. Thanks

edit: functionality exists in the addons node-wrangler and arrange nodes. They can align all nodes so that none are overlapping, but they both re-arrange the whole graph, which is not what I want.

  • $\begingroup$ I don't think there's any way of avoiding that at the moment but it might be worth suggesting it on blender.community/c/rightclickselect stating the reason you have given here. $\endgroup$
    – John Eason
    Apr 27, 2023 at 20:25

1 Answer 1


Run the below script, then go to your node editor (I tested in geometry nodes), F3 "Find Overlapping Node". It should select first found overlapping node. Not necessarily a node completely hidden behind another, but I think nodes shouldn't overlap anyway…

import bpy
from math import floor, ceil

the_id = "find_overlapping_node"


def main(C):
    nodes = C.area.spaces[0].node_tree.nodes
    grid_cells_taken = set()
    for n in nodes:
        left = ceil(n.location.x / RESOLUTION)
        right = floor(left + n.dimensions.x / RESOLUTION)
        top = floor(n.location.y / RESOLUTION)
        bottom = ceil(top - n.dimensions.y / RESOLUTION)
        for x in range(left+1, right-1):
            for y in range(bottom+1, top-1):
                if (x, y) in grid_cells_taken:
                    n.select = True
                    print(f"{n} is overlapping another node!")
                    raise Exception(f"{n} is overlapping another node!")
                    return  # comment out the above line to not have an error message
                grid_cells_taken.add((x, y))

class FindOverlappingNode(bpy.types.Operator):
    """Detect and select first found node that significantly overlaps another"""
    bl_idname = f"object.{the_id}"
    bl_label = "Find Overlapping Node"

    def poll(cls, context):
        return context.area.type == 'NODE_EDITOR'

    def execute(self, context):
        return {'FINISHED'}

def menu_func(self, context):
    self.layout.operator(FindOverlappingNode.bl_idname, text=FindOverlappingNode.bl_label)

def register():
    setattr(bpy.types.WindowManager, f"{the_id}_cls", FindOverlappingNode)
    setattr(bpy.types.WindowManager, f"{the_id}_fun", menu_func)

def unregister():
    oldclass = getattr(bpy.types.WindowManager, f"{the_id}_cls")
    oldfunc = getattr(bpy.types.WindowManager, f"{the_id}_fun")
    delattr(bpy.types.WindowManager, f"{the_id}_cls")
    delattr(bpy.types.WindowManager, f"{the_id}_fun")

if __name__ == "__main__":
    except AttributeError:

  • $\begingroup$ That's fine if you remember to run it! :^) $\endgroup$
    – John Eason
    Apr 27, 2023 at 20:44
  • $\begingroup$ could this be implemented as a modal operator in an addon perhaps. Would be nice if it screamed without user initializing it. $\endgroup$ Apr 28, 2023 at 0:37
  • $\begingroup$ You'd need to implement a cache to store the node locations otherwise I expect the performance ot be horrendous in big node trees $\endgroup$
    – Gorgious
    Apr 28, 2023 at 4:30
  • $\begingroup$ Of course you can make an add-on. Also consider instead of a grid approach, sorting the nodes by x, and for each node iterating over all nodes with similar x, until you go outside a given range of x, and then sort the found nodes by y and repeat. $\endgroup$ Apr 28, 2023 at 8:30
  • $\begingroup$ Thanks, works.. $\endgroup$ May 9, 2023 at 20:07

You must log in to answer this question.

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