From 2f5373782353203102067b07be626ae664297b25 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 27 Aug 2024 23:47:42 +0200 Subject: [PATCH 1/5] Remap usd layer save paths to AYON Entity URIs --- .../plugins/publish/extract_usd.py | 68 +++++++++++++++++-- server/settings/publish.py | 28 +++++++- 2 files changed, 88 insertions(+), 8 deletions(-) diff --git a/client/ayon_houdini/plugins/publish/extract_usd.py b/client/ayon_houdini/plugins/publish/extract_usd.py index e8e7d6a583..484df220c8 100644 --- a/client/ayon_houdini/plugins/publish/extract_usd.py +++ b/client/ayon_houdini/plugins/publish/extract_usd.py @@ -3,20 +3,26 @@ import pyblish.api +from ayon_core.lib import BoolDef +from ayon_core.pipeline import AYONPyblishPluginMixin from ayon_core.pipeline.publish.lib import get_instance_expected_output_path from ayon_houdini.api import plugin from ayon_houdini.api.lib import render_rop from ayon_houdini.api.usd import remap_paths +from ayon_core.pipeline.entity_uri import construct_ayon_entity_uri import hou -class ExtractUSD(plugin.HoudiniExtractorPlugin): +class ExtractUSD(plugin.HoudiniExtractorPlugin, AYONPyblishPluginMixin): order = pyblish.api.ExtractorOrder label = "Extract USD" families = ["usdrop"] + use_ayon_entity_uri = False + use_ayon_entity_uri_optional = True + def process(self, instance): ropnode = hou.node(instance.data.get("instance_node")) @@ -29,7 +35,11 @@ def process(self, instance): self.log.info("Writing USD '%s' to '%s'" % (file_name, staging_dir)) - mapping = self.get_source_to_publish_paths(instance.context) + attr_values = self.get_attr_values_from_data(instance.data) + use_ayon_entity_uri: bool = attr_values.get( + "use_ayon_entity_uri", self.use_ayon_entity_uri) + mapping = self.get_source_to_publish_paths( + instance.context, use_ayon_entity_uri) # Allow instance-specific path remapping overrides, e.g. changing # paths on used resources/textures for looks @@ -55,10 +65,22 @@ def process(self, instance): } instance.data["representations"].append(representation) - def get_source_to_publish_paths(self, context): + def get_source_to_publish_paths(self, + context, + use_ayon_entity_uri): """Define a mapping of all current instances in context from source file to publish file so this can be used on the USD save to remap - asset layer paths on publish via AyonRemapPaths output processor""" + asset layer paths on publish via AyonRemapPaths output processor + + Arguments: + context (pyblish.api.Context): Publish context. + use_ayon_entity_uri (bool): Whether to remap to AYON Entity URI + or to a resolved publish filepath. + + Returns: + dict[str, str]: Mapping from source path to remapped path. + + """ mapping = {} for instance in context: @@ -76,15 +98,47 @@ def get_source_to_publish_paths(self, context): # asset paths that are set use e.g. $F # TODO: If the representation has multiple files we might need # to define the path remapping per file of the sequence - path = get_instance_expected_output_path( - instance, representation_name=name, ext=ext - ) + if use_ayon_entity_uri: + # Construct AYON entity URI + # Note: entity does not exist yet + path = construct_ayon_entity_uri( + project_name=context.data["projectName"], + folder_path=instance.data["folderPath"], + product=instance.data["productName"], + version=instance.data["version"], + representation_name=name + ) + else: + # Resolved publish filepath + path = get_instance_expected_output_path( + instance, representation_name=name, ext=ext + ) + for source_path in get_source_paths(instance, repre): source_path = os.path.normpath(source_path) mapping[source_path] = path return mapping + @classmethod + def get_attribute_defs(cls): + + attributes = [] + if cls.use_ayon_entity_uri_optional: + attributes.append( + BoolDef( + "use_ayon_entity_uri", + label="Use AYON Entity URI", + tooltip=( + "Remap explicit save layers to AYON Entity URI on " + "publish instead of the resolved publish filepaths." + ), + default=cls.use_ayon_entity_uri + ) + ) + + return attributes + def get_source_paths( instance: pyblish.api.Instance, diff --git a/server/settings/publish.py b/server/settings/publish.py index b21de39e93..38c04b4863 100644 --- a/server/settings/publish.py +++ b/server/settings/publish.py @@ -97,6 +97,25 @@ class BasicEnabledStatesModel(BaseSettingsModel): active: bool = SettingsField(title="Active") +class ExtractUsdModel(BaseSettingsModel): + use_ayon_entity_uri: bool = SettingsField( + False, + title="Remap save layers to AYON Entity URI", + description=( + "Remap explicit save layers to AYON Entity URI on publish " + "instead of the resolved publish filepaths." + ) + ) + use_ayon_entity_uri_optional: bool = SettingsField( + True, + title="Make remap save layers to AYON Entity URI optional", + description=( + "When optional a toggle for 'Use AYON Entity URI' will be " + "available for the instance in the publisher UI." + ) + ) + + class PublishPluginsModel(BaseSettingsModel): CollectAssetHandles: CollectAssetHandlesModel = SettingsField( default_factory=CollectAssetHandlesModel, @@ -142,6 +161,10 @@ class PublishPluginsModel(BaseSettingsModel): title="Extract Active View Thumbnail", section="Extractors" ) + ExtractUSD: ExtractUsdModel = SettingsField( + default_factory=ExtractUsdModel, + title="Extract USD" + ) DEFAULT_HOUDINI_PUBLISH_SETTINGS = { @@ -157,7 +180,7 @@ class PublishPluginsModel(BaseSettingsModel): "enabled": False, "optional": True, "active": True, - "families" : [] + "families": [] }, "CollectLocalRenderInstances": { "use_deadline_aov_filter": False, @@ -214,5 +237,8 @@ class PublishPluginsModel(BaseSettingsModel): "enabled": True, "optional": False, "active": True + }, + "ExtractUSD": { + "use_ayon_entity_uri": False } } From abb7ae71644dcb1a6b54b0c4a9d0b2a0eec08bf4 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 27 Aug 2024 23:57:09 +0200 Subject: [PATCH 2/5] Remove per-instance optional state for "Use AYON Entity URI" Due to a limitation of the Publisher UI the attribute definitions for the `usdrop` family won't be shown in the Publisher UI. The Publisher UI only shows attribute definitions for the main primary product type, not for the other "families" on the Created Instance. Because `usd` is the primary product type, and not `usdrop` the attributes would never show. --- .../plugins/publish/extract_usd.py | 39 +++---------------- server/settings/publish.py | 8 ---- 2 files changed, 5 insertions(+), 42 deletions(-) diff --git a/client/ayon_houdini/plugins/publish/extract_usd.py b/client/ayon_houdini/plugins/publish/extract_usd.py index 484df220c8..f797f2db05 100644 --- a/client/ayon_houdini/plugins/publish/extract_usd.py +++ b/client/ayon_houdini/plugins/publish/extract_usd.py @@ -3,8 +3,6 @@ import pyblish.api -from ayon_core.lib import BoolDef -from ayon_core.pipeline import AYONPyblishPluginMixin from ayon_core.pipeline.publish.lib import get_instance_expected_output_path from ayon_houdini.api import plugin from ayon_houdini.api.lib import render_rop @@ -14,14 +12,13 @@ import hou -class ExtractUSD(plugin.HoudiniExtractorPlugin, AYONPyblishPluginMixin): +class ExtractUSD(plugin.HoudiniExtractorPlugin): order = pyblish.api.ExtractorOrder label = "Extract USD" families = ["usdrop"] - use_ayon_entity_uri = False - use_ayon_entity_uri_optional = True + use_ayon_entity_uri = True def process(self, instance): @@ -35,11 +32,7 @@ def process(self, instance): self.log.info("Writing USD '%s' to '%s'" % (file_name, staging_dir)) - attr_values = self.get_attr_values_from_data(instance.data) - use_ayon_entity_uri: bool = attr_values.get( - "use_ayon_entity_uri", self.use_ayon_entity_uri) - mapping = self.get_source_to_publish_paths( - instance.context, use_ayon_entity_uri) + mapping = self.get_source_to_publish_paths(instance.context) # Allow instance-specific path remapping overrides, e.g. changing # paths on used resources/textures for looks @@ -66,16 +59,13 @@ def process(self, instance): instance.data["representations"].append(representation) def get_source_to_publish_paths(self, - context, - use_ayon_entity_uri): + context): """Define a mapping of all current instances in context from source file to publish file so this can be used on the USD save to remap asset layer paths on publish via AyonRemapPaths output processor Arguments: context (pyblish.api.Context): Publish context. - use_ayon_entity_uri (bool): Whether to remap to AYON Entity URI - or to a resolved publish filepath. Returns: dict[str, str]: Mapping from source path to remapped path. @@ -98,7 +88,7 @@ def get_source_to_publish_paths(self, # asset paths that are set use e.g. $F # TODO: If the representation has multiple files we might need # to define the path remapping per file of the sequence - if use_ayon_entity_uri: + if self.use_ayon_entity_uri: # Construct AYON entity URI # Note: entity does not exist yet path = construct_ayon_entity_uri( @@ -120,25 +110,6 @@ def get_source_to_publish_paths(self, return mapping - @classmethod - def get_attribute_defs(cls): - - attributes = [] - if cls.use_ayon_entity_uri_optional: - attributes.append( - BoolDef( - "use_ayon_entity_uri", - label="Use AYON Entity URI", - tooltip=( - "Remap explicit save layers to AYON Entity URI on " - "publish instead of the resolved publish filepaths." - ), - default=cls.use_ayon_entity_uri - ) - ) - - return attributes - def get_source_paths( instance: pyblish.api.Instance, diff --git a/server/settings/publish.py b/server/settings/publish.py index 38c04b4863..e69b979994 100644 --- a/server/settings/publish.py +++ b/server/settings/publish.py @@ -106,14 +106,6 @@ class ExtractUsdModel(BaseSettingsModel): "instead of the resolved publish filepaths." ) ) - use_ayon_entity_uri_optional: bool = SettingsField( - True, - title="Make remap save layers to AYON Entity URI optional", - description=( - "When optional a toggle for 'Use AYON Entity URI' will be " - "available for the instance in the publisher UI." - ) - ) class PublishPluginsModel(BaseSettingsModel): From 4d192204886fd15d6d87ac84d4ca04792b187f09 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 27 Aug 2024 23:57:32 +0200 Subject: [PATCH 3/5] Add debug log of what's being remapped, if anything --- client/ayon_houdini/plugins/publish/extract_usd.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/ayon_houdini/plugins/publish/extract_usd.py b/client/ayon_houdini/plugins/publish/extract_usd.py index f797f2db05..82a8df8654 100644 --- a/client/ayon_houdini/plugins/publish/extract_usd.py +++ b/client/ayon_houdini/plugins/publish/extract_usd.py @@ -33,6 +33,8 @@ def process(self, instance): self.log.info("Writing USD '%s' to '%s'" % (file_name, staging_dir)) mapping = self.get_source_to_publish_paths(instance.context) + if mapping: + self.log.debug(f"Remapping paths: {mapping}") # Allow instance-specific path remapping overrides, e.g. changing # paths on used resources/textures for looks From 1fa7df0bd5af401d5baa444ea5ef1626d7c18cbd Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 27 Aug 2024 23:59:14 +0200 Subject: [PATCH 4/5] Set default to false for backwards compatibility --- client/ayon_houdini/plugins/publish/extract_usd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_houdini/plugins/publish/extract_usd.py b/client/ayon_houdini/plugins/publish/extract_usd.py index 82a8df8654..7c97700255 100644 --- a/client/ayon_houdini/plugins/publish/extract_usd.py +++ b/client/ayon_houdini/plugins/publish/extract_usd.py @@ -18,7 +18,7 @@ class ExtractUSD(plugin.HoudiniExtractorPlugin): label = "Extract USD" families = ["usdrop"] - use_ayon_entity_uri = True + use_ayon_entity_uri = False def process(self, instance): From e1ef4926dddada171a131a1337048aee5daf4d66 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 28 Aug 2024 00:18:49 +0200 Subject: [PATCH 5/5] Cosmetics --- client/ayon_houdini/plugins/publish/extract_usd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/ayon_houdini/plugins/publish/extract_usd.py b/client/ayon_houdini/plugins/publish/extract_usd.py index 7c97700255..9a8c755926 100644 --- a/client/ayon_houdini/plugins/publish/extract_usd.py +++ b/client/ayon_houdini/plugins/publish/extract_usd.py @@ -3,11 +3,11 @@ import pyblish.api +from ayon_core.pipeline.entity_uri import construct_ayon_entity_uri from ayon_core.pipeline.publish.lib import get_instance_expected_output_path from ayon_houdini.api import plugin from ayon_houdini.api.lib import render_rop from ayon_houdini.api.usd import remap_paths -from ayon_core.pipeline.entity_uri import construct_ayon_entity_uri import hou