New hotkey: Display Nearest Node

   7059   16   3
User Avatar
Member
5167 posts
Joined: Feb. 2012
Online
Not sure if anyone needs it but I wrote a shelf tool that sets the display/render flag to the nearest node to your cursor in the network editor. When you bind it to a hotkey, it boosts your productivity by 2% as you don't have to carefully focus on the display flag of nodes to set them Just hover around with your pen.

If there is a simpler way to get the current cursor position over the network editor, I would love to know. Here is the code:

import ctypes

MOUSEEVENTF_LEFTDOWN = 0x0002 # Left button down
MOUSEEVENTF_LEFTUP = 0x0004 # Left button up
MOUSEEVENTF_CLICK = MOUSEEVENTF_LEFTDOWN + MOUSEEVENTF_LEFTUP

selNodes = hou.selectedNodes ( )
networkEditor = hou.ui.paneTabOfType ( hou.paneTabType.NetworkEditor )
currentPath = networkEditor.pwd ( ).path ( )
context = networkEditor.pwd ( ).childTypeCategory ( )

ctypes.windll.user32.mouse_event ( MOUSEEVENTF_CLICK, 0, 0, 0, 0 )
ctypes.windll.user32.mouse_event ( MOUSEEVENTF_CLICK, 0, 0, 0, 0 )
pos = networkEditor.selectPosition ( None, -1, None, -1 )


nodes = hou.node ( currentPath ).children ( )
nearestNode = None
dist = 999999999.0

for node in nodes:
d = node.position ( ).distanceTo ( pos )
if d < dist:
nearestNode = node
dist = d

if nearestNode:
nearestNode.setDisplayFlag ( True )
nearestNode.setRenderFlag ( True )
nearestNode.setSelected ( True, clear_all_selected=True )



Enjoy
Senior FX TD @ Industrial Light & Magic
Get to the NEXT level in Houdini & VEX with Pragmatic VEX! [www.pragmatic-vfx.com] https://lnk.bio/animatrix [lnk.bio]
User Avatar
Member
392 posts
Joined: Nov. 2008
Offline
Interesting hack, thanks.

networkEditor.cursorPosition()

Enjoy
User Avatar
Member
5167 posts
Joined: Feb. 2012
Online
Thanks a lot, simplifies my code a lot Now I wonder why that is not documented?:
http://www.sidefx.com/docs/houdini14.0/hom/hou/NetworkEditor [sidefx.com]
Senior FX TD @ Industrial Light & Magic
Get to the NEXT level in Houdini & VEX with Pragmatic VEX! [www.pragmatic-vfx.com] https://lnk.bio/animatrix [lnk.bio]
User Avatar
Member
678 posts
Joined: July 2005
Offline
pusat
… it boosts your productivity by 2%…

Err… thanks???
Edited by - April 28, 2015 22:41:19
User Avatar
Member
333 posts
Joined: Oct. 2012
Offline
kewl. thanks
User Avatar
Member
5167 posts
Joined: Feb. 2012
Online
mantragora
pusat
… it boosts your productivity by 2%…

Err… thanks???

It's up to 7% now

New changes:
Simplified position checking (thanks to pezetko)
More accurate distance calculation
For Object level nodes, it dives inside the nearest node
If a node is already selected either manually or with this tool and it's called again near the same node, it dives inside. So press the same hotkey twice if you want to dive inside Attrib VOPSOP, Volume VOPSOP, etc.
For VOP nodes, it selects the nearest node

networkEditor = kwargs
currentPath = networkEditor.pwd ( ).path ( )
context = networkEditor.pwd ( ).childTypeCategory ( )
currentContext = context.name()
pos = networkEditor.cursorPosition ( )

nodes = hou.node ( currentPath ).children ( )
nearestNode = None
dist = 999999999.0
for node in nodes:
d = ( node.position ( ) + ( node.size ( ) * 0.5 ) ).distanceTo ( pos )
#print “{0} {1} {2}”.format(d, node.position(), node.name())
if d < dist:
nearestNode = node
dist = d

handled = False
if nearestNode:
if currentContext == ‘Object’:
networkEditor.cd ( nearestNode.path ( ) )

if currentContext == ‘Sop’:
if nearestNode.isDisplayFlagSet ( ):
networkEditor.cd ( nearestNode.path ( ) )
handled = True
else:
nearestNode.setDisplayFlag ( True )
nearestNode.setRenderFlag ( True )

if currentContext != ‘Object’ and not handled:
nearestNode.setSelected ( True, clear_all_selected=True )

Feedback is welcome as always
Edited by - April 30, 2015 16:02:50
Senior FX TD @ Industrial Light & Magic
Get to the NEXT level in Houdini & VEX with Pragmatic VEX! [www.pragmatic-vfx.com] https://lnk.bio/animatrix [lnk.bio]
User Avatar
Member
538 posts
Joined: Dec. 2006
Offline
Very nice!!!
https://gumroad.com/alexeyvanzhula [gumroad.com]
User Avatar
Member
5167 posts
Joined: Feb. 2012
Online
Thanks mate
Senior FX TD @ Industrial Light & Magic
Get to the NEXT level in Houdini & VEX with Pragmatic VEX! [www.pragmatic-vfx.com] https://lnk.bio/animatrix [lnk.bio]
User Avatar
Member
538 posts
Joined: Dec. 2006
Offline
I think most of users will assign it to Network Pane Hotkey, so you can use kwargs instead of paneTabOfType.
Maybe it will be 0.0000000000000000001% faster
https://gumroad.com/alexeyvanzhula [gumroad.com]
User Avatar
Member
5167 posts
Joined: Feb. 2012
Online
Thanks that's a good point Changed the code to reflect that.
Senior FX TD @ Industrial Light & Magic
Get to the NEXT level in Houdini & VEX with Pragmatic VEX! [www.pragmatic-vfx.com] https://lnk.bio/animatrix [lnk.bio]
User Avatar
Member
691 posts
Joined: June 2006
Offline
Very Nice!!
Feel The Knowledge, Kiss The Goat!!!
http://www.linkedin.com/in/alejandroecheverry [linkedin.com]
http://vimeo.com/lordpazuzu/videos [vimeo.com]
User Avatar
Member
5167 posts
Joined: Feb. 2012
Online
Thanks It would be awesome if I could conditionally assign it to wacom pen. I never use the right click menu on the network editor outside the nodes. It would be nice if this could be configured so if you right click on the empty area of the network editor, it would invoke this hotkey.
Senior FX TD @ Industrial Light & Magic
Get to the NEXT level in Houdini & VEX with Pragmatic VEX! [www.pragmatic-vfx.com] https://lnk.bio/animatrix [lnk.bio]
User Avatar
Member
165 posts
Joined: Aug. 2013
Offline
Can we get this to work in modern versions?!
User Avatar
Member
5167 posts
Joined: Feb. 2012
Online
This is 2026 version from Houdini supercharged extension:

_EXCLUDE_DISPLAY = {"Driver", "Shop", "Vop"}
_EXCLUDE_RENDER  = {"Object", "Driver", "Dop", "Shop", "Chop", "Vop", "Lop", "Cop"}

def toggleNodeDisplayFlag(node, context):
    if context not in _EXCLUDE_DISPLAY and hasattr(node, "setDisplayFlag"):
            node.setDisplayFlag(not node.isDisplayFlagSet())

def toggleNodeRenderFlag(node, context):
    if context not in _EXCLUDE_RENDER and hasattr(node, "setRenderFlag"):
            node.setRenderFlag(not node.isRenderFlagSet())

def findNearestNode(editor):
    pos = editor.cursorPosition()
    currentPath = editor.pwd().path()

    nodes = hou.node(currentPath).children()
    nearestNode = None
    dist = 999999999.0
    for node in nodes:
        d = (node.position() + (node.size() * 0.5)).distanceTo(pos)
        if d < dist:
            nearestNode = node
            dist = d

    return nearestNode

def displayNearestNodeInEditor():
    editor = hou.ui.paneTabUnderCursor()
    editortype = editor.type()
    if editortype == hou.paneTabType.NetworkEditor:
        nearestNode = findNearestNode(editor)
        if nearestNode and editor.pwd().isEditable():
            with hou.undos.group("Display Nearest Node"):
                context = nearestNode.type().category().name() 
                toggleNodeDisplayFlag(nearestNode, context)
                toggleNodeRenderFlag(nearestNode, context)
Senior FX TD @ Industrial Light & Magic
Get to the NEXT level in Houdini & VEX with Pragmatic VEX! [www.pragmatic-vfx.com] https://lnk.bio/animatrix [lnk.bio]
User Avatar
Member
165 posts
Joined: Aug. 2013
Offline
animatrix_
This is 2026 version from Houdini supercharged extension:

_EXCLUDE_DISPLAY = {"Driver", "Shop", "Vop"}
_EXCLUDE_RENDER  = {"Object", "Driver", "Dop", "Shop", "Chop", "Vop", "Lop", "Cop"}

def toggleNodeDisplayFlag(node, context):
    if context not in _EXCLUDE_DISPLAY and hasattr(node, "setDisplayFlag"):
            node.setDisplayFlag(not node.isDisplayFlagSet())

def toggleNodeRenderFlag(node, context):
    if context not in _EXCLUDE_RENDER and hasattr(node, "setRenderFlag"):
            node.setRenderFlag(not node.isRenderFlagSet())

def findNearestNode(editor):
    pos = editor.cursorPosition()
    currentPath = editor.pwd().path()

    nodes = hou.node(currentPath).children()
    nearestNode = None
    dist = 999999999.0
    for node in nodes:
        d = (node.position() + (node.size() * 0.5)).distanceTo(pos)
        if d < dist:
            nearestNode = node
            dist = d

    return nearestNode

def displayNearestNodeInEditor():
    editor = hou.ui.paneTabUnderCursor()
    editortype = editor.type()
    if editortype == hou.paneTabType.NetworkEditor:
        nearestNode = findNearestNode(editor)
        if nearestNode and editor.pwd().isEditable():
            with hou.undos.group("Display Nearest Node"):
                context = nearestNode.type().category().name() 
                toggleNodeDisplayFlag(nearestNode, context)
                toggleNodeRenderFlag(nearestNode, context)

Very grateful, thank you! Although for some reason it still doesn't work. Nothing happens when I press the keys. I see you define some functions but if I'm not mistaken they're not called.
User Avatar
Member
5167 posts
Joined: Feb. 2012
Online
coccarolla
animatrix_
This is 2026 version from Houdini supercharged extension:

_EXCLUDE_DISPLAY = {"Driver", "Shop", "Vop"}
_EXCLUDE_RENDER  = {"Object", "Driver", "Dop", "Shop", "Chop", "Vop", "Lop", "Cop"}

def toggleNodeDisplayFlag(node, context):
    if context not in _EXCLUDE_DISPLAY and hasattr(node, "setDisplayFlag"):
            node.setDisplayFlag(not node.isDisplayFlagSet())

def toggleNodeRenderFlag(node, context):
    if context not in _EXCLUDE_RENDER and hasattr(node, "setRenderFlag"):
            node.setRenderFlag(not node.isRenderFlagSet())

def findNearestNode(editor):
    pos = editor.cursorPosition()
    currentPath = editor.pwd().path()

    nodes = hou.node(currentPath).children()
    nearestNode = None
    dist = 999999999.0
    for node in nodes:
        d = (node.position() + (node.size() * 0.5)).distanceTo(pos)
        if d < dist:
            nearestNode = node
            dist = d

    return nearestNode

def displayNearestNodeInEditor():
    editor = hou.ui.paneTabUnderCursor()
    editortype = editor.type()
    if editortype == hou.paneTabType.NetworkEditor:
        nearestNode = findNearestNode(editor)
        if nearestNode and editor.pwd().isEditable():
            with hou.undos.group("Display Nearest Node"):
                context = nearestNode.type().category().name() 
                toggleNodeDisplayFlag(nearestNode, context)
                toggleNodeRenderFlag(nearestNode, context)

Very grateful, thank you! Although for some reason it still doesn't work. Nothing happens when I press the keys. I see you define some functions but if I'm not mistaken they're not called.

Oh yes I didnt include the call because that depends on how you want to use them. So you can just include a simple function call at the end of the code like this if you want to use them from shelf tool via a hotkey for example:

displayNearestNodeInEditor()
Senior FX TD @ Industrial Light & Magic
Get to the NEXT level in Houdini & VEX with Pragmatic VEX! [www.pragmatic-vfx.com] https://lnk.bio/animatrix [lnk.bio]
User Avatar
Member
118 posts
Joined: Oct. 2018
Offline
Not sure about posted versions, but this version works 100%, 99% of the time and is optimized 110%.

import hou

def node_supports_display(node):
    try:
        node.isDisplayFlagSet()
        return True
    except:
        return False

def node_distance_to_cursor(node, pos):
    p = node.position()
    s = node.size()

    min_x, max_x = p[0], p[0] + s[0]
    min_y, max_y = p[1], p[1] + s[1]

    # Clamp cursor to node bounding box
    x = min(max(pos[0], min_x), max_x)
    y = min(max(pos[1], min_y), max_y)

    closest = hou.Vector2(x, y)
    return closest.distanceTo(pos)

def find_nearest_node(editor):
    pos = editor.cursorPosition()
    nearest = None
    best_dist = float('inf')

    for node in editor.pwd().children():

        if not node_supports_display(node):
            continue

        d = node_distance_to_cursor(node, pos)

        if d < best_dist:
            best_dist = d
            nearest = node

    #print("cursor:", pos)
    #print("nearest:", nearest.path() if nearest else "None")
    return nearest

def sloppy_node_selection():
    editor = hou.ui.paneTabUnderCursor()
    if not editor or editor.type() != hou.paneTabType.NetworkEditor:
        return

    nearest = find_nearest_node(editor)
    if not nearest:
        return

    with hou.undos.group("Set Display Flag on Nearest Node"):
        nearest.setDisplayFlag(True)
        nearest.setRenderFlag(True)

sloppy_node_selection()
Edited by hMonkey - March 9, 2026 00:10:55
  • Quick Links