Created
February 23, 2024 15:16
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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