Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Houdini: Publish any ROP node (Generic Creator) #542

Closed
Closed
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
c199564
Fix workfile path validation for certain nodes that come with express…
BigRoy May 20, 2024
3dae818
Include staging dir with the frames to be published
BigRoy May 20, 2024
24dfc22
Add Dynamic (in-memory) runtime creator for Houdini + add Generic ROP…
BigRoy May 20, 2024
17d42f8
Preserve `dynamic` family for publishing logic
BigRoy May 20, 2024
dcd7d11
Remove unused logic
BigRoy May 20, 2024
2d178ad
Allow passing `representations` in instance data from Create Context …
BigRoy May 20, 2024
5bcc8d7
Fix publish representation data
BigRoy May 22, 2024
078499d
Merge branch 'develop' into enhancement/houdini_generic_publish
MustafaJafar May 23, 2024
4eba35a
add 'Make AYON Publishable' to OPMenu
MustafaJafar May 23, 2024
7aa80fb
add 'generic' family to collect farm instances and skip render if loc…
MustafaJafar May 23, 2024
1f31d21
Merge pull request #5 from ynput/enhancement/houdini_generic_publish_…
BigRoy Jun 3, 2024
9bf2284
Merge pull request #4 from ynput/enhancement/houdini_generic_publish_…
BigRoy Jun 3, 2024
350afbe
Merge branch 'develop' of https://github.com/ynput/ayon-core into enh…
BigRoy Jun 3, 2024
e301f8b
Refactor `ayon_core.hosts.houdini` usage in HDA to `ayon_houdini`
BigRoy Jun 3, 2024
2b86cf8
Merge branch 'develop' of https://github.com/ynput/ayon-core into enh…
BigRoy Jun 21, 2024
6869b49
Add todo
BigRoy Jun 21, 2024
97d66a8
Docstring + cosmetics
BigRoy Jun 21, 2024
2d81756
Fix certain parms only getting generated on first save.
BigRoy Jun 21, 2024
8c9afe0
Add todo
BigRoy Jun 21, 2024
f9e0d15
Merge branch 'develop' of https://github.com/ynput/ayon-core into enh…
BigRoy Jun 21, 2024
e49be70
Set variant parm default to `$OS` (node name)
BigRoy Jun 21, 2024
15d1f68
Do not show the generic creator in the tab menus
BigRoy Jun 21, 2024
981e2ea
Support `LabsKarma` node out of the box
BigRoy Jun 21, 2024
4c7a201
Draft: Automatically make nodes publishable on creation
BigRoy Jun 21, 2024
cb74f1e
Support auto create without breaking the older creators
BigRoy Jun 24, 2024
82b8eb1
Merge branch 'develop' of https://github.com/ynput/ayon-core into enh…
BigRoy Jun 24, 2024
afde2a8
Add "usdrender_rop"
BigRoy Jun 24, 2024
d1d2ca5
Remove implemented todo
BigRoy Jun 24, 2024
9f1eca7
Prepare for node type products to be defined from settings
BigRoy Jun 24, 2024
037c64f
Move the node type defaults to Creator in preparation of move to sett…
BigRoy Jun 24, 2024
2a76da8
Fix karma labs parm
BigRoy Jun 24, 2024
bfaf156
Remove simple runtime instance creator to separate for another PR
BigRoy Jun 24, 2024
cbd3d53
Remove logic related to simple runtime instance creator to separate f…
BigRoy Jun 24, 2024
c0d6829
Cleanup
BigRoy Jun 24, 2024
33bc530
Implement more product types
BigRoy Jun 24, 2024
fe2de0c
Draft: Take the list from the Creator directly for now
BigRoy Jun 24, 2024
71b20e0
Cosmetics
BigRoy Jun 24, 2024
0125413
Support many more node types for `get_output_parameter`, also see #692
BigRoy Jun 24, 2024
16b6122
Merge branch 'develop' of https://github.com/ynput/ayon-core into enh…
BigRoy Jun 25, 2024
6cb8b5d
Only create on RopNode type
BigRoy Jun 25, 2024
f689cee
Fix import
BigRoy Jun 25, 2024
939ee37
Fix using node name by default with `$OS` from publisher UI
BigRoy Jun 25, 2024
0579901
Update server_addon/houdini/client/ayon_houdini/plugins/create/create…
BigRoy Jun 25, 2024
3e4c2a1
Merge branch 'develop' of https://github.com/ynput/ayon-core into enh…
BigRoy Jun 26, 2024
47658e6
Add more issues as todo
BigRoy Jun 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def create_instance(
"productType": in_data["productType"],
"family": in_data["productType"],
"families": instance_families,
"representations": [],
"representations": in_data.get("representations", []),
"thumbnailSource": thumbnail_path
})
for key, value in in_data.items():
Expand Down
15 changes: 15 additions & 0 deletions server_addon/houdini/client/ayon_houdini/api/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ def get_output_parameter(node):
return node.parm("outputimage")
elif node_type == "vray_renderer":
return node.parm("SettingsOutput_img_file_path")
elif node_type == "labs::karma::2.0":
return node.parm("file")

raise TypeError("Node type '%s' not supported" % node_type)

Expand Down Expand Up @@ -1193,3 +1195,16 @@ def prompt_reset_context():
update_content_on_context_change()

dialog.deleteLater()


@contextmanager
def no_auto_create_publishable():
value = os.environ.get("AYON_HOUDINI_AUTOCREATE")
os.environ["AYON_HOUDINI_AUTOCREATE"] = "0"
try:
yield
finally:
if value is None:
del os.environ["AYON_HOUDINI_AUTOCREATE"]
else:
os.environ["AYON_HOUDINI_AUTOCREATE"] = value
13 changes: 10 additions & 3 deletions server_addon/houdini/client/ayon_houdini/api/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,13 @@
)
from ayon_core.lib import BoolDef

from .lib import imprint, read, lsattr, add_self_publish_button
from .lib import (
imprint,
read,
lsattr,
add_self_publish_button,
no_auto_create_publishable
)


SETTINGS_CATEGORY = "houdini"
Expand Down Expand Up @@ -192,8 +198,9 @@ def create(self, product_name, instance_data, pre_create_data):

folder_path = instance_data["folderPath"]

instance_node = self.create_instance_node(
folder_path, product_name, "/out", node_type)
with no_auto_create_publishable():
instance_node = self.create_instance_node(
folder_path, product_name, "/out", node_type)

self.customize_node_look(instance_node)

Expand Down
BigRoy marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import os

from ayon_core.pipeline.create import (
Creator,
CreatedInstance,
get_product_name
)
from ayon_api import get_folder_by_path, get_task_by_name


def create_representation_data(files):
"""Create representation data needed for `instance.data['representations']"""
first_file = files[0]
folder, filename = os.path.split(first_file)

# Files should be filename only in representation
files = [os.path.basename(filepath) for filepath in files]

ext = os.path.splitext(filename)[-1].strip(".")
return {
"name": ext,
"ext": ext,
"files": files if len(files) > 1 else first_file,
"stagingDir": folder,
}


class CreateRuntimeInstance(Creator):
"""Create in-memory instances for dynamic PDG publishing of files.

These instances do not persist and are meant for headless automated
publishing. The created instances are transient and will be gone on
resetting the `CreateContext` since they will not be recollected.

TODO: The goal is for this runtime instance to be so generic that it can
run anywhere, globally - and needs no knowledge about its host. It's
the simplest 'entry point' to ingesting something from anywhere.

"""
# TODO: This should be a global HIDDEN creator instead!
# TODO: This should eventually not have a Houdini specific identifier
identifier = "io.openpype.creators.houdini.batch"
label = "Ingest"
product_type = "dynamic" # not actually used
icon = "gears"

def create(self, product_name, instance_data, pre_create_data):

# Unfortunately the Create Context will provide the product name
# even before the `create` call without listening to pre create data
# or the instance data - so instead we ignore the product name here
# and redefine it ourselves based on the `variant` in instance data
product_type = pre_create_data.get("product_type") or instance_data["product_type"]
project_name = self.create_context.project_name
folder_entity = get_folder_by_path(project_name,
instance_data["folderPath"])
task_entity = get_task_by_name(project_name,
folder_id=folder_entity["id"],
task_name=instance_data["task"])
product_name = self._get_product_name_dynamic(
self.create_context.project_name,
folder_entity=folder_entity,
task_entity=task_entity,
variant=instance_data["variant"],
product_type=product_type
)

custom_instance_data = pre_create_data.get("instance_data")
if custom_instance_data:
instance_data.update(custom_instance_data)

# TODO: Add support for multiple representations
files = pre_create_data["files"]
representations = [create_representation_data(files)]
instance_data["representations"] = representations
instance_data["families"] = ["dynamic"]

# We ingest it as a different product type then the creator's generic
# ingest product type. For example, we specify `pointcache`
instance = CreatedInstance(
product_type=product_type,
product_name=product_name,
data=instance_data,
creator=self
)
self._add_instance_to_context(instance)

return instance

# Instances are all dynamic at run-time and cannot be persisted or
# re-collected
def collect_instances(self):
pass

def update_instances(self, update_list):
pass

def remove_instances(self, instances):
for instance in instances:
self._remove_instance_from_context(instance)

def _get_product_name_dynamic(
self,
project_name,
folder_entity,
task_entity,
variant,
product_type,
host_name=None,
instance=None
):
"""Implementation similar to `self.get_product_name` but taking
`productType` as argument instead of using the 'generic' product type
on the Creator itself."""
if host_name is None:
host_name = self.create_context.host_name

task_name = task_type = None
if task_entity:
task_name = task_entity["name"]
task_type = task_entity["taskType"]

dynamic_data = self.get_dynamic_data(
project_name,
folder_entity,
task_entity,
variant,
host_name,
instance
)

return get_product_name(
project_name,
task_name,
task_type,
host_name,
product_type,
variant,
dynamic_data=dynamic_data,
project_settings=self.project_settings
)
Loading
Loading