diff --git a/openpype/hosts/fusion/plugins/load/load_usd.py b/openpype/hosts/fusion/plugins/load/load_usd.py new file mode 100644 index 0000000000..4f1813a646 --- /dev/null +++ b/openpype/hosts/fusion/plugins/load/load_usd.py @@ -0,0 +1,87 @@ +from openpype.pipeline import ( + load, + get_representation_path, +) +from openpype.hosts.fusion.api import ( + imprint_container, + get_current_comp, + comp_lock_and_undo_chunk +) +from openpype.hosts.fusion.api.lib import get_fusion_module + + +class FusionLoadUSD(load.LoaderPlugin): + """Load USD into Fusion + + Support for USD was added since Fusion 18.5 + """ + + families = ["*"] + representations = ["*"] + extensions = {"usd", "usda", "usdz"} + + label = "Load USD" + order = -10 + icon = "code-fork" + color = "orange" + + tool_type = "uLoader" + + @classmethod + def apply_settings(cls, project_settings, system_settings): + super(FusionLoadUSD, cls).apply_settings(project_settings, + system_settings) + if cls.enabled: + # Enable only in Fusion 18.5+ + fusion = get_fusion_module() + version = fusion.GetVersion() + major = version[1] + minor = version[2] + is_usd_supported = (major, minor) >= (18, 5) + cls.enabled = is_usd_supported + + def load(self, context, name, namespace, data): + # Fallback to asset name when namespace is None + if namespace is None: + namespace = context['asset']['name'] + + # Create the Loader with the filename path set + comp = get_current_comp() + with comp_lock_and_undo_chunk(comp, "Create tool"): + + path = self.fname + + args = (-32768, -32768) + tool = comp.AddTool(self.tool_type, *args) + tool["Filename"] = path + + imprint_container(tool, + name=name, + namespace=namespace, + context=context, + loader=self.__class__.__name__) + + def switch(self, container, representation): + self.update(container, representation) + + def update(self, container, representation): + + tool = container["_tool"] + assert tool.ID == self.tool_type, f"Must be {self.tool_type}" + comp = tool.Comp() + + path = get_representation_path(representation) + + with comp_lock_and_undo_chunk(comp, "Update tool"): + tool["Filename"] = path + + # Update the imprinted representation + tool.SetData("avalon.representation", str(representation["_id"])) + + def remove(self, container): + tool = container["_tool"] + assert tool.ID == self.tool_type, f"Must be {self.tool_type}" + comp = tool.Comp() + + with comp_lock_and_undo_chunk(comp, "Remove tool"): + tool.Delete() diff --git a/openpype/lib/attribute_definitions.py b/openpype/lib/attribute_definitions.py index a71d6cc72a..3dd284b8e4 100644 --- a/openpype/lib/attribute_definitions.py +++ b/openpype/lib/attribute_definitions.py @@ -237,8 +237,13 @@ class UISeparatorDef(UIDef): class UILabelDef(UIDef): type = "label" - def __init__(self, label): - super(UILabelDef, self).__init__(label=label) + def __init__(self, label, key=None): + super(UILabelDef, self).__init__(label=label, key=key) + + def __eq__(self, other): + if not super(UILabelDef, self).__eq__(other): + return False + return self.label == other.label # --------------------------------------- diff --git a/openpype/plugins/publish/collect_rendered_files.py b/openpype/plugins/publish/collect_rendered_files.py index 8a5a5a83f1..a249b3acda 100644 --- a/openpype/plugins/publish/collect_rendered_files.py +++ b/openpype/plugins/publish/collect_rendered_files.py @@ -56,6 +56,17 @@ class CollectRenderedFiles(pyblish.api.ContextPlugin): data_object["stagingDir"] = anatomy.fill_root(staging_dir) def _process_path(self, data, anatomy): + """Process data of a single JSON publish metadata file. + + Args: + data: The loaded metadata from the JSON file + anatomy: Anatomy for the current context + + Returns: + bool: Whether any instance of this particular metadata file + has a persistent staging dir. + + """ # validate basic necessary data data_err = "invalid json file - missing data" required = ["asset", "user", "comment", @@ -89,6 +100,7 @@ class CollectRenderedFiles(pyblish.api.ContextPlugin): os.environ["FTRACK_SERVER"] = ftrack["FTRACK_SERVER"] # now we can just add instances from json file and we are done + any_staging_dir_persistent = False for instance_data in data.get("instances"): self.log.debug(" - processing instance for {}".format( @@ -106,6 +118,9 @@ class CollectRenderedFiles(pyblish.api.ContextPlugin): staging_dir_persistent = instance.data.get( "stagingDir_persistent", False ) + if staging_dir_persistent: + any_staging_dir_persistent = True + representations = [] for repre_data in instance_data.get("representations") or []: self._fill_staging_dir(repre_data, anatomy) @@ -127,7 +142,7 @@ class CollectRenderedFiles(pyblish.api.ContextPlugin): self.log.debug( f"Adding audio to instance: {instance.data['audio']}") - return staging_dir_persistent + return any_staging_dir_persistent def process(self, context): self._context = context