"""Functions related to Houdini nodes."""
# Future
from __future__ import annotations
# Standard Library
import json
from typing import TYPE_CHECKING, Any
# Houdini
import hou
if TYPE_CHECKING:
from collections.abc import Sequence
# Functions
[docs]
def disconnect_all_outputs(node: hou.Node) -> None:
"""Disconnect all of this node's outputs.
Args:
node: The node to disconnect all outputs for.
"""
connections = node.outputConnections()
with hou.undos.group("Disconnect outputs"):
for connection in connections:
connection.outputNode().setInput(connection.inputIndex(), None)
[docs]
def get_containing_node(node: hou.Node) -> hou.Node | None:
"""Returns the nearest parent node which is of a different node type category.
Args:
node: The node to find the containing node of.
Returns:
The containing node.
"""
parent = node.parent()
while parent is not None:
parent_type = parent.type()
parent_category = parent_type.category()
# If the parent node is the root node, /, then an exception
# will be thrown so we need to account for it.
try:
parent_child_type = parent_type.childTypeCategory()
except hou.OperationFailed:
parent_child_type = None
if parent_category != parent_child_type:
return parent
parent = parent.parent()
return None
[docs]
def get_node_author(node: hou.OpNode) -> str:
"""Get the name of the node creator.
Args:
node: The node to get the author of.
Returns:
The author name.
"""
return hou.hscript(f"opls -d -l {node.path()}")[0].strip().split()[-2]
[docs]
def get_nodes_from_paths(paths: Sequence[str]) -> tuple[hou.Node, ...]:
"""Convert a list of string paths to hou.Node objects.
Args:
paths: A list of paths.
Returns:
A tuple of hou.Node objects.
"""
return tuple(hou.node(path) for path in paths if path)
[docs]
def node_is_contained_by(node: hou.Node, containing_node: hou.Node) -> bool:
"""Test if a node is a contained within another node.
Args:
node: The node to check for being contained.
containing_node: A node which may contain this node
Returns:
Whether this node is a child of the passed node.
"""
# Get this node's parent.
parent = node.parent()
# Keep looking until we have no more parents.
while parent is not None:
# If the parent is the target node, return True.
if parent == containing_node:
return True
# Get the parent's parent and try again.
parent = parent.parent()
# Didn't find the node, so return False.
return False
[docs]
def read_from_user_data(node: hou.Node, user_data_name: str) -> Any:
"""Read a data structure stored in a node's user data dictionary.
Use this in conjunction with `store_as_user_data`.
Args:
node: The node the data is stored on.
user_data_name: The user data key the data is stored under.
Returns:
The stored data.
"""
return json.loads(node.userData(user_data_name))
[docs]
def store_as_user_data(node: hou.Node, user_data_name: str, data: Any) -> None:
"""Store a data structure in a node's user data dictionary.
Use this in conjunction with `read_from_user_data`.
The structure to be stored must be encodable by json.
Args:
node: The node to store the data on.
user_data_name: The user data key to store the data under.
data: The data to store.
"""
node.setUserData(user_data_name, json.dumps(data))