Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save BigRoy/57d66d0ea2bddb1b1782aaca97c3c3aa to your computer and use it in GitHub Desktop.
Save BigRoy/57d66d0ea2bddb1b1782aaca97c3c3aa to your computer and use it in GitHub Desktop.
Houdini Solaris find the Houdini Editor Node for a Shader or Material in a Houdini Material Library
import os
import logging
from typing import List
import hou
import loputils
from pxr import Usd, UsdShade
log = logging.getLogger(__name__)
def get_editor_nodes(prim: Usd.Prim) -> List[hou.Node]:
editor_nodes = loputils._getEditorNodes(prim, allow_locked_nodes=False)
return editor_nodes
def get_houdini_node_from_usd_shader(prim: Usd.Prim) -> hou.VopNode:
"""From a USD Shader or USD Material prim get the Houdini editor node.
This requires that the USD Material Prim has Houdini's
custom metadata that stores the relevant 'Editor Node'.
"""
material = None
if prim.IsA(UsdShade.Material):
material = prim
elif prim.IsA(UsdShade.Shader):
# Get the parent material from the shader because the
# Shader prims do not store any "Editor Node" metadata
parent = prim.GetParent()
while True:
if parent.IsPseudoRoot():
return
if parent.IsA(UsdShade.Material):
material = parent
break
parent = parent.GetParent()
else:
log.warning(f"Primitive is not a shader or material: {prim}")
return
if material is None:
raise RuntimeError("Material is None; this is a bug.")
editor_nodes = get_editor_nodes(material)
if not editor_nodes:
# No houdini editor node found
return
# Find the material library that created it.
for editor_node in editor_nodes:
# TODO: Validate editor node is VOP node
material_node = editor_node
if not material_node:
raise KeyError(
f"Unable to find Houdini node for material: {material}")
# If the original node was a shader we might want to find the child VOP
# node of the material. So we do a relative path check.
relative = os.path.relpath(prim.GetPath().pathString,
material.GetPath().pathString)
if relative == ".":
return material_node
shader_path = "/".join([material_node.path(), relative])
shader_node = hou.node(shader_path)
if shader_node:
return shader_node
return
# Example usage
# Get the current selected USD Prims in Houdini /stage
# and find the relevant Houdini Material or Shader editor nodes
lop_network: hou.LopNetwork = hou.node("/stage")
stage = lop_network.viewerNode().stage()
for path in lop_network.selection():
prim = stage.GetPrimAtPath(path)
node = get_houdini_node_from_usd_shader(prim)
if node:
print(path, node.path())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment