Merge pull request #4834 from BigRoy/enhancement/houdini_create_node_tab_with_nulls

This commit is contained in:
Ondřej Samohel 2023-05-03 14:10:47 +02:00 committed by GitHub
commit 2636c668f9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 121 additions and 12 deletions

View file

@ -12,26 +12,43 @@ import tempfile
import logging
import os
from openpype.client import get_asset_by_name
from openpype.pipeline import registered_host
from openpype.pipeline.create import CreateContext
from openpype.resources import get_openpype_icon_filepath
import hou
import stateutils
import soptoolutils
import loptoolutils
import cop2toolutils
log = logging.getLogger(__name__)
CATEGORY_GENERIC_TOOL = {
hou.sopNodeTypeCategory(): soptoolutils.genericTool,
hou.cop2NodeTypeCategory(): cop2toolutils.genericTool,
hou.lopNodeTypeCategory(): loptoolutils.genericTool
}
CREATE_SCRIPT = """
from openpype.hosts.houdini.api.creator_node_shelves import create_interactive
create_interactive("{identifier}")
create_interactive("{identifier}", **kwargs)
"""
def create_interactive(creator_identifier):
def create_interactive(creator_identifier, **kwargs):
"""Create a Creator using its identifier interactively.
This is used by the generated shelf tools as callback when a user selects
the creator from the node tab search menu.
The `kwargs` should be what Houdini passes to the tool create scripts
context. For more information see:
https://www.sidefx.com/docs/houdini/hom/tool_script.html#arguments
Args:
creator_identifier (str): The creator identifier of the Creator plugin
to create.
@ -58,6 +75,33 @@ def create_interactive(creator_identifier):
host = registered_host()
context = CreateContext(host)
creator = context.manual_creators.get(creator_identifier)
if not creator:
raise RuntimeError("Invalid creator identifier: "
"{}".format(creator_identifier))
# TODO: Once more elaborate unique create behavior should exist per Creator
# instead of per network editor area then we should move this from here
# to a method on the Creators for which this could be the default
# implementation.
pane = stateutils.activePane(kwargs)
if isinstance(pane, hou.NetworkEditor):
pwd = pane.pwd()
subset_name = creator.get_subset_name(
variant=variant,
task_name=context.get_current_task_name(),
asset_doc=get_asset_by_name(
project_name=context.get_current_project_name(),
asset_name=context.get_current_asset_name()
),
project_name=context.get_current_project_name(),
host_name=context.host_name
)
tool_fn = CATEGORY_GENERIC_TOOL.get(pwd.childTypeCategory())
if tool_fn is not None:
out_null = tool_fn(kwargs, "null")
out_null.setName("OUT_{}".format(subset_name), unique_name=True)
before = context.instances_by_id.copy()
@ -135,12 +179,20 @@ def install():
log.debug("Writing OpenPype Creator nodes to shelf: {}".format(filepath))
tools = []
with shelves_change_block():
for identifier, creator in create_context.manual_creators.items():
# TODO: Allow the creator plug-in itself to override the categories
# for where they are shown, by e.g. defining
# `Creator.get_network_categories()`
# Allow the creator plug-in itself to override the categories
# for where they are shown with `Creator.get_network_categories()`
if not hasattr(creator, "get_network_categories"):
log.debug("Creator {} has no `get_network_categories` method "
"and will not be added to TAB search.")
continue
network_categories = creator.get_network_categories()
if not network_categories:
continue
key = "openpype_create.{}".format(identifier)
log.debug(f"Registering {key}")
@ -153,17 +205,13 @@ def install():
creator.label
),
"help_url": None,
"network_categories": [
hou.ropNodeTypeCategory(),
hou.sopNodeTypeCategory()
],
"network_categories": network_categories,
"viewer_categories": [],
"cop_viewer_categories": [],
"network_op_type": None,
"viewer_op_type": None,
"locations": ["OpenPype"]
}
label = "Create {}".format(creator.label)
tool = hou.shelves.tool(key)
if tool:

View file

@ -276,3 +276,19 @@ class HoudiniCreator(NewCreator, HoudiniCreatorBase):
color = hou.Color((0.616, 0.871, 0.769))
node.setUserData('nodeshape', shape)
node.setColor(color)
def get_network_categories(self):
"""Return in which network view type this creator should show.
The node type categories returned here will be used to define where
the creator will show up in the TAB search for nodes in Houdini's
Network View.
This can be overridden in inherited classes to define where that
particular Creator should be visible in the TAB search.
Returns:
list: List of houdini node type categories
"""
return [hou.ropNodeTypeCategory()]

View file

@ -3,6 +3,8 @@
from openpype.hosts.houdini.api import plugin
from openpype.pipeline import CreatedInstance, CreatorError
import hou
class CreateAlembicCamera(plugin.HoudiniCreator):
"""Single baked camera from Alembic ROP."""
@ -47,3 +49,9 @@ class CreateAlembicCamera(plugin.HoudiniCreator):
self.lock_parameters(instance_node, to_lock)
instance_node.parm("trange").set(1)
def get_network_categories(self):
return [
hou.ropNodeTypeCategory(),
hou.objNodeTypeCategory()
]

View file

@ -1,7 +1,9 @@
# -*- coding: utf-8 -*-
"""Creator plugin for creating composite sequences."""
from openpype.hosts.houdini.api import plugin
from openpype.pipeline import CreatedInstance
from openpype.pipeline import CreatedInstance, CreatorError
import hou
class CreateCompositeSequence(plugin.HoudiniCreator):
@ -35,8 +37,20 @@ class CreateCompositeSequence(plugin.HoudiniCreator):
"copoutput": filepath
}
if self.selected_nodes:
if len(self.selected_nodes) > 1:
raise CreatorError("More than one item selected.")
path = self.selected_nodes[0].path()
parms["coppath"] = path
instance_node.setParms(parms)
# Lock any parameters in this list
to_lock = ["prim_to_detail_pattern"]
self.lock_parameters(instance_node, to_lock)
def get_network_categories(self):
return [
hou.ropNodeTypeCategory(),
hou.cop2NodeTypeCategory()
]

View file

@ -3,6 +3,8 @@
from openpype.hosts.houdini.api import plugin
from openpype.pipeline import CreatedInstance
import hou
class CreatePointCache(plugin.HoudiniCreator):
"""Alembic ROP to pointcache"""
@ -49,3 +51,9 @@ class CreatePointCache(plugin.HoudiniCreator):
# Lock any parameters in this list
to_lock = ["prim_to_detail_pattern"]
self.lock_parameters(instance_node, to_lock)
def get_network_categories(self):
return [
hou.ropNodeTypeCategory(),
hou.sopNodeTypeCategory()
]

View file

@ -3,6 +3,8 @@
from openpype.hosts.houdini.api import plugin
from openpype.pipeline import CreatedInstance
import hou
class CreateUSD(plugin.HoudiniCreator):
"""Universal Scene Description"""
@ -13,7 +15,6 @@ class CreateUSD(plugin.HoudiniCreator):
enabled = False
def create(self, subset_name, instance_data, pre_create_data):
import hou # noqa
instance_data.pop("active", None)
instance_data.update({"node_type": "usd"})
@ -43,3 +44,9 @@ class CreateUSD(plugin.HoudiniCreator):
"id",
]
self.lock_parameters(instance_node, to_lock)
def get_network_categories(self):
return [
hou.ropNodeTypeCategory(),
hou.lopNodeTypeCategory()
]

View file

@ -3,6 +3,8 @@
from openpype.hosts.houdini.api import plugin
from openpype.pipeline import CreatedInstance
import hou
class CreateVDBCache(plugin.HoudiniCreator):
"""OpenVDB from Geometry ROP"""
@ -34,3 +36,9 @@ class CreateVDBCache(plugin.HoudiniCreator):
parms["soppath"] = self.selected_nodes[0].path()
instance_node.setParms(parms)
def get_network_categories(self):
return [
hou.ropNodeTypeCategory(),
hou.sopNodeTypeCategory()
]