From 494e662582011ab5e62fc5e814d48a62ef3747f0 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 13 Jul 2023 15:13:53 +0800 Subject: [PATCH 001/154] add optional viewport camera validator for validation of renderable camera --- .../publish/validate_no_max_content.py | 1 - .../publish/validate_viewport_camera.py | 43 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 openpype/hosts/max/plugins/publish/validate_viewport_camera.py diff --git a/openpype/hosts/max/plugins/publish/validate_no_max_content.py b/openpype/hosts/max/plugins/publish/validate_no_max_content.py index c6a27dace3..73e12e75c9 100644 --- a/openpype/hosts/max/plugins/publish/validate_no_max_content.py +++ b/openpype/hosts/max/plugins/publish/validate_no_max_content.py @@ -13,7 +13,6 @@ class ValidateMaxContents(pyblish.api.InstancePlugin): order = pyblish.api.ValidatorOrder families = ["camera", "maxScene", - "maxrender", "review"] hosts = ["max"] label = "Max Scene Contents" diff --git a/openpype/hosts/max/plugins/publish/validate_viewport_camera.py b/openpype/hosts/max/plugins/publish/validate_viewport_camera.py new file mode 100644 index 0000000000..a52b7e0212 --- /dev/null +++ b/openpype/hosts/max/plugins/publish/validate_viewport_camera.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +import pyblish.api +from openpype.pipeline import ( + PublishValidationError, + OptionalPyblishPluginMixin) +from openpype.pipeline.publish import RepairAction + +from pymxs import runtime as rt + + +class ValidateViewportCamera(pyblish.api.InstancePlugin, + OptionalPyblishPluginMixin): + """Validates Viewport Camera + + Check if the renderable camera in scene used as viewport + camera for rendering + """ + + order = pyblish.api.ValidatorOrder + families = ["maxrender"] + hosts = ["max"] + label = "Viewport Camera" + optional = True + actions = [RepairAction] + + def process(self, instance): + if not self.is_active(instance.data): + return + cameras_in_scene = [c for c in rt.Objects + if rt.classOf(c) in rt.Camera.Classes] + if rt.viewport.getCamera() not in cameras_in_scene: + raise PublishValidationError( + "Cameras in Scene not used as viewport camera" + ) + + @classmethod + def repair(cls, instance): + # Get all cameras in the scene + cameras_in_scene = [c for c in rt.Objects + if rt.classOf(c) in rt.Camera.Classes] + # Set the first camera as viewport camera for rendering + if cameras_in_scene: + rt.viewport.setCamera(cameras_in_scene[0]) \ No newline at end of file From ceaffbbfa92f50d2da009b3be30c5df94d015eed Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 13 Jul 2023 15:26:32 +0800 Subject: [PATCH 002/154] add log for repair action --- .../hosts/max/plugins/publish/validate_viewport_camera.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/max/plugins/publish/validate_viewport_camera.py b/openpype/hosts/max/plugins/publish/validate_viewport_camera.py index a52b7e0212..d5cf85eb69 100644 --- a/openpype/hosts/max/plugins/publish/validate_viewport_camera.py +++ b/openpype/hosts/max/plugins/publish/validate_viewport_camera.py @@ -36,8 +36,10 @@ class ValidateViewportCamera(pyblish.api.InstancePlugin, @classmethod def repair(cls, instance): # Get all cameras in the scene - cameras_in_scene = [c for c in rt.Objects + cameras_in_scene = [c.name for c in rt.Objects if rt.classOf(c) in rt.Camera.Classes] # Set the first camera as viewport camera for rendering if cameras_in_scene: - rt.viewport.setCamera(cameras_in_scene[0]) \ No newline at end of file + camera = rt.getNodeByName(cameras_in_scene[0]) + rt.viewport.setCamera(camera) + cls.log.info(f"Camera {camera} set as viewport camera") From 1a6e7aa041cfdaffbae58ddfada7e03c753b89b5 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 1 Aug 2023 22:05:16 +0800 Subject: [PATCH 003/154] adding OpenpypeData parameter as custom attributes back to the loaded objects --- openpype/hosts/max/api/pipeline.py | 25 ++++++++++++++++++ .../hosts/max/plugins/load/load_camera_fbx.py | 26 ++++++++----------- .../hosts/max/plugins/load/load_max_scene.py | 16 +++++++----- openpype/hosts/max/plugins/load/load_model.py | 18 +++++++++---- .../hosts/max/plugins/load/load_model_fbx.py | 9 ++++--- .../hosts/max/plugins/load/load_model_obj.py | 12 +++++---- .../hosts/max/plugins/load/load_model_usd.py | 11 +++++--- .../hosts/max/plugins/load/load_pointcache.py | 15 ++++++++--- .../hosts/max/plugins/load/load_pointcloud.py | 15 ++++++----- .../max/plugins/load/load_redshift_proxy.py | 5 ++-- 10 files changed, 101 insertions(+), 51 deletions(-) diff --git a/openpype/hosts/max/api/pipeline.py b/openpype/hosts/max/api/pipeline.py index 03b85a4066..82470dd510 100644 --- a/openpype/hosts/max/api/pipeline.py +++ b/openpype/hosts/max/api/pipeline.py @@ -15,8 +15,10 @@ from openpype.pipeline import ( ) from openpype.hosts.max.api.menu import OpenPypeMenu from openpype.hosts.max.api import lib +from openpype.hosts.max.api.plugin import MS_CUSTOM_ATTRIB from openpype.hosts.max import MAX_HOST_DIR + from pymxs import runtime as rt # noqa log = logging.getLogger("openpype.hosts.max") @@ -170,3 +172,26 @@ def containerise(name: str, nodes: list, context, loader=None, suffix="_CON"): if not lib.imprint(container_name, data): print(f"imprinting of {container_name} failed.") return container + + +def load_OpenpypeData(container, loaded_nodes): + """Function to load the OpenpypeData Parameter along with + the published objects + + Args: + container (str): target container to set up + the custom attributes + loaded_nodes (list): list of nodes to be loaded + """ + attrs = rt.Execute(MS_CUSTOM_ATTRIB) + if rt.custAttributes.get(container.baseObject, attrs): + rt.custAttributes.delete(container.baseObject, attrs) + rt.custAttributes.add(container.baseObject, attrs) + node_list = [] + for i in loaded_nodes: + node_ref = rt.NodeTransformMonitor(node=i) + node_list.append(node_ref) + + # Setting the property + rt.setProperty( + container.openPypeData, "all_handles", node_list) diff --git a/openpype/hosts/max/plugins/load/load_camera_fbx.py b/openpype/hosts/max/plugins/load/load_camera_fbx.py index 62284b23d9..6b16bfe474 100644 --- a/openpype/hosts/max/plugins/load/load_camera_fbx.py +++ b/openpype/hosts/max/plugins/load/load_camera_fbx.py @@ -1,7 +1,7 @@ import os from openpype.hosts.max.api import lib, maintained_selection -from openpype.hosts.max.api.pipeline import containerise +from openpype.hosts.max.api.pipeline import containerise, load_OpenpypeData from openpype.pipeline import get_representation_path, load @@ -32,8 +32,9 @@ class FbxLoader(load.LoaderPlugin): if not container: container = rt.Container() container.name = f"{name}" - - for selection in rt.GetCurrentSelection(): + selections = rt.GetCurrentSelection() + load_OpenpypeData(container, selections) + for selection in selections: selection.Parent = container return containerise( @@ -45,18 +46,13 @@ class FbxLoader(load.LoaderPlugin): path = get_representation_path(representation) node = rt.GetNodeByName(container["instance_node"]) rt.Select(node.Children) - fbx_reimport_cmd = ( - f""" - -FBXImporterSetParam "Animation" true -FBXImporterSetParam "Cameras" true -FBXImporterSetParam "AxisConversionMethod" true -FbxExporterSetParam "UpAxis" "Y" -FbxExporterSetParam "Preserveinstances" true - -importFile @"{path}" #noPrompt using:FBXIMP - """) - rt.Execute(fbx_reimport_cmd) + rt.FBXImporterSetParam("Animation", True) + rt.FBXImporterSetParam("Camera", True) + rt.FBXImporterSetParam("AxisConversionMethod", True) + rt.FBXImporterSetParam("Preserveinstances", True) + rt.ImportFile( + path, rt.name("noPrompt"), using=rt.FBXIMP) + load_OpenpypeData(node, node.Children) with maintained_selection(): rt.Select(node) diff --git a/openpype/hosts/max/plugins/load/load_max_scene.py b/openpype/hosts/max/plugins/load/load_max_scene.py index 76cd3bf367..468461bc0e 100644 --- a/openpype/hosts/max/plugins/load/load_max_scene.py +++ b/openpype/hosts/max/plugins/load/load_max_scene.py @@ -1,7 +1,8 @@ import os from openpype.hosts.max.api import lib -from openpype.hosts.max.api.pipeline import containerise +from openpype.hosts.max.api.pipeline import containerise, load_OpenpypeData + from openpype.pipeline import get_representation_path, load @@ -27,6 +28,7 @@ class MaxSceneLoader(load.LoaderPlugin): rt.MergeMaxFile(path) max_objects = rt.getLastMergedNodes() max_container = rt.Container(name=f"{name}") + load_OpenpypeData(max_container, max_objects) for max_object in max_objects: max_object.Parent = max_container @@ -39,16 +41,16 @@ class MaxSceneLoader(load.LoaderPlugin): path = get_representation_path(representation) node_name = container["instance_node"] - rt.MergeMaxFile(path, - rt.Name("noRedraw"), - rt.Name("deleteOldDups"), - rt.Name("useSceneMtlDups")) + rt.MergeMaxFile(path) max_objects = rt.getLastMergedNodes() container_node = rt.GetNodeByName(node_name) + instance_name, _ = os.path.splitext(node_name) + instance_container = rt.GetNodeByName(instance_name) for max_object in max_objects: - max_object.Parent = container_node - + max_object.Parent = instance_container + instance_container.Parent = container_node + load_OpenpypeData(container_node, max_objects) lib.imprint(container["instance_node"], { "representation": str(representation["_id"]) }) diff --git a/openpype/hosts/max/plugins/load/load_model.py b/openpype/hosts/max/plugins/load/load_model.py index cff82a593c..810fc65968 100644 --- a/openpype/hosts/max/plugins/load/load_model.py +++ b/openpype/hosts/max/plugins/load/load_model.py @@ -1,6 +1,6 @@ import os from openpype.pipeline import load, get_representation_path -from openpype.hosts.max.api.pipeline import containerise +from openpype.hosts.max.api.pipeline import containerise, load_OpenpypeData from openpype.hosts.max.api import lib from openpype.hosts.max.api.lib import maintained_selection @@ -45,7 +45,10 @@ class ModelAbcLoader(load.LoaderPlugin): self.log.error("Something failed when loading.") abc_container = abc_containers.pop() - + selections = rt.GetCurrentSelection() + abc_selections = [abc for abc in selections + if abc.name != "Alembic"] + load_OpenpypeData(abc_container, abc_selections) return containerise( name, [abc_container], context, loader=self.__class__.__name__ ) @@ -57,6 +60,10 @@ class ModelAbcLoader(load.LoaderPlugin): node = rt.GetNodeByName(container["instance_node"]) rt.Select(node.Children) + nodes_list = [] + with maintained_selection(): + rt.Select(node) + for alembic in rt.Selection: abc = rt.GetNodeByName(alembic.name) rt.Select(abc.Children) @@ -67,9 +74,10 @@ class ModelAbcLoader(load.LoaderPlugin): for abc_obj in rt.Selection: alembic_obj = rt.GetNodeByName(abc_obj.name) alembic_obj.source = path - - with maintained_selection(): - rt.Select(node) + nodes_list.append(alembic_obj) + abc_selections = [abc for abc in nodes_list + if abc.name != "Alembic"] + load_OpenpypeData(node, abc_selections) lib.imprint( container["instance_node"], diff --git a/openpype/hosts/max/plugins/load/load_model_fbx.py b/openpype/hosts/max/plugins/load/load_model_fbx.py index 12f526ab95..8f2b4f4ac3 100644 --- a/openpype/hosts/max/plugins/load/load_model_fbx.py +++ b/openpype/hosts/max/plugins/load/load_model_fbx.py @@ -1,6 +1,6 @@ import os from openpype.pipeline import load, get_representation_path -from openpype.hosts.max.api.pipeline import containerise +from openpype.hosts.max.api.pipeline import containerise, load_OpenpypeData from openpype.hosts.max.api import lib from openpype.hosts.max.api.lib import maintained_selection @@ -28,7 +28,10 @@ class FbxModelLoader(load.LoaderPlugin): container = rt.Container() container.name = name - for selection in rt.GetCurrentSelection(): + selections = rt.GetCurrentSelection() + load_OpenpypeData(container, selections) + + for selection in selections: selection.Parent = container return containerise( @@ -47,7 +50,7 @@ class FbxModelLoader(load.LoaderPlugin): rt.FBXImporterSetParam("UpAxis", "Y") rt.FBXImporterSetParam("Preserveinstances", True) rt.importFile(path, rt.name("noPrompt"), using=rt.FBXIMP) - + load_OpenpypeData(container, node.Children) with maintained_selection(): rt.Select(node) diff --git a/openpype/hosts/max/plugins/load/load_model_obj.py b/openpype/hosts/max/plugins/load/load_model_obj.py index 18a19414fa..83b5ec49b9 100644 --- a/openpype/hosts/max/plugins/load/load_model_obj.py +++ b/openpype/hosts/max/plugins/load/load_model_obj.py @@ -2,7 +2,7 @@ import os from openpype.hosts.max.api import lib from openpype.hosts.max.api.lib import maintained_selection -from openpype.hosts.max.api.pipeline import containerise +from openpype.hosts.max.api.pipeline import containerise, load_OpenpypeData from openpype.pipeline import get_representation_path, load @@ -25,9 +25,10 @@ class ObjLoader(load.LoaderPlugin): # create "missing" container for obj import container = rt.Container() container.name = name - + selections = rt.GetCurrentSelection() + load_OpenpypeData(container, selections) # get current selection - for selection in rt.GetCurrentSelection(): + for selection in selections: selection.Parent = container asset = rt.GetNodeByName(name) @@ -49,9 +50,10 @@ class ObjLoader(load.LoaderPlugin): rt.Execute(f'importFile @"{path}" #noPrompt using:ObjImp') # get current selection - for selection in rt.GetCurrentSelection(): + selections = rt.GetCurrentSelection() + for selection in selections: selection.Parent = container - + load_OpenpypeData(container, container.Children) with maintained_selection(): rt.Select(node) diff --git a/openpype/hosts/max/plugins/load/load_model_usd.py b/openpype/hosts/max/plugins/load/load_model_usd.py index 48b50b9b18..a1961e6d89 100644 --- a/openpype/hosts/max/plugins/load/load_model_usd.py +++ b/openpype/hosts/max/plugins/load/load_model_usd.py @@ -2,7 +2,7 @@ import os from openpype.hosts.max.api import lib from openpype.hosts.max.api.lib import maintained_selection -from openpype.hosts.max.api.pipeline import containerise +from openpype.hosts.max.api.pipeline import containerise, load_OpenpypeData from openpype.pipeline import get_representation_path, load @@ -30,8 +30,10 @@ class ModelUSDLoader(load.LoaderPlugin): rt.LogLevel = rt.Name("info") rt.USDImporter.importFile(filepath, importOptions=import_options) - + selections = rt.GetCurrentSelection() asset = rt.GetNodeByName(name) + mesh_selections = [r for r in selections if r != asset] + load_OpenpypeData(asset, mesh_selections) return containerise( name, [asset], context, loader=self.__class__.__name__) @@ -55,11 +57,12 @@ class ModelUSDLoader(load.LoaderPlugin): rt.LogPath = log_filepath rt.LogLevel = rt.Name("info") - rt.USDImporter.importFile(path, - importOptions=import_options) + rt.USDImporter.importFile( + path, importOptions=import_options) asset = rt.GetNodeByName(instance_name) asset.Parent = node + load_OpenpypeData(asset, asset.Children) with maintained_selection(): rt.Select(node) diff --git a/openpype/hosts/max/plugins/load/load_pointcache.py b/openpype/hosts/max/plugins/load/load_pointcache.py index 290503e053..026938feff 100644 --- a/openpype/hosts/max/plugins/load/load_pointcache.py +++ b/openpype/hosts/max/plugins/load/load_pointcache.py @@ -7,7 +7,7 @@ Because of limited api, alembics can be only loaded, but not easily updated. import os from openpype.pipeline import load, get_representation_path from openpype.hosts.max.api import lib, maintained_selection -from openpype.hosts.max.api.pipeline import containerise +from openpype.hosts.max.api.pipeline import containerise, load_OpenpypeData class AbcLoader(load.LoaderPlugin): @@ -48,11 +48,15 @@ class AbcLoader(load.LoaderPlugin): self.log.error("Something failed when loading.") abc_container = abc_containers.pop() - - for abc in rt.GetCurrentSelection(): + selections = rt.GetCurrentSelection() + abc_selections = [abc for abc in selections + if abc.name != "Alembic"] + load_OpenpypeData(abc_container, abc_selections) + for abc in selections: for cam_shape in abc.Children: cam_shape.playbackType = 2 + return containerise( name, [abc_container], context, loader=self.__class__.__name__ ) @@ -71,7 +75,7 @@ class AbcLoader(load.LoaderPlugin): container["instance_node"], {"representation": str(representation["_id"])}, ) - + nodes_list = [] with maintained_selection(): rt.Select(node.Children) @@ -85,6 +89,9 @@ class AbcLoader(load.LoaderPlugin): for abc_obj in rt.Selection: alembic_obj = rt.GetNodeByName(abc_obj.name) alembic_obj.source = path + nodes_list.append(alembic_obj) + abc_selections = [abc for abc in nodes_list if abc.name != "Alembic"] + load_OpenpypeData(node, abc_selections) def switch(self, container, representation): self.update(container, representation) diff --git a/openpype/hosts/max/plugins/load/load_pointcloud.py b/openpype/hosts/max/plugins/load/load_pointcloud.py index 2a1175167a..18998f4529 100644 --- a/openpype/hosts/max/plugins/load/load_pointcloud.py +++ b/openpype/hosts/max/plugins/load/load_pointcloud.py @@ -1,7 +1,7 @@ import os from openpype.hosts.max.api import lib, maintained_selection -from openpype.hosts.max.api.pipeline import containerise +from openpype.hosts.max.api.pipeline import containerise, load_OpenpypeData from openpype.pipeline import get_representation_path, load @@ -21,8 +21,11 @@ class PointCloudLoader(load.LoaderPlugin): filepath = os.path.normpath(self.filepath_from_context(context)) obj = rt.tyCache() obj.filename = filepath - prt_container = rt.GetNodeByName(obj.name) + prt_container = rt.container() + prt_container.name = name + obj.Parent = prt_container + load_OpenpypeData(prt_container, [obj]) return containerise( name, [prt_container], context, loader=self.__class__.__name__) @@ -38,10 +41,10 @@ class PointCloudLoader(load.LoaderPlugin): for prt in rt.Selection: prt_object = rt.GetNodeByName(prt.name) prt_object.filename = path - - lib.imprint(container["instance_node"], { - "representation": str(representation["_id"]) - }) + load_OpenpypeData(node, node.Children) + lib.imprint(container["instance_node"], { + "representation": str(representation["_id"]) + }) def switch(self, container, representation): self.update(container, representation) diff --git a/openpype/hosts/max/plugins/load/load_redshift_proxy.py b/openpype/hosts/max/plugins/load/load_redshift_proxy.py index 31692f6367..b62400d2e5 100644 --- a/openpype/hosts/max/plugins/load/load_redshift_proxy.py +++ b/openpype/hosts/max/plugins/load/load_redshift_proxy.py @@ -5,7 +5,7 @@ from openpype.pipeline import ( load, get_representation_path ) -from openpype.hosts.max.api.pipeline import containerise +from openpype.hosts.max.api.pipeline import containerise, load_OpenpypeData from openpype.hosts.max.api import lib @@ -33,7 +33,7 @@ class RedshiftProxyLoader(load.LoaderPlugin): container = rt.container() container.name = name rs_proxy.Parent = container - + load_OpenpypeData(container, [rs_proxy]) asset = rt.getNodeByName(name) return containerise( @@ -49,6 +49,7 @@ class RedshiftProxyLoader(load.LoaderPlugin): for proxy in children_node.Children: proxy.file = path + load_OpenpypeData(node, node.Children) lib.imprint(container["instance_node"], { "representation": str(representation["_id"]) }) From 9d1b8c6af9e721ae3703f8b11ce2cb2c3fe3c4f4 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 3 Aug 2023 19:34:36 +0800 Subject: [PATCH 004/154] use alembic object to store the OP parameters --- openpype/hosts/max/plugins/load/load_model.py | 4 +++- openpype/hosts/max/plugins/load/load_pointcache.py | 8 +++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/max/plugins/load/load_model.py b/openpype/hosts/max/plugins/load/load_model.py index 810fc65968..efd758063d 100644 --- a/openpype/hosts/max/plugins/load/load_model.py +++ b/openpype/hosts/max/plugins/load/load_model.py @@ -61,6 +61,7 @@ class ModelAbcLoader(load.LoaderPlugin): rt.Select(node.Children) nodes_list = [] + abc_object = None with maintained_selection(): rt.Select(node) @@ -69,6 +70,7 @@ class ModelAbcLoader(load.LoaderPlugin): rt.Select(abc.Children) for abc_con in rt.Selection: container = rt.GetNodeByName(abc_con.name) + abc_object = container container.source = path rt.Select(container.Children) for abc_obj in rt.Selection: @@ -77,7 +79,7 @@ class ModelAbcLoader(load.LoaderPlugin): nodes_list.append(alembic_obj) abc_selections = [abc for abc in nodes_list if abc.name != "Alembic"] - load_OpenpypeData(node, abc_selections) + load_OpenpypeData(abc_object, abc_selections) lib.imprint( container["instance_node"], diff --git a/openpype/hosts/max/plugins/load/load_pointcache.py b/openpype/hosts/max/plugins/load/load_pointcache.py index 026938feff..7af588566e 100644 --- a/openpype/hosts/max/plugins/load/load_pointcache.py +++ b/openpype/hosts/max/plugins/load/load_pointcache.py @@ -67,15 +67,12 @@ class AbcLoader(load.LoaderPlugin): path = get_representation_path(representation) node = rt.GetNodeByName(container["instance_node"]) - alembic_objects = self.get_container_children(node, "AlembicObject") - for alembic_object in alembic_objects: - alembic_object.source = path - lib.imprint( container["instance_node"], {"representation": str(representation["_id"])}, ) nodes_list = [] + abc_object = None with maintained_selection(): rt.Select(node.Children) @@ -84,6 +81,7 @@ class AbcLoader(load.LoaderPlugin): rt.Select(abc.Children) for abc_con in rt.Selection: container = rt.GetNodeByName(abc_con.name) + abc_object = container container.source = path rt.Select(container.Children) for abc_obj in rt.Selection: @@ -91,7 +89,7 @@ class AbcLoader(load.LoaderPlugin): alembic_obj.source = path nodes_list.append(alembic_obj) abc_selections = [abc for abc in nodes_list if abc.name != "Alembic"] - load_OpenpypeData(node, abc_selections) + load_OpenpypeData(abc_object, abc_selections) def switch(self, container, representation): self.update(container, representation) From 5b68f0cef6fc72b0a7e011e31acfc9bd6b7b2c9d Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 7 Aug 2023 16:32:34 +0800 Subject: [PATCH 005/154] remove loading openpype attributes in load max scene as it is being loaded differently --- openpype/hosts/max/plugins/load/load_max_scene.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/openpype/hosts/max/plugins/load/load_max_scene.py b/openpype/hosts/max/plugins/load/load_max_scene.py index 468461bc0e..f161a19a4c 100644 --- a/openpype/hosts/max/plugins/load/load_max_scene.py +++ b/openpype/hosts/max/plugins/load/load_max_scene.py @@ -1,7 +1,7 @@ import os from openpype.hosts.max.api import lib -from openpype.hosts.max.api.pipeline import containerise, load_OpenpypeData +from openpype.hosts.max.api.pipeline import containerise from openpype.pipeline import get_representation_path, load @@ -28,7 +28,6 @@ class MaxSceneLoader(load.LoaderPlugin): rt.MergeMaxFile(path) max_objects = rt.getLastMergedNodes() max_container = rt.Container(name=f"{name}") - load_OpenpypeData(max_container, max_objects) for max_object in max_objects: max_object.Parent = max_container @@ -50,7 +49,6 @@ class MaxSceneLoader(load.LoaderPlugin): for max_object in max_objects: max_object.Parent = instance_container instance_container.Parent = container_node - load_OpenpypeData(container_node, max_objects) lib.imprint(container["instance_node"], { "representation": str(representation["_id"]) }) From 69f88b33d2ce3a96463105e7e3ff7e4066509bbc Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 7 Aug 2023 18:17:10 +0800 Subject: [PATCH 006/154] rstore max scene code --- openpype/hosts/max/plugins/load/load_max_scene.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/max/plugins/load/load_max_scene.py b/openpype/hosts/max/plugins/load/load_max_scene.py index f161a19a4c..468461bc0e 100644 --- a/openpype/hosts/max/plugins/load/load_max_scene.py +++ b/openpype/hosts/max/plugins/load/load_max_scene.py @@ -1,7 +1,7 @@ import os from openpype.hosts.max.api import lib -from openpype.hosts.max.api.pipeline import containerise +from openpype.hosts.max.api.pipeline import containerise, load_OpenpypeData from openpype.pipeline import get_representation_path, load @@ -28,6 +28,7 @@ class MaxSceneLoader(load.LoaderPlugin): rt.MergeMaxFile(path) max_objects = rt.getLastMergedNodes() max_container = rt.Container(name=f"{name}") + load_OpenpypeData(max_container, max_objects) for max_object in max_objects: max_object.Parent = max_container @@ -49,6 +50,7 @@ class MaxSceneLoader(load.LoaderPlugin): for max_object in max_objects: max_object.Parent = instance_container instance_container.Parent = container_node + load_OpenpypeData(container_node, max_objects) lib.imprint(container["instance_node"], { "representation": str(representation["_id"]) }) From e35c9898af6716703f5d468f3e7490cdc7ddecc9 Mon Sep 17 00:00:00 2001 From: Fabia Serra Arrizabalaga Date: Mon, 7 Aug 2023 19:08:31 +0200 Subject: [PATCH 007/154] Align creator settings to use default_variants instead of defaults --- .../plugins/create/create_arnold_ass.py | 2 +- .../plugins/create/create_arnold_rop.py | 2 +- .../plugins/create/create_karma_rop.py | 2 +- .../plugins/create/create_mantra_rop.py | 2 +- .../plugins/create/create_redshift_rop.py | 2 +- .../houdini/plugins/create/create_vray_rop.py | 2 +- .../defaults/project_settings/houdini.json | 56 ++++- .../defaults/project_settings/maya.json | 47 ++-- .../schemas/schema_houdini_create.json | 206 ++++++++++-------- .../schemas/schema_maya_create.json | 26 ++- .../schemas/schema_maya_create_render.json | 4 +- .../schemas/template_create_plugin.json | 4 +- 12 files changed, 211 insertions(+), 144 deletions(-) diff --git a/openpype/hosts/houdini/plugins/create/create_arnold_ass.py b/openpype/hosts/houdini/plugins/create/create_arnold_ass.py index 8b310753d0..e587041e70 100644 --- a/openpype/hosts/houdini/plugins/create/create_arnold_ass.py +++ b/openpype/hosts/houdini/plugins/create/create_arnold_ass.py @@ -10,7 +10,7 @@ class CreateArnoldAss(plugin.HoudiniCreator): label = "Arnold ASS" family = "ass" icon = "magic" - defaults = ["Main"] + default_variants = ["Main"] # Default extension: `.ass` or `.ass.gz` ext = ".ass" diff --git a/openpype/hosts/houdini/plugins/create/create_arnold_rop.py b/openpype/hosts/houdini/plugins/create/create_arnold_rop.py index ca516619f6..7d00e8b3e5 100644 --- a/openpype/hosts/houdini/plugins/create/create_arnold_rop.py +++ b/openpype/hosts/houdini/plugins/create/create_arnold_rop.py @@ -9,7 +9,7 @@ class CreateArnoldRop(plugin.HoudiniCreator): label = "Arnold ROP" family = "arnold_rop" icon = "magic" - defaults = ["master"] + default_variants = ["master"] # Default extension ext = "exr" diff --git a/openpype/hosts/houdini/plugins/create/create_karma_rop.py b/openpype/hosts/houdini/plugins/create/create_karma_rop.py index 71c2bf1b28..e8b77c12e5 100644 --- a/openpype/hosts/houdini/plugins/create/create_karma_rop.py +++ b/openpype/hosts/houdini/plugins/create/create_karma_rop.py @@ -11,7 +11,7 @@ class CreateKarmaROP(plugin.HoudiniCreator): label = "Karma ROP" family = "karma_rop" icon = "magic" - defaults = ["master"] + default_variants = ["master"] def create(self, subset_name, instance_data, pre_create_data): import hou # noqa diff --git a/openpype/hosts/houdini/plugins/create/create_mantra_rop.py b/openpype/hosts/houdini/plugins/create/create_mantra_rop.py index 5c29adb33f..b2846d53fa 100644 --- a/openpype/hosts/houdini/plugins/create/create_mantra_rop.py +++ b/openpype/hosts/houdini/plugins/create/create_mantra_rop.py @@ -11,7 +11,7 @@ class CreateMantraROP(plugin.HoudiniCreator): label = "Mantra ROP" family = "mantra_rop" icon = "magic" - defaults = ["master"] + default_variants = ["master"] def create(self, subset_name, instance_data, pre_create_data): import hou # noqa diff --git a/openpype/hosts/houdini/plugins/create/create_redshift_rop.py b/openpype/hosts/houdini/plugins/create/create_redshift_rop.py index 8f4aa1327d..9b0a36ddd1 100644 --- a/openpype/hosts/houdini/plugins/create/create_redshift_rop.py +++ b/openpype/hosts/houdini/plugins/create/create_redshift_rop.py @@ -13,7 +13,7 @@ class CreateRedshiftROP(plugin.HoudiniCreator): label = "Redshift ROP" family = "redshift_rop" icon = "magic" - defaults = ["master"] + default_variants = ["master"] ext = "exr" def create(self, subset_name, instance_data, pre_create_data): diff --git a/openpype/hosts/houdini/plugins/create/create_vray_rop.py b/openpype/hosts/houdini/plugins/create/create_vray_rop.py index 58748d4c34..a3ae01f5ae 100644 --- a/openpype/hosts/houdini/plugins/create/create_vray_rop.py +++ b/openpype/hosts/houdini/plugins/create/create_vray_rop.py @@ -14,7 +14,7 @@ class CreateVrayROP(plugin.HoudiniCreator): label = "VRay ROP" family = "vray_rop" icon = "magic" - defaults = ["master"] + default_variants = ["master"] ext = "exr" diff --git a/openpype/settings/defaults/project_settings/houdini.json b/openpype/settings/defaults/project_settings/houdini.json index a53f1ff202..389fdc6d96 100644 --- a/openpype/settings/defaults/project_settings/houdini.json +++ b/openpype/settings/defaults/project_settings/houdini.json @@ -14,48 +14,80 @@ "create": { "CreateArnoldAss": { "enabled": true, - "defaults": [], + "default_variants": [], "ext": ".ass" }, + "CreateArnoldRop": { + "enabled": true, + "default_variants": [] + }, "CreateAlembicCamera": { "enabled": true, - "defaults": [] + "default_variants": [] + }, + "CreateBGEO": { + "enabled": true, + "default_variants": [] }, "CreateCompositeSequence": { "enabled": true, - "defaults": [] + "default_variants": [] + }, + "CreateHDA": { + "enabled": true, + "default_variants": [] + }, + "CreateKarmaROP": { + "enabled": true, + "default_variants": [] + }, + "CreateMantraROP": { + "enabled": true, + "default_variants": [] }, "CreatePointCache": { "enabled": true, - "defaults": [] + "default_variants": [] + }, + "CreateRedshiftProxy": { + "enabled": true, + "default_variants": [] }, "CreateRedshiftROP": { "enabled": true, - "defaults": [] + "default_variants": [] }, "CreateRemotePublish": { "enabled": true, - "defaults": [] + "default_variants": [] }, - "CreateVDBCache": { + "CreateReview": { "enabled": true, - "defaults": [] + "default_variants": [] }, "CreateUSD": { "enabled": false, - "defaults": [] + "default_variants": [] }, "CreateUSDModel": { "enabled": false, - "defaults": [] + "default_variants": [] }, "USDCreateShadingWorkspace": { "enabled": false, - "defaults": [] + "default_variants": [] }, "CreateUSDRender": { "enabled": false, - "defaults": [] + "default_variants": [] + }, + "CreateVDBCache": { + "enabled": true, + "default_variants": [] + }, + "CreateVrayROP": { + "enabled": true, + "default_variants": [] } }, "publish": { diff --git a/openpype/settings/defaults/project_settings/maya.json b/openpype/settings/defaults/project_settings/maya.json index 8e1022f877..b9817fe400 100644 --- a/openpype/settings/defaults/project_settings/maya.json +++ b/openpype/settings/defaults/project_settings/maya.json @@ -521,19 +521,19 @@ "enabled": true, "make_tx": true, "rs_tex": false, - "defaults": [ + "default_variants": [ "Main" ] }, "CreateRender": { "enabled": true, - "defaults": [ + "default_variants": [ "Main" ] }, "CreateUnrealStaticMesh": { "enabled": true, - "defaults": [ + "default_variants": [ "", "_Main" ], @@ -547,7 +547,7 @@ }, "CreateUnrealSkeletalMesh": { "enabled": true, - "defaults": [], + "default_variants": [], "joint_hints": "jnt_org" }, "CreateMultiverseLook": { @@ -555,11 +555,12 @@ "publish_mip_map": true }, "CreateAnimation": { + "enabled": false, "write_color_sets": false, "write_face_sets": false, "include_parent_hierarchy": false, "include_user_defined_attributes": false, - "defaults": [ + "default_variants": [ "Main" ] }, @@ -567,7 +568,7 @@ "enabled": true, "write_color_sets": false, "write_face_sets": false, - "defaults": [ + "default_variants": [ "Main", "Proxy", "Sculpt" @@ -578,7 +579,7 @@ "write_color_sets": false, "write_face_sets": false, "include_user_defined_attributes": false, - "defaults": [ + "default_variants": [ "Main" ] }, @@ -586,20 +587,20 @@ "enabled": true, "write_color_sets": false, "write_face_sets": false, - "defaults": [ + "default_variants": [ "Main" ] }, "CreateReview": { "enabled": true, - "defaults": [ + "default_variants": [ "Main" ], "useMayaTimeline": true }, "CreateAss": { "enabled": true, - "defaults": [ + "default_variants": [ "Main" ], "expandProcedurals": false, @@ -621,61 +622,61 @@ "enabled": true, "vrmesh": true, "alembic": true, - "defaults": [ + "default_variants": [ "Main" ] }, "CreateMultiverseUsd": { "enabled": true, - "defaults": [ + "default_variants": [ "Main" ] }, "CreateMultiverseUsdComp": { "enabled": true, - "defaults": [ + "default_variants": [ "Main" ] }, "CreateMultiverseUsdOver": { "enabled": true, - "defaults": [ + "default_variants": [ "Main" ] }, "CreateAssembly": { "enabled": true, - "defaults": [ + "default_variants": [ "Main" ] }, "CreateCamera": { "enabled": true, - "defaults": [ + "default_variants": [ "Main" ] }, "CreateLayout": { "enabled": true, - "defaults": [ + "default_variants": [ "Main" ] }, "CreateMayaScene": { "enabled": true, - "defaults": [ + "default_variants": [ "Main" ] }, "CreateRenderSetup": { "enabled": true, - "defaults": [ + "default_variants": [ "Main" ] }, "CreateRig": { "enabled": true, - "defaults": [ + "default_variants": [ "Main", "Sim", "Cloth" @@ -683,20 +684,20 @@ }, "CreateSetDress": { "enabled": true, - "defaults": [ + "default_variants": [ "Main", "Anim" ] }, "CreateVRayScene": { "enabled": true, - "defaults": [ + "default_variants": [ "Main" ] }, "CreateYetiRig": { "enabled": true, - "defaults": [ + "default_variants": [ "Main" ] } diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_houdini_create.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_houdini_create.json index 83e0cf789a..52a03677da 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_houdini_create.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_houdini_create.json @@ -1,89 +1,121 @@ { - "type": "dict", - "collapsible": true, - "key": "create", - "label": "Creator plugins", - "children": [ - { - "type": "dict", - "collapsible": true, - "key": "CreateArnoldAss", - "label": "Create Arnold Ass", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "list", - "key": "defaults", - "label": "Default Subsets", - "object_type": "text" - }, - { - "type": "enum", - "key": "ext", - "label": "Default Output Format (extension)", - "multiselection": false, - "enum_items": [ - { - ".ass": ".ass" - }, - { - ".ass.gz": ".ass.gz (gzipped)" - } - ] - } - ] - - }, + "type": "dict", + "collapsible": true, + "key": "create", + "label": "Creator plugins", + "children": [ { - "type": "schema_template", - "name": "template_create_plugin", - "template_data": [ - { - "key": "CreateAlembicCamera", - "label": "Create Alembic Camera" - }, - { - "key": "CreateCompositeSequence", - "label": "Create Composite (Image Sequence)" - }, - { - "key": "CreatePointCache", - "label": "Create Point Cache" - }, - { - "key": "CreateRedshiftROP", - "label": "Create Redshift ROP" - }, - { - "key": "CreateRemotePublish", - "label": "Create Remote Publish" - }, - { - "key": "CreateVDBCache", - "label": "Create VDB Cache" - }, - { - "key": "CreateUSD", - "label": "Create USD" - }, - { - "key": "CreateUSDModel", - "label": "Create USD Model" - }, - { - "key": "USDCreateShadingWorkspace", - "label": "Create USD Shading Workspace" - }, - { - "key": "CreateUSDRender", - "label": "Create USD Render" - } - ] - } - ] -} \ No newline at end of file + "type": "dict", + "collapsible": true, + "key": "CreateArnoldAss", + "label": "Create Arnold Ass", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "list", + "key": "default_variants", + "label": "Default Variants", + "object_type": "text" + }, + { + "type": "enum", + "key": "ext", + "label": "Default Output Format (extension)", + "multiselection": false, + "enum_items": [ + { + ".ass": ".ass" + }, + { + ".ass.gz": ".ass.gz (gzipped)" + } + ] + } + ] + + }, + { + "type": "schema_template", + "name": "template_create_plugin", + "template_data": [ + { + "key": "CreateArnoldRop", + "label": "Create Arnold ROP" + }, + { + "key": "CreateAlembicCamera", + "label": "Create Alembic Camera" + }, + { + "key": "CreateBGEO", + "label": "Create Houdini BGEO" + }, + { + "key": "CreateCompositeSequence", + "label": "Create Composite (Image Sequence)" + }, + { + "key": "CreateKarmaROP", + "label": "Create Karma ROP" + }, + { + "key": "CreateMantraROP", + "label": "Create Mantra ROP" + }, + { + "key": "CreateHDA", + "label": "Create HDA" + }, + { + "key": "CreatePointCache", + "label": "Create Point Cache" + }, + { + "key": "CreateRedshiftProxy", + "label": "Create Redshift Proxy" + }, + { + "key": "CreateRedshiftROP", + "label": "Create Redshift ROP" + }, + { + "key": "CreateRemotePublish", + "label": "Create Remote Publish" + }, + { + "key": "CreateReview", + "label": "Create Review" + }, + { + "key": "CreateUSD", + "label": "Create USD" + }, + { + "key": "CreateUSDModel", + "label": "Create USD Model" + }, + { + "key": "USDCreateShadingWorkspace", + "label": "Create USD Shading Workspace" + }, + { + "key": "CreateUSDRender", + "label": "Create USD Render" + }, + { + "key": "CreateVDBCache", + "label": "Create VDB Cache" + }, + { + "key": "CreateVrayROP", + "label": "Create VRay ROP" + } + ] + } + ] +} diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json index d28d42c10c..8faf3fcae8 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json @@ -28,7 +28,7 @@ }, { "type": "list", - "key": "defaults", + "key": "default_variants", "label": "Default Subsets", "object_type": "text" } @@ -52,7 +52,7 @@ }, { "type": "list", - "key": "defaults", + "key": "default_variants", "label": "Default Subsets", "object_type": "text" }, @@ -84,7 +84,7 @@ }, { "type": "list", - "key": "defaults", + "key": "default_variants", "label": "Default Subsets", "object_type": "text" }, @@ -120,10 +120,12 @@ "collapsible": true, "key": "CreateAnimation", "label": "Create Animation", + "checkbox_key": "enabled", "children": [ { - "type": "label", - "label": "This plugin is not optional due to implicit creation through loading the \"rig\" family.\nThis family is also hidden from creation due to complexity in setup." + "type": "boolean", + "key": "enabled", + "label": "Enabled" }, { "type": "boolean", @@ -147,7 +149,7 @@ }, { "type": "list", - "key": "defaults", + "key": "default_variants", "label": "Default Subsets", "object_type": "text" } @@ -177,7 +179,7 @@ }, { "type": "list", - "key": "defaults", + "key": "default_variants", "label": "Default Subsets", "object_type": "text" } @@ -212,7 +214,7 @@ }, { "type": "list", - "key": "defaults", + "key": "default_variants", "label": "Default Subsets", "object_type": "text" } @@ -242,7 +244,7 @@ }, { "type": "list", - "key": "defaults", + "key": "default_variants", "label": "Default Subsets", "object_type": "text" } @@ -262,7 +264,7 @@ }, { "type": "list", - "key": "defaults", + "key": "default_variants", "label": "Default Subsets", "object_type": "text" }, @@ -287,7 +289,7 @@ }, { "type": "list", - "key": "defaults", + "key": "default_variants", "label": "Default Subsets", "object_type": "text" }, @@ -389,7 +391,7 @@ }, { "type": "list", - "key": "defaults", + "key": "default_variants", "label": "Default Subsets", "object_type": "text" } diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create_render.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create_render.json index 68ad7ad63d..9d7432fe51 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create_render.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create_render.json @@ -12,9 +12,9 @@ }, { "type": "list", - "key": "defaults", + "key": "default_variants", "label": "Default Subsets", "object_type": "text" } ] -} \ No newline at end of file +} diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/template_create_plugin.json b/openpype/settings/entities/schemas/projects_schema/schemas/template_create_plugin.json index 14d15e7840..3d2ed9f3d4 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/template_create_plugin.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/template_create_plugin.json @@ -13,8 +13,8 @@ }, { "type": "list", - "key": "defaults", - "label": "Default Subsets", + "key": "default_variants", + "label": "Default Variants", "object_type": "text" } ] From 1b794361034c023acef1c3362df6065f1839245a Mon Sep 17 00:00:00 2001 From: Fabia Serra Arrizabalaga Date: Mon, 7 Aug 2023 19:08:50 +0200 Subject: [PATCH 008/154] Add function so Houdini creator settings get applied to instances --- openpype/hosts/houdini/api/plugin.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/openpype/hosts/houdini/api/plugin.py b/openpype/hosts/houdini/api/plugin.py index 1e7eaa7e22..a5efb73c67 100644 --- a/openpype/hosts/houdini/api/plugin.py +++ b/openpype/hosts/houdini/api/plugin.py @@ -292,3 +292,22 @@ class HoudiniCreator(NewCreator, HoudiniCreatorBase): """ return [hou.ropNodeTypeCategory()] + + def get_creator_settings(self, project_settings, settings_key=None): + if not settings_key: + settings_key = self.__class__.__name__ + return project_settings["houdini"]["create"][settings_key] + + def apply_settings( + self, + project_settings, + system_settings + ): + """Method called on initialization of plugin to apply settings.""" + + # plugin settings + plugin_settings = self.get_creator_settings(project_settings) + + # individual attributes + self.default_variants = plugin_settings.get( + "default_variants") or self.default_variants From 73bbc86d8b54dbe7859737f34d6db71120d6f693 Mon Sep 17 00:00:00 2001 From: Fabia Serra Arrizabalaga Date: Mon, 7 Aug 2023 19:09:27 +0200 Subject: [PATCH 009/154] Use default variant from creator plugin for interactive shelve tool --- .../hosts/houdini/api/creator_node_shelves.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/openpype/hosts/houdini/api/creator_node_shelves.py b/openpype/hosts/houdini/api/creator_node_shelves.py index 7c6122cffe..c724acb16d 100644 --- a/openpype/hosts/houdini/api/creator_node_shelves.py +++ b/openpype/hosts/houdini/api/creator_node_shelves.py @@ -35,11 +35,11 @@ CATEGORY_GENERIC_TOOL = { CREATE_SCRIPT = """ from openpype.hosts.houdini.api.creator_node_shelves import create_interactive -create_interactive("{identifier}", **kwargs) +create_interactive("{identifier}", "{variant}", **kwargs) """ -def create_interactive(creator_identifier, **kwargs): +def create_interactive(creator_identifier, default_variant, **kwargs): """Create a Creator using its identifier interactively. This is used by the generated shelf tools as callback when a user selects @@ -59,9 +59,9 @@ def create_interactive(creator_identifier, **kwargs): """ # TODO Use Qt instead - result, variant = hou.ui.readInput('Define variant name', + result, variant = hou.ui.readInput("Define variant name", buttons=("Ok", "Cancel"), - initial_contents='Main', + initial_contents=default_variant, title="Define variant", help="Set the variant for the " "publish instance", @@ -196,7 +196,14 @@ def install(): key = "openpype_create.{}".format(identifier) log.debug(f"Registering {key}") - script = CREATE_SCRIPT.format(identifier=identifier) + default_variant = "Main" + if hasattr(creator, "default_variant"): + default_variant = creator.default_variant + elif hasattr(creator, "default_variants"): + default_variant = creator.default_variants[0] + script = CREATE_SCRIPT.format( + identifier=identifier, variant=default_variant + ) data = { "script": script, "language": hou.scriptLanguage.Python, From 3f626080d6fd042e5f5a5505d8ff08ae298b8b45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabi=C3=A0=20Serra=20Arrizabalaga?= Date: Mon, 7 Aug 2023 19:28:19 +0200 Subject: [PATCH 010/154] Remove default_variants class variable --- openpype/hosts/houdini/plugins/create/create_arnold_ass.py | 2 -- openpype/hosts/houdini/plugins/create/create_arnold_rop.py | 1 - openpype/hosts/houdini/plugins/create/create_karma_rop.py | 1 - openpype/hosts/houdini/plugins/create/create_mantra_rop.py | 1 - openpype/hosts/houdini/plugins/create/create_redshift_rop.py | 1 - openpype/hosts/houdini/plugins/create/create_vray_rop.py | 1 - 6 files changed, 7 deletions(-) diff --git a/openpype/hosts/houdini/plugins/create/create_arnold_ass.py b/openpype/hosts/houdini/plugins/create/create_arnold_ass.py index 72b12ddba2..12d08f7d83 100644 --- a/openpype/hosts/houdini/plugins/create/create_arnold_ass.py +++ b/openpype/hosts/houdini/plugins/create/create_arnold_ass.py @@ -10,8 +10,6 @@ class CreateArnoldAss(plugin.HoudiniCreator): label = "Arnold ASS" family = "ass" icon = "magic" - default_variants = ["Main"] - # Default extension: `.ass` or `.ass.gz` # however calling HoudiniCreator.create() diff --git a/openpype/hosts/houdini/plugins/create/create_arnold_rop.py b/openpype/hosts/houdini/plugins/create/create_arnold_rop.py index 7d00e8b3e5..b58c377a20 100644 --- a/openpype/hosts/houdini/plugins/create/create_arnold_rop.py +++ b/openpype/hosts/houdini/plugins/create/create_arnold_rop.py @@ -9,7 +9,6 @@ class CreateArnoldRop(plugin.HoudiniCreator): label = "Arnold ROP" family = "arnold_rop" icon = "magic" - default_variants = ["master"] # Default extension ext = "exr" diff --git a/openpype/hosts/houdini/plugins/create/create_karma_rop.py b/openpype/hosts/houdini/plugins/create/create_karma_rop.py index cb9c6dd711..4e1360ca45 100644 --- a/openpype/hosts/houdini/plugins/create/create_karma_rop.py +++ b/openpype/hosts/houdini/plugins/create/create_karma_rop.py @@ -11,7 +11,6 @@ class CreateKarmaROP(plugin.HoudiniCreator): label = "Karma ROP" family = "karma_rop" icon = "magic" - default_variants = ["master"] def create(self, subset_name, instance_data, pre_create_data): import hou # noqa diff --git a/openpype/hosts/houdini/plugins/create/create_mantra_rop.py b/openpype/hosts/houdini/plugins/create/create_mantra_rop.py index b2846d53fa..d2f0e735a8 100644 --- a/openpype/hosts/houdini/plugins/create/create_mantra_rop.py +++ b/openpype/hosts/houdini/plugins/create/create_mantra_rop.py @@ -11,7 +11,6 @@ class CreateMantraROP(plugin.HoudiniCreator): label = "Mantra ROP" family = "mantra_rop" icon = "magic" - default_variants = ["master"] def create(self, subset_name, instance_data, pre_create_data): import hou # noqa diff --git a/openpype/hosts/houdini/plugins/create/create_redshift_rop.py b/openpype/hosts/houdini/plugins/create/create_redshift_rop.py index 9bb1d58d8f..e37718129c 100644 --- a/openpype/hosts/houdini/plugins/create/create_redshift_rop.py +++ b/openpype/hosts/houdini/plugins/create/create_redshift_rop.py @@ -13,7 +13,6 @@ class CreateRedshiftROP(plugin.HoudiniCreator): label = "Redshift ROP" family = "redshift_rop" icon = "magic" - default_variants = ["master"] ext = "exr" diff --git a/openpype/hosts/houdini/plugins/create/create_vray_rop.py b/openpype/hosts/houdini/plugins/create/create_vray_rop.py index a3ae01f5ae..34c8906bb0 100644 --- a/openpype/hosts/houdini/plugins/create/create_vray_rop.py +++ b/openpype/hosts/houdini/plugins/create/create_vray_rop.py @@ -14,7 +14,6 @@ class CreateVrayROP(plugin.HoudiniCreator): label = "VRay ROP" family = "vray_rop" icon = "magic" - default_variants = ["master"] ext = "exr" From adca11d44bed5c705d4c3e7d9740f732053b7779 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabi=C3=A0=20Serra=20Arrizabalaga?= Date: Mon, 7 Aug 2023 19:28:58 +0200 Subject: [PATCH 011/154] Remove extra whitespace --- openpype/hosts/houdini/plugins/create/create_redshift_rop.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/hosts/houdini/plugins/create/create_redshift_rop.py b/openpype/hosts/houdini/plugins/create/create_redshift_rop.py index e37718129c..1b8826a932 100644 --- a/openpype/hosts/houdini/plugins/create/create_redshift_rop.py +++ b/openpype/hosts/houdini/plugins/create/create_redshift_rop.py @@ -13,7 +13,6 @@ class CreateRedshiftROP(plugin.HoudiniCreator): label = "Redshift ROP" family = "redshift_rop" icon = "magic" - ext = "exr" def create(self, subset_name, instance_data, pre_create_data): From 84e3ade492bf51084824d520fb914a334a2361d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabi=C3=A0=20Serra=20Arrizabalaga?= Date: Mon, 7 Aug 2023 19:30:16 +0200 Subject: [PATCH 012/154] Revert merge conflict --- .../schemas/projects_schema/schemas/schema_maya_create.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json index 8faf3fcae8..10d5bff445 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json @@ -12,9 +12,8 @@ "checkbox_key": "enabled", "children": [ { - "type": "boolean", - "key": "enabled", - "label": "Enabled" + "type": "label", + "label": "This plugin is not optional due to implicit creation through loading the \"rig\" family.\nThis family is also hidden from creation due to complexity in setup." }, { "type": "boolean", From b57c8a79c090332ce488dc6daad78c77f7d59240 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabi=C3=A0=20Serra=20Arrizabalaga?= Date: Mon, 7 Aug 2023 19:33:46 +0200 Subject: [PATCH 013/154] Remove extra whitespace --- openpype/hosts/houdini/plugins/create/create_vray_rop.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/hosts/houdini/plugins/create/create_vray_rop.py b/openpype/hosts/houdini/plugins/create/create_vray_rop.py index 34c8906bb0..793a544fdf 100644 --- a/openpype/hosts/houdini/plugins/create/create_vray_rop.py +++ b/openpype/hosts/houdini/plugins/create/create_vray_rop.py @@ -14,7 +14,6 @@ class CreateVrayROP(plugin.HoudiniCreator): label = "VRay ROP" family = "vray_rop" icon = "magic" - ext = "exr" def create(self, subset_name, instance_data, pre_create_data): From bb42369af27992a125ba7110954cd5a365cad542 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabi=C3=A0=20Serra=20Arrizabalaga?= Date: Mon, 7 Aug 2023 19:34:51 +0200 Subject: [PATCH 014/154] Fix merge conflict --- .../projects_schema/schemas/schema_maya_create.json | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json index 10d5bff445..8dec0a8817 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json @@ -12,8 +12,9 @@ "checkbox_key": "enabled", "children": [ { - "type": "label", - "label": "This plugin is not optional due to implicit creation through loading the \"rig\" family.\nThis family is also hidden from creation due to complexity in setup." + "type": "boolean", + "key": "enabled", + "label": "Enabled" }, { "type": "boolean", @@ -119,12 +120,10 @@ "collapsible": true, "key": "CreateAnimation", "label": "Create Animation", - "checkbox_key": "enabled", "children": [ { - "type": "boolean", - "key": "enabled", - "label": "Enabled" + "type": "label", + "label": "This plugin is not optional due to implicit creation through loading the \"rig\" family.\nThis family is also hidden from creation due to complexity in setup." }, { "type": "boolean", From 92254e2abc32d2305497dadf9319ebdef040ee14 Mon Sep 17 00:00:00 2001 From: Fabia Serra Arrizabalaga Date: Mon, 7 Aug 2023 19:53:32 +0200 Subject: [PATCH 015/154] Add a default variant to all Houdini creators --- openpype/hosts/houdini/api/plugin.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openpype/hosts/houdini/api/plugin.py b/openpype/hosts/houdini/api/plugin.py index 70c837205e..3d3b0e49b9 100644 --- a/openpype/hosts/houdini/api/plugin.py +++ b/openpype/hosts/houdini/api/plugin.py @@ -169,6 +169,8 @@ class HoudiniCreator(NewCreator, HoudiniCreatorBase): selected_nodes = [] settings_name = None + default_variant = "Main" + def create(self, subset_name, instance_data, pre_create_data): try: self.selected_nodes = [] From 9604656017cf06fb444435dcd37c15e8681719ee Mon Sep 17 00:00:00 2001 From: Fabia Serra Arrizabalaga Date: Mon, 7 Aug 2023 20:21:13 +0200 Subject: [PATCH 016/154] Add default variant on all creators --- .../defaults/project_settings/houdini.json | 29 +++++++++++++++---- .../defaults/project_settings/maya.json | 23 +++++++++++++++ .../schemas/schema_houdini_create.json | 5 ++++ .../schemas/schema_maya_create.json | 5 ++++ .../schemas/template_create_plugin.json | 5 ++++ 5 files changed, 62 insertions(+), 5 deletions(-) diff --git a/openpype/settings/defaults/project_settings/houdini.json b/openpype/settings/defaults/project_settings/houdini.json index 389fdc6d96..cf5d1c93d5 100644 --- a/openpype/settings/defaults/project_settings/houdini.json +++ b/openpype/settings/defaults/project_settings/houdini.json @@ -14,80 +14,99 @@ "create": { "CreateArnoldAss": { "enabled": true, + "default_variant": "Main", "default_variants": [], "ext": ".ass" }, "CreateArnoldRop": { "enabled": true, - "default_variants": [] + "default_variant": "master", + "default_variants": ["master"] }, "CreateAlembicCamera": { "enabled": true, + "default_variant": "Main", "default_variants": [] }, "CreateBGEO": { "enabled": true, + "default_variant": "Main", "default_variants": [] }, "CreateCompositeSequence": { "enabled": true, + "default_variant": "Main", "default_variants": [] }, "CreateHDA": { "enabled": true, + "default_variant": "Main", "default_variants": [] }, "CreateKarmaROP": { "enabled": true, - "default_variants": [] + "default_variant": "master", + "default_variants": ["master"] }, "CreateMantraROP": { "enabled": true, - "default_variants": [] + "default_variant": "master", + "default_variants": ["master"] }, "CreatePointCache": { "enabled": true, + "default_variant": "Main", "default_variants": [] }, "CreateRedshiftProxy": { "enabled": true, - "default_variants": [] + "default_variant": "master", + "default_variants": ["master"] }, "CreateRedshiftROP": { "enabled": true, + "default_variant": "Main", "default_variants": [] }, "CreateRemotePublish": { "enabled": true, + "default_variant": "Main", "default_variants": [] }, "CreateReview": { "enabled": true, + "default_variant": "Main", "default_variants": [] }, "CreateUSD": { "enabled": false, + "default_variant": "Main", "default_variants": [] }, "CreateUSDModel": { "enabled": false, + "default_variant": "Main", "default_variants": [] }, "USDCreateShadingWorkspace": { "enabled": false, + "default_variant": "Main", "default_variants": [] }, "CreateUSDRender": { "enabled": false, + "default_variant": "Main", "default_variants": [] }, "CreateVDBCache": { "enabled": true, + "default_variant": "Main", "default_variants": [] }, "CreateVrayROP": { "enabled": true, - "default_variants": [] + "default_variant": "master", + "default_variants": ["master"] } }, "publish": { diff --git a/openpype/settings/defaults/project_settings/maya.json b/openpype/settings/defaults/project_settings/maya.json index b9817fe400..f53501c7ac 100644 --- a/openpype/settings/defaults/project_settings/maya.json +++ b/openpype/settings/defaults/project_settings/maya.json @@ -521,18 +521,21 @@ "enabled": true, "make_tx": true, "rs_tex": false, + "default_variant": "Main", "default_variants": [ "Main" ] }, "CreateRender": { "enabled": true, + "default_variant": "Main", "default_variants": [ "Main" ] }, "CreateUnrealStaticMesh": { "enabled": true, + "default_variant": "", "default_variants": [ "", "_Main" @@ -547,6 +550,7 @@ }, "CreateUnrealSkeletalMesh": { "enabled": true, + "default_variant": "", "default_variants": [], "joint_hints": "jnt_org" }, @@ -560,6 +564,7 @@ "write_face_sets": false, "include_parent_hierarchy": false, "include_user_defined_attributes": false, + "default_variant": "Main", "default_variants": [ "Main" ] @@ -568,6 +573,7 @@ "enabled": true, "write_color_sets": false, "write_face_sets": false, + "default_variant": "Main", "default_variants": [ "Main", "Proxy", @@ -579,6 +585,7 @@ "write_color_sets": false, "write_face_sets": false, "include_user_defined_attributes": false, + "default_variant": "Main", "default_variants": [ "Main" ] @@ -587,12 +594,14 @@ "enabled": true, "write_color_sets": false, "write_face_sets": false, + "default_variant": "Main", "default_variants": [ "Main" ] }, "CreateReview": { "enabled": true, + "default_variant": "Main", "default_variants": [ "Main" ], @@ -600,6 +609,7 @@ }, "CreateAss": { "enabled": true, + "default_variant": "Main", "default_variants": [ "Main" ], @@ -622,60 +632,70 @@ "enabled": true, "vrmesh": true, "alembic": true, + "default_variant": "Main", "default_variants": [ "Main" ] }, "CreateMultiverseUsd": { "enabled": true, + "default_variant": "Main", "default_variants": [ "Main" ] }, "CreateMultiverseUsdComp": { "enabled": true, + "default_variant": "Main", "default_variants": [ "Main" ] }, "CreateMultiverseUsdOver": { "enabled": true, + "default_variant": "Main", "default_variants": [ "Main" ] }, "CreateAssembly": { "enabled": true, + "default_variant": "Main", "default_variants": [ "Main" ] }, "CreateCamera": { "enabled": true, + "default_variant": "Main", "default_variants": [ "Main" ] }, "CreateLayout": { "enabled": true, + "default_variant": "Main", "default_variants": [ "Main" ] }, "CreateMayaScene": { "enabled": true, + "default_variant": "Main", "default_variants": [ "Main" ] }, "CreateRenderSetup": { "enabled": true, + "default_variant": "Main", "default_variants": [ "Main" ] }, "CreateRig": { "enabled": true, + "default_variant": "Main", "default_variants": [ "Main", "Sim", @@ -684,6 +704,7 @@ }, "CreateSetDress": { "enabled": true, + "default_variant": "Main", "default_variants": [ "Main", "Anim" @@ -691,12 +712,14 @@ }, "CreateVRayScene": { "enabled": true, + "default_variant": "Main", "default_variants": [ "Main" ] }, "CreateYetiRig": { "enabled": true, + "default_variant": "Main", "default_variants": [ "Main" ] diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_houdini_create.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_houdini_create.json index a1736c811d..6e1eaf7146 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_houdini_create.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_houdini_create.json @@ -16,6 +16,11 @@ "key": "enabled", "label": "Enabled" }, + { + "type": "text", + "key": "default_variant", + "label": "Default variant" + }, { "type": "list", "key": "default_variants", diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json index 8dec0a8817..a8105bdb5d 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json @@ -387,6 +387,11 @@ "key": "alembic", "label": "Alembic" }, + { + "type": "text", + "key": "default_variant", + "label": "Default variant" + }, { "type": "list", "key": "default_variants", diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/template_create_plugin.json b/openpype/settings/entities/schemas/projects_schema/schemas/template_create_plugin.json index 3d2ed9f3d4..7384060625 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/template_create_plugin.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/template_create_plugin.json @@ -11,6 +11,11 @@ "key": "enabled", "label": "Enabled" }, + { + "type": "text", + "key": "default_variant", + "label": "Default variant" + }, { "type": "list", "key": "default_variants", From 8a02654dbc133563fe57a0f7190fd7f72b2210ec Mon Sep 17 00:00:00 2001 From: Fabia Serra Arrizabalaga Date: Mon, 7 Aug 2023 20:24:31 +0200 Subject: [PATCH 017/154] Fill up default variants --- .../defaults/project_settings/houdini.json | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/openpype/settings/defaults/project_settings/houdini.json b/openpype/settings/defaults/project_settings/houdini.json index cf5d1c93d5..630b189743 100644 --- a/openpype/settings/defaults/project_settings/houdini.json +++ b/openpype/settings/defaults/project_settings/houdini.json @@ -15,7 +15,7 @@ "CreateArnoldAss": { "enabled": true, "default_variant": "Main", - "default_variants": [], + "default_variants": ["Main"], "ext": ".ass" }, "CreateArnoldRop": { @@ -26,22 +26,22 @@ "CreateAlembicCamera": { "enabled": true, "default_variant": "Main", - "default_variants": [] + "default_variants": ["Main"] }, "CreateBGEO": { "enabled": true, "default_variant": "Main", - "default_variants": [] + "default_variants": ["Main"] }, "CreateCompositeSequence": { "enabled": true, "default_variant": "Main", - "default_variants": [] + "default_variants": ["Main"] }, "CreateHDA": { "enabled": true, "default_variant": "Main", - "default_variants": [] + "default_variants": ["Main"] }, "CreateKarmaROP": { "enabled": true, @@ -56,7 +56,7 @@ "CreatePointCache": { "enabled": true, "default_variant": "Main", - "default_variants": [] + "default_variants": ["Main"] }, "CreateRedshiftProxy": { "enabled": true, @@ -66,42 +66,42 @@ "CreateRedshiftROP": { "enabled": true, "default_variant": "Main", - "default_variants": [] + "default_variants": ["Main"] }, "CreateRemotePublish": { "enabled": true, "default_variant": "Main", - "default_variants": [] + "default_variants": ["Main"] }, "CreateReview": { "enabled": true, "default_variant": "Main", - "default_variants": [] + "default_variants": ["Main"] }, "CreateUSD": { "enabled": false, "default_variant": "Main", - "default_variants": [] + "default_variants": ["Main"] }, "CreateUSDModel": { "enabled": false, "default_variant": "Main", - "default_variants": [] + "default_variants": ["Main"] }, "USDCreateShadingWorkspace": { "enabled": false, "default_variant": "Main", - "default_variants": [] + "default_variants": ["Main"] }, "CreateUSDRender": { "enabled": false, "default_variant": "Main", - "default_variants": [] + "default_variants": ["Main"] }, "CreateVDBCache": { "enabled": true, "default_variant": "Main", - "default_variants": [] + "default_variants": ["Main"] }, "CreateVrayROP": { "enabled": true, From 38b905c6f92b7ff4b3b9977c27b77153a35f9e8d Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 8 Aug 2023 18:27:13 +0800 Subject: [PATCH 018/154] restore the load max scene for resolving the possible conflict --- .../hosts/max/plugins/load/load_max_scene.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/openpype/hosts/max/plugins/load/load_max_scene.py b/openpype/hosts/max/plugins/load/load_max_scene.py index 468461bc0e..76cd3bf367 100644 --- a/openpype/hosts/max/plugins/load/load_max_scene.py +++ b/openpype/hosts/max/plugins/load/load_max_scene.py @@ -1,8 +1,7 @@ import os from openpype.hosts.max.api import lib -from openpype.hosts.max.api.pipeline import containerise, load_OpenpypeData - +from openpype.hosts.max.api.pipeline import containerise from openpype.pipeline import get_representation_path, load @@ -28,7 +27,6 @@ class MaxSceneLoader(load.LoaderPlugin): rt.MergeMaxFile(path) max_objects = rt.getLastMergedNodes() max_container = rt.Container(name=f"{name}") - load_OpenpypeData(max_container, max_objects) for max_object in max_objects: max_object.Parent = max_container @@ -41,16 +39,16 @@ class MaxSceneLoader(load.LoaderPlugin): path = get_representation_path(representation) node_name = container["instance_node"] - rt.MergeMaxFile(path) + rt.MergeMaxFile(path, + rt.Name("noRedraw"), + rt.Name("deleteOldDups"), + rt.Name("useSceneMtlDups")) max_objects = rt.getLastMergedNodes() container_node = rt.GetNodeByName(node_name) - instance_name, _ = os.path.splitext(node_name) - instance_container = rt.GetNodeByName(instance_name) for max_object in max_objects: - max_object.Parent = instance_container - instance_container.Parent = container_node - load_OpenpypeData(container_node, max_objects) + max_object.Parent = container_node + lib.imprint(container["instance_node"], { "representation": str(representation["_id"]) }) From 20479595061f2e08c9ca3b3bb710cbe0f3147956 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabi=C3=A0=20Serra=20Arrizabalaga?= Date: Tue, 8 Aug 2023 20:06:56 +0200 Subject: [PATCH 019/154] Make use of `get_default_variant` function --- openpype/hosts/houdini/api/creator_node_shelves.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/openpype/hosts/houdini/api/creator_node_shelves.py b/openpype/hosts/houdini/api/creator_node_shelves.py index c724acb16d..01da2fc3e1 100644 --- a/openpype/hosts/houdini/api/creator_node_shelves.py +++ b/openpype/hosts/houdini/api/creator_node_shelves.py @@ -196,13 +196,8 @@ def install(): key = "openpype_create.{}".format(identifier) log.debug(f"Registering {key}") - default_variant = "Main" - if hasattr(creator, "default_variant"): - default_variant = creator.default_variant - elif hasattr(creator, "default_variants"): - default_variant = creator.default_variants[0] script = CREATE_SCRIPT.format( - identifier=identifier, variant=default_variant + identifier=identifier, variant=creator.get_default_variant() ) data = { "script": script, From 2f663bc011ef4bd934f9cc7d690dfd3fd4769eda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabi=C3=A0=20Serra=20Arrizabalaga?= Date: Tue, 8 Aug 2023 20:20:08 +0200 Subject: [PATCH 020/154] Remove 'default_variant' from schemas --- .../defaults/project_settings/houdini.json | 57 +++++++------------ .../defaults/project_settings/maya.json | 24 -------- .../schemas/schema_houdini_create.json | 5 -- .../schemas/template_create_plugin.json | 5 -- 4 files changed, 19 insertions(+), 72 deletions(-) diff --git a/openpype/settings/defaults/project_settings/houdini.json b/openpype/settings/defaults/project_settings/houdini.json index 630b189743..512690bfd7 100644 --- a/openpype/settings/defaults/project_settings/houdini.json +++ b/openpype/settings/defaults/project_settings/houdini.json @@ -14,99 +14,80 @@ "create": { "CreateArnoldAss": { "enabled": true, - "default_variant": "Main", - "default_variants": ["Main"], + "default_variants": ["main"], "ext": ".ass" }, "CreateArnoldRop": { "enabled": true, - "default_variant": "master", - "default_variants": ["master"] + "default_variants": ["main"] }, "CreateAlembicCamera": { "enabled": true, - "default_variant": "Main", - "default_variants": ["Main"] + "default_variants": ["main"] }, "CreateBGEO": { "enabled": true, - "default_variant": "Main", - "default_variants": ["Main"] + "default_variants": ["main"] }, "CreateCompositeSequence": { "enabled": true, - "default_variant": "Main", - "default_variants": ["Main"] + "default_variants": ["main"] }, "CreateHDA": { "enabled": true, - "default_variant": "Main", - "default_variants": ["Main"] + "default_variants": ["main"] }, "CreateKarmaROP": { "enabled": true, - "default_variant": "master", - "default_variants": ["master"] + "default_variants": ["main"] }, "CreateMantraROP": { "enabled": true, - "default_variant": "master", - "default_variants": ["master"] + "default_variants": ["main"] }, "CreatePointCache": { "enabled": true, - "default_variant": "Main", - "default_variants": ["Main"] + "default_variants": ["main"] }, "CreateRedshiftProxy": { "enabled": true, - "default_variant": "master", - "default_variants": ["master"] + "default_variants": ["main"] }, "CreateRedshiftROP": { "enabled": true, - "default_variant": "Main", - "default_variants": ["Main"] + "default_variants": ["main"] }, "CreateRemotePublish": { "enabled": true, - "default_variant": "Main", - "default_variants": ["Main"] + "default_variants": ["main"] }, "CreateReview": { "enabled": true, - "default_variant": "Main", - "default_variants": ["Main"] + "default_variants": ["main"] }, "CreateUSD": { "enabled": false, - "default_variant": "Main", - "default_variants": ["Main"] + "default_variants": ["main"] }, "CreateUSDModel": { "enabled": false, - "default_variant": "Main", - "default_variants": ["Main"] + "default_variants": ["main"] }, "USDCreateShadingWorkspace": { "enabled": false, - "default_variant": "Main", - "default_variants": ["Main"] + "default_variants": ["main"] }, "CreateUSDRender": { "enabled": false, - "default_variant": "Main", - "default_variants": ["Main"] + "default_variants": ["main"] }, "CreateVDBCache": { "enabled": true, - "default_variant": "Main", - "default_variants": ["Main"] + "default_variants": ["main"] }, "CreateVrayROP": { "enabled": true, - "default_variant": "master", - "default_variants": ["master"] + "default_variants": ["main"] } }, "publish": { diff --git a/openpype/settings/defaults/project_settings/maya.json b/openpype/settings/defaults/project_settings/maya.json index f53501c7ac..e1c6d2d827 100644 --- a/openpype/settings/defaults/project_settings/maya.json +++ b/openpype/settings/defaults/project_settings/maya.json @@ -521,21 +521,18 @@ "enabled": true, "make_tx": true, "rs_tex": false, - "default_variant": "Main", "default_variants": [ "Main" ] }, "CreateRender": { "enabled": true, - "default_variant": "Main", "default_variants": [ "Main" ] }, "CreateUnrealStaticMesh": { "enabled": true, - "default_variant": "", "default_variants": [ "", "_Main" @@ -550,7 +547,6 @@ }, "CreateUnrealSkeletalMesh": { "enabled": true, - "default_variant": "", "default_variants": [], "joint_hints": "jnt_org" }, @@ -559,12 +555,10 @@ "publish_mip_map": true }, "CreateAnimation": { - "enabled": false, "write_color_sets": false, "write_face_sets": false, "include_parent_hierarchy": false, "include_user_defined_attributes": false, - "default_variant": "Main", "default_variants": [ "Main" ] @@ -573,7 +567,6 @@ "enabled": true, "write_color_sets": false, "write_face_sets": false, - "default_variant": "Main", "default_variants": [ "Main", "Proxy", @@ -585,7 +578,6 @@ "write_color_sets": false, "write_face_sets": false, "include_user_defined_attributes": false, - "default_variant": "Main", "default_variants": [ "Main" ] @@ -594,14 +586,12 @@ "enabled": true, "write_color_sets": false, "write_face_sets": false, - "default_variant": "Main", "default_variants": [ "Main" ] }, "CreateReview": { "enabled": true, - "default_variant": "Main", "default_variants": [ "Main" ], @@ -609,7 +599,6 @@ }, "CreateAss": { "enabled": true, - "default_variant": "Main", "default_variants": [ "Main" ], @@ -632,70 +621,60 @@ "enabled": true, "vrmesh": true, "alembic": true, - "default_variant": "Main", "default_variants": [ "Main" ] }, "CreateMultiverseUsd": { "enabled": true, - "default_variant": "Main", "default_variants": [ "Main" ] }, "CreateMultiverseUsdComp": { "enabled": true, - "default_variant": "Main", "default_variants": [ "Main" ] }, "CreateMultiverseUsdOver": { "enabled": true, - "default_variant": "Main", "default_variants": [ "Main" ] }, "CreateAssembly": { "enabled": true, - "default_variant": "Main", "default_variants": [ "Main" ] }, "CreateCamera": { "enabled": true, - "default_variant": "Main", "default_variants": [ "Main" ] }, "CreateLayout": { "enabled": true, - "default_variant": "Main", "default_variants": [ "Main" ] }, "CreateMayaScene": { "enabled": true, - "default_variant": "Main", "default_variants": [ "Main" ] }, "CreateRenderSetup": { "enabled": true, - "default_variant": "Main", "default_variants": [ "Main" ] }, "CreateRig": { "enabled": true, - "default_variant": "Main", "default_variants": [ "Main", "Sim", @@ -704,7 +683,6 @@ }, "CreateSetDress": { "enabled": true, - "default_variant": "Main", "default_variants": [ "Main", "Anim" @@ -712,14 +690,12 @@ }, "CreateVRayScene": { "enabled": true, - "default_variant": "Main", "default_variants": [ "Main" ] }, "CreateYetiRig": { "enabled": true, - "default_variant": "Main", "default_variants": [ "Main" ] diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_houdini_create.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_houdini_create.json index 6e1eaf7146..a1736c811d 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_houdini_create.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_houdini_create.json @@ -16,11 +16,6 @@ "key": "enabled", "label": "Enabled" }, - { - "type": "text", - "key": "default_variant", - "label": "Default variant" - }, { "type": "list", "key": "default_variants", diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/template_create_plugin.json b/openpype/settings/entities/schemas/projects_schema/schemas/template_create_plugin.json index 7384060625..3d2ed9f3d4 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/template_create_plugin.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/template_create_plugin.json @@ -11,11 +11,6 @@ "key": "enabled", "label": "Enabled" }, - { - "type": "text", - "key": "default_variant", - "label": "Default variant" - }, { "type": "list", "key": "default_variants", From d06b9dcdca4e6af00789a77806ed67f240bea4f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabi=C3=A0=20Serra=20Arrizabalaga?= Date: Tue, 8 Aug 2023 20:21:02 +0200 Subject: [PATCH 021/154] Remove fallback default_variant from Houdini base creator --- openpype/hosts/houdini/api/plugin.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/openpype/hosts/houdini/api/plugin.py b/openpype/hosts/houdini/api/plugin.py index 3d3b0e49b9..70c837205e 100644 --- a/openpype/hosts/houdini/api/plugin.py +++ b/openpype/hosts/houdini/api/plugin.py @@ -169,8 +169,6 @@ class HoudiniCreator(NewCreator, HoudiniCreatorBase): selected_nodes = [] settings_name = None - default_variant = "Main" - def create(self, subset_name, instance_data, pre_create_data): try: self.selected_nodes = [] From 0703c1c0d18206966cbb37885f9dc96b0e4336aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabi=C3=A0=20Serra=20Arrizabalaga?= Date: Tue, 8 Aug 2023 20:22:08 +0200 Subject: [PATCH 022/154] Remove default_variant from Maya schema --- .../schemas/projects_schema/schemas/schema_maya_create.json | 5 ----- 1 file changed, 5 deletions(-) diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json index a8105bdb5d..8dec0a8817 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create.json @@ -387,11 +387,6 @@ "key": "alembic", "label": "Alembic" }, - { - "type": "text", - "key": "default_variant", - "label": "Default variant" - }, { "type": "list", "key": "default_variants", From ef50ba5130d6be0b6f709ef60aa49181c67016a4 Mon Sep 17 00:00:00 2001 From: Fabia Serra Arrizabalaga Date: Wed, 9 Aug 2023 15:25:48 +0200 Subject: [PATCH 023/154] Remove schema setting changes from PR --- .../defaults/project_settings/houdini.json | 76 ++++-------- .../defaults/project_settings/maya.json | 26 ++-- .../schemas/schema_houdini_create.json | 113 +++++++----------- .../schemas/schema_maya_create_render.json | 2 +- .../schemas/template_create_plugin.json | 4 +- 5 files changed, 79 insertions(+), 142 deletions(-) diff --git a/openpype/settings/defaults/project_settings/houdini.json b/openpype/settings/defaults/project_settings/houdini.json index 512690bfd7..a5256aad8b 100644 --- a/openpype/settings/defaults/project_settings/houdini.json +++ b/openpype/settings/defaults/project_settings/houdini.json @@ -14,80 +14,48 @@ "create": { "CreateArnoldAss": { "enabled": true, - "default_variants": ["main"], + "default_variants": [], "ext": ".ass" }, - "CreateArnoldRop": { - "enabled": true, - "default_variants": ["main"] - }, "CreateAlembicCamera": { "enabled": true, - "default_variants": ["main"] - }, - "CreateBGEO": { - "enabled": true, - "default_variants": ["main"] + "defaults": [] }, "CreateCompositeSequence": { "enabled": true, - "default_variants": ["main"] - }, - "CreateHDA": { - "enabled": true, - "default_variants": ["main"] - }, - "CreateKarmaROP": { - "enabled": true, - "default_variants": ["main"] - }, - "CreateMantraROP": { - "enabled": true, - "default_variants": ["main"] + "defaults": [] }, "CreatePointCache": { "enabled": true, - "default_variants": ["main"] - }, - "CreateRedshiftProxy": { - "enabled": true, - "default_variants": ["main"] + "defaults": [] }, "CreateRedshiftROP": { "enabled": true, - "default_variants": ["main"] + "defaults": [] }, "CreateRemotePublish": { "enabled": true, - "default_variants": ["main"] - }, - "CreateReview": { - "enabled": true, - "default_variants": ["main"] - }, - "CreateUSD": { - "enabled": false, - "default_variants": ["main"] - }, - "CreateUSDModel": { - "enabled": false, - "default_variants": ["main"] - }, - "USDCreateShadingWorkspace": { - "enabled": false, - "default_variants": ["main"] - }, - "CreateUSDRender": { - "enabled": false, - "default_variants": ["main"] + "defaults": [] }, "CreateVDBCache": { "enabled": true, - "default_variants": ["main"] + "defaults": [] }, - "CreateVrayROP": { - "enabled": true, - "default_variants": ["main"] + "CreateUSD": { + "enabled": false, + "defaults": [] + }, + "CreateUSDModel": { + "enabled": false, + "defaults": [] + }, + "USDCreateShadingWorkspace": { + "enabled": false, + "defaults": [] + }, + "CreateUSDRender": { + "enabled": false, + "defaults": [] } }, "publish": { diff --git a/openpype/settings/defaults/project_settings/maya.json b/openpype/settings/defaults/project_settings/maya.json index e1c6d2d827..342d2bfb2a 100644 --- a/openpype/settings/defaults/project_settings/maya.json +++ b/openpype/settings/defaults/project_settings/maya.json @@ -527,7 +527,7 @@ }, "CreateRender": { "enabled": true, - "default_variants": [ + "defaults": [ "Main" ] }, @@ -627,55 +627,55 @@ }, "CreateMultiverseUsd": { "enabled": true, - "default_variants": [ + "defaults": [ "Main" ] }, "CreateMultiverseUsdComp": { "enabled": true, - "default_variants": [ + "defaults": [ "Main" ] }, "CreateMultiverseUsdOver": { "enabled": true, - "default_variants": [ + "defaults": [ "Main" ] }, "CreateAssembly": { "enabled": true, - "default_variants": [ + "defaults": [ "Main" ] }, "CreateCamera": { "enabled": true, - "default_variants": [ + "defaults": [ "Main" ] }, "CreateLayout": { "enabled": true, - "default_variants": [ + "defaults": [ "Main" ] }, "CreateMayaScene": { "enabled": true, - "default_variants": [ + "defaults": [ "Main" ] }, "CreateRenderSetup": { "enabled": true, - "default_variants": [ + "defaults": [ "Main" ] }, "CreateRig": { "enabled": true, - "default_variants": [ + "defaults": [ "Main", "Sim", "Cloth" @@ -683,20 +683,20 @@ }, "CreateSetDress": { "enabled": true, - "default_variants": [ + "defaults": [ "Main", "Anim" ] }, "CreateVRayScene": { "enabled": true, - "default_variants": [ + "defaults": [ "Main" ] }, "CreateYetiRig": { "enabled": true, - "default_variants": [ + "defaults": [ "Main" ] } diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_houdini_create.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_houdini_create.json index a1736c811d..4eb976d7b6 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_houdini_create.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_houdini_create.json @@ -1,83 +1,60 @@ { - "type": "dict", - "collapsible": true, - "key": "create", - "label": "Creator plugins", - "children": [ - { - "type": "dict", - "collapsible": true, - "key": "CreateArnoldAss", - "label": "Create Arnold Ass", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "list", - "key": "default_variants", - "label": "Default Subsets", - "object_type": "text" - }, - { - "type": "enum", - "key": "ext", - "label": "Default Output Format (extension)", - "multiselection": false, - "enum_items": [ - { - ".ass": ".ass" - }, - { - ".ass.gz": ".ass.gz (gzipped)" - } - ] - } - ] + "type": "dict", + "collapsible": true, + "key": "create", + "label": "Creator plugins", + "children": [ + { + "type": "dict", + "collapsible": true, + "key": "CreateArnoldAss", + "label": "Create Arnold Ass", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "list", + "key": "default_variants", + "label": "Default Subsets", + "object_type": "text" + }, + { + "type": "enum", + "key": "ext", + "label": "Default Output Format (extension)", + "multiselection": false, + "enum_items": [ + { + ".ass": ".ass" + }, + { + ".ass.gz": ".ass.gz (gzipped)" + } + ] + } + ] + }, { "type": "schema_template", "name": "template_create_plugin", "template_data": [ - { - "key": "CreateArnoldRop", - "label": "Create Arnold ROP" - }, { "key": "CreateAlembicCamera", "label": "Create Alembic Camera" }, - { - "key": "CreateBGEO", - "label": "Create Houdini BGEO" - }, { "key": "CreateCompositeSequence", "label": "Create Composite (Image Sequence)" }, - { - "key": "CreateKarmaROP", - "label": "Create Karma ROP" - }, - { - "key": "CreateMantraROP", - "label": "Create Mantra ROP" - }, - { - "key": "CreateHDA", - "label": "Create HDA" - }, { "key": "CreatePointCache", "label": "Create Point Cache" }, - { - "key": "CreateRedshiftProxy", - "label": "Create Redshift Proxy" - }, { "key": "CreateRedshiftROP", "label": "Create Redshift ROP" @@ -87,8 +64,8 @@ "label": "Create Remote Publish" }, { - "key": "CreateReview", - "label": "Create Review" + "key": "CreateVDBCache", + "label": "Create VDB Cache" }, { "key": "CreateUSD", @@ -105,14 +82,6 @@ { "key": "CreateUSDRender", "label": "Create USD Render" - }, - { - "key": "CreateVDBCache", - "label": "Create VDB Cache" - }, - { - "key": "CreateVrayROP", - "label": "Create VRay ROP" } ] } diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create_render.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create_render.json index 9d7432fe51..bc203a0514 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create_render.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_create_render.json @@ -12,7 +12,7 @@ }, { "type": "list", - "key": "default_variants", + "key": "defaults", "label": "Default Subsets", "object_type": "text" } diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/template_create_plugin.json b/openpype/settings/entities/schemas/projects_schema/schemas/template_create_plugin.json index 3d2ed9f3d4..14d15e7840 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/template_create_plugin.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/template_create_plugin.json @@ -13,8 +13,8 @@ }, { "type": "list", - "key": "default_variants", - "label": "Default Variants", + "key": "defaults", + "label": "Default Subsets", "object_type": "text" } ] From a9fd8349fc27b4744b19d6a125a25440de973917 Mon Sep 17 00:00:00 2001 From: Fabia Serra Arrizabalaga Date: Wed, 9 Aug 2023 15:27:08 +0200 Subject: [PATCH 024/154] Remove whitespace differences --- .../schemas/schema_houdini_create.json | 170 +++++++++--------- 1 file changed, 85 insertions(+), 85 deletions(-) diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_houdini_create.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_houdini_create.json index 4eb976d7b6..64d157d281 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_houdini_create.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_houdini_create.json @@ -1,89 +1,89 @@ { - "type": "dict", - "collapsible": true, - "key": "create", - "label": "Creator plugins", - "children": [ - { - "type": "dict", - "collapsible": true, - "key": "CreateArnoldAss", - "label": "Create Arnold Ass", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "list", - "key": "default_variants", - "label": "Default Subsets", - "object_type": "text" - }, - { - "type": "enum", - "key": "ext", - "label": "Default Output Format (extension)", - "multiselection": false, - "enum_items": [ - { - ".ass": ".ass" - }, - { - ".ass.gz": ".ass.gz (gzipped)" - } - ] - } - ] + "type": "dict", + "collapsible": true, + "key": "create", + "label": "Creator plugins", + "children": [ + { + "type": "dict", + "collapsible": true, + "key": "CreateArnoldAss", + "label": "Create Arnold Ass", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "list", + "key": "default_variants", + "label": "Default Subsets", + "object_type": "text" + }, + { + "type": "enum", + "key": "ext", + "label": "Default Output Format (extension)", + "multiselection": false, + "enum_items": [ + { + ".ass": ".ass" + }, + { + ".ass.gz": ".ass.gz (gzipped)" + } + ] + } + ] - }, - { - "type": "schema_template", - "name": "template_create_plugin", - "template_data": [ - { - "key": "CreateAlembicCamera", - "label": "Create Alembic Camera" }, - { - "key": "CreateCompositeSequence", - "label": "Create Composite (Image Sequence)" - }, - { - "key": "CreatePointCache", - "label": "Create Point Cache" - }, - { - "key": "CreateRedshiftROP", - "label": "Create Redshift ROP" - }, - { - "key": "CreateRemotePublish", - "label": "Create Remote Publish" - }, - { - "key": "CreateVDBCache", - "label": "Create VDB Cache" - }, - { - "key": "CreateUSD", - "label": "Create USD" - }, - { - "key": "CreateUSDModel", - "label": "Create USD Model" - }, - { - "key": "USDCreateShadingWorkspace", - "label": "Create USD Shading Workspace" - }, - { - "key": "CreateUSDRender", - "label": "Create USD Render" - } - ] - } - ] + { + "type": "schema_template", + "name": "template_create_plugin", + "template_data": [ + { + "key": "CreateAlembicCamera", + "label": "Create Alembic Camera" + }, + { + "key": "CreateCompositeSequence", + "label": "Create Composite (Image Sequence)" + }, + { + "key": "CreatePointCache", + "label": "Create Point Cache" + }, + { + "key": "CreateRedshiftROP", + "label": "Create Redshift ROP" + }, + { + "key": "CreateRemotePublish", + "label": "Create Remote Publish" + }, + { + "key": "CreateVDBCache", + "label": "Create VDB Cache" + }, + { + "key": "CreateUSD", + "label": "Create USD" + }, + { + "key": "CreateUSDModel", + "label": "Create USD Model" + }, + { + "key": "USDCreateShadingWorkspace", + "label": "Create USD Shading Workspace" + }, + { + "key": "CreateUSDRender", + "label": "Create USD Render" + } + ] + } + ] } From 67840465ab7cdd2c9f282b13324d53620cbce60d Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 14 Aug 2023 14:36:35 +0800 Subject: [PATCH 025/154] update the attribute after OP Param update --- openpype/hosts/max/api/pipeline.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/max/api/pipeline.py b/openpype/hosts/max/api/pipeline.py index 82470dd510..36c29ddbbb 100644 --- a/openpype/hosts/max/api/pipeline.py +++ b/openpype/hosts/max/api/pipeline.py @@ -194,4 +194,4 @@ def load_OpenpypeData(container, loaded_nodes): # Setting the property rt.setProperty( - container.openPypeData, "all_handles", node_list) + container.modifiers[0].openPypeData, "all_handles", node_list) From cb086d113ec10131663d17d3a9e06495558f840d Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 14 Aug 2023 18:06:23 +0800 Subject: [PATCH 026/154] clean up the load OpenpypeData code --- openpype/hosts/max/api/pipeline.py | 25 ++++--------------- .../hosts/max/plugins/load/load_camera_fbx.py | 4 +-- openpype/hosts/max/plugins/load/load_model.py | 11 +++----- .../hosts/max/plugins/load/load_model_fbx.py | 4 +-- .../hosts/max/plugins/load/load_model_obj.py | 4 +-- .../hosts/max/plugins/load/load_model_usd.py | 6 ++--- .../hosts/max/plugins/load/load_pointcache.py | 8 ++---- .../hosts/max/plugins/load/load_pointcloud.py | 4 +-- .../max/plugins/load/load_redshift_proxy.py | 4 +-- 9 files changed, 22 insertions(+), 48 deletions(-) diff --git a/openpype/hosts/max/api/pipeline.py b/openpype/hosts/max/api/pipeline.py index 36c29ddbbb..602b506ef0 100644 --- a/openpype/hosts/max/api/pipeline.py +++ b/openpype/hosts/max/api/pipeline.py @@ -174,24 +174,9 @@ def containerise(name: str, nodes: list, context, loader=None, suffix="_CON"): return container -def load_OpenpypeData(container, loaded_nodes): - """Function to load the OpenpypeData Parameter along with - the published objects - - Args: - container (str): target container to set up - the custom attributes - loaded_nodes (list): list of nodes to be loaded +def load_OpenpypeData(): + """Re-loading the Openpype parameter built by the creator + Returns: + attribute: re-loading the custom OP attributes set in Maxscript """ - attrs = rt.Execute(MS_CUSTOM_ATTRIB) - if rt.custAttributes.get(container.baseObject, attrs): - rt.custAttributes.delete(container.baseObject, attrs) - rt.custAttributes.add(container.baseObject, attrs) - node_list = [] - for i in loaded_nodes: - node_ref = rt.NodeTransformMonitor(node=i) - node_list.append(node_ref) - - # Setting the property - rt.setProperty( - container.modifiers[0].openPypeData, "all_handles", node_list) + return rt.Execute(MS_CUSTOM_ATTRIB) diff --git a/openpype/hosts/max/plugins/load/load_camera_fbx.py b/openpype/hosts/max/plugins/load/load_camera_fbx.py index 6b16bfe474..e7aa482b2e 100644 --- a/openpype/hosts/max/plugins/load/load_camera_fbx.py +++ b/openpype/hosts/max/plugins/load/load_camera_fbx.py @@ -33,7 +33,7 @@ class FbxLoader(load.LoaderPlugin): container = rt.Container() container.name = f"{name}" selections = rt.GetCurrentSelection() - load_OpenpypeData(container, selections) + load_OpenpypeData() for selection in selections: selection.Parent = container @@ -52,7 +52,7 @@ class FbxLoader(load.LoaderPlugin): rt.FBXImporterSetParam("Preserveinstances", True) rt.ImportFile( path, rt.name("noPrompt"), using=rt.FBXIMP) - load_OpenpypeData(node, node.Children) + load_OpenpypeData() with maintained_selection(): rt.Select(node) diff --git a/openpype/hosts/max/plugins/load/load_model.py b/openpype/hosts/max/plugins/load/load_model.py index efd758063d..e987e5e900 100644 --- a/openpype/hosts/max/plugins/load/load_model.py +++ b/openpype/hosts/max/plugins/load/load_model.py @@ -45,10 +45,7 @@ class ModelAbcLoader(load.LoaderPlugin): self.log.error("Something failed when loading.") abc_container = abc_containers.pop() - selections = rt.GetCurrentSelection() - abc_selections = [abc for abc in selections - if abc.name != "Alembic"] - load_OpenpypeData(abc_container, abc_selections) + load_OpenpypeData() return containerise( name, [abc_container], context, loader=self.__class__.__name__ ) @@ -61,7 +58,6 @@ class ModelAbcLoader(load.LoaderPlugin): rt.Select(node.Children) nodes_list = [] - abc_object = None with maintained_selection(): rt.Select(node) @@ -77,9 +73,8 @@ class ModelAbcLoader(load.LoaderPlugin): alembic_obj = rt.GetNodeByName(abc_obj.name) alembic_obj.source = path nodes_list.append(alembic_obj) - abc_selections = [abc for abc in nodes_list - if abc.name != "Alembic"] - load_OpenpypeData(abc_object, abc_selections) + + load_OpenpypeData() lib.imprint( container["instance_node"], diff --git a/openpype/hosts/max/plugins/load/load_model_fbx.py b/openpype/hosts/max/plugins/load/load_model_fbx.py index 8f2b4f4ac3..76c2639388 100644 --- a/openpype/hosts/max/plugins/load/load_model_fbx.py +++ b/openpype/hosts/max/plugins/load/load_model_fbx.py @@ -29,7 +29,7 @@ class FbxModelLoader(load.LoaderPlugin): container.name = name selections = rt.GetCurrentSelection() - load_OpenpypeData(container, selections) + load_OpenpypeData() for selection in selections: selection.Parent = container @@ -50,7 +50,7 @@ class FbxModelLoader(load.LoaderPlugin): rt.FBXImporterSetParam("UpAxis", "Y") rt.FBXImporterSetParam("Preserveinstances", True) rt.importFile(path, rt.name("noPrompt"), using=rt.FBXIMP) - load_OpenpypeData(container, node.Children) + load_OpenpypeData() with maintained_selection(): rt.Select(node) diff --git a/openpype/hosts/max/plugins/load/load_model_obj.py b/openpype/hosts/max/plugins/load/load_model_obj.py index 83b5ec49b9..5a7181f438 100644 --- a/openpype/hosts/max/plugins/load/load_model_obj.py +++ b/openpype/hosts/max/plugins/load/load_model_obj.py @@ -26,7 +26,7 @@ class ObjLoader(load.LoaderPlugin): container = rt.Container() container.name = name selections = rt.GetCurrentSelection() - load_OpenpypeData(container, selections) + load_OpenpypeData() # get current selection for selection in selections: selection.Parent = container @@ -53,7 +53,7 @@ class ObjLoader(load.LoaderPlugin): selections = rt.GetCurrentSelection() for selection in selections: selection.Parent = container - load_OpenpypeData(container, container.Children) + load_OpenpypeData() with maintained_selection(): rt.Select(node) diff --git a/openpype/hosts/max/plugins/load/load_model_usd.py b/openpype/hosts/max/plugins/load/load_model_usd.py index a1961e6d89..0e275dd02e 100644 --- a/openpype/hosts/max/plugins/load/load_model_usd.py +++ b/openpype/hosts/max/plugins/load/load_model_usd.py @@ -30,10 +30,8 @@ class ModelUSDLoader(load.LoaderPlugin): rt.LogLevel = rt.Name("info") rt.USDImporter.importFile(filepath, importOptions=import_options) - selections = rt.GetCurrentSelection() asset = rt.GetNodeByName(name) - mesh_selections = [r for r in selections if r != asset] - load_OpenpypeData(asset, mesh_selections) + load_OpenpypeData() return containerise( name, [asset], context, loader=self.__class__.__name__) @@ -62,7 +60,7 @@ class ModelUSDLoader(load.LoaderPlugin): asset = rt.GetNodeByName(instance_name) asset.Parent = node - load_OpenpypeData(asset, asset.Children) + load_OpenpypeData() with maintained_selection(): rt.Select(node) diff --git a/openpype/hosts/max/plugins/load/load_pointcache.py b/openpype/hosts/max/plugins/load/load_pointcache.py index 7af588566e..dda57add69 100644 --- a/openpype/hosts/max/plugins/load/load_pointcache.py +++ b/openpype/hosts/max/plugins/load/load_pointcache.py @@ -49,9 +49,7 @@ class AbcLoader(load.LoaderPlugin): abc_container = abc_containers.pop() selections = rt.GetCurrentSelection() - abc_selections = [abc for abc in selections - if abc.name != "Alembic"] - load_OpenpypeData(abc_container, abc_selections) + load_OpenpypeData() for abc in selections: for cam_shape in abc.Children: cam_shape.playbackType = 2 @@ -72,7 +70,6 @@ class AbcLoader(load.LoaderPlugin): {"representation": str(representation["_id"])}, ) nodes_list = [] - abc_object = None with maintained_selection(): rt.Select(node.Children) @@ -88,8 +85,7 @@ class AbcLoader(load.LoaderPlugin): alembic_obj = rt.GetNodeByName(abc_obj.name) alembic_obj.source = path nodes_list.append(alembic_obj) - abc_selections = [abc for abc in nodes_list if abc.name != "Alembic"] - load_OpenpypeData(abc_object, abc_selections) + load_OpenpypeData() def switch(self, container, representation): self.update(container, representation) diff --git a/openpype/hosts/max/plugins/load/load_pointcloud.py b/openpype/hosts/max/plugins/load/load_pointcloud.py index 18998f4529..8ab81d79e7 100644 --- a/openpype/hosts/max/plugins/load/load_pointcloud.py +++ b/openpype/hosts/max/plugins/load/load_pointcloud.py @@ -25,7 +25,7 @@ class PointCloudLoader(load.LoaderPlugin): prt_container = rt.container() prt_container.name = name obj.Parent = prt_container - load_OpenpypeData(prt_container, [obj]) + load_OpenpypeData() return containerise( name, [prt_container], context, loader=self.__class__.__name__) @@ -41,7 +41,7 @@ class PointCloudLoader(load.LoaderPlugin): for prt in rt.Selection: prt_object = rt.GetNodeByName(prt.name) prt_object.filename = path - load_OpenpypeData(node, node.Children) + load_OpenpypeData() lib.imprint(container["instance_node"], { "representation": str(representation["_id"]) }) diff --git a/openpype/hosts/max/plugins/load/load_redshift_proxy.py b/openpype/hosts/max/plugins/load/load_redshift_proxy.py index b62400d2e5..23f78d0629 100644 --- a/openpype/hosts/max/plugins/load/load_redshift_proxy.py +++ b/openpype/hosts/max/plugins/load/load_redshift_proxy.py @@ -33,7 +33,7 @@ class RedshiftProxyLoader(load.LoaderPlugin): container = rt.container() container.name = name rs_proxy.Parent = container - load_OpenpypeData(container, [rs_proxy]) + load_OpenpypeData() asset = rt.getNodeByName(name) return containerise( @@ -49,7 +49,7 @@ class RedshiftProxyLoader(load.LoaderPlugin): for proxy in children_node.Children: proxy.file = path - load_OpenpypeData(node, node.Children) + load_OpenpypeData() lib.imprint(container["instance_node"], { "representation": str(representation["_id"]) }) From fdad1a48b0cc0f460df53b6c9dc101a24b98d656 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 14 Aug 2023 18:09:02 +0800 Subject: [PATCH 027/154] Hound --- openpype/hosts/max/plugins/load/load_model.py | 2 -- openpype/hosts/max/plugins/load/load_pointcache.py | 1 - 2 files changed, 3 deletions(-) diff --git a/openpype/hosts/max/plugins/load/load_model.py b/openpype/hosts/max/plugins/load/load_model.py index e987e5e900..7ba048c5e7 100644 --- a/openpype/hosts/max/plugins/load/load_model.py +++ b/openpype/hosts/max/plugins/load/load_model.py @@ -60,13 +60,11 @@ class ModelAbcLoader(load.LoaderPlugin): nodes_list = [] with maintained_selection(): rt.Select(node) - for alembic in rt.Selection: abc = rt.GetNodeByName(alembic.name) rt.Select(abc.Children) for abc_con in rt.Selection: container = rt.GetNodeByName(abc_con.name) - abc_object = container container.source = path rt.Select(container.Children) for abc_obj in rt.Selection: diff --git a/openpype/hosts/max/plugins/load/load_pointcache.py b/openpype/hosts/max/plugins/load/load_pointcache.py index dda57add69..ec379e39f7 100644 --- a/openpype/hosts/max/plugins/load/load_pointcache.py +++ b/openpype/hosts/max/plugins/load/load_pointcache.py @@ -78,7 +78,6 @@ class AbcLoader(load.LoaderPlugin): rt.Select(abc.Children) for abc_con in rt.Selection: container = rt.GetNodeByName(abc_con.name) - abc_object = container container.source = path rt.Select(container.Children) for abc_obj in rt.Selection: From e666ff641b4e80dc5aaff837fffd2b0f9651f6c2 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 15 Aug 2023 17:14:42 +0800 Subject: [PATCH 028/154] reload the modifiers to the container with OP Data --- openpype/hosts/max/api/pipeline.py | 27 +++++++++++++++++++ .../hosts/max/plugins/load/load_camera_fbx.py | 18 +++++++------ openpype/hosts/max/plugins/load/load_model.py | 11 ++++---- .../hosts/max/plugins/load/load_model_fbx.py | 13 ++++++--- .../hosts/max/plugins/load/load_model_obj.py | 6 ++--- .../hosts/max/plugins/load/load_model_usd.py | 8 +++--- .../hosts/max/plugins/load/load_pointcache.py | 11 +++++--- .../hosts/max/plugins/load/load_pointcloud.py | 8 +++--- .../max/plugins/load/load_redshift_proxy.py | 8 +++--- 9 files changed, 78 insertions(+), 32 deletions(-) diff --git a/openpype/hosts/max/api/pipeline.py b/openpype/hosts/max/api/pipeline.py index 602b506ef0..6b02f06b85 100644 --- a/openpype/hosts/max/api/pipeline.py +++ b/openpype/hosts/max/api/pipeline.py @@ -180,3 +180,30 @@ def load_OpenpypeData(): attribute: re-loading the custom OP attributes set in Maxscript """ return rt.Execute(MS_CUSTOM_ATTRIB) + + +def import_OpenpypeData(container, selections): + attrs = load_OpenpypeData() + modifier = rt.EmptyModifier() + rt.addModifier(container, modifier) + container.modifiers[0].name = "OP Data" + rt.custAttributes.add(container.modifiers[0], attrs) + node_list = [] + sel_list = [] + for i in selections: + node_ref = rt.NodeTransformMonitor(node=i) + node_list.append(node_ref) + sel_list.append(str(i)) + # Setting the property + rt.setProperty( + container.modifiers[0].openPypeData, + "all_handles", node_list) + rt.setProperty( + container.modifiers[0].openPypeData, + "sel_list", sel_list) + + +def update_Openpype_Data(container, selections): + if container.modifiers[0].name == "OP Data": + rt.deleteModifier(container, container.modifiers[0]) + import_OpenpypeData(container, selections) diff --git a/openpype/hosts/max/plugins/load/load_camera_fbx.py b/openpype/hosts/max/plugins/load/load_camera_fbx.py index e7aa482b2e..7bd02e4615 100644 --- a/openpype/hosts/max/plugins/load/load_camera_fbx.py +++ b/openpype/hosts/max/plugins/load/load_camera_fbx.py @@ -1,7 +1,9 @@ import os from openpype.hosts.max.api import lib, maintained_selection -from openpype.hosts.max.api.pipeline import containerise, load_OpenpypeData +from openpype.hosts.max.api.pipeline import ( + containerise, import_OpenpypeData, update_Openpype_Data +) from openpype.pipeline import get_representation_path, load @@ -16,24 +18,21 @@ class FbxLoader(load.LoaderPlugin): def load(self, context, name=None, namespace=None, data=None): from pymxs import runtime as rt - filepath = self.filepath_from_context(context) filepath = os.path.normpath(filepath) rt.FBXImporterSetParam("Animation", True) rt.FBXImporterSetParam("Camera", True) rt.FBXImporterSetParam("AxisConversionMethod", True) + rt.FBXImporterSetParam("Mode", rt.Name("create")) rt.FBXImporterSetParam("Preserveinstances", True) rt.ImportFile( filepath, rt.name("noPrompt"), using=rt.FBXIMP) - container = rt.GetNodeByName(f"{name}") - if not container: - container = rt.Container() - container.name = f"{name}" + container = rt.container(name=name) selections = rt.GetCurrentSelection() - load_OpenpypeData() + import_OpenpypeData(container, selections) for selection in selections: selection.Parent = container @@ -45,14 +44,17 @@ class FbxLoader(load.LoaderPlugin): path = get_representation_path(representation) node = rt.GetNodeByName(container["instance_node"]) + inst_name, _ = os.path.split(container["instance_node"]) + container = rt.getNodeByName(inst_name) rt.Select(node.Children) + update_Openpype_Data(container, rt.GetCurrentSelection()) rt.FBXImporterSetParam("Animation", True) rt.FBXImporterSetParam("Camera", True) + rt.FBXImporterSetParam("Mode", rt.Name("merge")) rt.FBXImporterSetParam("AxisConversionMethod", True) rt.FBXImporterSetParam("Preserveinstances", True) rt.ImportFile( path, rt.name("noPrompt"), using=rt.FBXIMP) - load_OpenpypeData() with maintained_selection(): rt.Select(node) diff --git a/openpype/hosts/max/plugins/load/load_model.py b/openpype/hosts/max/plugins/load/load_model.py index 7ba048c5e7..ea60c33c19 100644 --- a/openpype/hosts/max/plugins/load/load_model.py +++ b/openpype/hosts/max/plugins/load/load_model.py @@ -1,6 +1,8 @@ import os from openpype.pipeline import load, get_representation_path -from openpype.hosts.max.api.pipeline import containerise, load_OpenpypeData +from openpype.hosts.max.api.pipeline import ( + containerise, import_OpenpypeData, update_Openpype_Data +) from openpype.hosts.max.api import lib from openpype.hosts.max.api.lib import maintained_selection @@ -30,7 +32,7 @@ class ModelAbcLoader(load.LoaderPlugin): rt.AlembicImport.CustomAttributes = True rt.AlembicImport.UVs = True rt.AlembicImport.VertexColors = True - rt.importFile(file_path, rt.name("noPrompt")) + rt.importFile(file_path, rt.name("noPrompt"), using=rt.AlembicImport) abc_after = { c @@ -45,7 +47,7 @@ class ModelAbcLoader(load.LoaderPlugin): self.log.error("Something failed when loading.") abc_container = abc_containers.pop() - load_OpenpypeData() + import_OpenpypeData(abc_container, abc_container.Children) return containerise( name, [abc_container], context, loader=self.__class__.__name__ ) @@ -62,6 +64,7 @@ class ModelAbcLoader(load.LoaderPlugin): rt.Select(node) for alembic in rt.Selection: abc = rt.GetNodeByName(alembic.name) + import_OpenpypeData(abc, abc.Children) rt.Select(abc.Children) for abc_con in rt.Selection: container = rt.GetNodeByName(abc_con.name) @@ -72,8 +75,6 @@ class ModelAbcLoader(load.LoaderPlugin): alembic_obj.source = path nodes_list.append(alembic_obj) - load_OpenpypeData() - lib.imprint( container["instance_node"], {"representation": str(representation["_id"])}, diff --git a/openpype/hosts/max/plugins/load/load_model_fbx.py b/openpype/hosts/max/plugins/load/load_model_fbx.py index 76c2639388..9f80875d5b 100644 --- a/openpype/hosts/max/plugins/load/load_model_fbx.py +++ b/openpype/hosts/max/plugins/load/load_model_fbx.py @@ -1,6 +1,8 @@ import os from openpype.pipeline import load, get_representation_path -from openpype.hosts.max.api.pipeline import containerise, load_OpenpypeData +from openpype.hosts.max.api.pipeline import ( + containerise, import_OpenpypeData, update_Openpype_Data +) from openpype.hosts.max.api import lib from openpype.hosts.max.api.lib import maintained_selection @@ -20,6 +22,7 @@ class FbxModelLoader(load.LoaderPlugin): filepath = os.path.normpath(self.filepath_from_context(context)) rt.FBXImporterSetParam("Animation", False) rt.FBXImporterSetParam("Cameras", False) + rt.FBXImporterSetParam("Mode", rt.Name("create")) rt.FBXImporterSetParam("Preserveinstances", True) rt.importFile(filepath, rt.name("noPrompt"), using=rt.FBXIMP) @@ -29,7 +32,7 @@ class FbxModelLoader(load.LoaderPlugin): container.name = name selections = rt.GetCurrentSelection() - load_OpenpypeData() + import_OpenpypeData(container, selections) for selection in selections: selection.Parent = container @@ -42,15 +45,19 @@ class FbxModelLoader(load.LoaderPlugin): from pymxs import runtime as rt path = get_representation_path(representation) node = rt.getNodeByName(container["instance_node"]) + inst_name, _ = os.path.splitext(container["instance_node"]) rt.select(node.Children) rt.FBXImporterSetParam("Animation", False) rt.FBXImporterSetParam("Cameras", False) + rt.FBXImporterSetParam("Mode", rt.Name("merge")) rt.FBXImporterSetParam("AxisConversionMethod", True) rt.FBXImporterSetParam("UpAxis", "Y") rt.FBXImporterSetParam("Preserveinstances", True) rt.importFile(path, rt.name("noPrompt"), using=rt.FBXIMP) - load_OpenpypeData() + + container = rt.getNodeByName(inst_name) + update_Openpype_Data(container, rt.GetCurrentSelection()) with maintained_selection(): rt.Select(node) diff --git a/openpype/hosts/max/plugins/load/load_model_obj.py b/openpype/hosts/max/plugins/load/load_model_obj.py index 5a7181f438..f4791bfbb3 100644 --- a/openpype/hosts/max/plugins/load/load_model_obj.py +++ b/openpype/hosts/max/plugins/load/load_model_obj.py @@ -2,7 +2,7 @@ import os from openpype.hosts.max.api import lib from openpype.hosts.max.api.lib import maintained_selection -from openpype.hosts.max.api.pipeline import containerise, load_OpenpypeData +from openpype.hosts.max.api.pipeline import containerise, import_OpenpypeData from openpype.pipeline import get_representation_path, load @@ -26,7 +26,7 @@ class ObjLoader(load.LoaderPlugin): container = rt.Container() container.name = name selections = rt.GetCurrentSelection() - load_OpenpypeData() + import_OpenpypeData(container, selections) # get current selection for selection in selections: selection.Parent = container @@ -53,7 +53,7 @@ class ObjLoader(load.LoaderPlugin): selections = rt.GetCurrentSelection() for selection in selections: selection.Parent = container - load_OpenpypeData() + import_OpenpypeData(container, selections) with maintained_selection(): rt.Select(node) diff --git a/openpype/hosts/max/plugins/load/load_model_usd.py b/openpype/hosts/max/plugins/load/load_model_usd.py index 0e275dd02e..96b5cdedf0 100644 --- a/openpype/hosts/max/plugins/load/load_model_usd.py +++ b/openpype/hosts/max/plugins/load/load_model_usd.py @@ -2,7 +2,9 @@ import os from openpype.hosts.max.api import lib from openpype.hosts.max.api.lib import maintained_selection -from openpype.hosts.max.api.pipeline import containerise, load_OpenpypeData +from openpype.hosts.max.api.pipeline import ( + containerise, import_OpenpypeData, update_Openpype_Data +) from openpype.pipeline import get_representation_path, load @@ -31,7 +33,7 @@ class ModelUSDLoader(load.LoaderPlugin): rt.USDImporter.importFile(filepath, importOptions=import_options) asset = rt.GetNodeByName(name) - load_OpenpypeData() + import_OpenpypeData(asset, asset.Children) return containerise( name, [asset], context, loader=self.__class__.__name__) @@ -60,7 +62,7 @@ class ModelUSDLoader(load.LoaderPlugin): asset = rt.GetNodeByName(instance_name) asset.Parent = node - load_OpenpypeData() + update_Openpype_Data(asset, asset.Children) with maintained_selection(): rt.Select(node) diff --git a/openpype/hosts/max/plugins/load/load_pointcache.py b/openpype/hosts/max/plugins/load/load_pointcache.py index ec379e39f7..18a68732e9 100644 --- a/openpype/hosts/max/plugins/load/load_pointcache.py +++ b/openpype/hosts/max/plugins/load/load_pointcache.py @@ -7,7 +7,9 @@ Because of limited api, alembics can be only loaded, but not easily updated. import os from openpype.pipeline import load, get_representation_path from openpype.hosts.max.api import lib, maintained_selection -from openpype.hosts.max.api.pipeline import containerise, load_OpenpypeData +from openpype.hosts.max.api.pipeline import ( + containerise, import_OpenpypeData, update_Openpype_Data +) class AbcLoader(load.LoaderPlugin): @@ -33,7 +35,7 @@ class AbcLoader(load.LoaderPlugin): } rt.AlembicImport.ImportToRoot = False - rt.importFile(file_path, rt.name("noPrompt")) + rt.importFile(file_path, rt.name("noPrompt"), using=rt.AlembicImport) abc_after = { c @@ -49,7 +51,7 @@ class AbcLoader(load.LoaderPlugin): abc_container = abc_containers.pop() selections = rt.GetCurrentSelection() - load_OpenpypeData() + import_OpenpypeData(abc_container, abc_container.Children) for abc in selections: for cam_shape in abc.Children: cam_shape.playbackType = 2 @@ -75,6 +77,7 @@ class AbcLoader(load.LoaderPlugin): for alembic in rt.Selection: abc = rt.GetNodeByName(alembic.name) + update_Openpype_Data(abc, abc.Children) rt.Select(abc.Children) for abc_con in rt.Selection: container = rt.GetNodeByName(abc_con.name) @@ -84,7 +87,7 @@ class AbcLoader(load.LoaderPlugin): alembic_obj = rt.GetNodeByName(abc_obj.name) alembic_obj.source = path nodes_list.append(alembic_obj) - load_OpenpypeData() + def switch(self, container, representation): self.update(container, representation) diff --git a/openpype/hosts/max/plugins/load/load_pointcloud.py b/openpype/hosts/max/plugins/load/load_pointcloud.py index 8ab81d79e7..2f41173bce 100644 --- a/openpype/hosts/max/plugins/load/load_pointcloud.py +++ b/openpype/hosts/max/plugins/load/load_pointcloud.py @@ -1,7 +1,9 @@ import os from openpype.hosts.max.api import lib, maintained_selection -from openpype.hosts.max.api.pipeline import containerise, load_OpenpypeData +from openpype.hosts.max.api.pipeline import ( + containerise, import_OpenpypeData, update_Openpype_Data +) from openpype.pipeline import get_representation_path, load @@ -25,7 +27,7 @@ class PointCloudLoader(load.LoaderPlugin): prt_container = rt.container() prt_container.name = name obj.Parent = prt_container - load_OpenpypeData() + import_OpenpypeData(prt_container, [obj]) return containerise( name, [prt_container], context, loader=self.__class__.__name__) @@ -41,7 +43,7 @@ class PointCloudLoader(load.LoaderPlugin): for prt in rt.Selection: prt_object = rt.GetNodeByName(prt.name) prt_object.filename = path - load_OpenpypeData() + update_Openpype_Data(node, node.Children) lib.imprint(container["instance_node"], { "representation": str(representation["_id"]) }) diff --git a/openpype/hosts/max/plugins/load/load_redshift_proxy.py b/openpype/hosts/max/plugins/load/load_redshift_proxy.py index 23f78d0629..4b488bcb7c 100644 --- a/openpype/hosts/max/plugins/load/load_redshift_proxy.py +++ b/openpype/hosts/max/plugins/load/load_redshift_proxy.py @@ -5,7 +5,9 @@ from openpype.pipeline import ( load, get_representation_path ) -from openpype.hosts.max.api.pipeline import containerise, load_OpenpypeData +from openpype.hosts.max.api.pipeline import ( + containerise, import_OpenpypeData, update_Openpype_Data +) from openpype.hosts.max.api import lib @@ -33,7 +35,7 @@ class RedshiftProxyLoader(load.LoaderPlugin): container = rt.container() container.name = name rs_proxy.Parent = container - load_OpenpypeData() + import_OpenpypeData(container, [rs_proxy]) asset = rt.getNodeByName(name) return containerise( @@ -49,7 +51,7 @@ class RedshiftProxyLoader(load.LoaderPlugin): for proxy in children_node.Children: proxy.file = path - load_OpenpypeData() + update_Openpype_Data(node, node.Children) lib.imprint(container["instance_node"], { "representation": str(representation["_id"]) }) From 5f54f9082477162d65d9944365a285e732fad0fd Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 15 Aug 2023 17:16:14 +0800 Subject: [PATCH 029/154] reload the moddifier with OP Data in load model --- openpype/hosts/max/plugins/load/load_model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/max/plugins/load/load_model.py b/openpype/hosts/max/plugins/load/load_model.py index ea60c33c19..e1978e35ad 100644 --- a/openpype/hosts/max/plugins/load/load_model.py +++ b/openpype/hosts/max/plugins/load/load_model.py @@ -64,7 +64,7 @@ class ModelAbcLoader(load.LoaderPlugin): rt.Select(node) for alembic in rt.Selection: abc = rt.GetNodeByName(alembic.name) - import_OpenpypeData(abc, abc.Children) + update_Openpype_Data(abc, abc.Children) rt.Select(abc.Children) for abc_con in rt.Selection: container = rt.GetNodeByName(abc_con.name) From cf4ce6bbc5d2684f7fbbcc4b66865dd1be2ebc98 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 15 Aug 2023 22:36:28 +0800 Subject: [PATCH 030/154] rename the loadOpenpypedata functions --- openpype/hosts/max/api/pipeline.py | 27 ++++++++++++++----- .../hosts/max/plugins/load/load_camera_fbx.py | 9 ++++--- openpype/hosts/max/plugins/load/load_model.py | 9 ++++--- .../hosts/max/plugins/load/load_model_fbx.py | 7 ++--- .../hosts/max/plugins/load/load_model_obj.py | 10 ++++--- .../hosts/max/plugins/load/load_model_usd.py | 8 +++--- .../hosts/max/plugins/load/load_pointcache.py | 9 ++++--- .../hosts/max/plugins/load/load_pointcloud.py | 8 +++--- .../max/plugins/load/load_redshift_proxy.py | 8 +++--- 9 files changed, 65 insertions(+), 30 deletions(-) diff --git a/openpype/hosts/max/api/pipeline.py b/openpype/hosts/max/api/pipeline.py index 6b02f06b85..08ff5c6baf 100644 --- a/openpype/hosts/max/api/pipeline.py +++ b/openpype/hosts/max/api/pipeline.py @@ -174,16 +174,24 @@ def containerise(name: str, nodes: list, context, loader=None, suffix="_CON"): return container -def load_OpenpypeData(): - """Re-loading the Openpype parameter built by the creator +def load_custom_attribute_data(): + """Re-loading the Openpype/AYON custom parameter built by the creator + Returns: attribute: re-loading the custom OP attributes set in Maxscript """ return rt.Execute(MS_CUSTOM_ATTRIB) -def import_OpenpypeData(container, selections): - attrs = load_OpenpypeData() +def import_custom_attribute_data(container: str, selections: list): + """Importing the Openpype/AYON custom parameter built by the creator + + Args: + container (str): target container which adds custom attributes + selections (_type_): nodes to be added into + group in custom attributes + """ + attrs = load_custom_attribute_data() modifier = rt.EmptyModifier() rt.addModifier(container, modifier) container.modifiers[0].name = "OP Data" @@ -203,7 +211,14 @@ def import_OpenpypeData(container, selections): "sel_list", sel_list) -def update_Openpype_Data(container, selections): +def update_custom_attribute_data(container: str, selections: list): + """Updating the Openpype/AYON custom parameter built by the creator + + Args: + container (str): target container which adds custom attributes + selections (_type_): nodes to be added into + group in custom attributes + """ if container.modifiers[0].name == "OP Data": rt.deleteModifier(container, container.modifiers[0]) - import_OpenpypeData(container, selections) + import_custom_attribute_data(container, selections) diff --git a/openpype/hosts/max/plugins/load/load_camera_fbx.py b/openpype/hosts/max/plugins/load/load_camera_fbx.py index 7bd02e4615..1e4e5b3e91 100644 --- a/openpype/hosts/max/plugins/load/load_camera_fbx.py +++ b/openpype/hosts/max/plugins/load/load_camera_fbx.py @@ -2,7 +2,9 @@ import os from openpype.hosts.max.api import lib, maintained_selection from openpype.hosts.max.api.pipeline import ( - containerise, import_OpenpypeData, update_Openpype_Data + containerise, + import_custom_attribute_data, + update_custom_attribute_data ) from openpype.pipeline import get_representation_path, load @@ -32,7 +34,7 @@ class FbxLoader(load.LoaderPlugin): container = rt.container(name=name) selections = rt.GetCurrentSelection() - import_OpenpypeData(container, selections) + import_custom_attribute_data(container, selections) for selection in selections: selection.Parent = container @@ -47,7 +49,8 @@ class FbxLoader(load.LoaderPlugin): inst_name, _ = os.path.split(container["instance_node"]) container = rt.getNodeByName(inst_name) rt.Select(node.Children) - update_Openpype_Data(container, rt.GetCurrentSelection()) + update_custom_attribute_data( + container, rt.GetCurrentSelection()) rt.FBXImporterSetParam("Animation", True) rt.FBXImporterSetParam("Camera", True) rt.FBXImporterSetParam("Mode", rt.Name("merge")) diff --git a/openpype/hosts/max/plugins/load/load_model.py b/openpype/hosts/max/plugins/load/load_model.py index e1978e35ad..f71e4e8f7f 100644 --- a/openpype/hosts/max/plugins/load/load_model.py +++ b/openpype/hosts/max/plugins/load/load_model.py @@ -1,7 +1,9 @@ import os from openpype.pipeline import load, get_representation_path from openpype.hosts.max.api.pipeline import ( - containerise, import_OpenpypeData, update_Openpype_Data + containerise, + import_custom_attribute_data, + update_custom_attribute_data ) from openpype.hosts.max.api import lib from openpype.hosts.max.api.lib import maintained_selection @@ -47,7 +49,8 @@ class ModelAbcLoader(load.LoaderPlugin): self.log.error("Something failed when loading.") abc_container = abc_containers.pop() - import_OpenpypeData(abc_container, abc_container.Children) + import_custom_attribute_data( + abc_container, abc_container.Children) return containerise( name, [abc_container], context, loader=self.__class__.__name__ ) @@ -64,7 +67,7 @@ class ModelAbcLoader(load.LoaderPlugin): rt.Select(node) for alembic in rt.Selection: abc = rt.GetNodeByName(alembic.name) - update_Openpype_Data(abc, abc.Children) + update_custom_attribute_data(abc, abc.Children) rt.Select(abc.Children) for abc_con in rt.Selection: container = rt.GetNodeByName(abc_con.name) diff --git a/openpype/hosts/max/plugins/load/load_model_fbx.py b/openpype/hosts/max/plugins/load/load_model_fbx.py index 9f80875d5b..26520307c9 100644 --- a/openpype/hosts/max/plugins/load/load_model_fbx.py +++ b/openpype/hosts/max/plugins/load/load_model_fbx.py @@ -1,7 +1,7 @@ import os from openpype.pipeline import load, get_representation_path from openpype.hosts.max.api.pipeline import ( - containerise, import_OpenpypeData, update_Openpype_Data + containerise, import_custom_attribute_data, update_custom_attribute_data ) from openpype.hosts.max.api import lib from openpype.hosts.max.api.lib import maintained_selection @@ -32,7 +32,7 @@ class FbxModelLoader(load.LoaderPlugin): container.name = name selections = rt.GetCurrentSelection() - import_OpenpypeData(container, selections) + import_custom_attribute_data(container, selections) for selection in selections: selection.Parent = container @@ -57,7 +57,8 @@ class FbxModelLoader(load.LoaderPlugin): rt.importFile(path, rt.name("noPrompt"), using=rt.FBXIMP) container = rt.getNodeByName(inst_name) - update_Openpype_Data(container, rt.GetCurrentSelection()) + update_custom_attribute_data( + container, rt.GetCurrentSelection()) with maintained_selection(): rt.Select(node) diff --git a/openpype/hosts/max/plugins/load/load_model_obj.py b/openpype/hosts/max/plugins/load/load_model_obj.py index f4791bfbb3..05f37f9e5a 100644 --- a/openpype/hosts/max/plugins/load/load_model_obj.py +++ b/openpype/hosts/max/plugins/load/load_model_obj.py @@ -2,7 +2,11 @@ import os from openpype.hosts.max.api import lib from openpype.hosts.max.api.lib import maintained_selection -from openpype.hosts.max.api.pipeline import containerise, import_OpenpypeData +from openpype.hosts.max.api.pipeline import ( + containerise, + import_custom_attribute_data, + update_custom_attribute_data +) from openpype.pipeline import get_representation_path, load @@ -26,7 +30,7 @@ class ObjLoader(load.LoaderPlugin): container = rt.Container() container.name = name selections = rt.GetCurrentSelection() - import_OpenpypeData(container, selections) + import_custom_attribute_data(container, selections) # get current selection for selection in selections: selection.Parent = container @@ -53,7 +57,7 @@ class ObjLoader(load.LoaderPlugin): selections = rt.GetCurrentSelection() for selection in selections: selection.Parent = container - import_OpenpypeData(container, selections) + update_custom_attribute_data(container, selections) with maintained_selection(): rt.Select(node) diff --git a/openpype/hosts/max/plugins/load/load_model_usd.py b/openpype/hosts/max/plugins/load/load_model_usd.py index 96b5cdedf0..425b152278 100644 --- a/openpype/hosts/max/plugins/load/load_model_usd.py +++ b/openpype/hosts/max/plugins/load/load_model_usd.py @@ -3,7 +3,9 @@ import os from openpype.hosts.max.api import lib from openpype.hosts.max.api.lib import maintained_selection from openpype.hosts.max.api.pipeline import ( - containerise, import_OpenpypeData, update_Openpype_Data + containerise, + import_custom_attribute_data, + update_custom_attribute_data ) from openpype.pipeline import get_representation_path, load @@ -33,7 +35,7 @@ class ModelUSDLoader(load.LoaderPlugin): rt.USDImporter.importFile(filepath, importOptions=import_options) asset = rt.GetNodeByName(name) - import_OpenpypeData(asset, asset.Children) + import_custom_attribute_data(asset, asset.Children) return containerise( name, [asset], context, loader=self.__class__.__name__) @@ -62,7 +64,7 @@ class ModelUSDLoader(load.LoaderPlugin): asset = rt.GetNodeByName(instance_name) asset.Parent = node - update_Openpype_Data(asset, asset.Children) + update_custom_attribute_data(asset, asset.Children) with maintained_selection(): rt.Select(node) diff --git a/openpype/hosts/max/plugins/load/load_pointcache.py b/openpype/hosts/max/plugins/load/load_pointcache.py index 18a68732e9..0ec9fda3d5 100644 --- a/openpype/hosts/max/plugins/load/load_pointcache.py +++ b/openpype/hosts/max/plugins/load/load_pointcache.py @@ -8,7 +8,9 @@ import os from openpype.pipeline import load, get_representation_path from openpype.hosts.max.api import lib, maintained_selection from openpype.hosts.max.api.pipeline import ( - containerise, import_OpenpypeData, update_Openpype_Data + containerise, + import_custom_attribute_data, + update_custom_attribute_data ) @@ -51,7 +53,8 @@ class AbcLoader(load.LoaderPlugin): abc_container = abc_containers.pop() selections = rt.GetCurrentSelection() - import_OpenpypeData(abc_container, abc_container.Children) + import_custom_attribute_data( + abc_container, abc_container.Children) for abc in selections: for cam_shape in abc.Children: cam_shape.playbackType = 2 @@ -77,7 +80,7 @@ class AbcLoader(load.LoaderPlugin): for alembic in rt.Selection: abc = rt.GetNodeByName(alembic.name) - update_Openpype_Data(abc, abc.Children) + update_custom_attribute_data(abc, abc.Children) rt.Select(abc.Children) for abc_con in rt.Selection: container = rt.GetNodeByName(abc_con.name) diff --git a/openpype/hosts/max/plugins/load/load_pointcloud.py b/openpype/hosts/max/plugins/load/load_pointcloud.py index 2f41173bce..c263019beb 100644 --- a/openpype/hosts/max/plugins/load/load_pointcloud.py +++ b/openpype/hosts/max/plugins/load/load_pointcloud.py @@ -2,7 +2,9 @@ import os from openpype.hosts.max.api import lib, maintained_selection from openpype.hosts.max.api.pipeline import ( - containerise, import_OpenpypeData, update_Openpype_Data + containerise, + import_custom_attribute_data, + update_custom_attribute_data ) from openpype.pipeline import get_representation_path, load @@ -27,7 +29,7 @@ class PointCloudLoader(load.LoaderPlugin): prt_container = rt.container() prt_container.name = name obj.Parent = prt_container - import_OpenpypeData(prt_container, [obj]) + import_custom_attribute_data(prt_container, [obj]) return containerise( name, [prt_container], context, loader=self.__class__.__name__) @@ -43,7 +45,7 @@ class PointCloudLoader(load.LoaderPlugin): for prt in rt.Selection: prt_object = rt.GetNodeByName(prt.name) prt_object.filename = path - update_Openpype_Data(node, node.Children) + update_custom_attribute_data(node, node.Children) lib.imprint(container["instance_node"], { "representation": str(representation["_id"]) }) diff --git a/openpype/hosts/max/plugins/load/load_redshift_proxy.py b/openpype/hosts/max/plugins/load/load_redshift_proxy.py index 4b488bcb7c..6b100df611 100644 --- a/openpype/hosts/max/plugins/load/load_redshift_proxy.py +++ b/openpype/hosts/max/plugins/load/load_redshift_proxy.py @@ -6,7 +6,9 @@ from openpype.pipeline import ( get_representation_path ) from openpype.hosts.max.api.pipeline import ( - containerise, import_OpenpypeData, update_Openpype_Data + containerise, + import_custom_attribute_data, + update_custom_attribute_data ) from openpype.hosts.max.api import lib @@ -35,7 +37,7 @@ class RedshiftProxyLoader(load.LoaderPlugin): container = rt.container() container.name = name rs_proxy.Parent = container - import_OpenpypeData(container, [rs_proxy]) + import_custom_attribute_data(container, [rs_proxy]) asset = rt.getNodeByName(name) return containerise( @@ -51,7 +53,7 @@ class RedshiftProxyLoader(load.LoaderPlugin): for proxy in children_node.Children: proxy.file = path - update_Openpype_Data(node, node.Children) + update_custom_attribute_data(node, node.Children) lib.imprint(container["instance_node"], { "representation": str(representation["_id"]) }) From 8b0ba25c37d177b7b6a43f3536d3f98e9eb67898 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 16 Aug 2023 14:12:58 +0800 Subject: [PATCH 031/154] add load maxscene family --- .../hosts/max/plugins/load/load_max_scene.py | 44 ++++++++++++------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/openpype/hosts/max/plugins/load/load_max_scene.py b/openpype/hosts/max/plugins/load/load_max_scene.py index 76cd3bf367..637659ed44 100644 --- a/openpype/hosts/max/plugins/load/load_max_scene.py +++ b/openpype/hosts/max/plugins/load/load_max_scene.py @@ -1,7 +1,10 @@ import os from openpype.hosts.max.api import lib -from openpype.hosts.max.api.pipeline import containerise +from openpype.hosts.max.api.pipeline import ( + containerise, import_custom_attribute_data, + update_custom_attribute_data +) from openpype.pipeline import get_representation_path, load @@ -19,36 +22,43 @@ class MaxSceneLoader(load.LoaderPlugin): def load(self, context, name=None, namespace=None, data=None): from pymxs import runtime as rt - path = self.filepath_from_context(context) path = os.path.normpath(path) # import the max scene by using "merge file" path = path.replace('\\', '/') - rt.MergeMaxFile(path) + rt.MergeMaxFile(path, quiet=True) max_objects = rt.getLastMergedNodes() - max_container = rt.Container(name=f"{name}") - for max_object in max_objects: - max_object.Parent = max_container - + # implement the OP/AYON custom attributes before load + max_container = [] + container = rt.Container(name=name) + import_custom_attribute_data(container, max_objects) + max_container.append(container) + max_container.extend(max_objects) return containerise( - name, [max_container], context, loader=self.__class__.__name__) + name, max_container, context, loader=self.__class__.__name__) def update(self, container, representation): from pymxs import runtime as rt path = get_representation_path(representation) node_name = container["instance_node"] - - rt.MergeMaxFile(path, - rt.Name("noRedraw"), - rt.Name("deleteOldDups"), - rt.Name("useSceneMtlDups")) - + node = rt.GetNodeByName(node_name) + inst_name, _ = os.path.splitext(node_name) + old_container = rt.getNodeByName(inst_name) + # delete the old container with attribute + # delete old duplicate + rt.Delete(old_container) + rt.MergeMaxFile(path, rt.Name("deleteOldDups")) + new_container = rt.Container(name=inst_name) max_objects = rt.getLastMergedNodes() - container_node = rt.GetNodeByName(node_name) - for max_object in max_objects: - max_object.Parent = container_node + max_objects_list = [] + max_objects_list.append(new_container) + max_objects_list.extend(max_objects) + + for max_object in max_objects_list: + max_object.Parent = node + update_custom_attribute_data(new_container, max_objects) lib.imprint(container["instance_node"], { "representation": str(representation["_id"]) }) From 0825afa73a0f4a706d3b091cfb068565381d5a40 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 16 Aug 2023 14:22:14 +0800 Subject: [PATCH 032/154] add includedfullgroup support for merging scene in max scene family --- openpype/hosts/max/plugins/load/load_max_scene.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/max/plugins/load/load_max_scene.py b/openpype/hosts/max/plugins/load/load_max_scene.py index 637659ed44..7bbc6419b8 100644 --- a/openpype/hosts/max/plugins/load/load_max_scene.py +++ b/openpype/hosts/max/plugins/load/load_max_scene.py @@ -26,7 +26,7 @@ class MaxSceneLoader(load.LoaderPlugin): path = os.path.normpath(path) # import the max scene by using "merge file" path = path.replace('\\', '/') - rt.MergeMaxFile(path, quiet=True) + rt.MergeMaxFile(path, quiet=True, includeFullGroup=True) max_objects = rt.getLastMergedNodes() # implement the OP/AYON custom attributes before load max_container = [] From 86f86db4f84db54eecd127cbac528f3f9752107e Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 16 Aug 2023 17:55:07 +0800 Subject: [PATCH 033/154] also resolves OP-6526_3dsMax-loading-an-asset-multiple-times --- openpype/hosts/max/api/pipeline.py | 4 ++-- openpype/hosts/max/plugins/load/load_max_scene.py | 6 +++++- openpype/hosts/max/plugins/load/load_model_fbx.py | 6 +----- openpype/hosts/max/plugins/load/load_model_obj.py | 8 +++----- openpype/hosts/max/plugins/load/load_model_usd.py | 1 + 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/openpype/hosts/max/api/pipeline.py b/openpype/hosts/max/api/pipeline.py index 08ff5c6baf..f58bd05a13 100644 --- a/openpype/hosts/max/api/pipeline.py +++ b/openpype/hosts/max/api/pipeline.py @@ -188,7 +188,7 @@ def import_custom_attribute_data(container: str, selections: list): Args: container (str): target container which adds custom attributes - selections (_type_): nodes to be added into + selections (list): nodes to be added into group in custom attributes """ attrs = load_custom_attribute_data() @@ -216,7 +216,7 @@ def update_custom_attribute_data(container: str, selections: list): Args: container (str): target container which adds custom attributes - selections (_type_): nodes to be added into + selections (list): nodes to be added into group in custom attributes """ if container.modifiers[0].name == "OP Data": diff --git a/openpype/hosts/max/plugins/load/load_max_scene.py b/openpype/hosts/max/plugins/load/load_max_scene.py index 7bbc6419b8..2f5108aec5 100644 --- a/openpype/hosts/max/plugins/load/load_max_scene.py +++ b/openpype/hosts/max/plugins/load/load_max_scene.py @@ -51,7 +51,11 @@ class MaxSceneLoader(load.LoaderPlugin): rt.MergeMaxFile(path, rt.Name("deleteOldDups")) new_container = rt.Container(name=inst_name) max_objects = rt.getLastMergedNodes() - + current_max_objects = rt.getLastMergedNodes() + for current_object in current_max_objects: + prev_max_objects = prev_max_objects.remove(current_object) + for prev_object in prev_max_objects: + rt.Delete(prev_object) max_objects_list = [] max_objects_list.append(new_container) max_objects_list.extend(max_objects) diff --git a/openpype/hosts/max/plugins/load/load_model_fbx.py b/openpype/hosts/max/plugins/load/load_model_fbx.py index 26520307c9..d076bf2de9 100644 --- a/openpype/hosts/max/plugins/load/load_model_fbx.py +++ b/openpype/hosts/max/plugins/load/load_model_fbx.py @@ -26,11 +26,7 @@ class FbxModelLoader(load.LoaderPlugin): rt.FBXImporterSetParam("Preserveinstances", True) rt.importFile(filepath, rt.name("noPrompt"), using=rt.FBXIMP) - container = rt.GetNodeByName(name) - if not container: - container = rt.Container() - container.name = name - + container = rt.Container(name=name) selections = rt.GetCurrentSelection() import_custom_attribute_data(container, selections) diff --git a/openpype/hosts/max/plugins/load/load_model_obj.py b/openpype/hosts/max/plugins/load/load_model_obj.py index 05f37f9e5a..bac5b8b4f3 100644 --- a/openpype/hosts/max/plugins/load/load_model_obj.py +++ b/openpype/hosts/max/plugins/load/load_model_obj.py @@ -27,18 +27,16 @@ class ObjLoader(load.LoaderPlugin): rt.Execute(f'importFile @"{filepath}" #noPrompt using:ObjImp') # create "missing" container for obj import - container = rt.Container() - container.name = name + container = rt.Container(name=name) selections = rt.GetCurrentSelection() import_custom_attribute_data(container, selections) # get current selection for selection in selections: selection.Parent = container - - asset = rt.GetNodeByName(name) + self.log.debug(f"{container.ClassID}") return containerise( - name, [asset], context, loader=self.__class__.__name__) + name, [container], context, loader=self.__class__.__name__) def update(self, container, representation): from pymxs import runtime as rt diff --git a/openpype/hosts/max/plugins/load/load_model_usd.py b/openpype/hosts/max/plugins/load/load_model_usd.py index 425b152278..d3669fc10e 100644 --- a/openpype/hosts/max/plugins/load/load_model_usd.py +++ b/openpype/hosts/max/plugins/load/load_model_usd.py @@ -35,6 +35,7 @@ class ModelUSDLoader(load.LoaderPlugin): rt.USDImporter.importFile(filepath, importOptions=import_options) asset = rt.GetNodeByName(name) + import_custom_attribute_data(asset, asset.Children) return containerise( From ae42d524c80bab1d5f3583111eb5208c9d515caf Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 16 Aug 2023 18:22:59 +0800 Subject: [PATCH 034/154] fixing the error when updating the max scene in the loader --- openpype/hosts/max/plugins/load/load_max_scene.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/max/plugins/load/load_max_scene.py b/openpype/hosts/max/plugins/load/load_max_scene.py index 2f5108aec5..f73bb1941e 100644 --- a/openpype/hosts/max/plugins/load/load_max_scene.py +++ b/openpype/hosts/max/plugins/load/load_max_scene.py @@ -45,12 +45,12 @@ class MaxSceneLoader(load.LoaderPlugin): node = rt.GetNodeByName(node_name) inst_name, _ = os.path.splitext(node_name) old_container = rt.getNodeByName(inst_name) + prev_max_objects = rt.getLastMergedNodes() # delete the old container with attribute # delete old duplicate rt.Delete(old_container) rt.MergeMaxFile(path, rt.Name("deleteOldDups")) new_container = rt.Container(name=inst_name) - max_objects = rt.getLastMergedNodes() current_max_objects = rt.getLastMergedNodes() for current_object in current_max_objects: prev_max_objects = prev_max_objects.remove(current_object) @@ -58,11 +58,11 @@ class MaxSceneLoader(load.LoaderPlugin): rt.Delete(prev_object) max_objects_list = [] max_objects_list.append(new_container) - max_objects_list.extend(max_objects) + max_objects_list.extend(current_max_objects) for max_object in max_objects_list: max_object.Parent = node - update_custom_attribute_data(new_container, max_objects) + update_custom_attribute_data(new_container, current_max_objects) lib.imprint(container["instance_node"], { "representation": str(representation["_id"]) }) From 8aa150cfe5af1c7259b5f4466835638249c29b73 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 16 Aug 2023 21:37:49 +0800 Subject: [PATCH 035/154] fixing the bug of not being able to update the scene when using maxSceneloader and some clean up --- .../hosts/max/plugins/load/load_camera_fbx.py | 13 ++++---- .../hosts/max/plugins/load/load_max_scene.py | 33 ++++++++++--------- openpype/hosts/max/plugins/load/load_model.py | 6 ++-- .../hosts/max/plugins/load/load_model_fbx.py | 14 +++++--- .../hosts/max/plugins/load/load_model_obj.py | 7 ++-- .../hosts/max/plugins/load/load_pointcache.py | 14 ++++---- 6 files changed, 46 insertions(+), 41 deletions(-) diff --git a/openpype/hosts/max/plugins/load/load_camera_fbx.py b/openpype/hosts/max/plugins/load/load_camera_fbx.py index 1e4e5b3e91..87745ae881 100644 --- a/openpype/hosts/max/plugins/load/load_camera_fbx.py +++ b/openpype/hosts/max/plugins/load/load_camera_fbx.py @@ -45,12 +45,11 @@ class FbxLoader(load.LoaderPlugin): from pymxs import runtime as rt path = get_representation_path(representation) - node = rt.GetNodeByName(container["instance_node"]) - inst_name, _ = os.path.split(container["instance_node"]) - container = rt.getNodeByName(inst_name) + node_name = container["instance_node"] + node = rt.getNodeByName(node_name) + inst_name, _ = node_name.split("_") rt.Select(node.Children) - update_custom_attribute_data( - container, rt.GetCurrentSelection()) + rt.FBXImporterSetParam("Animation", True) rt.FBXImporterSetParam("Camera", True) rt.FBXImporterSetParam("Mode", rt.Name("merge")) @@ -58,7 +57,9 @@ class FbxLoader(load.LoaderPlugin): rt.FBXImporterSetParam("Preserveinstances", True) rt.ImportFile( path, rt.name("noPrompt"), using=rt.FBXIMP) - + inst_container = rt.getNodeByName(inst_name) + update_custom_attribute_data( + inst_container, rt.GetCurrentSelection()) with maintained_selection(): rt.Select(node) diff --git a/openpype/hosts/max/plugins/load/load_max_scene.py b/openpype/hosts/max/plugins/load/load_max_scene.py index f73bb1941e..348b940b22 100644 --- a/openpype/hosts/max/plugins/load/load_max_scene.py +++ b/openpype/hosts/max/plugins/load/load_max_scene.py @@ -42,27 +42,28 @@ class MaxSceneLoader(load.LoaderPlugin): path = get_representation_path(representation) node_name = container["instance_node"] - node = rt.GetNodeByName(node_name) - inst_name, _ = os.path.splitext(node_name) - old_container = rt.getNodeByName(inst_name) - prev_max_objects = rt.getLastMergedNodes() + node = rt.getNodeByName(node_name) + inst_name, _ = node_name.split("_") + inst_container = rt.getNodeByName(inst_name) # delete the old container with attribute # delete old duplicate - rt.Delete(old_container) + prev_max_object_names = [obj.name for obj in rt.getLastMergedNodes()] rt.MergeMaxFile(path, rt.Name("deleteOldDups")) - new_container = rt.Container(name=inst_name) - current_max_objects = rt.getLastMergedNodes() - for current_object in current_max_objects: - prev_max_objects = prev_max_objects.remove(current_object) - for prev_object in prev_max_objects: - rt.Delete(prev_object) - max_objects_list = [] - max_objects_list.append(new_container) - max_objects_list.extend(current_max_objects) - for max_object in max_objects_list: + current_max_objects = rt.getLastMergedNodes() + current_max_object_names = [obj.name for obj in rt.getLastMergedNodes()] + for obj in current_max_object_names: + idx = rt.findItem(prev_max_object_names, obj) + if idx: + prev_max_object_names = rt.deleteItem(prev_max_object_names, idx) + for object_name in prev_max_object_names: + prev_max_object = rt.getNodeByName(object_name) + rt.Delete(prev_max_object) + + update_custom_attribute_data(inst_container, current_max_objects) + + for max_object in current_max_objects: max_object.Parent = node - update_custom_attribute_data(new_container, current_max_objects) lib.imprint(container["instance_node"], { "representation": str(representation["_id"]) }) diff --git a/openpype/hosts/max/plugins/load/load_model.py b/openpype/hosts/max/plugins/load/load_model.py index f71e4e8f7f..a84d497aab 100644 --- a/openpype/hosts/max/plugins/load/load_model.py +++ b/openpype/hosts/max/plugins/load/load_model.py @@ -70,9 +70,9 @@ class ModelAbcLoader(load.LoaderPlugin): update_custom_attribute_data(abc, abc.Children) rt.Select(abc.Children) for abc_con in rt.Selection: - container = rt.GetNodeByName(abc_con.name) - container.source = path - rt.Select(container.Children) + abc_container = rt.GetNodeByName(abc_con.name) + abc_container.source = path + rt.Select(abc_container.Children) for abc_obj in rt.Selection: alembic_obj = rt.GetNodeByName(abc_obj.name) alembic_obj.source = path diff --git a/openpype/hosts/max/plugins/load/load_model_fbx.py b/openpype/hosts/max/plugins/load/load_model_fbx.py index d076bf2de9..f7d3dab60c 100644 --- a/openpype/hosts/max/plugins/load/load_model_fbx.py +++ b/openpype/hosts/max/plugins/load/load_model_fbx.py @@ -26,7 +26,10 @@ class FbxModelLoader(load.LoaderPlugin): rt.FBXImporterSetParam("Preserveinstances", True) rt.importFile(filepath, rt.name("noPrompt"), using=rt.FBXIMP) + container = rt.GetNodeByName(name) + container = rt.Container(name=name) + selections = rt.GetCurrentSelection() import_custom_attribute_data(container, selections) @@ -40,8 +43,9 @@ class FbxModelLoader(load.LoaderPlugin): def update(self, container, representation): from pymxs import runtime as rt path = get_representation_path(representation) - node = rt.getNodeByName(container["instance_node"]) - inst_name, _ = os.path.splitext(container["instance_node"]) + node_name = container["instance_node"] + node = rt.getNodeByName(node_name) + inst_name, _ = node_name.split("_") rt.select(node.Children) rt.FBXImporterSetParam("Animation", False) @@ -52,14 +56,14 @@ class FbxModelLoader(load.LoaderPlugin): rt.FBXImporterSetParam("Preserveinstances", True) rt.importFile(path, rt.name("noPrompt"), using=rt.FBXIMP) - container = rt.getNodeByName(inst_name) + inst_container = rt.getNodeByName(inst_name) update_custom_attribute_data( - container, rt.GetCurrentSelection()) + inst_container, rt.GetCurrentSelection()) with maintained_selection(): rt.Select(node) lib.imprint( - container["instance_node"], + node_name, {"representation": str(representation["_id"])}, ) diff --git a/openpype/hosts/max/plugins/load/load_model_obj.py b/openpype/hosts/max/plugins/load/load_model_obj.py index bac5b8b4f3..9979ca36b0 100644 --- a/openpype/hosts/max/plugins/load/load_model_obj.py +++ b/openpype/hosts/max/plugins/load/load_model_obj.py @@ -33,7 +33,6 @@ class ObjLoader(load.LoaderPlugin): # get current selection for selection in selections: selection.Parent = container - self.log.debug(f"{container.ClassID}") return containerise( name, [container], context, loader=self.__class__.__name__) @@ -46,7 +45,7 @@ class ObjLoader(load.LoaderPlugin): node = rt.GetNodeByName(node_name) instance_name, _ = node_name.split("_") - container = rt.GetNodeByName(instance_name) + inst_container = rt.GetNodeByName(instance_name) for child in container.Children: rt.Delete(child) @@ -54,8 +53,8 @@ class ObjLoader(load.LoaderPlugin): # get current selection selections = rt.GetCurrentSelection() for selection in selections: - selection.Parent = container - update_custom_attribute_data(container, selections) + selection.Parent = inst_container + update_custom_attribute_data(inst_container, selections) with maintained_selection(): rt.Select(node) diff --git a/openpype/hosts/max/plugins/load/load_pointcache.py b/openpype/hosts/max/plugins/load/load_pointcache.py index 0ec9fda3d5..953141c4ac 100644 --- a/openpype/hosts/max/plugins/load/load_pointcache.py +++ b/openpype/hosts/max/plugins/load/load_pointcache.py @@ -70,10 +70,6 @@ class AbcLoader(load.LoaderPlugin): path = get_representation_path(representation) node = rt.GetNodeByName(container["instance_node"]) - lib.imprint( - container["instance_node"], - {"representation": str(representation["_id"])}, - ) nodes_list = [] with maintained_selection(): rt.Select(node.Children) @@ -83,14 +79,18 @@ class AbcLoader(load.LoaderPlugin): update_custom_attribute_data(abc, abc.Children) rt.Select(abc.Children) for abc_con in rt.Selection: - container = rt.GetNodeByName(abc_con.name) - container.source = path - rt.Select(container.Children) + abc_container = rt.GetNodeByName(abc_con.name) + abc_container.source = path + rt.Select(abc_container.Children) for abc_obj in rt.Selection: alembic_obj = rt.GetNodeByName(abc_obj.name) alembic_obj.source = path nodes_list.append(alembic_obj) + lib.imprint( + container["instance_node"], + {"representation": str(representation["_id"])}, + ) def switch(self, container, representation): self.update(container, representation) From 3342ceff2cee9a44c34c265cb51c7e2e8bcfa799 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 16 Aug 2023 22:39:36 +0800 Subject: [PATCH 036/154] clean up on the fbx and max_scene code --- openpype/hosts/max/plugins/load/load_camera_fbx.py | 4 ++++ openpype/hosts/max/plugins/load/load_max_scene.py | 10 ++++++---- openpype/hosts/max/plugins/load/load_model_fbx.py | 11 ++++++----- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/openpype/hosts/max/plugins/load/load_camera_fbx.py b/openpype/hosts/max/plugins/load/load_camera_fbx.py index 87745ae881..86e201afa8 100644 --- a/openpype/hosts/max/plugins/load/load_camera_fbx.py +++ b/openpype/hosts/max/plugins/load/load_camera_fbx.py @@ -57,7 +57,11 @@ class FbxLoader(load.LoaderPlugin): rt.FBXImporterSetParam("Preserveinstances", True) rt.ImportFile( path, rt.name("noPrompt"), using=rt.FBXIMP) + current_fbx_objects = rt.GetCurrentSelection() inst_container = rt.getNodeByName(inst_name) + for fbx_object in current_fbx_objects: + if fbx_object.Parent != inst_container: + fbx_object.Parent = inst_container update_custom_attribute_data( inst_container, rt.GetCurrentSelection()) with maintained_selection(): diff --git a/openpype/hosts/max/plugins/load/load_max_scene.py b/openpype/hosts/max/plugins/load/load_max_scene.py index 348b940b22..4f29f6bd3a 100644 --- a/openpype/hosts/max/plugins/load/load_max_scene.py +++ b/openpype/hosts/max/plugins/load/load_max_scene.py @@ -47,13 +47,15 @@ class MaxSceneLoader(load.LoaderPlugin): inst_container = rt.getNodeByName(inst_name) # delete the old container with attribute # delete old duplicate - prev_max_object_names = [obj.name for obj in rt.getLastMergedNodes()] + prev_max_object_names = [obj.name for obj + in rt.getLastMergedNodes()] rt.MergeMaxFile(path, rt.Name("deleteOldDups")) current_max_objects = rt.getLastMergedNodes() - current_max_object_names = [obj.name for obj in rt.getLastMergedNodes()] - for obj in current_max_object_names: - idx = rt.findItem(prev_max_object_names, obj) + current_max_object_names = [obj.name for obj + in current_max_objects] + for name in current_max_object_names: + idx = rt.findItem(prev_max_object_names, name) if idx: prev_max_object_names = rt.deleteItem(prev_max_object_names, idx) for object_name in prev_max_object_names: diff --git a/openpype/hosts/max/plugins/load/load_model_fbx.py b/openpype/hosts/max/plugins/load/load_model_fbx.py index f7d3dab60c..67252a73ff 100644 --- a/openpype/hosts/max/plugins/load/load_model_fbx.py +++ b/openpype/hosts/max/plugins/load/load_model_fbx.py @@ -46,19 +46,20 @@ class FbxModelLoader(load.LoaderPlugin): node_name = container["instance_node"] node = rt.getNodeByName(node_name) inst_name, _ = node_name.split("_") - rt.select(node.Children) + inst_container = rt.getNodeByName(inst_name) rt.FBXImporterSetParam("Animation", False) rt.FBXImporterSetParam("Cameras", False) rt.FBXImporterSetParam("Mode", rt.Name("merge")) rt.FBXImporterSetParam("AxisConversionMethod", True) - rt.FBXImporterSetParam("UpAxis", "Y") rt.FBXImporterSetParam("Preserveinstances", True) rt.importFile(path, rt.name("noPrompt"), using=rt.FBXIMP) - - inst_container = rt.getNodeByName(inst_name) + current_fbx_objects = rt.GetCurrentSelection() + for fbx_object in current_fbx_objects: + if fbx_object.Parent != inst_container: + fbx_object.Parent = inst_container update_custom_attribute_data( - inst_container, rt.GetCurrentSelection()) + inst_container, current_fbx_objects) with maintained_selection(): rt.Select(node) From 8345298913cf88205b1217c261ad3c0dcdf6a946 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 16 Aug 2023 22:40:56 +0800 Subject: [PATCH 037/154] hound --- openpype/hosts/max/plugins/load/load_max_scene.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/max/plugins/load/load_max_scene.py b/openpype/hosts/max/plugins/load/load_max_scene.py index 4f29f6bd3a..9c7468b8fc 100644 --- a/openpype/hosts/max/plugins/load/load_max_scene.py +++ b/openpype/hosts/max/plugins/load/load_max_scene.py @@ -57,7 +57,8 @@ class MaxSceneLoader(load.LoaderPlugin): for name in current_max_object_names: idx = rt.findItem(prev_max_object_names, name) if idx: - prev_max_object_names = rt.deleteItem(prev_max_object_names, idx) + prev_max_object_names = rt.deleteItem( + prev_max_object_names, idx) for object_name in prev_max_object_names: prev_max_object = rt.getNodeByName(object_name) rt.Delete(prev_max_object) From b2a6e16ae8a1466843fdd4958a7b49bb14adc34a Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 17 Aug 2023 21:22:34 +0800 Subject: [PATCH 038/154] master container is now with the namespace --- openpype/hosts/max/api/lib.py | 58 ++++++++++++++++++- openpype/hosts/max/api/pipeline.py | 7 ++- .../hosts/max/plugins/load/load_camera_fbx.py | 9 ++- .../hosts/max/plugins/load/load_max_scene.py | 10 +++- openpype/hosts/max/plugins/load/load_model.py | 13 ++++- .../hosts/max/plugins/load/load_model_fbx.py | 8 ++- .../hosts/max/plugins/load/load_model_obj.py | 8 ++- .../hosts/max/plugins/load/load_model_usd.py | 9 ++- .../hosts/max/plugins/load/load_pointcache.py | 8 ++- .../hosts/max/plugins/load/load_pointcloud.py | 9 ++- .../max/plugins/load/load_redshift_proxy.py | 9 ++- 11 files changed, 134 insertions(+), 14 deletions(-) diff --git a/openpype/hosts/max/api/lib.py b/openpype/hosts/max/api/lib.py index ccd4cd67e1..b58b4f5b11 100644 --- a/openpype/hosts/max/api/lib.py +++ b/openpype/hosts/max/api/lib.py @@ -6,7 +6,7 @@ from typing import Any, Dict, Union import six from openpype.pipeline.context_tools import ( - get_current_project, get_current_project_asset,) + get_current_project, get_current_project_asset) from pymxs import runtime as rt JSON_PREFIX = "JSON::" @@ -312,3 +312,59 @@ def set_timeline(frameStart, frameEnd): """ rt.animationRange = rt.interval(frameStart, frameEnd) return rt.animationRange + + +def unique_namespace(namespace, format="%02d", + prefix="", suffix="", con_suffix="CON"): + from pymxs import runtime as rt + """Return unique namespace + + Arguments: + namespace (str): Name of namespace to consider + format (str, optional): Formatting of the given iteration number + suffix (str, optional): Only consider namespaces with this suffix. + con_suffix: max only, for finding the name of the master container + + >>> unique_namespace("bar") + # bar01 + >>> unique_namespace(":hello") + # :hello01 + >>> unique_namespace("bar:", suffix="_NS") + # bar01_NS: + + """ + + def current_namespace(): + current = namespace + # When inside a namespace Maya adds no trailing : + if not current.endswith(":"): + current += ":" + return current + + # Always check against the absolute namespace root + # There's no clash with :x if we're defining namespace :a:x + ROOT = ":" if namespace.startswith(":") else current_namespace() + + # Strip trailing `:` tokens since we might want to add a suffix + start = ":" if namespace.startswith(":") else "" + end = ":" if namespace.endswith(":") else "" + namespace = namespace.strip(":") + if ":" in namespace: + # Split off any nesting that we don't uniqify anyway. + parents, namespace = namespace.rsplit(":", 1) + start += parents + ":" + ROOT += start + + iteration = 1 + increment_version = True + while increment_version: + nr_namespace = namespace + format % iteration + unique = prefix + nr_namespace + suffix + container_name = f"{unique}:{namespace}{con_suffix}" + if not rt.getNodeByName(container_name): + name_space = start + unique + end + increment_version = False + return name_space + else: + increment_version = True + iteration +=1 diff --git a/openpype/hosts/max/api/pipeline.py b/openpype/hosts/max/api/pipeline.py index f58bd05a13..459c8b32f0 100644 --- a/openpype/hosts/max/api/pipeline.py +++ b/openpype/hosts/max/api/pipeline.py @@ -154,17 +154,18 @@ def ls() -> list: yield lib.read(container) -def containerise(name: str, nodes: list, context, loader=None, suffix="_CON"): +def containerise(name: str, nodes: list, context, + namespace=None, loader=None, suffix="_CON"): data = { "schema": "openpype:container-2.0", "id": AVALON_CONTAINER_ID, "name": name, - "namespace": "", + "namespace": namespace, "loader": loader, "representation": context["representation"]["_id"], } - container_name = f"{name}{suffix}" + container_name = f"{namespace}:{name}{suffix}" container = rt.container(name=container_name) for node in nodes: node.Parent = container diff --git a/openpype/hosts/max/plugins/load/load_camera_fbx.py b/openpype/hosts/max/plugins/load/load_camera_fbx.py index 86e201afa8..180c1b48b8 100644 --- a/openpype/hosts/max/plugins/load/load_camera_fbx.py +++ b/openpype/hosts/max/plugins/load/load_camera_fbx.py @@ -1,6 +1,7 @@ import os from openpype.hosts.max.api import lib, maintained_selection +from openpype.hosts.max.api.lib import unique_namespace from openpype.hosts.max.api.pipeline import ( containerise, import_custom_attribute_data, @@ -38,8 +39,14 @@ class FbxLoader(load.LoaderPlugin): for selection in selections: selection.Parent = container + namespace = unique_namespace( + name + "_", + suffix="_", + ) + return containerise( - name, [container], context, loader=self.__class__.__name__) + name, [container], context, + namespace, loader=self.__class__.__name__) def update(self, container, representation): from pymxs import runtime as rt diff --git a/openpype/hosts/max/plugins/load/load_max_scene.py b/openpype/hosts/max/plugins/load/load_max_scene.py index 9c7468b8fc..7c00706676 100644 --- a/openpype/hosts/max/plugins/load/load_max_scene.py +++ b/openpype/hosts/max/plugins/load/load_max_scene.py @@ -1,6 +1,7 @@ import os from openpype.hosts.max.api import lib +from openpype.hosts.max.api.lib import unique_namespace from openpype.hosts.max.api.pipeline import ( containerise, import_custom_attribute_data, update_custom_attribute_data @@ -34,8 +35,15 @@ class MaxSceneLoader(load.LoaderPlugin): import_custom_attribute_data(container, max_objects) max_container.append(container) max_container.extend(max_objects) + + namespace = unique_namespace( + name + "_", + suffix="_", + ) + return containerise( - name, max_container, context, loader=self.__class__.__name__) + name, max_container, context, + namespace, loader=self.__class__.__name__) def update(self, container, representation): from pymxs import runtime as rt diff --git a/openpype/hosts/max/plugins/load/load_model.py b/openpype/hosts/max/plugins/load/load_model.py index a84d497aab..ebf3d684c8 100644 --- a/openpype/hosts/max/plugins/load/load_model.py +++ b/openpype/hosts/max/plugins/load/load_model.py @@ -6,7 +6,9 @@ from openpype.hosts.max.api.pipeline import ( update_custom_attribute_data ) from openpype.hosts.max.api import lib -from openpype.hosts.max.api.lib import maintained_selection +from openpype.hosts.max.api.lib import ( + maintained_selection, unique_namespace +) class ModelAbcLoader(load.LoaderPlugin): @@ -51,8 +53,15 @@ class ModelAbcLoader(load.LoaderPlugin): abc_container = abc_containers.pop() import_custom_attribute_data( abc_container, abc_container.Children) + + namespace = unique_namespace( + name + "_", + suffix="_", + ) + return containerise( - name, [abc_container], context, loader=self.__class__.__name__ + name, [abc_container], context, + namespace, loader=self.__class__.__name__ ) def update(self, container, representation): diff --git a/openpype/hosts/max/plugins/load/load_model_fbx.py b/openpype/hosts/max/plugins/load/load_model_fbx.py index 67252a73ff..34ac263821 100644 --- a/openpype/hosts/max/plugins/load/load_model_fbx.py +++ b/openpype/hosts/max/plugins/load/load_model_fbx.py @@ -4,6 +4,7 @@ from openpype.hosts.max.api.pipeline import ( containerise, import_custom_attribute_data, update_custom_attribute_data ) from openpype.hosts.max.api import lib +from openpype.hosts.max.api.lib import unique_namespace from openpype.hosts.max.api.lib import maintained_selection @@ -36,8 +37,13 @@ class FbxModelLoader(load.LoaderPlugin): for selection in selections: selection.Parent = container + namespace = unique_namespace( + name + "_", + suffix="_", + ) return containerise( - name, [container], context, loader=self.__class__.__name__ + name, [container], context, + namespace, loader=self.__class__.__name__ ) def update(self, container, representation): diff --git a/openpype/hosts/max/plugins/load/load_model_obj.py b/openpype/hosts/max/plugins/load/load_model_obj.py index 9979ca36b0..e4ae687802 100644 --- a/openpype/hosts/max/plugins/load/load_model_obj.py +++ b/openpype/hosts/max/plugins/load/load_model_obj.py @@ -1,6 +1,7 @@ import os from openpype.hosts.max.api import lib +from openpype.hosts.max.api.lib import unique_namespace from openpype.hosts.max.api.lib import maintained_selection from openpype.hosts.max.api.pipeline import ( containerise, @@ -34,8 +35,13 @@ class ObjLoader(load.LoaderPlugin): for selection in selections: selection.Parent = container + namespace = unique_namespace( + name + "_", + suffix="_", + ) return containerise( - name, [container], context, loader=self.__class__.__name__) + name, [container], context, + namespace, loader=self.__class__.__name__) def update(self, container, representation): from pymxs import runtime as rt diff --git a/openpype/hosts/max/plugins/load/load_model_usd.py b/openpype/hosts/max/plugins/load/load_model_usd.py index d3669fc10e..fa013f54ce 100644 --- a/openpype/hosts/max/plugins/load/load_model_usd.py +++ b/openpype/hosts/max/plugins/load/load_model_usd.py @@ -1,6 +1,7 @@ import os from openpype.hosts.max.api import lib +from openpype.hosts.max.api.lib import unique_namespace from openpype.hosts.max.api.lib import maintained_selection from openpype.hosts.max.api.pipeline import ( containerise, @@ -38,8 +39,14 @@ class ModelUSDLoader(load.LoaderPlugin): import_custom_attribute_data(asset, asset.Children) + namespace = unique_namespace( + name + "_", + suffix="_", + ) + return containerise( - name, [asset], context, loader=self.__class__.__name__) + name, [asset], context, + namespace, loader=self.__class__.__name__) def update(self, container, representation): from pymxs import runtime as rt diff --git a/openpype/hosts/max/plugins/load/load_pointcache.py b/openpype/hosts/max/plugins/load/load_pointcache.py index 953141c4ac..3dacab11c7 100644 --- a/openpype/hosts/max/plugins/load/load_pointcache.py +++ b/openpype/hosts/max/plugins/load/load_pointcache.py @@ -7,6 +7,7 @@ Because of limited api, alembics can be only loaded, but not easily updated. import os from openpype.pipeline import load, get_representation_path from openpype.hosts.max.api import lib, maintained_selection +from openpype.hosts.max.api.lib import unique_namespace from openpype.hosts.max.api.pipeline import ( containerise, import_custom_attribute_data, @@ -59,9 +60,14 @@ class AbcLoader(load.LoaderPlugin): for cam_shape in abc.Children: cam_shape.playbackType = 2 + namespace = unique_namespace( + name + "_", + suffix="_", + ) return containerise( - name, [abc_container], context, loader=self.__class__.__name__ + name, [abc_container], context, + namespace, loader=self.__class__.__name__ ) def update(self, container, representation): diff --git a/openpype/hosts/max/plugins/load/load_pointcloud.py b/openpype/hosts/max/plugins/load/load_pointcloud.py index c263019beb..58d5057aa7 100644 --- a/openpype/hosts/max/plugins/load/load_pointcloud.py +++ b/openpype/hosts/max/plugins/load/load_pointcloud.py @@ -1,6 +1,7 @@ import os from openpype.hosts.max.api import lib, maintained_selection +from openpype.hosts.max.api.lib import unique_namespace from openpype.hosts.max.api.pipeline import ( containerise, import_custom_attribute_data, @@ -31,8 +32,14 @@ class PointCloudLoader(load.LoaderPlugin): obj.Parent = prt_container import_custom_attribute_data(prt_container, [obj]) + namespace = unique_namespace( + name + "_", + suffix="_", + ) + return containerise( - name, [prt_container], context, loader=self.__class__.__name__) + name, [prt_container], context, + namespace, loader=self.__class__.__name__) def update(self, container, representation): """update the container""" diff --git a/openpype/hosts/max/plugins/load/load_redshift_proxy.py b/openpype/hosts/max/plugins/load/load_redshift_proxy.py index 6b100df611..b4772ac0bc 100644 --- a/openpype/hosts/max/plugins/load/load_redshift_proxy.py +++ b/openpype/hosts/max/plugins/load/load_redshift_proxy.py @@ -11,6 +11,7 @@ from openpype.hosts.max.api.pipeline import ( update_custom_attribute_data ) from openpype.hosts.max.api import lib +from openpype.hosts.max.api.lib import unique_namespace class RedshiftProxyLoader(load.LoaderPlugin): @@ -40,8 +41,14 @@ class RedshiftProxyLoader(load.LoaderPlugin): import_custom_attribute_data(container, [rs_proxy]) asset = rt.getNodeByName(name) + namespace = unique_namespace( + name + "_", + suffix="_", + ) + return containerise( - name, [asset], context, loader=self.__class__.__name__) + name, [asset], context, + namespace, loader=self.__class__.__name__) def update(self, container, representation): from pymxs import runtime as rt From 5a00cab24cd1f0dc4dd2988f28fa9b7b88b0b63b Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 17 Aug 2023 21:24:10 +0800 Subject: [PATCH 039/154] hound --- openpype/hosts/max/api/lib.py | 2 +- openpype/hosts/max/api/pipeline.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/max/api/lib.py b/openpype/hosts/max/api/lib.py index b58b4f5b11..e357080cbc 100644 --- a/openpype/hosts/max/api/lib.py +++ b/openpype/hosts/max/api/lib.py @@ -367,4 +367,4 @@ def unique_namespace(namespace, format="%02d", return name_space else: increment_version = True - iteration +=1 + iteration += 1 diff --git a/openpype/hosts/max/api/pipeline.py b/openpype/hosts/max/api/pipeline.py index 459c8b32f0..161e2bdc7b 100644 --- a/openpype/hosts/max/api/pipeline.py +++ b/openpype/hosts/max/api/pipeline.py @@ -160,7 +160,7 @@ def containerise(name: str, nodes: list, context, "schema": "openpype:container-2.0", "id": AVALON_CONTAINER_ID, "name": name, - "namespace": namespace, + "namespace": namespace or "", "loader": loader, "representation": context["representation"]["_id"], } From ab3d94fdb6f607b958704a06d3fa87187ac03d71 Mon Sep 17 00:00:00 2001 From: Fabia Serra Arrizabalaga Date: Thu, 17 Aug 2023 15:59:46 -0700 Subject: [PATCH 040/154] Move variant query to the create_interactive function --- .../hosts/houdini/api/creator_node_shelves.py | 47 ++++++++++--------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/openpype/hosts/houdini/api/creator_node_shelves.py b/openpype/hosts/houdini/api/creator_node_shelves.py index 01da2fc3e1..1f9fef7417 100644 --- a/openpype/hosts/houdini/api/creator_node_shelves.py +++ b/openpype/hosts/houdini/api/creator_node_shelves.py @@ -35,11 +35,11 @@ CATEGORY_GENERIC_TOOL = { CREATE_SCRIPT = """ from openpype.hosts.houdini.api.creator_node_shelves import create_interactive -create_interactive("{identifier}", "{variant}", **kwargs) +create_interactive("{identifier}", **kwargs) """ -def create_interactive(creator_identifier, default_variant, **kwargs): +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 @@ -57,28 +57,31 @@ def create_interactive(creator_identifier, default_variant, **kwargs): list: The created instances. """ - - # TODO Use Qt instead - result, variant = hou.ui.readInput("Define variant name", - buttons=("Ok", "Cancel"), - initial_contents=default_variant, - title="Define variant", - help="Set the variant for the " - "publish instance", - close_choice=1) - if result == 1: - # User interrupted - return - variant = variant.strip() - if not variant: - raise RuntimeError("Empty variant value entered.") - host = registered_host() context = CreateContext(host) creator = context.manual_creators.get(creator_identifier) if not creator: - raise RuntimeError("Invalid creator identifier: " - "{}".format(creator_identifier)) + raise RuntimeError("Invalid creator identifier: {}".format( + creator_identifier) + ) + + # TODO Use Qt instead + result, variant = hou.ui.readInput( + "Define variant name", + buttons=("Ok", "Cancel"), + initial_contents=creator.get_default_variant(), + title="Define variant", + help="Set the variant for the publish instance", + close_choice=1 + ) + + if result == 1: + # User interrupted + return + + variant = variant.strip() + if not variant: + raise RuntimeError("Empty variant value entered.") # TODO: Once more elaborate unique create behavior should exist per Creator # instead of per network editor area then we should move this from here @@ -196,9 +199,7 @@ def install(): key = "openpype_create.{}".format(identifier) log.debug(f"Registering {key}") - script = CREATE_SCRIPT.format( - identifier=identifier, variant=creator.get_default_variant() - ) + script = CREATE_SCRIPT.format(identifier=identifier) data = { "script": script, "language": hou.scriptLanguage.Python, From f4e42e27ac01faa61c71b2dec930a78361645578 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Fri, 18 Aug 2023 18:43:13 +0800 Subject: [PATCH 041/154] updating version should be updated as expected --- .../hosts/max/plugins/load/load_camera_fbx.py | 15 ++++++++--- .../hosts/max/plugins/load/load_max_scene.py | 15 +++++++---- openpype/hosts/max/plugins/load/load_model.py | 26 ++++++++----------- .../hosts/max/plugins/load/load_model_fbx.py | 17 +++++++----- .../hosts/max/plugins/load/load_model_obj.py | 8 +++--- .../hosts/max/plugins/load/load_model_usd.py | 11 +++++--- .../hosts/max/plugins/load/load_pointcache.py | 14 ++++------ .../hosts/max/plugins/load/load_pointcloud.py | 14 +++++----- .../max/plugins/load/load_redshift_proxy.py | 15 +++++------ 9 files changed, 75 insertions(+), 60 deletions(-) diff --git a/openpype/hosts/max/plugins/load/load_camera_fbx.py b/openpype/hosts/max/plugins/load/load_camera_fbx.py index 180c1b48b8..c0e1172a6d 100644 --- a/openpype/hosts/max/plugins/load/load_camera_fbx.py +++ b/openpype/hosts/max/plugins/load/load_camera_fbx.py @@ -54,7 +54,10 @@ class FbxLoader(load.LoaderPlugin): path = get_representation_path(representation) node_name = container["instance_node"] node = rt.getNodeByName(node_name) - inst_name, _ = node_name.split("_") + container_name = node_name.split(":")[-1] + param_container, _ = container_name.split("_") + + inst_container = rt.getNodeByName(param_container) rt.Select(node.Children) rt.FBXImporterSetParam("Animation", True) @@ -65,12 +68,16 @@ class FbxLoader(load.LoaderPlugin): rt.ImportFile( path, rt.name("noPrompt"), using=rt.FBXIMP) current_fbx_objects = rt.GetCurrentSelection() - inst_container = rt.getNodeByName(inst_name) for fbx_object in current_fbx_objects: if fbx_object.Parent != inst_container: fbx_object.Parent = inst_container - update_custom_attribute_data( - inst_container, rt.GetCurrentSelection()) + + for children in node.Children: + if rt.classOf(children) == rt.Container: + if children.name == param_container: + update_custom_attribute_data( + children, current_fbx_objects) + with maintained_selection(): rt.Select(node) diff --git a/openpype/hosts/max/plugins/load/load_max_scene.py b/openpype/hosts/max/plugins/load/load_max_scene.py index 7c00706676..aa177291d8 100644 --- a/openpype/hosts/max/plugins/load/load_max_scene.py +++ b/openpype/hosts/max/plugins/load/load_max_scene.py @@ -40,7 +40,6 @@ class MaxSceneLoader(load.LoaderPlugin): name + "_", suffix="_", ) - return containerise( name, max_container, context, namespace, loader=self.__class__.__name__) @@ -50,9 +49,11 @@ class MaxSceneLoader(load.LoaderPlugin): path = get_representation_path(representation) node_name = container["instance_node"] + node = rt.getNodeByName(node_name) - inst_name, _ = node_name.split("_") - inst_container = rt.getNodeByName(inst_name) + container_name = node_name.split(":")[-1] + param_container, _ = container_name.split("_") + # delete the old container with attribute # delete old duplicate prev_max_object_names = [obj.name for obj @@ -71,10 +72,14 @@ class MaxSceneLoader(load.LoaderPlugin): prev_max_object = rt.getNodeByName(object_name) rt.Delete(prev_max_object) - update_custom_attribute_data(inst_container, current_max_objects) - for max_object in current_max_objects: max_object.Parent = node + for children in node.Children: + if rt.classOf(children) == rt.Container: + if children.name == param_container: + update_custom_attribute_data( + children, current_max_objects) + lib.imprint(container["instance_node"], { "representation": str(representation["_id"]) }) diff --git a/openpype/hosts/max/plugins/load/load_model.py b/openpype/hosts/max/plugins/load/load_model.py index ebf3d684c8..deb3389992 100644 --- a/openpype/hosts/max/plugins/load/load_model.py +++ b/openpype/hosts/max/plugins/load/load_model.py @@ -69,23 +69,19 @@ class ModelAbcLoader(load.LoaderPlugin): path = get_representation_path(representation) node = rt.GetNodeByName(container["instance_node"]) - rt.Select(node.Children) - nodes_list = [] with maintained_selection(): - rt.Select(node) - for alembic in rt.Selection: - abc = rt.GetNodeByName(alembic.name) - update_custom_attribute_data(abc, abc.Children) - rt.Select(abc.Children) - for abc_con in rt.Selection: - abc_container = rt.GetNodeByName(abc_con.name) - abc_container.source = path - rt.Select(abc_container.Children) - for abc_obj in rt.Selection: - alembic_obj = rt.GetNodeByName(abc_obj.name) - alembic_obj.source = path - nodes_list.append(alembic_obj) + rt.Select(node.Children) + + for alembic in rt.Selection: + abc = rt.GetNodeByName(alembic.name) + update_custom_attribute_data(abc, abc.Children) + rt.Select(abc.Children) + for abc_con in abc.Children: + abc_con.source = path + rt.Select(abc_con.Children) + for abc_obj in abc_con.Children: + abc_obj.source = path lib.imprint( container["instance_node"], diff --git a/openpype/hosts/max/plugins/load/load_model_fbx.py b/openpype/hosts/max/plugins/load/load_model_fbx.py index 34ac263821..f85bfa03a1 100644 --- a/openpype/hosts/max/plugins/load/load_model_fbx.py +++ b/openpype/hosts/max/plugins/load/load_model_fbx.py @@ -1,7 +1,8 @@ import os from openpype.pipeline import load, get_representation_path from openpype.hosts.max.api.pipeline import ( - containerise, import_custom_attribute_data, update_custom_attribute_data + containerise, import_custom_attribute_data, + update_custom_attribute_data ) from openpype.hosts.max.api import lib from openpype.hosts.max.api.lib import unique_namespace @@ -51,9 +52,8 @@ class FbxModelLoader(load.LoaderPlugin): path = get_representation_path(representation) node_name = container["instance_node"] node = rt.getNodeByName(node_name) - inst_name, _ = node_name.split("_") - inst_container = rt.getNodeByName(inst_name) - + container_name = node_name.split(":")[-1] + param_container, _ = container_name.split("_") rt.FBXImporterSetParam("Animation", False) rt.FBXImporterSetParam("Cameras", False) rt.FBXImporterSetParam("Mode", rt.Name("merge")) @@ -61,11 +61,16 @@ class FbxModelLoader(load.LoaderPlugin): rt.FBXImporterSetParam("Preserveinstances", True) rt.importFile(path, rt.name("noPrompt"), using=rt.FBXIMP) current_fbx_objects = rt.GetCurrentSelection() + + inst_container = rt.getNodeByName(param_container) + for children in node.Children: + if rt.classOf(children) == rt.Container: + if children.name == param_container: + update_custom_attribute_data( + children, current_fbx_objects) for fbx_object in current_fbx_objects: if fbx_object.Parent != inst_container: fbx_object.Parent = inst_container - update_custom_attribute_data( - inst_container, current_fbx_objects) with maintained_selection(): rt.Select(node) diff --git a/openpype/hosts/max/plugins/load/load_model_obj.py b/openpype/hosts/max/plugins/load/load_model_obj.py index e4ae687802..b42ef399b0 100644 --- a/openpype/hosts/max/plugins/load/load_model_obj.py +++ b/openpype/hosts/max/plugins/load/load_model_obj.py @@ -50,9 +50,11 @@ class ObjLoader(load.LoaderPlugin): node_name = container["instance_node"] node = rt.GetNodeByName(node_name) - instance_name, _ = node_name.split("_") - inst_container = rt.GetNodeByName(instance_name) - for child in container.Children: + container_name = node_name.split(":")[-1] + param_container, _ = container_name.split("_") + + inst_container = rt.getNodeByName(param_container) + for child in inst_container.Children: rt.Delete(child) rt.Execute(f'importFile @"{path}" #noPrompt using:ObjImp') diff --git a/openpype/hosts/max/plugins/load/load_model_usd.py b/openpype/hosts/max/plugins/load/load_model_usd.py index fa013f54ce..4febba216e 100644 --- a/openpype/hosts/max/plugins/load/load_model_usd.py +++ b/openpype/hosts/max/plugins/load/load_model_usd.py @@ -58,7 +58,8 @@ class ModelUSDLoader(load.LoaderPlugin): for r in n.Children: rt.Delete(r) rt.Delete(n) - instance_name, _ = node_name.split("_") + container_name = node_name.split(":")[-1] + param_container, _ = container_name.split("_") import_options = rt.USDImporter.CreateOptions() base_filename = os.path.basename(path) @@ -70,9 +71,13 @@ class ModelUSDLoader(load.LoaderPlugin): rt.USDImporter.importFile( path, importOptions=import_options) - asset = rt.GetNodeByName(instance_name) + asset = rt.GetNodeByName(param_container) asset.Parent = node - update_custom_attribute_data(asset, asset.Children) + for children in node.Children: + if rt.classOf(children) == rt.Container: + if children.name == param_container: + update_custom_attribute_data( + asset, asset.Children) with maintained_selection(): rt.Select(node) diff --git a/openpype/hosts/max/plugins/load/load_pointcache.py b/openpype/hosts/max/plugins/load/load_pointcache.py index 3dacab11c7..af03e70236 100644 --- a/openpype/hosts/max/plugins/load/load_pointcache.py +++ b/openpype/hosts/max/plugins/load/load_pointcache.py @@ -76,7 +76,6 @@ class AbcLoader(load.LoaderPlugin): path = get_representation_path(representation) node = rt.GetNodeByName(container["instance_node"]) - nodes_list = [] with maintained_selection(): rt.Select(node.Children) @@ -84,14 +83,11 @@ class AbcLoader(load.LoaderPlugin): abc = rt.GetNodeByName(alembic.name) update_custom_attribute_data(abc, abc.Children) rt.Select(abc.Children) - for abc_con in rt.Selection: - abc_container = rt.GetNodeByName(abc_con.name) - abc_container.source = path - rt.Select(abc_container.Children) - for abc_obj in rt.Selection: - alembic_obj = rt.GetNodeByName(abc_obj.name) - alembic_obj.source = path - nodes_list.append(alembic_obj) + for abc_con in abc.Children: + abc_con.source = path + rt.Select(abc_con.Children) + for abc_obj in abc_con.Children: + abc_obj.source = path lib.imprint( container["instance_node"], diff --git a/openpype/hosts/max/plugins/load/load_pointcloud.py b/openpype/hosts/max/plugins/load/load_pointcloud.py index 58d5057aa7..6c94fb7847 100644 --- a/openpype/hosts/max/plugins/load/load_pointcloud.py +++ b/openpype/hosts/max/plugins/load/load_pointcloud.py @@ -26,9 +26,7 @@ class PointCloudLoader(load.LoaderPlugin): filepath = os.path.normpath(self.filepath_from_context(context)) obj = rt.tyCache() obj.filename = filepath - prt_container = rt.GetNodeByName(obj.name) - prt_container = rt.container() - prt_container.name = name + prt_container = rt.Container(name=name) obj.Parent = prt_container import_custom_attribute_data(prt_container, [obj]) @@ -49,10 +47,12 @@ class PointCloudLoader(load.LoaderPlugin): node = rt.GetNodeByName(container["instance_node"]) with maintained_selection(): rt.Select(node.Children) - for prt in rt.Selection: - prt_object = rt.GetNodeByName(prt.name) - prt_object.filename = path - update_custom_attribute_data(node, node.Children) + for sub_node in rt.Selection: + children_node = sub_node.Children + update_custom_attribute_data( + sub_node, sub_node.Children) + for prt in children_node: + prt.filename = path lib.imprint(container["instance_node"], { "representation": str(representation["_id"]) }) diff --git a/openpype/hosts/max/plugins/load/load_redshift_proxy.py b/openpype/hosts/max/plugins/load/load_redshift_proxy.py index b4772ac0bc..1c4cd02143 100644 --- a/openpype/hosts/max/plugins/load/load_redshift_proxy.py +++ b/openpype/hosts/max/plugins/load/load_redshift_proxy.py @@ -35,11 +35,9 @@ class RedshiftProxyLoader(load.LoaderPlugin): if collections: rs_proxy.is_sequence = True - container = rt.container() - container.name = name + container = rt.Container(name=name) rs_proxy.Parent = container import_custom_attribute_data(container, [rs_proxy]) - asset = rt.getNodeByName(name) namespace = unique_namespace( name + "_", @@ -47,7 +45,7 @@ class RedshiftProxyLoader(load.LoaderPlugin): ) return containerise( - name, [asset], context, + name, [container], context, namespace, loader=self.__class__.__name__) def update(self, container, representation): @@ -55,12 +53,13 @@ class RedshiftProxyLoader(load.LoaderPlugin): path = get_representation_path(representation) node = rt.getNodeByName(container["instance_node"]) - for children in node.Children: - children_node = rt.getNodeByName(children.name) - for proxy in children_node.Children: + for sub_node in node.Children: + children_node = sub_node.Children + update_custom_attribute_data( + sub_node, children_node) + for proxy in children_node: proxy.file = path - update_custom_attribute_data(node, node.Children) lib.imprint(container["instance_node"], { "representation": str(representation["_id"]) }) From e742dd61fd85c7cac3d5027ae758bef2f7aa5af7 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 21 Aug 2023 14:42:02 +0200 Subject: [PATCH 042/154] fill entities and update template data on instances during extract AYON hierarchy --- .../publish/extract_hierarchy_to_ayon.py | 44 ++++++++++++++++++- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/openpype/plugins/publish/extract_hierarchy_to_ayon.py b/openpype/plugins/publish/extract_hierarchy_to_ayon.py index 915650ae41..de9a70c233 100644 --- a/openpype/plugins/publish/extract_hierarchy_to_ayon.py +++ b/openpype/plugins/publish/extract_hierarchy_to_ayon.py @@ -8,6 +8,11 @@ from ayon_api import slugify_string from ayon_api.entity_hub import EntityHub from openpype import AYON_SERVER_ENABLED +from openpype.client import get_assets +from openpype.pipeline.template_data import ( + get_asset_template_data, + get_task_template_data, +) def _default_json_parse(value): @@ -27,13 +32,48 @@ class ExtractHierarchyToAYON(pyblish.api.ContextPlugin): hierarchy_context = context.data.get("hierarchyContext") if not hierarchy_context: - self.log.info("Skipping") + self.log.debug("Skipping") return project_name = context.data["projectName"] + self._create_hierarchy(context, project_name) + self._fill_instance_entities(context, project_name) + + def _fill_instance_entities(self, context, project_name): + instances_by_asset_name = collections.defaultdict(list) + for instance in context: + instance_entity = instance.data.get("assetEntity") + if instance_entity: + continue + + # Skip if instance asset does not match + instance_asset_name = instance.data.get("asset") + instances_by_asset_name[instance_asset_name] = instance + + project_doc = context.data["projectEntity"] + asset_docs = get_assets( + project_name, asset_names=instances_by_asset_name.keys() + ) + asset_docs_by_name = { + asset_doc["name"]: asset_doc + for asset_doc in asset_docs + } + for asset_name, instances in instances_by_asset_name.items(): + asset_doc = asset_docs_by_name[asset_name] + asset_data = get_asset_template_data(asset_doc, project_name) + for instance in instances: + task_name = instance.data.get("task") + template_data = get_task_template_data( + project_doc, asset_doc, task_name) + template_data.update(copy.deepcopy(asset_data)) + + instance.data["anatomyData"].update(template_data) + instance.data["assetEntity"] = asset_doc + + def _create_hierarchy(self, context, project_name): hierarchy_context = self._filter_hierarchy(context) if not hierarchy_context: - self.log.info("All folders were filtered out") + self.log.debug("All folders were filtered out") return self.log.debug("Hierarchy_context: {}".format( From 32b93f998aa95c3647797040b4a73fd1e68a305f Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 22 Aug 2023 12:47:36 +0800 Subject: [PATCH 043/154] allows the users to choose which camera as repair action in validate_viewport_camera --- openpype/hosts/max/api/lib_rendersettings.py | 5 +++-- .../publish/validate_viewport_camera.py | 19 +++++++++++-------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/openpype/hosts/max/api/lib_rendersettings.py b/openpype/hosts/max/api/lib_rendersettings.py index 1b62edabee..afde5008d5 100644 --- a/openpype/hosts/max/api/lib_rendersettings.py +++ b/openpype/hosts/max/api/lib_rendersettings.py @@ -43,7 +43,7 @@ class RenderSettings(object): rt.viewport.setCamera(sel) break if not found: - raise RuntimeError("Camera not found") + raise RuntimeError("Active Camera not found") def render_output(self, container): folder = rt.maxFilePath @@ -113,7 +113,8 @@ class RenderSettings(object): # for setting up renderable camera arv = rt.MAXToAOps.ArnoldRenderView() render_camera = rt.viewport.GetCamera() - arv.setOption("Camera", str(render_camera)) + if render_camera: + arv.setOption("Camera", str(render_camera)) # TODO: add AOVs and extension img_fmt = self._project_settings["max"]["RenderSettings"]["image_format"] # noqa diff --git a/openpype/hosts/max/plugins/publish/validate_viewport_camera.py b/openpype/hosts/max/plugins/publish/validate_viewport_camera.py index d5cf85eb69..b35ba482a9 100644 --- a/openpype/hosts/max/plugins/publish/validate_viewport_camera.py +++ b/openpype/hosts/max/plugins/publish/validate_viewport_camera.py @@ -4,6 +4,7 @@ from openpype.pipeline import ( PublishValidationError, OptionalPyblishPluginMixin) from openpype.pipeline.publish import RepairAction +from openpype.hosts.max.api.lib import get_current_renderer from pymxs import runtime as rt @@ -35,11 +36,13 @@ class ValidateViewportCamera(pyblish.api.InstancePlugin, @classmethod def repair(cls, instance): - # Get all cameras in the scene - cameras_in_scene = [c.name for c in rt.Objects - if rt.classOf(c) in rt.Camera.Classes] - # Set the first camera as viewport camera for rendering - if cameras_in_scene: - camera = rt.getNodeByName(cameras_in_scene[0]) - rt.viewport.setCamera(camera) - cls.log.info(f"Camera {camera} set as viewport camera") + + rt.viewport.setType(rt.Name("view_camera")) + camera = rt.viewport.GetCamera() + cls.log.info(f"Camera {camera} set as viewport camera") + renderer_class = get_current_renderer() + renderer = str(renderer_class).split(":")[0] + if renderer == "Arnold": + arv = rt.MAXToAOps.ArnoldRenderView() + arv.setOption("Camera", str(camera)) + arv.close() From 6376692fec24267af13f7900e2ac60fd65aed373 Mon Sep 17 00:00:00 2001 From: Ondrej Samohel Date: Tue, 22 Aug 2023 13:56:47 +0200 Subject: [PATCH 044/154] :recycle: use temp dir for project creation --- .../unreal/hooks/pre_workfile_preparation.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/unreal/hooks/pre_workfile_preparation.py b/openpype/hosts/unreal/hooks/pre_workfile_preparation.py index 202d7854f6..fad7a7ed0b 100644 --- a/openpype/hosts/unreal/hooks/pre_workfile_preparation.py +++ b/openpype/hosts/unreal/hooks/pre_workfile_preparation.py @@ -2,6 +2,7 @@ """Hook to launch Unreal and prepare projects.""" import os import copy +import tempfile from pathlib import Path from qtpy import QtCore @@ -224,10 +225,19 @@ class UnrealPrelaunchHook(PreLaunchHook): project_file = project_path / unreal_project_filename if not project_file.is_file(): - self.exec_ue_project_gen(engine_version, - unreal_project_name, - engine_path, - project_path) + with tempfile.TemporaryDirectory() as temp_dir: + temp_path = Path(temp_dir) / unreal_project_filename + self.exec_ue_project_gen(engine_version, + unreal_project_name, + engine_path, + temp_path) + try: + temp_path.rename(project_path) + except FileExistsError as e: + raise ApplicationLaunchFailed(( + f"{self.signature} Project folder " + f"already exists {project_path.as_posix()}" + )) from e self.launch_context.env["AYON_UNREAL_VERSION"] = engine_version # Append project file to launch arguments From 92165f521ef5f51e46758b3068083339f8d7a14d Mon Sep 17 00:00:00 2001 From: Ondrej Samohel Date: Tue, 22 Aug 2023 15:41:24 +0200 Subject: [PATCH 045/154] :bug: fix copy function --- .../unreal/hooks/pre_workfile_preparation.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/openpype/hosts/unreal/hooks/pre_workfile_preparation.py b/openpype/hosts/unreal/hooks/pre_workfile_preparation.py index fad7a7ed0b..fb489f04f7 100644 --- a/openpype/hosts/unreal/hooks/pre_workfile_preparation.py +++ b/openpype/hosts/unreal/hooks/pre_workfile_preparation.py @@ -2,6 +2,7 @@ """Hook to launch Unreal and prepare projects.""" import os import copy +import shutil import tempfile from pathlib import Path @@ -230,13 +231,19 @@ class UnrealPrelaunchHook(PreLaunchHook): self.exec_ue_project_gen(engine_version, unreal_project_name, engine_path, - temp_path) + Path(temp_dir)) try: - temp_path.rename(project_path) - except FileExistsError as e: + self.log.info(( + f"Moving from {temp_dir} to " + f"{project_path.as_posix()}" + )) + shutil.copytree( + temp_dir, project_path, dirs_exist_ok=True) + + except shutil.Error as e: raise ApplicationLaunchFailed(( - f"{self.signature} Project folder " - f"already exists {project_path.as_posix()}" + f"{self.signature} Cannot copy directory {temp_dir} " + f"to {project_path.as_posix()} - {e}" )) from e self.launch_context.env["AYON_UNREAL_VERSION"] = engine_version From c2b49a897eee6c33e405a3229bd48bcaee6c8178 Mon Sep 17 00:00:00 2001 From: Ondrej Samohel Date: Tue, 22 Aug 2023 15:43:48 +0200 Subject: [PATCH 046/154] :recycle: remove unused variable --- openpype/hosts/unreal/hooks/pre_workfile_preparation.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/hosts/unreal/hooks/pre_workfile_preparation.py b/openpype/hosts/unreal/hooks/pre_workfile_preparation.py index fb489f04f7..efbbed27c8 100644 --- a/openpype/hosts/unreal/hooks/pre_workfile_preparation.py +++ b/openpype/hosts/unreal/hooks/pre_workfile_preparation.py @@ -227,7 +227,6 @@ class UnrealPrelaunchHook(PreLaunchHook): if not project_file.is_file(): with tempfile.TemporaryDirectory() as temp_dir: - temp_path = Path(temp_dir) / unreal_project_filename self.exec_ue_project_gen(engine_version, unreal_project_name, engine_path, From 92000bc21e03d3ddf1fc99a62421ead1f278865f Mon Sep 17 00:00:00 2001 From: Ondrej Samohel Date: Tue, 22 Aug 2023 15:48:19 +0200 Subject: [PATCH 047/154] :rotating_light: fix hound :dog: --- openpype/hosts/unreal/hooks/pre_workfile_preparation.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/unreal/hooks/pre_workfile_preparation.py b/openpype/hosts/unreal/hooks/pre_workfile_preparation.py index efbbed27c8..a635bd4cab 100644 --- a/openpype/hosts/unreal/hooks/pre_workfile_preparation.py +++ b/openpype/hosts/unreal/hooks/pre_workfile_preparation.py @@ -233,8 +233,8 @@ class UnrealPrelaunchHook(PreLaunchHook): Path(temp_dir)) try: self.log.info(( - f"Moving from {temp_dir} to " - f"{project_path.as_posix()}" + f"Moving from {temp_dir} to " + f"{project_path.as_posix()}" )) shutil.copytree( temp_dir, project_path, dirs_exist_ok=True) From cd9ec2b73a269d4973db81622dbadb268ec7a24d Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 22 Aug 2023 17:40:58 +0200 Subject: [PATCH 048/154] OCIO: adding exception for nuke, hiero into hook --- openpype/hooks/pre_ocio_hook.py | 3 +++ openpype/hosts/nuke/api/lib.py | 1 + 2 files changed, 4 insertions(+) diff --git a/openpype/hooks/pre_ocio_hook.py b/openpype/hooks/pre_ocio_hook.py index 1307ed9f76..add3a0adaf 100644 --- a/openpype/hooks/pre_ocio_hook.py +++ b/openpype/hooks/pre_ocio_hook.py @@ -45,6 +45,9 @@ class OCIOEnvHook(PreLaunchHook): if config_data: ocio_path = config_data["path"] + if self.host_name in ["nuke", "hiero"]: + ocio_path = ocio_path.replace("\\", "/") + self.log.info( f"Setting OCIO environment to config path: {ocio_path}") diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py index 4a1e109b17..2a6c1fb12c 100644 --- a/openpype/hosts/nuke/api/lib.py +++ b/openpype/hosts/nuke/api/lib.py @@ -2177,6 +2177,7 @@ Reopening Nuke should synchronize these paths and resolve any discrepancies. """ # replace path with env var if possible ocio_path = self._replace_ocio_path_with_env_var(config_data) + ocio_path = ocio_path.replace("\\", "/") log.info("Setting OCIO config path to: `{}`".format( ocio_path)) From 83508a93eadb1387a49dca465d68bcf0d96badc6 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 23 Aug 2023 13:45:20 +0200 Subject: [PATCH 049/154] nuke: fixing thumbnail and monitor out root attributes --- openpype/hosts/nuke/api/lib.py | 54 +++++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py index 4a1e109b17..cedbe6d5e6 100644 --- a/openpype/hosts/nuke/api/lib.py +++ b/openpype/hosts/nuke/api/lib.py @@ -2041,6 +2041,7 @@ class WorkfileSettings(object): ) workfile_settings = imageio_host["workfile"] + viewer_process_settings = imageio_host["viewer"]["viewerProcess"] if not config_data: # TODO: backward compatibility for old projects - remove later @@ -2091,6 +2092,31 @@ class WorkfileSettings(object): workfile_settings.pop("colorManagement", None) workfile_settings.pop("OCIO_config", None) + # treat monitor lut separately + monitor_lut = workfile_settings.pop("monitorLut", None) + m_display, m_viewer = get_viewer_config_from_string(monitor_lut) + v_display, v_viewer = get_viewer_config_from_string( + viewer_process_settings + ) + + # set monitor lut differently for nuke version 14 + if nuke.NUKE_VERSION_MAJOR >= 14: + workfile_settings["monitorOutLUT"] = create_viewer_profile_string( + m_viewer, m_display, path_like=False) + # monitorLut=thumbnails - viewerProcess makes more sense + workfile_settings["monitorLut"] = create_viewer_profile_string( + v_viewer, v_display, path_like=False) + + if nuke.NUKE_VERSION_MAJOR == 13: + workfile_settings["monitorOutLUT"] = create_viewer_profile_string( + m_viewer, m_display, path_like=False) + # monitorLut=thumbnails - viewerProcess makes more sense + workfile_settings["monitorLut"] = create_viewer_profile_string( + v_viewer, v_display, path_like=True) + if nuke.NUKE_VERSION_MAJOR <= 12: + workfile_settings["monitorLut"] = create_viewer_profile_string( + m_viewer, m_display, path_like=True) + # then set the rest for knob, value_ in workfile_settings.items(): # skip unfilled ocio config path @@ -3320,11 +3346,11 @@ def get_viewer_config_from_string(input_string): display = split[0] elif "(" in viewer: pattern = r"([\w\d\s\.\-]+).*[(](.*)[)]" - result = re.findall(pattern, viewer) + result_ = re.findall(pattern, viewer) try: - result = result.pop() - display = str(result[1]).rstrip() - viewer = str(result[0]).rstrip() + result_ = result_.pop() + display = str(result_[1]).rstrip() + viewer = str(result_[0]).rstrip() except IndexError: raise IndexError(( "Viewer Input string is not correct. " @@ -3332,3 +3358,23 @@ def get_viewer_config_from_string(input_string): ).format(input_string)) return (display, viewer) + + +def create_viewer_profile_string(viewer, display=None, path_like=False): + """Convert viewer and display to string + + Args: + viewer (str): viewer name + display (Optional[str]): display name + path_like (Optional[bool]): if True, return path like string + + Returns: + str: viewer config string + """ + if display: + if path_like: + return "{}/{}".format(display, viewer) + else: + return "{} ({})".format(viewer, display) + else: + return viewer From 3603fdfe0012f905634d1786275a2f72b4ca2203 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 23 Aug 2023 15:11:26 +0200 Subject: [PATCH 050/154] Nuke: existing frames validator is repairing render target --- .../publish/validate_rendered_frames.py | 33 ++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/openpype/hosts/nuke/plugins/publish/validate_rendered_frames.py b/openpype/hosts/nuke/plugins/publish/validate_rendered_frames.py index 45c20412c8..ef3d4d0bb5 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_rendered_frames.py +++ b/openpype/hosts/nuke/plugins/publish/validate_rendered_frames.py @@ -14,19 +14,28 @@ class RepairActionBase(pyblish.api.Action): # Get the errored instances return get_errored_instances_from_context(context, plugin=plugin) - def repair_knob(self, instances, state): + def repair_knob(self, context, instances, state): + create_context = context.data["create_context"] for instance in instances: - node = instance.data["transientData"]["node"] - files_remove = [os.path.join(instance.data["outputDir"], f) - for r in instance.data.get("representations", []) - for f in r.get("files", []) - ] + files_remove = [ + os.path.join(instance.data["outputDir"], f_) + for r_ in instance.data.get("representations", []) + for f_ in r_.get("files", []) + ] self.log.info("Files to be removed: {}".format(files_remove)) - for f in files_remove: - os.remove(f) - self.log.debug("removing file: {}".format(f)) - node["render"].setValue(state) + for f_ in files_remove: + os.remove(f_) + self.log.debug("removing file: {}".format(f_)) + + # Reset the render knob + instance_id = instance.data["instance_id"] + created_instance = create_context.get_instance_by_id( + instance_id + ) + created_instance.creator_attributes["render_target"] = state + self.log.info("Rendering toggled to `{}`".format(state)) + create_context.save_changes() class RepairCollectionActionToLocal(RepairActionBase): @@ -34,7 +43,7 @@ class RepairCollectionActionToLocal(RepairActionBase): def process(self, context, plugin): instances = self.get_instance(context, plugin) - self.repair_knob(instances, "Local") + self.repair_knob(context, instances, "local") class RepairCollectionActionToFarm(RepairActionBase): @@ -42,7 +51,7 @@ class RepairCollectionActionToFarm(RepairActionBase): def process(self, context, plugin): instances = self.get_instance(context, plugin) - self.repair_knob(instances, "On farm") + self.repair_knob(context, instances, "farm") class ValidateRenderedFrames(pyblish.api.InstancePlugin): From fa80317f6a6fb8ac5f65d11304444cf128b0567a Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 24 Aug 2023 17:08:37 +0800 Subject: [PATCH 051/154] namespace fix for most loaders except alembic loaders --- openpype/hosts/max/api/lib.py | 9 ++++ .../hosts/max/plugins/load/load_camera_fbx.py | 32 ++++++++----- .../hosts/max/plugins/load/load_max_scene.py | 48 +++++++++---------- openpype/hosts/max/plugins/load/load_model.py | 7 +++ .../hosts/max/plugins/load/load_model_fbx.py | 43 ++++++++++------- .../hosts/max/plugins/load/load_model_obj.py | 38 ++++++++------- .../hosts/max/plugins/load/load_model_usd.py | 43 ++++++++++------- .../hosts/max/plugins/load/load_pointcache.py | 8 ++++ .../hosts/max/plugins/load/load_pointcloud.py | 24 ++++++---- .../max/plugins/load/load_redshift_proxy.py | 26 +++++----- 10 files changed, 168 insertions(+), 110 deletions(-) diff --git a/openpype/hosts/max/api/lib.py b/openpype/hosts/max/api/lib.py index e357080cbc..08819ba155 100644 --- a/openpype/hosts/max/api/lib.py +++ b/openpype/hosts/max/api/lib.py @@ -368,3 +368,12 @@ def unique_namespace(namespace, format="%02d", else: increment_version = True iteration += 1 + + +def get_namespace(container_name): + node = rt.getNodeByName(container_name) + if not node: + raise RuntimeError("Master Container Not Found..") + name = rt.getUserProp(node, "name") + namespace = rt.getUserProp(node, "namespace") + return namespace, name diff --git a/openpype/hosts/max/plugins/load/load_camera_fbx.py b/openpype/hosts/max/plugins/load/load_camera_fbx.py index c0e1172a6d..c70ece6293 100644 --- a/openpype/hosts/max/plugins/load/load_camera_fbx.py +++ b/openpype/hosts/max/plugins/load/load_camera_fbx.py @@ -1,7 +1,9 @@ import os from openpype.hosts.max.api import lib, maintained_selection -from openpype.hosts.max.api.lib import unique_namespace +from openpype.hosts.max.api.lib import ( + unique_namespace, get_namespace +) from openpype.hosts.max.api.pipeline import ( containerise, import_custom_attribute_data, @@ -33,16 +35,17 @@ class FbxLoader(load.LoaderPlugin): rt.name("noPrompt"), using=rt.FBXIMP) - container = rt.container(name=name) - selections = rt.GetCurrentSelection() - import_custom_attribute_data(container, selections) - for selection in selections: - selection.Parent = container - namespace = unique_namespace( name + "_", suffix="_", ) + container = rt.container(name=f"{namespace}:{name}") + selections = rt.GetCurrentSelection() + import_custom_attribute_data(container, selections) + + for selection in selections: + selection.Parent = container + selection.name = f"{namespace}:{selection.name}" return containerise( name, [container], context, @@ -54,11 +57,13 @@ class FbxLoader(load.LoaderPlugin): path = get_representation_path(representation) node_name = container["instance_node"] node = rt.getNodeByName(node_name) - container_name = node_name.split(":")[-1] - param_container, _ = container_name.split("_") - - inst_container = rt.getNodeByName(param_container) - rt.Select(node.Children) + namespace, name = get_namespace(node_name) + sub_node_name = f"{namespace}:{name}" + inst_container = rt.getNodeByName(sub_node_name) + rt.Select(inst_container.Children) + for prev_fbx_obj in rt.selection: + if rt.isValidNode(prev_fbx_obj): + rt.Delete(prev_fbx_obj) rt.FBXImporterSetParam("Animation", True) rt.FBXImporterSetParam("Camera", True) @@ -71,10 +76,11 @@ class FbxLoader(load.LoaderPlugin): for fbx_object in current_fbx_objects: if fbx_object.Parent != inst_container: fbx_object.Parent = inst_container + fbx_object.name = f"{namespace}:{fbx_object.name}" for children in node.Children: if rt.classOf(children) == rt.Container: - if children.name == param_container: + if children.name == sub_node_name: update_custom_attribute_data( children, current_fbx_objects) diff --git a/openpype/hosts/max/plugins/load/load_max_scene.py b/openpype/hosts/max/plugins/load/load_max_scene.py index aa177291d8..cf5f7736e3 100644 --- a/openpype/hosts/max/plugins/load/load_max_scene.py +++ b/openpype/hosts/max/plugins/load/load_max_scene.py @@ -1,7 +1,9 @@ import os from openpype.hosts.max.api import lib -from openpype.hosts.max.api.lib import unique_namespace +from openpype.hosts.max.api.lib import ( + unique_namespace, get_namespace +) from openpype.hosts.max.api.pipeline import ( containerise, import_custom_attribute_data, update_custom_attribute_data @@ -29,17 +31,21 @@ class MaxSceneLoader(load.LoaderPlugin): path = path.replace('\\', '/') rt.MergeMaxFile(path, quiet=True, includeFullGroup=True) max_objects = rt.getLastMergedNodes() + max_object_names = [obj.name for obj in max_objects] # implement the OP/AYON custom attributes before load max_container = [] - container = rt.Container(name=name) - import_custom_attribute_data(container, max_objects) - max_container.append(container) - max_container.extend(max_objects) namespace = unique_namespace( name + "_", suffix="_", ) + container_name = f"{namespace}:{name}" + container = rt.Container(name=container_name) + import_custom_attribute_data(container, max_objects) + max_container.append(container) + max_container.extend(max_objects) + for max_obj, obj_name in zip(max_objects, max_object_names): + max_obj.name = f"{namespace}:{obj_name}" return containerise( name, max_container, context, namespace, loader=self.__class__.__name__) @@ -51,34 +57,28 @@ class MaxSceneLoader(load.LoaderPlugin): node_name = container["instance_node"] node = rt.getNodeByName(node_name) - container_name = node_name.split(":")[-1] - param_container, _ = container_name.split("_") - + namespace, name = get_namespace(node_name) + sub_container_name = f"{namespace}:{name}" # delete the old container with attribute # delete old duplicate - prev_max_object_names = [obj.name for obj - in rt.getLastMergedNodes()] + #TODO: get the prev_max_objects by using node.Children + rt.Select(node.Children) + for prev_max_obj in rt.GetCurrentSelection(): + if rt.isValidNode(prev_max_obj) and prev_max_obj.name != sub_container_name: # noqa + rt.Delete(prev_max_obj) rt.MergeMaxFile(path, rt.Name("deleteOldDups")) current_max_objects = rt.getLastMergedNodes() current_max_object_names = [obj.name for obj in current_max_objects] - for name in current_max_object_names: - idx = rt.findItem(prev_max_object_names, name) - if idx: - prev_max_object_names = rt.deleteItem( - prev_max_object_names, idx) - for object_name in prev_max_object_names: - prev_max_object = rt.getNodeByName(object_name) - rt.Delete(prev_max_object) - + sub_container = rt.getNodeByName(sub_container_name) + update_custom_attribute_data(sub_container, current_max_objects) for max_object in current_max_objects: max_object.Parent = node - for children in node.Children: - if rt.classOf(children) == rt.Container: - if children.name == param_container: - update_custom_attribute_data( - children, current_max_objects) + for max_obj, obj_name in zip( + current_max_objects, current_max_object_names): + max_obj.name = f"{namespace}:{obj_name}" + lib.imprint(container["instance_node"], { "representation": str(representation["_id"]) diff --git a/openpype/hosts/max/plugins/load/load_model.py b/openpype/hosts/max/plugins/load/load_model.py index deb3389992..aee948f2e2 100644 --- a/openpype/hosts/max/plugins/load/load_model.py +++ b/openpype/hosts/max/plugins/load/load_model.py @@ -58,6 +58,13 @@ class ModelAbcLoader(load.LoaderPlugin): name + "_", suffix="_", ) + for abc_object in abc_container.Children: + abc_object.name = f"{namespace}:{abc_object.name}" + # rename the abc container with namespace + abc_container_name = f"{namespace}:{name}" + abc_container.name = abc_container_name + # get the correct container + abc_container = rt.GetNodeByName(abc_container_name) return containerise( name, [abc_container], context, diff --git a/openpype/hosts/max/plugins/load/load_model_fbx.py b/openpype/hosts/max/plugins/load/load_model_fbx.py index f85bfa03a1..6097a4ca6e 100644 --- a/openpype/hosts/max/plugins/load/load_model_fbx.py +++ b/openpype/hosts/max/plugins/load/load_model_fbx.py @@ -5,7 +5,9 @@ from openpype.hosts.max.api.pipeline import ( update_custom_attribute_data ) from openpype.hosts.max.api import lib -from openpype.hosts.max.api.lib import unique_namespace +from openpype.hosts.max.api.lib import ( + unique_namespace, get_namespace +) from openpype.hosts.max.api.lib import maintained_selection @@ -28,20 +30,18 @@ class FbxModelLoader(load.LoaderPlugin): rt.FBXImporterSetParam("Preserveinstances", True) rt.importFile(filepath, rt.name("noPrompt"), using=rt.FBXIMP) - container = rt.GetNodeByName(name) - - container = rt.Container(name=name) - + namespace = unique_namespace( + name + "_", + suffix="_", + ) + container = rt.container(name=f"{namespace}:{name}") selections = rt.GetCurrentSelection() import_custom_attribute_data(container, selections) for selection in selections: selection.Parent = container + selection.name = f"{namespace}:{selection.name}" - namespace = unique_namespace( - name + "_", - suffix="_", - ) return containerise( name, [container], context, namespace, loader=self.__class__.__name__ @@ -52,8 +52,14 @@ class FbxModelLoader(load.LoaderPlugin): path = get_representation_path(representation) node_name = container["instance_node"] node = rt.getNodeByName(node_name) - container_name = node_name.split(":")[-1] - param_container, _ = container_name.split("_") + namespace, name = get_namespace(node_name) + sub_node_name = f"{namespace}:{name}" + inst_container = rt.getNodeByName(sub_node_name) + rt.Select(inst_container.Children) + for prev_fbx_obj in rt.selection: + if rt.isValidNode(prev_fbx_obj): + rt.Delete(prev_fbx_obj) + rt.FBXImporterSetParam("Animation", False) rt.FBXImporterSetParam("Cameras", False) rt.FBXImporterSetParam("Mode", rt.Name("merge")) @@ -61,16 +67,17 @@ class FbxModelLoader(load.LoaderPlugin): rt.FBXImporterSetParam("Preserveinstances", True) rt.importFile(path, rt.name("noPrompt"), using=rt.FBXIMP) current_fbx_objects = rt.GetCurrentSelection() - - inst_container = rt.getNodeByName(param_container) - for children in node.Children: - if rt.classOf(children) == rt.Container: - if children.name == param_container: - update_custom_attribute_data( - children, current_fbx_objects) for fbx_object in current_fbx_objects: if fbx_object.Parent != inst_container: fbx_object.Parent = inst_container + fbx_object.name = f"{namespace}:{fbx_object.name}" + + for children in node.Children: + if rt.classOf(children) == rt.Container: + if children.name == sub_node_name: + update_custom_attribute_data( + children, current_fbx_objects) + with maintained_selection(): rt.Select(node) diff --git a/openpype/hosts/max/plugins/load/load_model_obj.py b/openpype/hosts/max/plugins/load/load_model_obj.py index b42ef399b0..225801b8d0 100644 --- a/openpype/hosts/max/plugins/load/load_model_obj.py +++ b/openpype/hosts/max/plugins/load/load_model_obj.py @@ -1,7 +1,9 @@ import os from openpype.hosts.max.api import lib -from openpype.hosts.max.api.lib import unique_namespace +from openpype.hosts.max.api.lib import ( + unique_namespace, get_namespace +) from openpype.hosts.max.api.lib import maintained_selection from openpype.hosts.max.api.pipeline import ( containerise, @@ -27,18 +29,19 @@ class ObjLoader(load.LoaderPlugin): self.log.debug("Executing command to import..") rt.Execute(f'importFile @"{filepath}" #noPrompt using:ObjImp') - # create "missing" container for obj import - container = rt.Container(name=name) - selections = rt.GetCurrentSelection() - import_custom_attribute_data(container, selections) - # get current selection - for selection in selections: - selection.Parent = container namespace = unique_namespace( name + "_", suffix="_", ) + # create "missing" container for obj import + container = rt.Container(name=f"{namespace}:{name}") + selections = rt.GetCurrentSelection() + import_custom_attribute_data(container, selections) + # get current selection + for selection in selections: + selection.Parent = container + selection.name = f"{namespace}:{selection.name}" return containerise( name, [container], context, namespace, loader=self.__class__.__name__) @@ -48,21 +51,22 @@ class ObjLoader(load.LoaderPlugin): path = get_representation_path(representation) node_name = container["instance_node"] - node = rt.GetNodeByName(node_name) - - container_name = node_name.split(":")[-1] - param_container, _ = container_name.split("_") - - inst_container = rt.getNodeByName(param_container) - for child in inst_container.Children: - rt.Delete(child) + node = rt.getNodeByName(node_name) + namespace, name = get_namespace(node_name) + sub_node_name = f"{namespace}:{name}" + inst_container = rt.getNodeByName(sub_node_name) + rt.Select(inst_container.Children) + for prev_obj in rt.selection: + if rt.isValidNode(prev_obj): + rt.Delete(prev_obj) rt.Execute(f'importFile @"{path}" #noPrompt using:ObjImp') # get current selection selections = rt.GetCurrentSelection() + update_custom_attribute_data(inst_container, selections) for selection in selections: selection.Parent = inst_container - update_custom_attribute_data(inst_container, selections) + selection.name = f"{namespace}:{selection.name}" with maintained_selection(): rt.Select(node) diff --git a/openpype/hosts/max/plugins/load/load_model_usd.py b/openpype/hosts/max/plugins/load/load_model_usd.py index 4febba216e..0c17736739 100644 --- a/openpype/hosts/max/plugins/load/load_model_usd.py +++ b/openpype/hosts/max/plugins/load/load_model_usd.py @@ -1,12 +1,13 @@ import os from openpype.hosts.max.api import lib -from openpype.hosts.max.api.lib import unique_namespace +from openpype.hosts.max.api.lib import ( + unique_namespace, get_namespace +) from openpype.hosts.max.api.lib import maintained_selection from openpype.hosts.max.api.pipeline import ( containerise, - import_custom_attribute_data, - update_custom_attribute_data + import_custom_attribute_data ) from openpype.pipeline import get_representation_path, load @@ -35,14 +36,20 @@ class ModelUSDLoader(load.LoaderPlugin): rt.LogLevel = rt.Name("info") rt.USDImporter.importFile(filepath, importOptions=import_options) - asset = rt.GetNodeByName(name) - - import_custom_attribute_data(asset, asset.Children) - namespace = unique_namespace( name + "_", suffix="_", ) + asset = rt.GetNodeByName(name) + import_custom_attribute_data(asset, asset.Children) + for usd_asset in asset.Children: + usd_asset.name = f"{namespace}:{usd_asset.name}" + + asset_name = f"{namespace}:{name}" + asset.name = asset_name + # need to get the correct container after renamed + asset = rt.GetNodeByName(asset_name) + return containerise( name, [asset], context, @@ -54,12 +61,14 @@ class ModelUSDLoader(load.LoaderPlugin): path = get_representation_path(representation) node_name = container["instance_node"] node = rt.GetNodeByName(node_name) + namespace, name = get_namespace(node_name) + sub_node_name = f"{namespace}:{name}" for n in node.Children: - for r in n.Children: - rt.Delete(r) + rt.Select(n.Children) + for prev_usd_asset in rt.selection: + if rt.isValidNode(prev_usd_asset): + rt.Delete(prev_usd_asset) rt.Delete(n) - container_name = node_name.split(":")[-1] - param_container, _ = container_name.split("_") import_options = rt.USDImporter.CreateOptions() base_filename = os.path.basename(path) @@ -71,13 +80,13 @@ class ModelUSDLoader(load.LoaderPlugin): rt.USDImporter.importFile( path, importOptions=import_options) - asset = rt.GetNodeByName(param_container) + asset = rt.GetNodeByName(name) asset.Parent = node - for children in node.Children: - if rt.classOf(children) == rt.Container: - if children.name == param_container: - update_custom_attribute_data( - asset, asset.Children) + import_custom_attribute_data(asset, asset.Children) + for children in asset.Children: + children.name = f"{namespace}:{children.name}" + asset.name = sub_node_name + with maintained_selection(): rt.Select(node) diff --git a/openpype/hosts/max/plugins/load/load_pointcache.py b/openpype/hosts/max/plugins/load/load_pointcache.py index af03e70236..ca833a383c 100644 --- a/openpype/hosts/max/plugins/load/load_pointcache.py +++ b/openpype/hosts/max/plugins/load/load_pointcache.py @@ -65,6 +65,14 @@ class AbcLoader(load.LoaderPlugin): suffix="_", ) + for abc_object in abc_container.Children: + abc_object.name = f"{namespace}:{abc_object.name}" + # rename the abc container with namespace + abc_container_name = f"{namespace}:{name}" + abc_container.name = abc_container_name + # get the correct container + abc_container = rt.GetNodeByName(abc_container_name) + return containerise( name, [abc_container], context, namespace, loader=self.__class__.__name__ diff --git a/openpype/hosts/max/plugins/load/load_pointcloud.py b/openpype/hosts/max/plugins/load/load_pointcloud.py index 6c94fb7847..87b7fce292 100644 --- a/openpype/hosts/max/plugins/load/load_pointcloud.py +++ b/openpype/hosts/max/plugins/load/load_pointcloud.py @@ -1,7 +1,9 @@ import os from openpype.hosts.max.api import lib, maintained_selection -from openpype.hosts.max.api.lib import unique_namespace +from openpype.hosts.max.api.lib import ( + unique_namespace, get_namespace +) from openpype.hosts.max.api.pipeline import ( containerise, import_custom_attribute_data, @@ -26,14 +28,15 @@ class PointCloudLoader(load.LoaderPlugin): filepath = os.path.normpath(self.filepath_from_context(context)) obj = rt.tyCache() obj.filename = filepath - prt_container = rt.Container(name=name) - obj.Parent = prt_container - import_custom_attribute_data(prt_container, [obj]) namespace = unique_namespace( name + "_", suffix="_", ) + prt_container = rt.Container(name=f"{namespace}:{name}") + import_custom_attribute_data(prt_container, [obj]) + obj.Parent = prt_container + obj.name = f"{namespace}:{obj.name}" return containerise( name, [prt_container], context, @@ -45,14 +48,15 @@ class PointCloudLoader(load.LoaderPlugin): path = get_representation_path(representation) node = rt.GetNodeByName(container["instance_node"]) + namespace, name = get_namespace(container["instance_node"]) + sub_node_name = f"{namespace}:{name}" + inst_container = rt.getNodeByName(sub_node_name) + update_custom_attribute_data( + inst_container, inst_container.Children) with maintained_selection(): rt.Select(node.Children) - for sub_node in rt.Selection: - children_node = sub_node.Children - update_custom_attribute_data( - sub_node, sub_node.Children) - for prt in children_node: - prt.filename = path + for prt in inst_container.Children: + prt.filename = path lib.imprint(container["instance_node"], { "representation": str(representation["_id"]) }) diff --git a/openpype/hosts/max/plugins/load/load_redshift_proxy.py b/openpype/hosts/max/plugins/load/load_redshift_proxy.py index 1c4cd02143..a64bfa7de2 100644 --- a/openpype/hosts/max/plugins/load/load_redshift_proxy.py +++ b/openpype/hosts/max/plugins/load/load_redshift_proxy.py @@ -11,7 +11,9 @@ from openpype.hosts.max.api.pipeline import ( update_custom_attribute_data ) from openpype.hosts.max.api import lib -from openpype.hosts.max.api.lib import unique_namespace +from openpype.hosts.max.api.lib import ( + unique_namespace, get_namespace +) class RedshiftProxyLoader(load.LoaderPlugin): @@ -35,14 +37,15 @@ class RedshiftProxyLoader(load.LoaderPlugin): if collections: rs_proxy.is_sequence = True - container = rt.Container(name=name) - rs_proxy.Parent = container - import_custom_attribute_data(container, [rs_proxy]) namespace = unique_namespace( name + "_", suffix="_", ) + container = rt.Container(name=f"{namespace}:{name}") + rs_proxy.Parent = container + rs_proxy.name = f"{namespace}:{rs_proxy.name}" + import_custom_attribute_data(container, [rs_proxy]) return containerise( name, [container], context, @@ -52,13 +55,14 @@ class RedshiftProxyLoader(load.LoaderPlugin): from pymxs import runtime as rt path = get_representation_path(representation) - node = rt.getNodeByName(container["instance_node"]) - for sub_node in node.Children: - children_node = sub_node.Children - update_custom_attribute_data( - sub_node, children_node) - for proxy in children_node: - proxy.file = path + namespace, name = get_namespace(container["instance_node"]) + sub_node_name = f"{namespace}:{name}" + inst_container = rt.getNodeByName(sub_node_name) + + update_custom_attribute_data( + inst_container, inst_container.Children) + for proxy in inst_container.Children: + proxy.file = path lib.imprint(container["instance_node"], { "representation": str(representation["_id"]) From 637c6396cad3bfe85f8537d969232986694f9af4 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 24 Aug 2023 17:13:38 +0800 Subject: [PATCH 052/154] hound --- openpype/hosts/max/plugins/load/load_max_scene.py | 5 ++--- openpype/hosts/max/plugins/load/load_redshift_proxy.py | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/max/plugins/load/load_max_scene.py b/openpype/hosts/max/plugins/load/load_max_scene.py index cf5f7736e3..fada871c6d 100644 --- a/openpype/hosts/max/plugins/load/load_max_scene.py +++ b/openpype/hosts/max/plugins/load/load_max_scene.py @@ -61,7 +61,6 @@ class MaxSceneLoader(load.LoaderPlugin): sub_container_name = f"{namespace}:{name}" # delete the old container with attribute # delete old duplicate - #TODO: get the prev_max_objects by using node.Children rt.Select(node.Children) for prev_max_obj in rt.GetCurrentSelection(): if rt.isValidNode(prev_max_obj) and prev_max_obj.name != sub_container_name: # noqa @@ -75,8 +74,8 @@ class MaxSceneLoader(load.LoaderPlugin): update_custom_attribute_data(sub_container, current_max_objects) for max_object in current_max_objects: max_object.Parent = node - for max_obj, obj_name in zip( - current_max_objects, current_max_object_names): + for max_obj, obj_name in zip(current_max_objects, + current_max_object_names): max_obj.name = f"{namespace}:{obj_name}" diff --git a/openpype/hosts/max/plugins/load/load_redshift_proxy.py b/openpype/hosts/max/plugins/load/load_redshift_proxy.py index a64bfa7de2..b240714314 100644 --- a/openpype/hosts/max/plugins/load/load_redshift_proxy.py +++ b/openpype/hosts/max/plugins/load/load_redshift_proxy.py @@ -37,7 +37,6 @@ class RedshiftProxyLoader(load.LoaderPlugin): if collections: rs_proxy.is_sequence = True - namespace = unique_namespace( name + "_", suffix="_", From d0857a63e0a9c107fdd9158c032b67afcd70d941 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 24 Aug 2023 17:27:52 +0800 Subject: [PATCH 053/154] alembic loader namespace fix --- openpype/hosts/max/plugins/load/load_model.py | 2 -- openpype/hosts/max/plugins/load/load_pointcache.py | 2 -- 2 files changed, 4 deletions(-) diff --git a/openpype/hosts/max/plugins/load/load_model.py b/openpype/hosts/max/plugins/load/load_model.py index aee948f2e2..acc2a4032b 100644 --- a/openpype/hosts/max/plugins/load/load_model.py +++ b/openpype/hosts/max/plugins/load/load_model.py @@ -63,8 +63,6 @@ class ModelAbcLoader(load.LoaderPlugin): # rename the abc container with namespace abc_container_name = f"{namespace}:{name}" abc_container.name = abc_container_name - # get the correct container - abc_container = rt.GetNodeByName(abc_container_name) return containerise( name, [abc_container], context, diff --git a/openpype/hosts/max/plugins/load/load_pointcache.py b/openpype/hosts/max/plugins/load/load_pointcache.py index ca833a383c..64bf7ddac0 100644 --- a/openpype/hosts/max/plugins/load/load_pointcache.py +++ b/openpype/hosts/max/plugins/load/load_pointcache.py @@ -70,8 +70,6 @@ class AbcLoader(load.LoaderPlugin): # rename the abc container with namespace abc_container_name = f"{namespace}:{name}" abc_container.name = abc_container_name - # get the correct container - abc_container = rt.GetNodeByName(abc_container_name) return containerise( name, [abc_container], context, From 93f897c780d5b6bda9ee56e013b12ee7b0ba6952 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 24 Aug 2023 13:59:34 +0200 Subject: [PATCH 054/154] deadline: adding collect farm target and removing redundant key --- .../plugins/publish/collect_render.py | 1 - .../fusion/plugins/publish/collect_render.py | 1 - .../plugins/publish/collect_farm_render.py | 1 - .../plugins/publish/submit_maya_muster.py | 1 - .../publish/submit_celaction_deadline.py | 2 +- .../publish/submit_houdini_render_deadline.py | 1 - .../plugins/publish/submit_max_deadline.py | 1 - .../plugins/publish/submit_maya_deadline.py | 1 - .../plugins/publish/submit_nuke_deadline.py | 1 - .../publish/abstract_collect_render.py | 1 - .../plugins/publish/collect_farm_target.py | 45 +++++++++++++++++++ 11 files changed, 46 insertions(+), 10 deletions(-) create mode 100644 openpype/plugins/publish/collect_farm_target.py diff --git a/openpype/hosts/aftereffects/plugins/publish/collect_render.py b/openpype/hosts/aftereffects/plugins/publish/collect_render.py index aa46461915..49874d6cff 100644 --- a/openpype/hosts/aftereffects/plugins/publish/collect_render.py +++ b/openpype/hosts/aftereffects/plugins/publish/collect_render.py @@ -138,7 +138,6 @@ class CollectAERender(publish.AbstractCollectRender): fam = "render.farm" if fam not in instance.families: instance.families.append(fam) - instance.toBeRenderedOn = "deadline" instance.renderer = "aerender" instance.farm = True # to skip integrate if "review" in instance.families: diff --git a/openpype/hosts/fusion/plugins/publish/collect_render.py b/openpype/hosts/fusion/plugins/publish/collect_render.py index a20a142701..341f3f191a 100644 --- a/openpype/hosts/fusion/plugins/publish/collect_render.py +++ b/openpype/hosts/fusion/plugins/publish/collect_render.py @@ -108,7 +108,6 @@ class CollectFusionRender( fam = "render.farm" if fam not in instance.families: instance.families.append(fam) - instance.toBeRenderedOn = "deadline" instance.farm = True # to skip integrate if "review" in instance.families: # to skip ExtractReview locally diff --git a/openpype/hosts/harmony/plugins/publish/collect_farm_render.py b/openpype/hosts/harmony/plugins/publish/collect_farm_render.py index 5e9b9094a7..5daa93cddb 100644 --- a/openpype/hosts/harmony/plugins/publish/collect_farm_render.py +++ b/openpype/hosts/harmony/plugins/publish/collect_farm_render.py @@ -174,7 +174,6 @@ class CollectFarmRender(publish.AbstractCollectRender): outputFormat=info[1], outputStartFrame=info[3], leadingZeros=info[2], - toBeRenderedOn='deadline', ignoreFrameHandleCheck=True ) diff --git a/openpype/hosts/maya/plugins/publish/submit_maya_muster.py b/openpype/hosts/maya/plugins/publish/submit_maya_muster.py index 8e219eae85..b79c9ed140 100644 --- a/openpype/hosts/maya/plugins/publish/submit_maya_muster.py +++ b/openpype/hosts/maya/plugins/publish/submit_maya_muster.py @@ -249,7 +249,6 @@ class MayaSubmitMuster(pyblish.api.InstancePlugin): Authenticate with Muster, collect all data, prepare path for post render publish job and submit job to farm. """ - instance.data["toBeRenderedOn"] = "muster" # setup muster environment self.MUSTER_REST_URL = os.environ.get("MUSTER_REST_URL") diff --git a/openpype/modules/deadline/plugins/publish/submit_celaction_deadline.py b/openpype/modules/deadline/plugins/publish/submit_celaction_deadline.py index ee28612b44..4aef914023 100644 --- a/openpype/modules/deadline/plugins/publish/submit_celaction_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_celaction_deadline.py @@ -27,7 +27,7 @@ class CelactionSubmitDeadline(pyblish.api.InstancePlugin): deadline_job_delay = "00:00:08:00" def process(self, instance): - instance.data["toBeRenderedOn"] = "deadline" + context = instance.context # get default deadline webservice url from deadline module diff --git a/openpype/modules/deadline/plugins/publish/submit_houdini_render_deadline.py b/openpype/modules/deadline/plugins/publish/submit_houdini_render_deadline.py index 108c377078..8f21a920be 100644 --- a/openpype/modules/deadline/plugins/publish/submit_houdini_render_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_houdini_render_deadline.py @@ -141,4 +141,3 @@ class HoudiniSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline): # Store output dir for unified publisher (filesequence) output_dir = os.path.dirname(instance.data["files"][0]) instance.data["outputDir"] = output_dir - instance.data["toBeRenderedOn"] = "deadline" diff --git a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py index 8e05582962..5d38903770 100644 --- a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py @@ -174,7 +174,6 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, first_file = next(self._iter_expected_files(files)) output_dir = os.path.dirname(first_file) instance.data["outputDir"] = output_dir - instance.data["toBeRenderedOn"] = "deadline" filename = os.path.basename(filepath) diff --git a/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py b/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py index 75d24b28f0..34f3905a17 100644 --- a/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py @@ -300,7 +300,6 @@ class MayaSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, first_file = next(iter_expected_files(expected_files)) output_dir = os.path.dirname(first_file) instance.data["outputDir"] = output_dir - instance.data["toBeRenderedOn"] = "deadline" # Patch workfile (only when use_published is enabled) if self.use_published: diff --git a/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py b/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py index cfdeb4968b..ded5cd179f 100644 --- a/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py @@ -97,7 +97,6 @@ class NukeSubmitDeadline(pyblish.api.InstancePlugin, instance.data["suspend_publish"] = instance.data["attributeValues"][ "suspend_publish"] - instance.data["toBeRenderedOn"] = "deadline" families = instance.data["families"] node = instance.data["transientData"]["node"] diff --git a/openpype/pipeline/publish/abstract_collect_render.py b/openpype/pipeline/publish/abstract_collect_render.py index 6877d556c3..8a26402bd8 100644 --- a/openpype/pipeline/publish/abstract_collect_render.py +++ b/openpype/pipeline/publish/abstract_collect_render.py @@ -75,7 +75,6 @@ class RenderInstance(object): tilesY = attr.ib(default=0) # number of tiles in Y # submit_publish_job - toBeRenderedOn = attr.ib(default=None) deadlineSubmissionJob = attr.ib(default=None) anatomyData = attr.ib(default=None) outputDir = attr.ib(default=None) diff --git a/openpype/plugins/publish/collect_farm_target.py b/openpype/plugins/publish/collect_farm_target.py new file mode 100644 index 0000000000..78410835dd --- /dev/null +++ b/openpype/plugins/publish/collect_farm_target.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +import pyblish.api + + +class CollectFarmTarget(pyblish.api.InstancePlugin): + """Collects the render target for the instance + """ + + order = pyblish.api.CollectorOrder + 0.499 + label = "Collect Farm Target" + targets = ["local"] + + def process(self, instance): + if not instance.data.get("farm"): + return + + context = instance.context + try: + deadline_module = context.data.get("openPypeModules")["deadline"] + if deadline_module.enabled: + instance.data["toBeRenderedOn"] = "deadline" + self.log.debug("Collected render target: deadline") + except AttributeError: + self.log.error("Cannot get OpenPype Deadline module.") + raise AssertionError("OpenPype Deadline module not found.") + + try: + royalrender_module = \ + context.data.get("openPypeModules")["royalrender"] + if royalrender_module.enabled: + instance.data["toBeRenderedOn"] = "royalrender" + self.log.debug("Collected render target: royalrender") + + except AttributeError: + self.log.error("Cannot get OpenPype RoyalRender module.") + raise AssertionError("OpenPype RoyalRender module not found.") + + try: + muster_module = context.data.get("openPypeModules")["muster"] + if muster_module.enabled: + instance.data["toBeRenderedOn"] = "muster" + self.log.debug("Collected render target: muster") + except AttributeError: + self.log.error("Cannot get OpenPype Muster module.") + raise AssertionError("OpenPype Muster module not found.") From 098bacddb9e87ac5eb7c8b9e5f1ef2d3f43fa74f Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Fri, 25 Aug 2023 11:54:44 +0800 Subject: [PATCH 055/154] fix incorrect position of the container during updating --- openpype/hosts/max/api/lib.py | 32 +++++++++++++++++++ .../hosts/max/plugins/load/load_camera_fbx.py | 11 ++++++- .../hosts/max/plugins/load/load_max_scene.py | 12 +++++-- .../hosts/max/plugins/load/load_model_fbx.py | 11 ++++++- .../hosts/max/plugins/load/load_model_obj.py | 12 ++++++- .../hosts/max/plugins/load/load_model_usd.py | 14 ++++++-- 6 files changed, 85 insertions(+), 7 deletions(-) diff --git a/openpype/hosts/max/api/lib.py b/openpype/hosts/max/api/lib.py index 08819ba155..267e75e5fe 100644 --- a/openpype/hosts/max/api/lib.py +++ b/openpype/hosts/max/api/lib.py @@ -371,9 +371,41 @@ def unique_namespace(namespace, format="%02d", def get_namespace(container_name): + """Get the namespace and name of the sub-container + + Args: + container_name (str): the name of master container + + Raises: + RuntimeError: when there is no master container found + + Returns: + namespace (str): namespace of the sub-container + name (str): name of the sub-container + """ node = rt.getNodeByName(container_name) if not node: raise RuntimeError("Master Container Not Found..") name = rt.getUserProp(node, "name") namespace = rt.getUserProp(node, "namespace") return namespace, name + +def object_transform_set(container_children): + """A function which allows to store the transform of + previous loaded object(s) + Args: + container_children(list): A list of nodes + + Returns: + transform_set (dict): A dict with all transform data of + the previous loaded object(s) + """ + transform_set = {} + for node in container_children: + name = f"{node.name}.transform" + transform_set[name] = node.pos + name = f"{node.name}.scale" + transform_set[name] = node.scale + name = f"{node.name}.rotation" + transform_set[name] = node.rotation + return transform_set diff --git a/openpype/hosts/max/plugins/load/load_camera_fbx.py b/openpype/hosts/max/plugins/load/load_camera_fbx.py index c70ece6293..acd77ad686 100644 --- a/openpype/hosts/max/plugins/load/load_camera_fbx.py +++ b/openpype/hosts/max/plugins/load/load_camera_fbx.py @@ -2,7 +2,9 @@ import os from openpype.hosts.max.api import lib, maintained_selection from openpype.hosts.max.api.lib import ( - unique_namespace, get_namespace + unique_namespace, + get_namespace, + object_transform_set ) from openpype.hosts.max.api.pipeline import ( containerise, @@ -61,6 +63,7 @@ class FbxLoader(load.LoaderPlugin): sub_node_name = f"{namespace}:{name}" inst_container = rt.getNodeByName(sub_node_name) rt.Select(inst_container.Children) + transform_data = object_transform_set(inst_container.Children) for prev_fbx_obj in rt.selection: if rt.isValidNode(prev_fbx_obj): rt.Delete(prev_fbx_obj) @@ -77,6 +80,12 @@ class FbxLoader(load.LoaderPlugin): if fbx_object.Parent != inst_container: fbx_object.Parent = inst_container fbx_object.name = f"{namespace}:{fbx_object.name}" + fbx_object.pos = transform_data[ + f"{fbx_object.name}.transform"] + fbx_object.rotation = transform_data[ + f"{fbx_object.name}.rotation"] + fbx_object.scale = transform_data[ + f"{fbx_object.name}.scale"] for children in node.Children: if rt.classOf(children) == rt.Container: diff --git a/openpype/hosts/max/plugins/load/load_max_scene.py b/openpype/hosts/max/plugins/load/load_max_scene.py index fada871c6d..3d524e261f 100644 --- a/openpype/hosts/max/plugins/load/load_max_scene.py +++ b/openpype/hosts/max/plugins/load/load_max_scene.py @@ -2,7 +2,9 @@ import os from openpype.hosts.max.api import lib from openpype.hosts.max.api.lib import ( - unique_namespace, get_namespace + unique_namespace, + get_namespace, + object_transform_set ) from openpype.hosts.max.api.pipeline import ( containerise, import_custom_attribute_data, @@ -62,6 +64,7 @@ class MaxSceneLoader(load.LoaderPlugin): # delete the old container with attribute # delete old duplicate rt.Select(node.Children) + transform_data = object_transform_set(node.Children) for prev_max_obj in rt.GetCurrentSelection(): if rt.isValidNode(prev_max_obj) and prev_max_obj.name != sub_container_name: # noqa rt.Delete(prev_max_obj) @@ -77,7 +80,12 @@ class MaxSceneLoader(load.LoaderPlugin): for max_obj, obj_name in zip(current_max_objects, current_max_object_names): max_obj.name = f"{namespace}:{obj_name}" - + max_obj.pos = transform_data[ + f"{max_obj.name}.transform"] + max_obj.rotation = transform_data[ + f"{max_obj.name}.rotation"] + max_obj.scale = transform_data[ + f"{max_obj.name}.scale"] lib.imprint(container["instance_node"], { "representation": str(representation["_id"]) diff --git a/openpype/hosts/max/plugins/load/load_model_fbx.py b/openpype/hosts/max/plugins/load/load_model_fbx.py index 6097a4ca6e..fcac72dae1 100644 --- a/openpype/hosts/max/plugins/load/load_model_fbx.py +++ b/openpype/hosts/max/plugins/load/load_model_fbx.py @@ -6,7 +6,9 @@ from openpype.hosts.max.api.pipeline import ( ) from openpype.hosts.max.api import lib from openpype.hosts.max.api.lib import ( - unique_namespace, get_namespace + unique_namespace, + get_namespace, + object_transform_set ) from openpype.hosts.max.api.lib import maintained_selection @@ -56,6 +58,7 @@ class FbxModelLoader(load.LoaderPlugin): sub_node_name = f"{namespace}:{name}" inst_container = rt.getNodeByName(sub_node_name) rt.Select(inst_container.Children) + transform_data = object_transform_set(inst_container.Children) for prev_fbx_obj in rt.selection: if rt.isValidNode(prev_fbx_obj): rt.Delete(prev_fbx_obj) @@ -71,6 +74,12 @@ class FbxModelLoader(load.LoaderPlugin): if fbx_object.Parent != inst_container: fbx_object.Parent = inst_container fbx_object.name = f"{namespace}:{fbx_object.name}" + fbx_object.pos = transform_data[ + f"{fbx_object.name}.transform"] + fbx_object.rotation = transform_data[ + f"{fbx_object.name}.rotation"] + fbx_object.scale = transform_data[ + f"{fbx_object.name}.scale"] for children in node.Children: if rt.classOf(children) == rt.Container: diff --git a/openpype/hosts/max/plugins/load/load_model_obj.py b/openpype/hosts/max/plugins/load/load_model_obj.py index 225801b8d0..04a0ac1679 100644 --- a/openpype/hosts/max/plugins/load/load_model_obj.py +++ b/openpype/hosts/max/plugins/load/load_model_obj.py @@ -2,7 +2,10 @@ import os from openpype.hosts.max.api import lib from openpype.hosts.max.api.lib import ( - unique_namespace, get_namespace + unique_namespace, + get_namespace, + maintained_selection, + object_transform_set ) from openpype.hosts.max.api.lib import maintained_selection from openpype.hosts.max.api.pipeline import ( @@ -56,6 +59,7 @@ class ObjLoader(load.LoaderPlugin): sub_node_name = f"{namespace}:{name}" inst_container = rt.getNodeByName(sub_node_name) rt.Select(inst_container.Children) + transform_data = object_transform_set(inst_container.Children) for prev_obj in rt.selection: if rt.isValidNode(prev_obj): rt.Delete(prev_obj) @@ -67,6 +71,12 @@ class ObjLoader(load.LoaderPlugin): for selection in selections: selection.Parent = inst_container selection.name = f"{namespace}:{selection.name}" + selection.pos = transform_data[ + f"{selection.name}.transform"] + selection.rotation = transform_data[ + f"{selection.name}.rotation"] + selection.scale = transform_data[ + f"{selection.name}.scale"] with maintained_selection(): rt.Select(node) diff --git a/openpype/hosts/max/plugins/load/load_model_usd.py b/openpype/hosts/max/plugins/load/load_model_usd.py index 0c17736739..14f339f039 100644 --- a/openpype/hosts/max/plugins/load/load_model_usd.py +++ b/openpype/hosts/max/plugins/load/load_model_usd.py @@ -2,7 +2,9 @@ import os from openpype.hosts.max.api import lib from openpype.hosts.max.api.lib import ( - unique_namespace, get_namespace + unique_namespace, + get_namespace, + object_transform_set ) from openpype.hosts.max.api.lib import maintained_selection from openpype.hosts.max.api.pipeline import ( @@ -63,8 +65,10 @@ class ModelUSDLoader(load.LoaderPlugin): node = rt.GetNodeByName(node_name) namespace, name = get_namespace(node_name) sub_node_name = f"{namespace}:{name}" + transform_data = None for n in node.Children: rt.Select(n.Children) + transform_data = object_transform_set(n.Children) for prev_usd_asset in rt.selection: if rt.isValidNode(prev_usd_asset): rt.Delete(prev_usd_asset) @@ -85,8 +89,14 @@ class ModelUSDLoader(load.LoaderPlugin): import_custom_attribute_data(asset, asset.Children) for children in asset.Children: children.name = f"{namespace}:{children.name}" - asset.name = sub_node_name + children.pos = transform_data[ + f"{children.name}.transform"] + children.rotation = transform_data[ + f"{children.name}.rotation"] + children.scale = transform_data[ + f"{children.name}.scale"] + asset.name = sub_node_name with maintained_selection(): rt.Select(node) From b490b2741f75d51d1dc4f6ec6fbbab238d11fa0c Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Fri, 25 Aug 2023 11:56:01 +0800 Subject: [PATCH 056/154] hound --- openpype/hosts/max/api/lib.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/hosts/max/api/lib.py b/openpype/hosts/max/api/lib.py index 267e75e5fe..712340c99a 100644 --- a/openpype/hosts/max/api/lib.py +++ b/openpype/hosts/max/api/lib.py @@ -390,6 +390,7 @@ def get_namespace(container_name): namespace = rt.getUserProp(node, "namespace") return namespace, name + def object_transform_set(container_children): """A function which allows to store the transform of previous loaded object(s) From e9952b5d53421794b58b278d015412f368baf88e Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 25 Aug 2023 11:26:03 +0200 Subject: [PATCH 057/154] global: avoiding cleanup of flagged representation --- openpype/pipeline/publish/lib.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/openpype/pipeline/publish/lib.py b/openpype/pipeline/publish/lib.py index ada12800a9..08ce8c2c9d 100644 --- a/openpype/pipeline/publish/lib.py +++ b/openpype/pipeline/publish/lib.py @@ -953,6 +953,7 @@ def replace_with_published_scene_path(instance, replace_in_path=True): return file_path + def add_repre_files_for_cleanup(instance, repre): """ Explicitly mark repre files to be deleted. @@ -961,7 +962,16 @@ def add_repre_files_for_cleanup(instance, repre): """ files = repre["files"] staging_dir = repre.get("stagingDir") - if not staging_dir or instance.data.get("stagingDir_persistent"): + + # first make sure representation level is not persistent + if ( + not staging_dir + or repre.get("stagingDir_persistent") + ): + return + + # then look into instance level if it's not persistent + if instance.data.get("stagingDir_persistent"): return if isinstance(files, str): From 1a61eb0c3e711cfcf856f7f1ef937949161e89f4 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Fri, 25 Aug 2023 21:29:34 +0800 Subject: [PATCH 058/154] Libor's comment on Container namespace issue and not support rotation --- openpype/hosts/max/api/lib.py | 2 -- openpype/hosts/max/plugins/load/load_camera_fbx.py | 8 ++++---- openpype/hosts/max/plugins/load/load_max_scene.py | 7 +++---- openpype/hosts/max/plugins/load/load_model.py | 3 ++- openpype/hosts/max/plugins/load/load_model_fbx.py | 8 ++++---- openpype/hosts/max/plugins/load/load_model_obj.py | 7 +++---- openpype/hosts/max/plugins/load/load_model_usd.py | 7 +++---- openpype/hosts/max/plugins/load/load_pointcache.py | 3 ++- openpype/hosts/max/plugins/load/load_pointcloud.py | 6 ++++-- openpype/hosts/max/plugins/load/load_redshift_proxy.py | 6 ++++-- 10 files changed, 29 insertions(+), 28 deletions(-) diff --git a/openpype/hosts/max/api/lib.py b/openpype/hosts/max/api/lib.py index 712340c99a..034307e72a 100644 --- a/openpype/hosts/max/api/lib.py +++ b/openpype/hosts/max/api/lib.py @@ -407,6 +407,4 @@ def object_transform_set(container_children): transform_set[name] = node.pos name = f"{node.name}.scale" transform_set[name] = node.scale - name = f"{node.name}.rotation" - transform_set[name] = node.rotation return transform_set diff --git a/openpype/hosts/max/plugins/load/load_camera_fbx.py b/openpype/hosts/max/plugins/load/load_camera_fbx.py index acd77ad686..f040115417 100644 --- a/openpype/hosts/max/plugins/load/load_camera_fbx.py +++ b/openpype/hosts/max/plugins/load/load_camera_fbx.py @@ -22,6 +22,7 @@ class FbxLoader(load.LoaderPlugin): order = -9 icon = "code-fork" color = "white" + postfix = "param" def load(self, context, name=None, namespace=None, data=None): from pymxs import runtime as rt @@ -41,7 +42,8 @@ class FbxLoader(load.LoaderPlugin): name + "_", suffix="_", ) - container = rt.container(name=f"{namespace}:{name}") + container = rt.container( + name=f"{namespace}:{name}_{self.postfix}") selections = rt.GetCurrentSelection() import_custom_attribute_data(container, selections) @@ -60,7 +62,7 @@ class FbxLoader(load.LoaderPlugin): node_name = container["instance_node"] node = rt.getNodeByName(node_name) namespace, name = get_namespace(node_name) - sub_node_name = f"{namespace}:{name}" + sub_node_name = f"{namespace}:{name}_{self.postfix}" inst_container = rt.getNodeByName(sub_node_name) rt.Select(inst_container.Children) transform_data = object_transform_set(inst_container.Children) @@ -82,8 +84,6 @@ class FbxLoader(load.LoaderPlugin): fbx_object.name = f"{namespace}:{fbx_object.name}" fbx_object.pos = transform_data[ f"{fbx_object.name}.transform"] - fbx_object.rotation = transform_data[ - f"{fbx_object.name}.rotation"] fbx_object.scale = transform_data[ f"{fbx_object.name}.scale"] diff --git a/openpype/hosts/max/plugins/load/load_max_scene.py b/openpype/hosts/max/plugins/load/load_max_scene.py index 3d524e261f..98e9be96e1 100644 --- a/openpype/hosts/max/plugins/load/load_max_scene.py +++ b/openpype/hosts/max/plugins/load/load_max_scene.py @@ -24,6 +24,7 @@ class MaxSceneLoader(load.LoaderPlugin): order = -8 icon = "code-fork" color = "green" + postfix = "param" def load(self, context, name=None, namespace=None, data=None): from pymxs import runtime as rt @@ -41,7 +42,7 @@ class MaxSceneLoader(load.LoaderPlugin): name + "_", suffix="_", ) - container_name = f"{namespace}:{name}" + container_name = f"{namespace}:{name}_{self.postfix}" container = rt.Container(name=container_name) import_custom_attribute_data(container, max_objects) max_container.append(container) @@ -60,7 +61,7 @@ class MaxSceneLoader(load.LoaderPlugin): node = rt.getNodeByName(node_name) namespace, name = get_namespace(node_name) - sub_container_name = f"{namespace}:{name}" + sub_container_name = f"{namespace}:{name}_{self.postfix}" # delete the old container with attribute # delete old duplicate rt.Select(node.Children) @@ -82,8 +83,6 @@ class MaxSceneLoader(load.LoaderPlugin): max_obj.name = f"{namespace}:{obj_name}" max_obj.pos = transform_data[ f"{max_obj.name}.transform"] - max_obj.rotation = transform_data[ - f"{max_obj.name}.rotation"] max_obj.scale = transform_data[ f"{max_obj.name}.scale"] diff --git a/openpype/hosts/max/plugins/load/load_model.py b/openpype/hosts/max/plugins/load/load_model.py index acc2a4032b..c5a73b4327 100644 --- a/openpype/hosts/max/plugins/load/load_model.py +++ b/openpype/hosts/max/plugins/load/load_model.py @@ -20,6 +20,7 @@ class ModelAbcLoader(load.LoaderPlugin): order = -10 icon = "code-fork" color = "orange" + postfix = "param" def load(self, context, name=None, namespace=None, data=None): from pymxs import runtime as rt @@ -61,7 +62,7 @@ class ModelAbcLoader(load.LoaderPlugin): for abc_object in abc_container.Children: abc_object.name = f"{namespace}:{abc_object.name}" # rename the abc container with namespace - abc_container_name = f"{namespace}:{name}" + abc_container_name = f"{namespace}:{name}_{self.postfix}" abc_container.name = abc_container_name return containerise( diff --git a/openpype/hosts/max/plugins/load/load_model_fbx.py b/openpype/hosts/max/plugins/load/load_model_fbx.py index fcac72dae1..56c8768675 100644 --- a/openpype/hosts/max/plugins/load/load_model_fbx.py +++ b/openpype/hosts/max/plugins/load/load_model_fbx.py @@ -21,6 +21,7 @@ class FbxModelLoader(load.LoaderPlugin): order = -9 icon = "code-fork" color = "white" + postfix = "param" def load(self, context, name=None, namespace=None, data=None): from pymxs import runtime as rt @@ -36,7 +37,8 @@ class FbxModelLoader(load.LoaderPlugin): name + "_", suffix="_", ) - container = rt.container(name=f"{namespace}:{name}") + container = rt.container( + name=f"{namespace}:{name}_{self.postfix}") selections = rt.GetCurrentSelection() import_custom_attribute_data(container, selections) @@ -55,7 +57,7 @@ class FbxModelLoader(load.LoaderPlugin): node_name = container["instance_node"] node = rt.getNodeByName(node_name) namespace, name = get_namespace(node_name) - sub_node_name = f"{namespace}:{name}" + sub_node_name = f"{namespace}:{name}_{self.postfix}" inst_container = rt.getNodeByName(sub_node_name) rt.Select(inst_container.Children) transform_data = object_transform_set(inst_container.Children) @@ -76,8 +78,6 @@ class FbxModelLoader(load.LoaderPlugin): fbx_object.name = f"{namespace}:{fbx_object.name}" fbx_object.pos = transform_data[ f"{fbx_object.name}.transform"] - fbx_object.rotation = transform_data[ - f"{fbx_object.name}.rotation"] fbx_object.scale = transform_data[ f"{fbx_object.name}.scale"] diff --git a/openpype/hosts/max/plugins/load/load_model_obj.py b/openpype/hosts/max/plugins/load/load_model_obj.py index 04a0ac1679..314889e6ec 100644 --- a/openpype/hosts/max/plugins/load/load_model_obj.py +++ b/openpype/hosts/max/plugins/load/load_model_obj.py @@ -24,6 +24,7 @@ class ObjLoader(load.LoaderPlugin): order = -9 icon = "code-fork" color = "white" + postfix = "param" def load(self, context, name=None, namespace=None, data=None): from pymxs import runtime as rt @@ -38,7 +39,7 @@ class ObjLoader(load.LoaderPlugin): suffix="_", ) # create "missing" container for obj import - container = rt.Container(name=f"{namespace}:{name}") + container = rt.Container(name=f"{namespace}:{name}_{self.postfix}") selections = rt.GetCurrentSelection() import_custom_attribute_data(container, selections) # get current selection @@ -56,7 +57,7 @@ class ObjLoader(load.LoaderPlugin): node_name = container["instance_node"] node = rt.getNodeByName(node_name) namespace, name = get_namespace(node_name) - sub_node_name = f"{namespace}:{name}" + sub_node_name = f"{namespace}:{name}_{self.postfix}" inst_container = rt.getNodeByName(sub_node_name) rt.Select(inst_container.Children) transform_data = object_transform_set(inst_container.Children) @@ -73,8 +74,6 @@ class ObjLoader(load.LoaderPlugin): selection.name = f"{namespace}:{selection.name}" selection.pos = transform_data[ f"{selection.name}.transform"] - selection.rotation = transform_data[ - f"{selection.name}.rotation"] selection.scale = transform_data[ f"{selection.name}.scale"] with maintained_selection(): diff --git a/openpype/hosts/max/plugins/load/load_model_usd.py b/openpype/hosts/max/plugins/load/load_model_usd.py index 14f339f039..f35d8e6327 100644 --- a/openpype/hosts/max/plugins/load/load_model_usd.py +++ b/openpype/hosts/max/plugins/load/load_model_usd.py @@ -23,6 +23,7 @@ class ModelUSDLoader(load.LoaderPlugin): order = -10 icon = "code-fork" color = "orange" + postfix = "param" def load(self, context, name=None, namespace=None, data=None): from pymxs import runtime as rt @@ -47,7 +48,7 @@ class ModelUSDLoader(load.LoaderPlugin): for usd_asset in asset.Children: usd_asset.name = f"{namespace}:{usd_asset.name}" - asset_name = f"{namespace}:{name}" + asset_name = f"{namespace}:{name}_{self.postfix}" asset.name = asset_name # need to get the correct container after renamed asset = rt.GetNodeByName(asset_name) @@ -64,7 +65,7 @@ class ModelUSDLoader(load.LoaderPlugin): node_name = container["instance_node"] node = rt.GetNodeByName(node_name) namespace, name = get_namespace(node_name) - sub_node_name = f"{namespace}:{name}" + sub_node_name = f"{namespace}:{name}_{self.postfix}" transform_data = None for n in node.Children: rt.Select(n.Children) @@ -91,8 +92,6 @@ class ModelUSDLoader(load.LoaderPlugin): children.name = f"{namespace}:{children.name}" children.pos = transform_data[ f"{children.name}.transform"] - children.rotation = transform_data[ - f"{children.name}.rotation"] children.scale = transform_data[ f"{children.name}.scale"] diff --git a/openpype/hosts/max/plugins/load/load_pointcache.py b/openpype/hosts/max/plugins/load/load_pointcache.py index 64bf7ddac0..070dea88d4 100644 --- a/openpype/hosts/max/plugins/load/load_pointcache.py +++ b/openpype/hosts/max/plugins/load/load_pointcache.py @@ -24,6 +24,7 @@ class AbcLoader(load.LoaderPlugin): order = -10 icon = "code-fork" color = "orange" + postfix = "param" def load(self, context, name=None, namespace=None, data=None): from pymxs import runtime as rt @@ -68,7 +69,7 @@ class AbcLoader(load.LoaderPlugin): for abc_object in abc_container.Children: abc_object.name = f"{namespace}:{abc_object.name}" # rename the abc container with namespace - abc_container_name = f"{namespace}:{name}" + abc_container_name = f"{namespace}:{name}_{self.postfix}" abc_container.name = abc_container_name return containerise( diff --git a/openpype/hosts/max/plugins/load/load_pointcloud.py b/openpype/hosts/max/plugins/load/load_pointcloud.py index 87b7fce292..c4c4cfbc6c 100644 --- a/openpype/hosts/max/plugins/load/load_pointcloud.py +++ b/openpype/hosts/max/plugins/load/load_pointcloud.py @@ -20,6 +20,7 @@ class PointCloudLoader(load.LoaderPlugin): order = -8 icon = "code-fork" color = "green" + postfix = "param" def load(self, context, name=None, namespace=None, data=None): """load point cloud by tyCache""" @@ -33,7 +34,8 @@ class PointCloudLoader(load.LoaderPlugin): name + "_", suffix="_", ) - prt_container = rt.Container(name=f"{namespace}:{name}") + prt_container = rt.Container( + name=f"{namespace}:{name}_{self.postfix}") import_custom_attribute_data(prt_container, [obj]) obj.Parent = prt_container obj.name = f"{namespace}:{obj.name}" @@ -49,7 +51,7 @@ class PointCloudLoader(load.LoaderPlugin): path = get_representation_path(representation) node = rt.GetNodeByName(container["instance_node"]) namespace, name = get_namespace(container["instance_node"]) - sub_node_name = f"{namespace}:{name}" + sub_node_name = f"{namespace}:{name}_{self.postfix}" inst_container = rt.getNodeByName(sub_node_name) update_custom_attribute_data( inst_container, inst_container.Children) diff --git a/openpype/hosts/max/plugins/load/load_redshift_proxy.py b/openpype/hosts/max/plugins/load/load_redshift_proxy.py index b240714314..f7dd95962b 100644 --- a/openpype/hosts/max/plugins/load/load_redshift_proxy.py +++ b/openpype/hosts/max/plugins/load/load_redshift_proxy.py @@ -25,6 +25,7 @@ class RedshiftProxyLoader(load.LoaderPlugin): order = -9 icon = "code-fork" color = "white" + postfix = "param" def load(self, context, name=None, namespace=None, data=None): from pymxs import runtime as rt @@ -41,7 +42,8 @@ class RedshiftProxyLoader(load.LoaderPlugin): name + "_", suffix="_", ) - container = rt.Container(name=f"{namespace}:{name}") + container = rt.Container( + name=f"{namespace}:{name}_{self.postfix}") rs_proxy.Parent = container rs_proxy.name = f"{namespace}:{rs_proxy.name}" import_custom_attribute_data(container, [rs_proxy]) @@ -55,7 +57,7 @@ class RedshiftProxyLoader(load.LoaderPlugin): path = get_representation_path(representation) namespace, name = get_namespace(container["instance_node"]) - sub_node_name = f"{namespace}:{name}" + sub_node_name = f"{namespace}:{name}_{self.postfix}" inst_container = rt.getNodeByName(sub_node_name) update_custom_attribute_data( From d491b4f18be6bdc95bca2eb08077d8da1d5c79d5 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 28 Aug 2023 14:28:31 +0200 Subject: [PATCH 059/154] Optimize query (use `cmds.ls` once), add Select Invalid action, improve validation report, avoid "Unknown object type" errors --- .../validate_plugin_path_attributes.py | 53 ++++++++++++------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_plugin_path_attributes.py b/openpype/hosts/maya/plugins/publish/validate_plugin_path_attributes.py index 78334cd01f..9f47bf7a3d 100644 --- a/openpype/hosts/maya/plugins/publish/validate_plugin_path_attributes.py +++ b/openpype/hosts/maya/plugins/publish/validate_plugin_path_attributes.py @@ -4,6 +4,8 @@ from maya import cmds import pyblish.api +from openpype.hosts.maya.api.lib import pairwise +from openpype.hosts.maya.api.action import SelectInvalidAction from openpype.pipeline.publish import ( ValidateContentsOrder, PublishValidationError @@ -19,31 +21,33 @@ class ValidatePluginPathAttributes(pyblish.api.InstancePlugin): hosts = ['maya'] families = ["workfile"] label = "Plug-in Path Attributes" + actions = [SelectInvalidAction] - def get_invalid(self, instance): + # Attributes are defined in project settings + attribute = [] + + @classmethod + def get_invalid(cls, instance): invalid = list() - # get the project setting - validate_path = ( - instance.context.data["project_settings"]["maya"]["publish"] - ) - file_attr = validate_path["ValidatePluginPathAttributes"]["attribute"] + file_attr = cls.attribute if not file_attr: return invalid - # get the nodes and file attributes - for node, attr in file_attr.items(): - # check the related nodes - targets = cmds.ls(type=node) + # Consider only valid node types to avoid "Unknown object type" warning + all_node_types = set(cmds.allNodeTypes()) + node_types = [key for key in file_attr.keys() if key in all_node_types] - for target in targets: - # get the filepath - file_attr = "{}.{}".format(target, attr) - filepath = cmds.getAttr(file_attr) + for node, node_type in pairwise(cmds.ls(type=node_types, + showType=True)): + # get the filepath + file_attr = "{}.{}".format(node, file_attr[node_type]) + filepath = cmds.getAttr(file_attr) - if filepath and not os.path.exists(filepath): - self.log.error("File {0} not exists".format(filepath)) # noqa - invalid.append(target) + if filepath and not os.path.exists(filepath): + cls.log.error("{} '{}' uses non-existing filepath: {}" + .format(node_type, node, filepath)) + invalid.append(node) return invalid @@ -51,5 +55,16 @@ class ValidatePluginPathAttributes(pyblish.api.InstancePlugin): """Process all directories Set as Filenames in Non-Maya Nodes""" invalid = self.get_invalid(instance) if invalid: - raise PublishValidationError("Non-existent Path " - "found: {0}".format(invalid)) + raise PublishValidationError( + title="Plug-in Path Attributes", + message="Non-existent filepath found on nodes: {}".format( + ", ".join(invalid) + ), + description=( + "## Plug-in nodes use invalid filepaths\n" + "The workfile contains nodes from plug-ins that use " + "filepaths which do not exist.\n\n" + "Please make sure their filepaths are correct and the " + "files exist on disk." + ) + ) From afebe088370cb3170ff3147f7258c55224654096 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 28 Aug 2023 16:23:36 +0200 Subject: [PATCH 060/154] Refactor to PublishValidationError to allow the RepairAction to work + provide informational report message --- .../plugins/publish/validate_shape_zero.py | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_shape_zero.py b/openpype/hosts/maya/plugins/publish/validate_shape_zero.py index 7a7e9a0aee..c7af6a60db 100644 --- a/openpype/hosts/maya/plugins/publish/validate_shape_zero.py +++ b/openpype/hosts/maya/plugins/publish/validate_shape_zero.py @@ -7,6 +7,7 @@ from openpype.hosts.maya.api import lib from openpype.pipeline.publish import ( ValidateContentsOrder, RepairAction, + PublishValidationError ) @@ -67,5 +68,30 @@ class ValidateShapeZero(pyblish.api.Validator): invalid = self.get_invalid(instance) if invalid: - raise ValueError("Shapes found with non-zero component tweaks: " - "{0}".format(invalid)) + raise PublishValidationError( + title="Shape Component Tweaks", + message="Shapes found with non-zero component tweaks: '{}'" + "".format(", ".join(invalid)), + description=( + "## Shapes found with component tweaks\n" + "Shapes were detected that have component tweaks on their " + "components. Please remove the component tweaks to " + "continue.\n\n" + "### Repair\n" + "The repair action will try to *freeze* the component " + "tweaks into the shapes, which is usually the correct fix " + "if the mesh has no construction history (= has its " + "history deleted)."), + detail=( + "Maya allows to store component tweaks within shape nodes " + "which are applied between its `inMesh` and `outMesh` " + "connections resulting in the output of a shape node " + "differing from the input. We usually want to avoid this " + "for published meshes (in particular for Maya scenes) as " + "it can have unintended results when using these meshes " + "as intermediate meshes since it applies positional " + "differences without being visible edits in the node " + "graph.\n\n" + "These tweaks are traditionally stored in the `.pnts` " + "attribute of shapes.") + ) From 7a513cde9a48b6185f2dbc27a267c80aea2b4f64 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 28 Aug 2023 16:29:52 +0200 Subject: [PATCH 061/154] Remove Validate Instance Attributes The new publisher always updates and imprints the publish instances with the latest Attribute Definitions of the Creator, thus making this legacy validator redundant. Currently legacy instances do not work through the new publisher (they need to be converted to work correctly) and thus even for legacy workfiles this validator is redundant. --- .../publish/validate_instance_attributes.py | 60 ------------------- 1 file changed, 60 deletions(-) delete mode 100644 openpype/hosts/maya/plugins/publish/validate_instance_attributes.py diff --git a/openpype/hosts/maya/plugins/publish/validate_instance_attributes.py b/openpype/hosts/maya/plugins/publish/validate_instance_attributes.py deleted file mode 100644 index f870c9f8c4..0000000000 --- a/openpype/hosts/maya/plugins/publish/validate_instance_attributes.py +++ /dev/null @@ -1,60 +0,0 @@ -from maya import cmds - -import pyblish.api -from openpype.pipeline.publish import ( - ValidateContentsOrder, PublishValidationError, RepairAction -) -from openpype.pipeline import discover_legacy_creator_plugins -from openpype.hosts.maya.api.lib import imprint - - -class ValidateInstanceAttributes(pyblish.api.InstancePlugin): - """Validate Instance Attributes. - - New attributes can be introduced as new features come in. Old instances - will need to be updated with these attributes for the documentation to make - sense, and users do not have to recreate the instances. - """ - - order = ValidateContentsOrder - hosts = ["maya"] - families = ["*"] - label = "Instance Attributes" - plugins_by_family = { - p.family: p for p in discover_legacy_creator_plugins() - } - actions = [RepairAction] - - @classmethod - def get_missing_attributes(self, instance): - plugin = self.plugins_by_family[instance.data["family"]] - subset = instance.data["subset"] - asset = instance.data["asset"] - objset = instance.data["objset"] - - missing_attributes = {} - for key, value in plugin(subset, asset).data.items(): - if not cmds.objExists("{}.{}".format(objset, key)): - missing_attributes[key] = value - - return missing_attributes - - def process(self, instance): - objset = instance.data.get("objset") - if objset is None: - self.log.debug( - "Skipping {} because no objectset found.".format(instance) - ) - return - - missing_attributes = self.get_missing_attributes(instance) - if missing_attributes: - raise PublishValidationError( - "Missing attributes on {}:\n{}".format( - objset, missing_attributes - ) - ) - - @classmethod - def repair(cls, instance): - imprint(instance.data["objset"], cls.get_missing_attributes(instance)) From e809050f15c98e965b5561249e8c7b604a3e15c9 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 28 Aug 2023 16:54:39 +0200 Subject: [PATCH 062/154] Re-use existing select invalid and repair actions, provide more elaborate PublishValidationError report, plus fix "optional" support by using `OptionalPyblishPluginMixin` base class. --- .../publish/validate_instance_in_context.py | 135 +++++++----------- 1 file changed, 49 insertions(+), 86 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_instance_in_context.py b/openpype/hosts/maya/plugins/publish/validate_instance_in_context.py index b257add7e8..4ded57137c 100644 --- a/openpype/hosts/maya/plugins/publish/validate_instance_in_context.py +++ b/openpype/hosts/maya/plugins/publish/validate_instance_in_context.py @@ -3,94 +3,19 @@ from __future__ import absolute_import import pyblish.api +import openpype.hosts.maya.api.action from openpype.pipeline.publish import ( - ValidateContentsOrder, PublishValidationError + RepairAction, + ValidateContentsOrder, + PublishValidationError, + OptionalPyblishPluginMixin ) from maya import cmds -class SelectInvalidInstances(pyblish.api.Action): - """Select invalid instances in Outliner.""" - - label = "Select Instances" - icon = "briefcase" - on = "failed" - - def process(self, context, plugin): - """Process invalid validators and select invalid instances.""" - # Get the errored instances - failed = [] - for result in context.data["results"]: - if ( - result["error"] is None - or result["instance"] is None - or result["instance"] in failed - or result["plugin"] != plugin - ): - continue - - failed.append(result["instance"]) - - # Apply pyblish.logic to get the instances for the plug-in - instances = pyblish.api.instances_by_plugin(failed, plugin) - - if instances: - self.log.info( - "Selecting invalid nodes: %s" % ", ".join( - [str(x) for x in instances] - ) - ) - self.select(instances) - else: - self.log.info("No invalid nodes found.") - self.deselect() - - def select(self, instances): - cmds.select(instances, replace=True, noExpand=True) - - def deselect(self): - cmds.select(deselect=True) - - -class RepairSelectInvalidInstances(pyblish.api.Action): - """Repair the instance asset.""" - - label = "Repair" - icon = "wrench" - on = "failed" - - def process(self, context, plugin): - # Get the errored instances - failed = [] - for result in context.data["results"]: - if result["error"] is None: - continue - if result["instance"] is None: - continue - if result["instance"] in failed: - continue - if result["plugin"] != plugin: - continue - - failed.append(result["instance"]) - - # Apply pyblish.logic to get the instances for the plug-in - instances = pyblish.api.instances_by_plugin(failed, plugin) - - context_asset = context.data["assetEntity"]["name"] - for instance in instances: - self.set_attribute(instance, context_asset) - - def set_attribute(self, instance, context_asset): - cmds.setAttr( - instance.data.get("name") + ".asset", - context_asset, - type="string" - ) - - -class ValidateInstanceInContext(pyblish.api.InstancePlugin): +class ValidateInstanceInContext(pyblish.api.InstancePlugin, + OptionalPyblishPluginMixin): """Validator to check if instance asset match context asset. When working in per-shot style you always publish data in context of @@ -104,11 +29,49 @@ class ValidateInstanceInContext(pyblish.api.InstancePlugin): label = "Instance in same Context" optional = True hosts = ["maya"] - actions = [SelectInvalidInstances, RepairSelectInvalidInstances] + actions = [ + openpype.hosts.maya.api.action.SelectInvalidAction, RepairAction + ] def process(self, instance): + if not self.is_active(instance.data): + return + asset = instance.data.get("asset") - context_asset = instance.context.data["assetEntity"]["name"] - msg = "{} has asset {}".format(instance.name, asset) + context_asset = self.get_context_asset(instance) if asset != context_asset: - raise PublishValidationError(msg) + raise PublishValidationError( + message=( + "Instance '{}' publishes to different asset than current " + "context: {}. Current context: {}".format( + instance.name, asset, context_asset + ) + ), + description=( + "## Publishing to a different asset\n" + "There are publish instances present which are publishing " + "into a different asset than your current context.\n\n" + "Usually this is not what you want but there can be cases " + "where you might want to publish into another asset or " + "shot. If that's the case you can disable the validation " + "on the instance to ignore it." + ) + ) + + @classmethod + def get_invalid(cls, instance): + return [instance.data["instance_node"]] + + @classmethod + def repair(cls, instance): + context_asset = cls.get_context_asset(instance) + instance_node = instance.data["instance_node"] + cmds.setAttr( + "{}.asset".format(instance_node), + context_asset, + type="string" + ) + + @staticmethod + def get_context_asset(instance): + return instance.context.data["assetEntity"]["name"] From 2b951d29f23916e3354ecb6a328452dbf24d5282 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 30 Aug 2023 09:50:59 +0200 Subject: [PATCH 063/154] Maya: Tweak logging for artist-facing reports in publisher --- .../maya/plugins/publish/collect_assembly.py | 3 -- .../maya/plugins/publish/collect_look.py | 29 ++++++++------- .../publish/collect_multiverse_look.py | 20 +++++----- .../maya/plugins/publish/collect_render.py | 12 +++--- .../publish/collect_render_layer_aovs.py | 6 +-- .../publish/collect_renderable_camera.py | 9 +++-- .../publish/collect_unreal_staticmesh.py | 4 +- .../maya/plugins/publish/collect_xgen.py | 2 +- .../maya/plugins/publish/collect_yeti_rig.py | 5 +-- .../publish/extract_arnold_scene_source.py | 10 ++--- .../maya/plugins/publish/extract_assembly.py | 2 +- .../plugins/publish/extract_camera_alembic.py | 4 +- .../publish/extract_camera_mayaScene.py | 8 ++-- .../hosts/maya/plugins/publish/extract_fbx.py | 8 ++-- .../maya/plugins/publish/extract_gltf.py | 7 +--- .../maya/plugins/publish/extract_gpu_cache.py | 2 +- .../publish/extract_import_reference.py | 12 +++--- .../maya/plugins/publish/extract_layout.py | 8 ++-- .../maya/plugins/publish/extract_look.py | 37 +++++++++---------- .../plugins/publish/extract_maya_scene_raw.py | 7 ++-- .../maya/plugins/publish/extract_model.py | 7 ++-- .../publish/extract_multiverse_look.py | 8 ++-- .../plugins/publish/extract_multiverse_usd.py | 13 +++---- .../publish/extract_multiverse_usd_comp.py | 10 ++--- .../publish/extract_multiverse_usd_over.py | 8 ++-- .../hosts/maya/plugins/publish/extract_obj.py | 8 ++-- .../maya/plugins/publish/extract_playblast.py | 8 ++-- .../plugins/publish/extract_pointcache.py | 4 +- .../maya/plugins/publish/extract_proxy_abc.py | 4 +- .../plugins/publish/extract_redshift_proxy.py | 6 +-- .../plugins/publish/extract_rendersetup.py | 2 +- .../hosts/maya/plugins/publish/extract_rig.py | 6 +-- .../maya/plugins/publish/extract_thumbnail.py | 6 +-- .../extract_unreal_skeletalmesh_abc.py | 10 ++--- .../extract_unreal_skeletalmesh_fbx.py | 10 ++--- .../publish/extract_unreal_staticmesh.py | 10 ++--- .../maya/plugins/publish/extract_vrayproxy.py | 6 +-- .../maya/plugins/publish/extract_vrayscene.py | 17 ++++----- .../plugins/publish/extract_workfile_xgen.py | 2 +- .../maya/plugins/publish/extract_xgen.py | 4 +- .../plugins/publish/extract_yeti_cache.py | 8 ++-- .../maya/plugins/publish/extract_yeti_rig.py | 12 +++--- .../plugins/publish/reset_xgen_attributes.py | 4 +- .../plugins/publish/submit_maya_muster.py | 8 ++-- .../plugins/publish/validate_assembly_name.py | 2 +- .../publish/validate_assembly_namespaces.py | 2 +- .../plugins/publish/validate_frame_range.py | 4 +- .../plugins/publish/validate_glsl_material.py | 14 +++---- .../publish/validate_instancer_content.py | 2 +- .../validate_instancer_frame_ranges.py | 9 +---- .../plugins/publish/validate_model_name.py | 2 +- .../publish/validate_mvlook_contents.py | 13 ++++--- .../validate_skeletalmesh_hierarchy.py | 2 +- .../validate_unreal_staticmesh_naming.py | 6 +-- .../validate_vray_distributed_rendering.py | 4 +- .../validate_yeti_renderscript_callbacks.py | 4 +- .../validate_yeti_rig_input_in_instance.py | 4 +- 57 files changed, 217 insertions(+), 227 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/collect_assembly.py b/openpype/hosts/maya/plugins/publish/collect_assembly.py index 2aef9ab908..f64d6bee44 100644 --- a/openpype/hosts/maya/plugins/publish/collect_assembly.py +++ b/openpype/hosts/maya/plugins/publish/collect_assembly.py @@ -35,14 +35,11 @@ class CollectAssembly(pyblish.api.InstancePlugin): # Get all content from the instance instance_lookup = set(cmds.ls(instance, type="transform", long=True)) data = defaultdict(list) - self.log.info(instance_lookup) hierarchy_nodes = [] for container in containers: - self.log.info(container) root = lib.get_container_transforms(container, root=True) - self.log.info(root) if not root or root not in instance_lookup: continue diff --git a/openpype/hosts/maya/plugins/publish/collect_look.py b/openpype/hosts/maya/plugins/publish/collect_look.py index b3da920566..a2c3d6acbf 100644 --- a/openpype/hosts/maya/plugins/publish/collect_look.py +++ b/openpype/hosts/maya/plugins/publish/collect_look.py @@ -356,8 +356,9 @@ class CollectLook(pyblish.api.InstancePlugin): # Thus the data will be limited to only what we need. self.log.debug("obj_set {}".format(sets[obj_set])) if not sets[obj_set]["members"]: - self.log.info( - "Removing redundant set information: {}".format(obj_set)) + self.log.debug( + "Removing redundant set information: {}".format(obj_set) + ) sets.pop(obj_set, None) self.log.debug("Gathering attribute changes to instance members..") @@ -396,9 +397,9 @@ class CollectLook(pyblish.api.InstancePlugin): if con: materials.extend(con) - self.log.info("Found materials:\n{}".format(materials)) + self.log.debug("Found materials:\n{}".format(materials)) - self.log.info("Found the following sets:\n{}".format(look_sets)) + self.log.debug("Found the following sets:\n{}".format(look_sets)) # Get the entire node chain of the look sets # history = cmds.listHistory(look_sets) history = [] @@ -456,7 +457,7 @@ class CollectLook(pyblish.api.InstancePlugin): instance.extend(shader for shader in look_sets if shader not in instance_lookup) - self.log.info("Collected look for %s" % instance) + self.log.debug("Collected look for %s" % instance) def collect_sets(self, instance): """Collect all objectSets which are of importance for publishing @@ -593,7 +594,7 @@ class CollectLook(pyblish.api.InstancePlugin): if attribute == "fileTextureName": computed_attribute = node + ".computedFileTextureNamePattern" - self.log.info(" - file source: {}".format(source)) + self.log.debug(" - file source: {}".format(source)) color_space_attr = "{}.colorSpace".format(node) try: color_space = cmds.getAttr(color_space_attr) @@ -621,7 +622,7 @@ class CollectLook(pyblish.api.InstancePlugin): dependNode=True) ) if not source and cmds.nodeType(node) in pxr_nodes: - self.log.info("Renderman: source is empty, skipping...") + self.log.debug("Renderman: source is empty, skipping...") continue # We replace backslashes with forward slashes because V-Ray # can't handle the UDIM files with the backslashes in the @@ -630,14 +631,14 @@ class CollectLook(pyblish.api.InstancePlugin): files = get_file_node_files(node) if len(files) == 0: - self.log.error("No valid files found from node `%s`" % node) + self.log.debug("No valid files found from node `%s`" % node) - self.log.info("collection of resource done:") - self.log.info(" - node: {}".format(node)) - self.log.info(" - attribute: {}".format(attribute)) - self.log.info(" - source: {}".format(source)) - self.log.info(" - file: {}".format(files)) - self.log.info(" - color space: {}".format(color_space)) + self.log.debug("collection of resource done:") + self.log.debug(" - node: {}".format(node)) + self.log.debug(" - attribute: {}".format(attribute)) + self.log.debug(" - source: {}".format(source)) + self.log.debug(" - file: {}".format(files)) + self.log.debug(" - color space: {}".format(color_space)) # Define the resource yield { diff --git a/openpype/hosts/maya/plugins/publish/collect_multiverse_look.py b/openpype/hosts/maya/plugins/publish/collect_multiverse_look.py index 33fc7a025f..f05fb76d48 100644 --- a/openpype/hosts/maya/plugins/publish/collect_multiverse_look.py +++ b/openpype/hosts/maya/plugins/publish/collect_multiverse_look.py @@ -268,7 +268,7 @@ class CollectMultiverseLookData(pyblish.api.InstancePlugin): cmds.loadPlugin("MultiverseForMaya", quiet=True) import multiverse - self.log.info("Processing mvLook for '{}'".format(instance)) + self.log.debug("Processing mvLook for '{}'".format(instance)) nodes = set() for node in instance: @@ -287,7 +287,7 @@ class CollectMultiverseLookData(pyblish.api.InstancePlugin): publishMipMap = instance.data["publishMipMap"] for node in nodes: - self.log.info("Getting resources for '{}'".format(node)) + self.log.debug("Getting resources for '{}'".format(node)) # We know what nodes need to be collected, now we need to # extract the materials overrides. @@ -380,12 +380,12 @@ class CollectMultiverseLookData(pyblish.api.InstancePlugin): if len(files) == 0: self.log.error("No valid files found from node `%s`" % node) - self.log.info("collection of resource done:") - self.log.info(" - node: {}".format(node)) - self.log.info(" - attribute: {}".format(fname_attrib)) - self.log.info(" - source: {}".format(source)) - self.log.info(" - file: {}".format(files)) - self.log.info(" - color space: {}".format(color_space)) + self.log.debug("collection of resource done:") + self.log.debug(" - node: {}".format(node)) + self.log.debug(" - attribute: {}".format(fname_attrib)) + self.log.debug(" - source: {}".format(source)) + self.log.debug(" - file: {}".format(files)) + self.log.debug(" - color space: {}".format(color_space)) # Define the resource resource = {"node": node, @@ -406,14 +406,14 @@ class CollectMultiverseLookData(pyblish.api.InstancePlugin): extra_files = [] self.log.debug("Expecting MipMaps, going to look for them.") for fname in files: - self.log.info("Checking '{}' for mipmaps".format(fname)) + self.log.debug("Checking '{}' for mipmaps".format(fname)) if is_mipmap(fname): self.log.debug(" - file is already MipMap, skipping.") continue mipmap = get_mipmap(fname) if mipmap: - self.log.info(" mipmap found for '{}'".format(fname)) + self.log.debug(" mipmap found for '{}'".format(fname)) extra_files.append(mipmap) else: self.log.warning(" no mipmap found for '{}'".format(fname)) diff --git a/openpype/hosts/maya/plugins/publish/collect_render.py b/openpype/hosts/maya/plugins/publish/collect_render.py index c17a8789e4..82392f67bd 100644 --- a/openpype/hosts/maya/plugins/publish/collect_render.py +++ b/openpype/hosts/maya/plugins/publish/collect_render.py @@ -105,7 +105,7 @@ class CollectMayaRender(pyblish.api.InstancePlugin): "family": cmds.getAttr("{}.family".format(s)), } ) - self.log.info(" -> attach render to: {}".format(s)) + self.log.debug(" -> attach render to: {}".format(s)) layer_name = layer.name() @@ -137,10 +137,10 @@ class CollectMayaRender(pyblish.api.InstancePlugin): has_cameras = any(product.camera for product in render_products) assert has_cameras, "No render cameras found." - self.log.info("multipart: {}".format( + self.log.debug("multipart: {}".format( multipart)) assert expected_files, "no file names were generated, this is a bug" - self.log.info( + self.log.debug( "expected files: {}".format( json.dumps(expected_files, indent=4, sort_keys=True) ) @@ -175,7 +175,7 @@ class CollectMayaRender(pyblish.api.InstancePlugin): publish_meta_path = os.path.dirname(full_path) aov_dict[aov_first_key] = full_paths full_exp_files = [aov_dict] - self.log.info(full_exp_files) + self.log.debug(full_exp_files) if publish_meta_path is None: raise KnownPublishError("Unable to detect any expected output " @@ -227,7 +227,7 @@ class CollectMayaRender(pyblish.api.InstancePlugin): if platform.system().lower() in ["linux", "darwin"]: common_publish_meta_path = "/" + common_publish_meta_path - self.log.info( + self.log.debug( "Publish meta path: {}".format(common_publish_meta_path)) # Get layer specific settings, might be overrides @@ -300,7 +300,7 @@ class CollectMayaRender(pyblish.api.InstancePlugin): ) if rr_settings["enabled"]: data["rrPathName"] = instance.data.get("rrPathName") - self.log.info(data["rrPathName"]) + self.log.debug(data["rrPathName"]) if self.sync_workfile_version: data["version"] = context.data["version"] diff --git a/openpype/hosts/maya/plugins/publish/collect_render_layer_aovs.py b/openpype/hosts/maya/plugins/publish/collect_render_layer_aovs.py index c3dc31ead9..035c531a9b 100644 --- a/openpype/hosts/maya/plugins/publish/collect_render_layer_aovs.py +++ b/openpype/hosts/maya/plugins/publish/collect_render_layer_aovs.py @@ -37,7 +37,7 @@ class CollectRenderLayerAOVS(pyblish.api.InstancePlugin): # Get renderer renderer = instance.data["renderer"] - self.log.info("Renderer found: {}".format(renderer)) + self.log.debug("Renderer found: {}".format(renderer)) rp_node_types = {"vray": ["VRayRenderElement", "VRayRenderElementSet"], "arnold": ["aiAOV"], @@ -66,8 +66,8 @@ class CollectRenderLayerAOVS(pyblish.api.InstancePlugin): result.append(render_pass) - self.log.info("Found {} render elements / AOVs for " - "'{}'".format(len(result), instance.data["subset"])) + self.log.debug("Found {} render elements / AOVs for " + "'{}'".format(len(result), instance.data["subset"])) instance.data["renderPasses"] = result diff --git a/openpype/hosts/maya/plugins/publish/collect_renderable_camera.py b/openpype/hosts/maya/plugins/publish/collect_renderable_camera.py index d1c3cf3b2c..4443e2e0db 100644 --- a/openpype/hosts/maya/plugins/publish/collect_renderable_camera.py +++ b/openpype/hosts/maya/plugins/publish/collect_renderable_camera.py @@ -21,11 +21,12 @@ class CollectRenderableCamera(pyblish.api.InstancePlugin): else: layer = instance.data["renderlayer"] - self.log.info("layer: {}".format(layer)) cameras = cmds.ls(type="camera", long=True) - renderable = [c for c in cameras if - get_attr_in_layer("%s.renderable" % c, layer)] + renderable = [cam for cam in cameras if + get_attr_in_layer("{}.renderable".format(cam), layer)] - self.log.info("Found cameras %s: %s" % (len(renderable), renderable)) + self.log.debug( + "Found renderable cameras %s: %s", len(renderable), renderable + ) instance.data["cameras"] = renderable diff --git a/openpype/hosts/maya/plugins/publish/collect_unreal_staticmesh.py b/openpype/hosts/maya/plugins/publish/collect_unreal_staticmesh.py index 79d0856fa0..03b6c4a188 100644 --- a/openpype/hosts/maya/plugins/publish/collect_unreal_staticmesh.py +++ b/openpype/hosts/maya/plugins/publish/collect_unreal_staticmesh.py @@ -19,7 +19,7 @@ class CollectUnrealStaticMesh(pyblish.api.InstancePlugin): instance.data["geometryMembers"] = cmds.sets( geometry_set, query=True) - self.log.info("geometry: {}".format( + self.log.debug("geometry: {}".format( pformat(instance.data.get("geometryMembers")))) collision_set = [ @@ -29,7 +29,7 @@ class CollectUnrealStaticMesh(pyblish.api.InstancePlugin): instance.data["collisionMembers"] = cmds.sets( collision_set, query=True) - self.log.info("collisions: {}".format( + self.log.debug("collisions: {}".format( pformat(instance.data.get("collisionMembers")))) frame = cmds.currentTime(query=True) diff --git a/openpype/hosts/maya/plugins/publish/collect_xgen.py b/openpype/hosts/maya/plugins/publish/collect_xgen.py index 46968f7d1a..45648e1776 100644 --- a/openpype/hosts/maya/plugins/publish/collect_xgen.py +++ b/openpype/hosts/maya/plugins/publish/collect_xgen.py @@ -67,5 +67,5 @@ class CollectXgen(pyblish.api.InstancePlugin): data["transfers"] = transfers - self.log.info(data) + self.log.debug(data) instance.data.update(data) diff --git a/openpype/hosts/maya/plugins/publish/collect_yeti_rig.py b/openpype/hosts/maya/plugins/publish/collect_yeti_rig.py index bc15edd9e0..df761cde13 100644 --- a/openpype/hosts/maya/plugins/publish/collect_yeti_rig.py +++ b/openpype/hosts/maya/plugins/publish/collect_yeti_rig.py @@ -119,7 +119,6 @@ class CollectYetiRig(pyblish.api.InstancePlugin): texture_filenames = [] if image_search_paths: - # TODO: Somehow this uses OS environment path separator, `:` vs `;` # Later on check whether this is pipeline OS cross-compatible. image_search_paths = [p for p in @@ -130,13 +129,13 @@ class CollectYetiRig(pyblish.api.InstancePlugin): # List all related textures texture_filenames = cmds.pgYetiCommand(node, listTextures=True) - self.log.info("Found %i texture(s)" % len(texture_filenames)) + self.log.debug("Found %i texture(s)" % len(texture_filenames)) # Get all reference nodes reference_nodes = cmds.pgYetiGraph(node, listNodes=True, type="reference") - self.log.info("Found %i reference node(s)" % len(reference_nodes)) + self.log.debug("Found %i reference node(s)" % len(reference_nodes)) if texture_filenames and not image_search_paths: raise ValueError("pgYetiMaya node '%s' is missing the path to the " diff --git a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py index 102f0e46a2..46cc9090bb 100644 --- a/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py +++ b/openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py @@ -100,7 +100,7 @@ class ExtractArnoldSceneSource(publish.Extractor): instance.data["representations"].append(representation) - self.log.info( + self.log.debug( "Extracted instance {} to: {}".format(instance.name, staging_dir) ) @@ -126,7 +126,7 @@ class ExtractArnoldSceneSource(publish.Extractor): instance.data["representations"].append(representation) def _extract(self, nodes, attribute_data, kwargs): - self.log.info( + self.log.debug( "Writing {} with:\n{}".format(kwargs["filename"], kwargs) ) filenames = [] @@ -180,12 +180,12 @@ class ExtractArnoldSceneSource(publish.Extractor): with lib.attribute_values(attribute_data): with lib.maintained_selection(): - self.log.info( + self.log.debug( "Writing: {}".format(duplicate_nodes) ) cmds.select(duplicate_nodes, noExpand=True) - self.log.info( + self.log.debug( "Extracting ass sequence with: {}".format(kwargs) ) @@ -194,6 +194,6 @@ class ExtractArnoldSceneSource(publish.Extractor): for file in exported_files: filenames.append(os.path.split(file)[1]) - self.log.info("Exported: {}".format(filenames)) + self.log.debug("Exported: {}".format(filenames)) return filenames, nodes_by_id diff --git a/openpype/hosts/maya/plugins/publish/extract_assembly.py b/openpype/hosts/maya/plugins/publish/extract_assembly.py index 9b2978d192..86ffdcef24 100644 --- a/openpype/hosts/maya/plugins/publish/extract_assembly.py +++ b/openpype/hosts/maya/plugins/publish/extract_assembly.py @@ -27,7 +27,7 @@ class ExtractAssembly(publish.Extractor): json_filename = "{}.json".format(instance.name) json_path = os.path.join(staging_dir, json_filename) - self.log.info("Dumping scene data for debugging ..") + self.log.debug("Dumping scene data for debugging ..") with open(json_path, "w") as filepath: json.dump(instance.data["scenedata"], filepath, ensure_ascii=False) diff --git a/openpype/hosts/maya/plugins/publish/extract_camera_alembic.py b/openpype/hosts/maya/plugins/publish/extract_camera_alembic.py index aa445a0387..4ec1399df4 100644 --- a/openpype/hosts/maya/plugins/publish/extract_camera_alembic.py +++ b/openpype/hosts/maya/plugins/publish/extract_camera_alembic.py @@ -94,7 +94,7 @@ class ExtractCameraAlembic(publish.Extractor): "Attributes to bake must be specified as a list" ) for attr in self.bake_attributes: - self.log.info("Adding {} attribute".format(attr)) + self.log.debug("Adding {} attribute".format(attr)) job_str += " -attr {0}".format(attr) with lib.evaluation("off"): @@ -112,5 +112,5 @@ class ExtractCameraAlembic(publish.Extractor): } instance.data["representations"].append(representation) - self.log.info("Extracted instance '{0}' to: {1}".format( + self.log.debug("Extracted instance '{0}' to: {1}".format( instance.name, path)) diff --git a/openpype/hosts/maya/plugins/publish/extract_camera_mayaScene.py b/openpype/hosts/maya/plugins/publish/extract_camera_mayaScene.py index 30e6b89f2f..a50a8f0dfa 100644 --- a/openpype/hosts/maya/plugins/publish/extract_camera_mayaScene.py +++ b/openpype/hosts/maya/plugins/publish/extract_camera_mayaScene.py @@ -111,7 +111,7 @@ class ExtractCameraMayaScene(publish.Extractor): for family in self.families: try: self.scene_type = ext_mapping[family] - self.log.info( + self.log.debug( "Using {} as scene type".format(self.scene_type)) break except KeyError: @@ -151,7 +151,7 @@ class ExtractCameraMayaScene(publish.Extractor): with lib.evaluation("off"): with lib.suspended_refresh(): if bake_to_worldspace: - self.log.info( + self.log.debug( "Performing camera bakes: {}".format(transform)) baked = lib.bake_to_world_space( transform, @@ -186,7 +186,7 @@ class ExtractCameraMayaScene(publish.Extractor): unlock(plug) cmds.setAttr(plug, value) - self.log.info("Performing extraction..") + self.log.debug("Performing extraction..") cmds.select(cmds.ls(members, dag=True, shapes=True, long=True), noExpand=True) cmds.file(path, @@ -217,5 +217,5 @@ class ExtractCameraMayaScene(publish.Extractor): } instance.data["representations"].append(representation) - self.log.info("Extracted instance '{0}' to: {1}".format( + self.log.debug("Extracted instance '{0}' to: {1}".format( instance.name, path)) diff --git a/openpype/hosts/maya/plugins/publish/extract_fbx.py b/openpype/hosts/maya/plugins/publish/extract_fbx.py index 9af3acef65..4f7eaf57bf 100644 --- a/openpype/hosts/maya/plugins/publish/extract_fbx.py +++ b/openpype/hosts/maya/plugins/publish/extract_fbx.py @@ -33,11 +33,11 @@ class ExtractFBX(publish.Extractor): # to format it into a string in a mel expression path = path.replace('\\', '/') - self.log.info("Extracting FBX to: {0}".format(path)) + self.log.debug("Extracting FBX to: {0}".format(path)) members = instance.data["setMembers"] - self.log.info("Members: {0}".format(members)) - self.log.info("Instance: {0}".format(instance[:])) + self.log.debug("Members: {0}".format(members)) + self.log.debug("Instance: {0}".format(instance[:])) fbx_exporter.set_options_from_instance(instance) @@ -58,4 +58,4 @@ class ExtractFBX(publish.Extractor): } instance.data["representations"].append(representation) - self.log.info("Extract FBX successful to: {0}".format(path)) + self.log.debug("Extract FBX successful to: {0}".format(path)) diff --git a/openpype/hosts/maya/plugins/publish/extract_gltf.py b/openpype/hosts/maya/plugins/publish/extract_gltf.py index ac258ffb3d..6d72d28525 100644 --- a/openpype/hosts/maya/plugins/publish/extract_gltf.py +++ b/openpype/hosts/maya/plugins/publish/extract_gltf.py @@ -20,14 +20,10 @@ class ExtractGLB(publish.Extractor): filename = "{0}.glb".format(instance.name) path = os.path.join(staging_dir, filename) - self.log.info("Extracting GLB to: {}".format(path)) - cmds.loadPlugin("maya2glTF", quiet=True) nodes = instance[:] - self.log.info("Instance: {0}".format(nodes)) - start_frame = instance.data('frameStart') or \ int(cmds.playbackOptions(query=True, animationStartTime=True))# noqa @@ -48,6 +44,7 @@ class ExtractGLB(publish.Extractor): "vno": True # visibleNodeOnly } + self.log.debug("Extracting GLB to: {}".format(path)) with lib.maintained_selection(): cmds.select(nodes, hi=True, noExpand=True) extract_gltf(staging_dir, @@ -65,4 +62,4 @@ class ExtractGLB(publish.Extractor): } instance.data["representations"].append(representation) - self.log.info("Extract GLB successful to: {0}".format(path)) + self.log.debug("Extract GLB successful to: {0}".format(path)) diff --git a/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py b/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py index 422f5ad019..16436c6fe4 100644 --- a/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py +++ b/openpype/hosts/maya/plugins/publish/extract_gpu_cache.py @@ -60,6 +60,6 @@ class ExtractGPUCache(publish.Extractor): instance.data["representations"].append(representation) - self.log.info( + self.log.debug( "Extracted instance {} to: {}".format(instance.name, staging_dir) ) diff --git a/openpype/hosts/maya/plugins/publish/extract_import_reference.py b/openpype/hosts/maya/plugins/publish/extract_import_reference.py index 8bb82be9b6..9d2ff1a3eb 100644 --- a/openpype/hosts/maya/plugins/publish/extract_import_reference.py +++ b/openpype/hosts/maya/plugins/publish/extract_import_reference.py @@ -46,7 +46,7 @@ class ExtractImportReference(publish.Extractor, for family in self.families: try: self.scene_type = ext_mapping[family] - self.log.info( + self.log.debug( "Using {} as scene type".format(self.scene_type)) break @@ -69,7 +69,7 @@ class ExtractImportReference(publish.Extractor, reference_path = os.path.join(dir_path, ref_scene_name) tmp_path = os.path.dirname(current_name) + "/" + ref_scene_name - self.log.info("Performing extraction..") + self.log.debug("Performing extraction..") # This generates script for mayapy to take care of reference # importing outside current session. It is passing current scene @@ -111,7 +111,7 @@ print("*** Done") # process until handles are closed by context manager. with tempfile.TemporaryDirectory() as tmp_dir_name: tmp_script_path = os.path.join(tmp_dir_name, "import_ref.py") - self.log.info("Using script file: {}".format(tmp_script_path)) + self.log.debug("Using script file: {}".format(tmp_script_path)) with open(tmp_script_path, "wt") as tmp: tmp.write(script) @@ -149,9 +149,9 @@ print("*** Done") "stagingDir": os.path.dirname(current_name), "outputName": "imported" } - self.log.info("%s" % ref_representation) + self.log.debug(ref_representation) instance.data["representations"].append(ref_representation) - self.log.info("Extracted instance '%s' to : '%s'" % (ref_scene_name, - reference_path)) + self.log.debug("Extracted instance '%s' to : '%s'" % (ref_scene_name, + reference_path)) diff --git a/openpype/hosts/maya/plugins/publish/extract_layout.py b/openpype/hosts/maya/plugins/publish/extract_layout.py index bf5b4fc0e7..75920b44a2 100644 --- a/openpype/hosts/maya/plugins/publish/extract_layout.py +++ b/openpype/hosts/maya/plugins/publish/extract_layout.py @@ -23,7 +23,7 @@ class ExtractLayout(publish.Extractor): stagingdir = self.staging_dir(instance) # Perform extraction - self.log.info("Performing extraction..") + self.log.debug("Performing extraction..") if "representations" not in instance.data: instance.data["representations"] = [] @@ -64,7 +64,7 @@ class ExtractLayout(publish.Extractor): fields=["parent", "context.family"] ) - self.log.info(representation) + self.log.debug(representation) version_id = representation.get("parent") family = representation.get("context").get("family") @@ -159,5 +159,5 @@ class ExtractLayout(publish.Extractor): } instance.data["representations"].append(json_representation) - self.log.info("Extracted instance '%s' to: %s", - instance.name, json_representation) + self.log.debug("Extracted instance '%s' to: %s", + instance.name, json_representation) diff --git a/openpype/hosts/maya/plugins/publish/extract_look.py b/openpype/hosts/maya/plugins/publish/extract_look.py index b13568c781..3506027a1f 100644 --- a/openpype/hosts/maya/plugins/publish/extract_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_look.py @@ -307,7 +307,7 @@ class MakeTX(TextureProcessor): render_colorspace = color_management["rendering_space"] - self.log.info("tx: converting colorspace {0} " + self.log.debug("tx: converting colorspace {0} " "-> {1}".format(colorspace, render_colorspace)) args.extend(["--colorconvert", colorspace, render_colorspace]) @@ -331,7 +331,7 @@ class MakeTX(TextureProcessor): if not os.path.exists(resources_dir): os.makedirs(resources_dir) - self.log.info("Generating .tx file for %s .." % source) + self.log.debug("Generating .tx file for %s .." % source) subprocess_args = maketx_args + [ "-v", # verbose @@ -421,7 +421,7 @@ class ExtractLook(publish.Extractor): for family in self.families: try: self.scene_type = ext_mapping[family] - self.log.info( + self.log.debug( "Using {} as scene type".format(self.scene_type)) break except KeyError: @@ -453,7 +453,7 @@ class ExtractLook(publish.Extractor): relationships = lookdata["relationships"] sets = list(relationships.keys()) if not sets: - self.log.info("No sets found for the look") + self.log.debug("No sets found for the look") return # Specify texture processing executables to activate @@ -485,7 +485,7 @@ class ExtractLook(publish.Extractor): remap = results["attrRemap"] # Extract in correct render layer - self.log.info("Extracting look maya scene file: {}".format(maya_path)) + self.log.debug("Extracting look maya scene file: {}".format(maya_path)) layer = instance.data.get("renderlayer", "defaultRenderLayer") with lib.renderlayer(layer): # TODO: Ensure membership edits don't become renderlayer overrides @@ -511,12 +511,12 @@ class ExtractLook(publish.Extractor): ) # Write the JSON data - self.log.info("Extract json..") data = { "attributes": lookdata["attributes"], "relationships": relationships } + self.log.debug("Extracting json file: {}".format(json_path)) with open(json_path, "w") as f: json.dump(data, f) @@ -557,8 +557,8 @@ class ExtractLook(publish.Extractor): # Source hash for the textures instance.data["sourceHashes"] = hashes - self.log.info("Extracted instance '%s' to: %s" % (instance.name, - maya_path)) + self.log.debug("Extracted instance '%s' to: %s" % (instance.name, + maya_path)) def _set_resource_result_colorspace(self, resource, colorspace): """Update resource resulting colorspace after texture processing""" @@ -589,14 +589,13 @@ class ExtractLook(publish.Extractor): resources = instance.data["resources"] color_management = lib.get_color_management_preferences() - # Temporary fix to NOT create hardlinks on windows machines - if platform.system().lower() == "windows": - self.log.info( + force_copy = instance.data.get("forceCopy", False) + if not force_copy and platform.system().lower() == "windows": + # Temporary fix to NOT create hardlinks on windows machines + self.log.warning( "Forcing copy instead of hardlink due to issues on Windows..." ) force_copy = True - else: - force_copy = instance.data.get("forceCopy", False) destinations_cache = {} @@ -671,11 +670,11 @@ class ExtractLook(publish.Extractor): destination = get_resource_destination_cached(source) if force_copy or texture_result.transfer_mode == COPY: transfers.append((source, destination)) - self.log.info('file will be copied {} -> {}'.format( + self.log.debug('file will be copied {} -> {}'.format( source, destination)) elif texture_result.transfer_mode == HARDLINK: hardlinks.append((source, destination)) - self.log.info('file will be hardlinked {} -> {}'.format( + self.log.debug('file will be hardlinked {} -> {}'.format( source, destination)) # Store the hashes from hash to destination to include in the @@ -707,7 +706,7 @@ class ExtractLook(publish.Extractor): color_space_attr = "{}.colorSpace".format(node) remap[color_space_attr] = resource["result_color_space"] - self.log.info("Finished remapping destinations ...") + self.log.debug("Finished remapping destinations ...") return { "fileTransfers": transfers, @@ -815,8 +814,8 @@ class ExtractLook(publish.Extractor): if not processed_result: raise RuntimeError("Texture Processor {} returned " "no result.".format(processor)) - self.log.info("Generated processed " - "texture: {}".format(processed_result.path)) + self.log.debug("Generated processed " + "texture: {}".format(processed_result.path)) # TODO: Currently all processors force copy instead of allowing # hardlinks using source hashes. This should be refactored @@ -827,7 +826,7 @@ class ExtractLook(publish.Extractor): if not force_copy: existing = self._get_existing_hashed_texture(filepath) if existing: - self.log.info("Found hash in database, preparing hardlink..") + self.log.debug("Found hash in database, preparing hardlink..") return TextureResult( path=filepath, file_hash=texture_hash, diff --git a/openpype/hosts/maya/plugins/publish/extract_maya_scene_raw.py b/openpype/hosts/maya/plugins/publish/extract_maya_scene_raw.py index d87d6c208a..ab170fe48c 100644 --- a/openpype/hosts/maya/plugins/publish/extract_maya_scene_raw.py +++ b/openpype/hosts/maya/plugins/publish/extract_maya_scene_raw.py @@ -34,7 +34,7 @@ class ExtractMayaSceneRaw(publish.Extractor): for family in self.families: try: self.scene_type = ext_mapping[family] - self.log.info( + self.log.debug( "Using {} as scene type".format(self.scene_type)) break except KeyError: @@ -63,7 +63,7 @@ class ExtractMayaSceneRaw(publish.Extractor): selection += self._get_loaded_containers(members) # Perform extraction - self.log.info("Performing extraction ...") + self.log.debug("Performing extraction ...") with maintained_selection(): cmds.select(selection, noExpand=True) cmds.file(path, @@ -87,7 +87,8 @@ class ExtractMayaSceneRaw(publish.Extractor): } instance.data["representations"].append(representation) - self.log.info("Extracted instance '%s' to: %s" % (instance.name, path)) + self.log.debug("Extracted instance '%s' to: %s" % (instance.name, + path)) @staticmethod def _get_loaded_containers(members): diff --git a/openpype/hosts/maya/plugins/publish/extract_model.py b/openpype/hosts/maya/plugins/publish/extract_model.py index 5137dffd94..29c952ebbc 100644 --- a/openpype/hosts/maya/plugins/publish/extract_model.py +++ b/openpype/hosts/maya/plugins/publish/extract_model.py @@ -44,7 +44,7 @@ class ExtractModel(publish.Extractor, for family in self.families: try: self.scene_type = ext_mapping[family] - self.log.info( + self.log.debug( "Using {} as scene type".format(self.scene_type)) break except KeyError: @@ -56,7 +56,7 @@ class ExtractModel(publish.Extractor, path = os.path.join(stagingdir, filename) # Perform extraction - self.log.info("Performing extraction ...") + self.log.debug("Performing extraction ...") # Get only the shape contents we need in such a way that we avoid # taking along intermediateObjects @@ -102,4 +102,5 @@ class ExtractModel(publish.Extractor, } instance.data["representations"].append(representation) - self.log.info("Extracted instance '%s' to: %s" % (instance.name, path)) + self.log.debug("Extracted instance '%s' to: %s" % (instance.name, + path)) diff --git a/openpype/hosts/maya/plugins/publish/extract_multiverse_look.py b/openpype/hosts/maya/plugins/publish/extract_multiverse_look.py index 6fe7cf0d55..c2bebeaee6 100644 --- a/openpype/hosts/maya/plugins/publish/extract_multiverse_look.py +++ b/openpype/hosts/maya/plugins/publish/extract_multiverse_look.py @@ -101,10 +101,10 @@ class ExtractMultiverseLook(publish.Extractor): # Parse export options options = self.default_options - self.log.info("Export options: {0}".format(options)) + self.log.debug("Export options: {0}".format(options)) # Perform extraction - self.log.info("Performing extraction ...") + self.log.debug("Performing extraction ...") with maintained_selection(): members = instance.data("setMembers") @@ -114,7 +114,7 @@ class ExtractMultiverseLook(publish.Extractor): type="mvUsdCompoundShape", noIntermediate=True, long=True) - self.log.info('Collected object {}'.format(members)) + self.log.debug('Collected object {}'.format(members)) if len(members) > 1: self.log.error('More than one member: {}'.format(members)) @@ -153,5 +153,5 @@ class ExtractMultiverseLook(publish.Extractor): } instance.data["representations"].append(representation) - self.log.info("Extracted instance {} to {}".format( + self.log.debug("Extracted instance {} to {}".format( instance.name, file_path)) diff --git a/openpype/hosts/maya/plugins/publish/extract_multiverse_usd.py b/openpype/hosts/maya/plugins/publish/extract_multiverse_usd.py index 4399eacda1..17d5891e59 100644 --- a/openpype/hosts/maya/plugins/publish/extract_multiverse_usd.py +++ b/openpype/hosts/maya/plugins/publish/extract_multiverse_usd.py @@ -150,7 +150,6 @@ class ExtractMultiverseUsd(publish.Extractor): return options def get_default_options(self): - self.log.info("ExtractMultiverseUsd get_default_options") return self.default_options def filter_members(self, members): @@ -173,19 +172,19 @@ class ExtractMultiverseUsd(publish.Extractor): # Parse export options options = self.get_default_options() options = self.parse_overrides(instance, options) - self.log.info("Export options: {0}".format(options)) + self.log.debug("Export options: {0}".format(options)) # Perform extraction - self.log.info("Performing extraction ...") + self.log.debug("Performing extraction ...") with maintained_selection(): members = instance.data("setMembers") - self.log.info('Collected objects: {}'.format(members)) + self.log.debug('Collected objects: {}'.format(members)) members = self.filter_members(members) if not members: self.log.error('No members!') return - self.log.info(' - filtered: {}'.format(members)) + self.log.debug(' - filtered: {}'.format(members)) import multiverse @@ -229,7 +228,7 @@ class ExtractMultiverseUsd(publish.Extractor): self.log.debug(" - {}={}".format(key, value)) setattr(asset_write_opts, key, value) - self.log.info('WriteAsset: {} / {}'.format(file_path, members)) + self.log.debug('WriteAsset: {} / {}'.format(file_path, members)) multiverse.WriteAsset(file_path, members, asset_write_opts) if "representations" not in instance.data: @@ -243,7 +242,7 @@ class ExtractMultiverseUsd(publish.Extractor): } instance.data["representations"].append(representation) - self.log.info("Extracted instance {} to {}".format( + self.log.debug("Extracted instance {} to {}".format( instance.name, file_path)) diff --git a/openpype/hosts/maya/plugins/publish/extract_multiverse_usd_comp.py b/openpype/hosts/maya/plugins/publish/extract_multiverse_usd_comp.py index a62729c198..7966c4fa93 100644 --- a/openpype/hosts/maya/plugins/publish/extract_multiverse_usd_comp.py +++ b/openpype/hosts/maya/plugins/publish/extract_multiverse_usd_comp.py @@ -105,14 +105,14 @@ class ExtractMultiverseUsdComposition(publish.Extractor): # Parse export options options = self.default_options options = self.parse_overrides(instance, options) - self.log.info("Export options: {0}".format(options)) + self.log.debug("Export options: {0}".format(options)) # Perform extraction - self.log.info("Performing extraction ...") + self.log.debug("Performing extraction ...") with maintained_selection(): members = instance.data("setMembers") - self.log.info('Collected object {}'.format(members)) + self.log.debug('Collected object {}'.format(members)) import multiverse @@ -175,5 +175,5 @@ class ExtractMultiverseUsdComposition(publish.Extractor): } instance.data["representations"].append(representation) - self.log.info("Extracted instance {} to {}".format( - instance.name, file_path)) + self.log.debug("Extracted instance {} to {}".format(instance.name, + file_path)) diff --git a/openpype/hosts/maya/plugins/publish/extract_multiverse_usd_over.py b/openpype/hosts/maya/plugins/publish/extract_multiverse_usd_over.py index cf610ac6b4..e4a97db6e4 100644 --- a/openpype/hosts/maya/plugins/publish/extract_multiverse_usd_over.py +++ b/openpype/hosts/maya/plugins/publish/extract_multiverse_usd_over.py @@ -87,10 +87,10 @@ class ExtractMultiverseUsdOverride(publish.Extractor): # Parse export options options = self.default_options - self.log.info("Export options: {0}".format(options)) + self.log.debug("Export options: {0}".format(options)) # Perform extraction - self.log.info("Performing extraction ...") + self.log.debug("Performing extraction ...") with maintained_selection(): members = instance.data("setMembers") @@ -100,7 +100,7 @@ class ExtractMultiverseUsdOverride(publish.Extractor): type="mvUsdCompoundShape", noIntermediate=True, long=True) - self.log.info("Collected object {}".format(members)) + self.log.debug("Collected object {}".format(members)) # TODO: Deal with asset, composition, override with options. import multiverse @@ -153,5 +153,5 @@ class ExtractMultiverseUsdOverride(publish.Extractor): } instance.data["representations"].append(representation) - self.log.info("Extracted instance {} to {}".format( + self.log.debug("Extracted instance {} to {}".format( instance.name, file_path)) diff --git a/openpype/hosts/maya/plugins/publish/extract_obj.py b/openpype/hosts/maya/plugins/publish/extract_obj.py index 518b0f0ff8..ca94130d09 100644 --- a/openpype/hosts/maya/plugins/publish/extract_obj.py +++ b/openpype/hosts/maya/plugins/publish/extract_obj.py @@ -30,7 +30,7 @@ class ExtractObj(publish.Extractor): # The export requires forward slashes because we need to # format it into a string in a mel expression - self.log.info("Extracting OBJ to: {0}".format(path)) + self.log.debug("Extracting OBJ to: {0}".format(path)) members = instance.data("setMembers") members = cmds.ls(members, @@ -39,8 +39,8 @@ class ExtractObj(publish.Extractor): type=("mesh", "nurbsCurve"), noIntermediate=True, long=True) - self.log.info("Members: {0}".format(members)) - self.log.info("Instance: {0}".format(instance[:])) + self.log.debug("Members: {0}".format(members)) + self.log.debug("Instance: {0}".format(instance[:])) if not cmds.pluginInfo('objExport', query=True, loaded=True): cmds.loadPlugin('objExport') @@ -74,4 +74,4 @@ class ExtractObj(publish.Extractor): } instance.data["representations"].append(representation) - self.log.info("Extract OBJ successful to: {0}".format(path)) + self.log.debug("Extract OBJ successful to: {0}".format(path)) diff --git a/openpype/hosts/maya/plugins/publish/extract_playblast.py b/openpype/hosts/maya/plugins/publish/extract_playblast.py index 9580c13841..cfab239da3 100644 --- a/openpype/hosts/maya/plugins/publish/extract_playblast.py +++ b/openpype/hosts/maya/plugins/publish/extract_playblast.py @@ -48,7 +48,7 @@ class ExtractPlayblast(publish.Extractor): self.log.debug("playblast path {}".format(path)) def process(self, instance): - self.log.info("Extracting capture..") + self.log.debug("Extracting capture..") # get scene fps fps = instance.data.get("fps") or instance.context.data.get("fps") @@ -62,7 +62,7 @@ class ExtractPlayblast(publish.Extractor): if end is None: end = cmds.playbackOptions(query=True, animationEndTime=True) - self.log.info("start: {}, end: {}".format(start, end)) + self.log.debug("start: {}, end: {}".format(start, end)) # get cameras camera = instance.data["review_camera"] @@ -119,7 +119,7 @@ class ExtractPlayblast(publish.Extractor): filename = "{0}".format(instance.name) path = os.path.join(stagingdir, filename) - self.log.info("Outputting images to %s" % path) + self.log.debug("Outputting images to %s" % path) preset["filename"] = path preset["overwrite"] = True @@ -237,7 +237,7 @@ class ExtractPlayblast(publish.Extractor): self.log.debug("collection head {}".format(filebase)) if filebase in filename: frame_collection = collection - self.log.info( + self.log.debug( "we found collection of interest {}".format( str(frame_collection))) diff --git a/openpype/hosts/maya/plugins/publish/extract_pointcache.py b/openpype/hosts/maya/plugins/publish/extract_pointcache.py index 9537a11ee4..5530446e3d 100644 --- a/openpype/hosts/maya/plugins/publish/extract_pointcache.py +++ b/openpype/hosts/maya/plugins/publish/extract_pointcache.py @@ -109,11 +109,11 @@ class ExtractAlembic(publish.Extractor): instance.context.data["cleanupFullPaths"].append(path) - self.log.info("Extracted {} to {}".format(instance, dirname)) + self.log.debug("Extracted {} to {}".format(instance, dirname)) # Extract proxy. if not instance.data.get("proxy"): - self.log.info("No proxy nodes found. Skipping proxy extraction.") + self.log.debug("No proxy nodes found. Skipping proxy extraction.") return path = path.replace(".abc", "_proxy.abc") diff --git a/openpype/hosts/maya/plugins/publish/extract_proxy_abc.py b/openpype/hosts/maya/plugins/publish/extract_proxy_abc.py index cf6351fdca..921ee44a24 100644 --- a/openpype/hosts/maya/plugins/publish/extract_proxy_abc.py +++ b/openpype/hosts/maya/plugins/publish/extract_proxy_abc.py @@ -32,7 +32,7 @@ class ExtractProxyAlembic(publish.Extractor): attr_prefixes = instance.data.get("attrPrefix", "").split(";") attr_prefixes = [value for value in attr_prefixes if value.strip()] - self.log.info("Extracting Proxy Alembic..") + self.log.debug("Extracting Proxy Alembic..") dirname = self.staging_dir(instance) filename = "{name}.abc".format(**instance.data) @@ -82,7 +82,7 @@ class ExtractProxyAlembic(publish.Extractor): instance.context.data["cleanupFullPaths"].append(path) - self.log.info("Extracted {} to {}".format(instance, dirname)) + self.log.debug("Extracted {} to {}".format(instance, dirname)) # remove the bounding box bbox_master = cmds.ls("bbox_grp") cmds.delete(bbox_master) diff --git a/openpype/hosts/maya/plugins/publish/extract_redshift_proxy.py b/openpype/hosts/maya/plugins/publish/extract_redshift_proxy.py index 834b335fc5..3868270b79 100644 --- a/openpype/hosts/maya/plugins/publish/extract_redshift_proxy.py +++ b/openpype/hosts/maya/plugins/publish/extract_redshift_proxy.py @@ -59,7 +59,7 @@ class ExtractRedshiftProxy(publish.Extractor): # vertex_colors = instance.data.get("vertexColors", False) # Write out rs file - self.log.info("Writing: '%s'" % file_path) + self.log.debug("Writing: '%s'" % file_path) with maintained_selection(): cmds.select(instance.data["setMembers"], noExpand=True) cmds.file(file_path, @@ -82,5 +82,5 @@ class ExtractRedshiftProxy(publish.Extractor): } instance.data["representations"].append(representation) - self.log.info("Extracted instance '%s' to: %s" - % (instance.name, staging_dir)) + self.log.debug("Extracted instance '%s' to: %s" + % (instance.name, staging_dir)) diff --git a/openpype/hosts/maya/plugins/publish/extract_rendersetup.py b/openpype/hosts/maya/plugins/publish/extract_rendersetup.py index 5970c038a4..7e21f5282e 100644 --- a/openpype/hosts/maya/plugins/publish/extract_rendersetup.py +++ b/openpype/hosts/maya/plugins/publish/extract_rendersetup.py @@ -37,5 +37,5 @@ class ExtractRenderSetup(publish.Extractor): } instance.data["representations"].append(representation) - self.log.info( + self.log.debug( "Extracted instance '%s' to: %s" % (instance.name, json_path)) diff --git a/openpype/hosts/maya/plugins/publish/extract_rig.py b/openpype/hosts/maya/plugins/publish/extract_rig.py index be57b9de07..1ffc9a7dae 100644 --- a/openpype/hosts/maya/plugins/publish/extract_rig.py +++ b/openpype/hosts/maya/plugins/publish/extract_rig.py @@ -27,7 +27,7 @@ class ExtractRig(publish.Extractor): for family in self.families: try: self.scene_type = ext_mapping[family] - self.log.info( + self.log.debug( "Using '.{}' as scene type".format(self.scene_type)) break except AttributeError: @@ -39,7 +39,7 @@ class ExtractRig(publish.Extractor): path = os.path.join(dir_path, filename) # Perform extraction - self.log.info("Performing extraction ...") + self.log.debug("Performing extraction ...") with maintained_selection(): cmds.select(instance, noExpand=True) cmds.file(path, @@ -63,4 +63,4 @@ class ExtractRig(publish.Extractor): } instance.data["representations"].append(representation) - self.log.info("Extracted instance '%s' to: %s" % (instance.name, path)) + self.log.debug("Extracted instance '%s' to: %s", instance.name, path) diff --git a/openpype/hosts/maya/plugins/publish/extract_thumbnail.py b/openpype/hosts/maya/plugins/publish/extract_thumbnail.py index 4160ac4cb2..e44204cae0 100644 --- a/openpype/hosts/maya/plugins/publish/extract_thumbnail.py +++ b/openpype/hosts/maya/plugins/publish/extract_thumbnail.py @@ -24,7 +24,7 @@ class ExtractThumbnail(publish.Extractor): families = ["review"] def process(self, instance): - self.log.info("Extracting capture..") + self.log.debug("Extracting capture..") camera = instance.data["review_camera"] @@ -96,7 +96,7 @@ class ExtractThumbnail(publish.Extractor): filename = "{0}".format(instance.name) path = os.path.join(dst_staging, filename) - self.log.info("Outputting images to %s" % path) + self.log.debug("Outputting images to %s" % path) preset["filename"] = path preset["overwrite"] = True @@ -159,7 +159,7 @@ class ExtractThumbnail(publish.Extractor): _, thumbnail = os.path.split(playblast) - self.log.info("file list {}".format(thumbnail)) + self.log.debug("file list {}".format(thumbnail)) if "representations" not in instance.data: instance.data["representations"] = [] diff --git a/openpype/hosts/maya/plugins/publish/extract_unreal_skeletalmesh_abc.py b/openpype/hosts/maya/plugins/publish/extract_unreal_skeletalmesh_abc.py index 4a797eb462..9c2f55a1ef 100644 --- a/openpype/hosts/maya/plugins/publish/extract_unreal_skeletalmesh_abc.py +++ b/openpype/hosts/maya/plugins/publish/extract_unreal_skeletalmesh_abc.py @@ -57,9 +57,9 @@ class ExtractUnrealSkeletalMeshAbc(publish.Extractor): # to format it into a string in a mel expression path = path.replace('\\', '/') - self.log.info("Extracting ABC to: {0}".format(path)) - self.log.info("Members: {0}".format(nodes)) - self.log.info("Instance: {0}".format(instance[:])) + self.log.debug("Extracting ABC to: {0}".format(path)) + self.log.debug("Members: {0}".format(nodes)) + self.log.debug("Instance: {0}".format(instance[:])) options = { "step": instance.data.get("step", 1.0), @@ -74,7 +74,7 @@ class ExtractUnrealSkeletalMeshAbc(publish.Extractor): "worldSpace": instance.data.get("worldSpace", True) } - self.log.info("Options: {}".format(options)) + self.log.debug("Options: {}".format(options)) if int(cmds.about(version=True)) >= 2017: # Since Maya 2017 alembic supports multiple uv sets - write them. @@ -105,4 +105,4 @@ class ExtractUnrealSkeletalMeshAbc(publish.Extractor): } instance.data["representations"].append(representation) - self.log.info("Extract ABC successful to: {0}".format(path)) + self.log.debug("Extract ABC successful to: {0}".format(path)) diff --git a/openpype/hosts/maya/plugins/publish/extract_unreal_skeletalmesh_fbx.py b/openpype/hosts/maya/plugins/publish/extract_unreal_skeletalmesh_fbx.py index b162ce47f7..96175a07d7 100644 --- a/openpype/hosts/maya/plugins/publish/extract_unreal_skeletalmesh_fbx.py +++ b/openpype/hosts/maya/plugins/publish/extract_unreal_skeletalmesh_fbx.py @@ -46,9 +46,9 @@ class ExtractUnrealSkeletalMeshFbx(publish.Extractor): # to format it into a string in a mel expression path = path.replace('\\', '/') - self.log.info("Extracting FBX to: {0}".format(path)) - self.log.info("Members: {0}".format(to_extract)) - self.log.info("Instance: {0}".format(instance[:])) + self.log.debug("Extracting FBX to: {0}".format(path)) + self.log.debug("Members: {0}".format(to_extract)) + self.log.debug("Instance: {0}".format(instance[:])) fbx_exporter.set_options_from_instance(instance) @@ -70,7 +70,7 @@ class ExtractUnrealSkeletalMeshFbx(publish.Extractor): renamed_to_extract.append("|".join(node_path)) with renamed(original_parent, parent_node): - self.log.info("Extracting: {}".format(renamed_to_extract, path)) + self.log.debug("Extracting: {}".format(renamed_to_extract, path)) fbx_exporter.export(renamed_to_extract, path) if "representations" not in instance.data: @@ -84,4 +84,4 @@ class ExtractUnrealSkeletalMeshFbx(publish.Extractor): } instance.data["representations"].append(representation) - self.log.info("Extract FBX successful to: {0}".format(path)) + self.log.debug("Extract FBX successful to: {0}".format(path)) diff --git a/openpype/hosts/maya/plugins/publish/extract_unreal_staticmesh.py b/openpype/hosts/maya/plugins/publish/extract_unreal_staticmesh.py index 44f0615a27..26ab0827e4 100644 --- a/openpype/hosts/maya/plugins/publish/extract_unreal_staticmesh.py +++ b/openpype/hosts/maya/plugins/publish/extract_unreal_staticmesh.py @@ -37,15 +37,15 @@ class ExtractUnrealStaticMesh(publish.Extractor): # to format it into a string in a mel expression path = path.replace('\\', '/') - self.log.info("Extracting FBX to: {0}".format(path)) - self.log.info("Members: {0}".format(members)) - self.log.info("Instance: {0}".format(instance[:])) + self.log.debug("Extracting FBX to: {0}".format(path)) + self.log.debug("Members: {0}".format(members)) + self.log.debug("Instance: {0}".format(instance[:])) fbx_exporter.set_options_from_instance(instance) with maintained_selection(): with parent_nodes(members): - self.log.info("Un-parenting: {}".format(members)) + self.log.debug("Un-parenting: {}".format(members)) fbx_exporter.export(members, path) if "representations" not in instance.data: @@ -59,4 +59,4 @@ class ExtractUnrealStaticMesh(publish.Extractor): } instance.data["representations"].append(representation) - self.log.info("Extract FBX successful to: {0}".format(path)) + self.log.debug("Extract FBX successful to: {0}".format(path)) diff --git a/openpype/hosts/maya/plugins/publish/extract_vrayproxy.py b/openpype/hosts/maya/plugins/publish/extract_vrayproxy.py index df16c6c357..21dfcfffc5 100644 --- a/openpype/hosts/maya/plugins/publish/extract_vrayproxy.py +++ b/openpype/hosts/maya/plugins/publish/extract_vrayproxy.py @@ -43,7 +43,7 @@ class ExtractVRayProxy(publish.Extractor): vertex_colors = instance.data.get("vertexColors", False) # Write out vrmesh file - self.log.info("Writing: '%s'" % file_path) + self.log.debug("Writing: '%s'" % file_path) with maintained_selection(): cmds.select(instance.data["setMembers"], noExpand=True) cmds.vrayCreateProxy(exportType=1, @@ -68,5 +68,5 @@ class ExtractVRayProxy(publish.Extractor): } instance.data["representations"].append(representation) - self.log.info("Extracted instance '%s' to: %s" - % (instance.name, staging_dir)) + self.log.debug("Extracted instance '%s' to: %s" + % (instance.name, staging_dir)) diff --git a/openpype/hosts/maya/plugins/publish/extract_vrayscene.py b/openpype/hosts/maya/plugins/publish/extract_vrayscene.py index 8442df1611..b0615149a9 100644 --- a/openpype/hosts/maya/plugins/publish/extract_vrayscene.py +++ b/openpype/hosts/maya/plugins/publish/extract_vrayscene.py @@ -20,13 +20,13 @@ class ExtractVrayscene(publish.Extractor): def process(self, instance): """Plugin entry point.""" if instance.data.get("exportOnFarm"): - self.log.info("vrayscenes will be exported on farm.") + self.log.debug("vrayscenes will be exported on farm.") raise NotImplementedError( "exporting vrayscenes is not implemented") # handle sequence if instance.data.get("vraySceneMultipleFiles"): - self.log.info("vrayscenes will be exported on farm.") + self.log.debug("vrayscenes will be exported on farm.") raise NotImplementedError( "exporting vrayscene sequences not implemented yet") @@ -40,7 +40,6 @@ class ExtractVrayscene(publish.Extractor): layer_name = instance.data.get("layer") staging_dir = self.staging_dir(instance) - self.log.info("staging: {}".format(staging_dir)) template = cmds.getAttr("{}.vrscene_filename".format(node)) start_frame = instance.data.get( "frameStartHandle") if instance.data.get( @@ -56,21 +55,21 @@ class ExtractVrayscene(publish.Extractor): staging_dir, "vrayscene", *formatted_name.split("/")) # Write out vrscene file - self.log.info("Writing: '%s'" % file_path) + self.log.debug("Writing: '%s'" % file_path) with maintained_selection(): if "*" not in instance.data["setMembers"]: - self.log.info( + self.log.debug( "Exporting: {}".format(instance.data["setMembers"])) set_members = instance.data["setMembers"] cmds.select(set_members, noExpand=True) else: - self.log.info("Exporting all ...") + self.log.debug("Exporting all ...") set_members = cmds.ls( long=True, objectsOnly=True, geometry=True, lights=True, cameras=True) cmds.select(set_members, noExpand=True) - self.log.info("Appending layer name {}".format(layer_name)) + self.log.debug("Appending layer name {}".format(layer_name)) set_members.append(layer_name) export_in_rs_layer( @@ -93,8 +92,8 @@ class ExtractVrayscene(publish.Extractor): } instance.data["representations"].append(representation) - self.log.info("Extracted instance '%s' to: %s" - % (instance.name, staging_dir)) + self.log.debug("Extracted instance '%s' to: %s" + % (instance.name, staging_dir)) @staticmethod def format_vray_output_filename( diff --git a/openpype/hosts/maya/plugins/publish/extract_workfile_xgen.py b/openpype/hosts/maya/plugins/publish/extract_workfile_xgen.py index 0d2a97bc4b..4bd01c2df2 100644 --- a/openpype/hosts/maya/plugins/publish/extract_workfile_xgen.py +++ b/openpype/hosts/maya/plugins/publish/extract_workfile_xgen.py @@ -241,7 +241,7 @@ class ExtractWorkfileXgen(publish.Extractor): data[palette] = {attr: old_value} cmds.setAttr(node_attr, value, type="string") - self.log.info( + self.log.debug( "Setting \"{}\" on \"{}\"".format(value, node_attr) ) diff --git a/openpype/hosts/maya/plugins/publish/extract_xgen.py b/openpype/hosts/maya/plugins/publish/extract_xgen.py index 3c9d0bd344..8409330e49 100644 --- a/openpype/hosts/maya/plugins/publish/extract_xgen.py +++ b/openpype/hosts/maya/plugins/publish/extract_xgen.py @@ -77,7 +77,7 @@ class ExtractXgen(publish.Extractor): xgenm.exportPalette( instance.data["xgmPalette"].replace("|", ""), temp_xgen_path ) - self.log.info("Extracted to {}".format(temp_xgen_path)) + self.log.debug("Extracted to {}".format(temp_xgen_path)) # Import xgen onto the duplicate. with maintained_selection(): @@ -118,7 +118,7 @@ class ExtractXgen(publish.Extractor): expressions=True ) - self.log.info("Extracted to {}".format(maya_filepath)) + self.log.debug("Extracted to {}".format(maya_filepath)) if os.path.exists(temp_xgen_path): os.remove(temp_xgen_path) diff --git a/openpype/hosts/maya/plugins/publish/extract_yeti_cache.py b/openpype/hosts/maya/plugins/publish/extract_yeti_cache.py index b61f599cab..b113e02219 100644 --- a/openpype/hosts/maya/plugins/publish/extract_yeti_cache.py +++ b/openpype/hosts/maya/plugins/publish/extract_yeti_cache.py @@ -39,7 +39,7 @@ class ExtractYetiCache(publish.Extractor): else: kwargs.update({"samples": samples}) - self.log.info( + self.log.debug( "Writing out cache {} - {}".format(start_frame, end_frame)) # Start writing the files for snap shot # will be replace by the Yeti node name @@ -53,7 +53,7 @@ class ExtractYetiCache(publish.Extractor): cache_files = [x for x in os.listdir(dirname) if x.endswith(".fur")] - self.log.info("Writing metadata file") + self.log.debug("Writing metadata file") settings = instance.data["fursettings"] fursettings_path = os.path.join(dirname, "yeti.fursettings") with open(fursettings_path, "w") as fp: @@ -63,7 +63,7 @@ class ExtractYetiCache(publish.Extractor): if "representations" not in instance.data: instance.data["representations"] = [] - self.log.info("cache files: {}".format(cache_files[0])) + self.log.debug("cache files: {}".format(cache_files[0])) # Workaround: We do not explicitly register these files with the # representation solely so that we can write multiple sequences @@ -87,4 +87,4 @@ class ExtractYetiCache(publish.Extractor): } ) - self.log.info("Extracted {} to {}".format(instance, dirname)) + self.log.debug("Extracted {} to {}".format(instance, dirname)) diff --git a/openpype/hosts/maya/plugins/publish/extract_yeti_rig.py b/openpype/hosts/maya/plugins/publish/extract_yeti_rig.py index 9a46c31177..da67cb911f 100644 --- a/openpype/hosts/maya/plugins/publish/extract_yeti_rig.py +++ b/openpype/hosts/maya/plugins/publish/extract_yeti_rig.py @@ -109,7 +109,7 @@ class ExtractYetiRig(publish.Extractor): for family in self.families: try: self.scene_type = ext_mapping[family] - self.log.info( + self.log.debug( "Using {} as scene type".format(self.scene_type)) break except KeyError: @@ -127,7 +127,7 @@ class ExtractYetiRig(publish.Extractor): maya_path = os.path.join(dirname, "yeti_rig.{}".format(self.scene_type)) - self.log.info("Writing metadata file") + self.log.debug("Writing metadata file: {}".format(settings_path)) image_search_path = resources_dir = instance.data["resourcesDir"] @@ -147,7 +147,7 @@ class ExtractYetiRig(publish.Extractor): dst = os.path.join(image_search_path, os.path.basename(file)) instance.data['transfers'].append([src, dst]) - self.log.info("adding transfer {} -> {}". format(src, dst)) + self.log.debug("adding transfer {} -> {}". format(src, dst)) # Ensure the imageSearchPath is being remapped to the publish folder attr_value = {"%s.imageSearchPath" % n: str(image_search_path) for @@ -182,7 +182,7 @@ class ExtractYetiRig(publish.Extractor): if "representations" not in instance.data: instance.data["representations"] = [] - self.log.info("rig file: {}".format(maya_path)) + self.log.debug("rig file: {}".format(maya_path)) instance.data["representations"].append( { 'name': self.scene_type, @@ -191,7 +191,7 @@ class ExtractYetiRig(publish.Extractor): 'stagingDir': dirname } ) - self.log.info("settings file: {}".format(settings_path)) + self.log.debug("settings file: {}".format(settings_path)) instance.data["representations"].append( { 'name': 'rigsettings', @@ -201,6 +201,6 @@ class ExtractYetiRig(publish.Extractor): } ) - self.log.info("Extracted {} to {}".format(instance, dirname)) + self.log.debug("Extracted {} to {}".format(instance, dirname)) cmds.select(clear=True) diff --git a/openpype/hosts/maya/plugins/publish/reset_xgen_attributes.py b/openpype/hosts/maya/plugins/publish/reset_xgen_attributes.py index d8e8554b68..759aa23258 100644 --- a/openpype/hosts/maya/plugins/publish/reset_xgen_attributes.py +++ b/openpype/hosts/maya/plugins/publish/reset_xgen_attributes.py @@ -23,7 +23,7 @@ class ResetXgenAttributes(pyblish.api.InstancePlugin): for palette, data in xgen_attributes.items(): for attr, value in data.items(): node_attr = "{}.{}".format(palette, attr) - self.log.info( + self.log.debug( "Setting \"{}\" on \"{}\"".format(value, node_attr) ) cmds.setAttr(node_attr, value, type="string") @@ -32,5 +32,5 @@ class ResetXgenAttributes(pyblish.api.InstancePlugin): # Need to save the scene, cause the attribute changes above does not # mark the scene as modified so user can exit without committing the # changes. - self.log.info("Saving changes.") + self.log.debug("Saving changes.") cmds.file(save=True) diff --git a/openpype/hosts/maya/plugins/publish/submit_maya_muster.py b/openpype/hosts/maya/plugins/publish/submit_maya_muster.py index 8e219eae85..ef58140115 100644 --- a/openpype/hosts/maya/plugins/publish/submit_maya_muster.py +++ b/openpype/hosts/maya/plugins/publish/submit_maya_muster.py @@ -215,9 +215,9 @@ class MayaSubmitMuster(pyblish.api.InstancePlugin): :rtype: int :raises: Exception if template ID isn't found """ - self.log.info("Trying to find template for [{}]".format(renderer)) + self.log.debug("Trying to find template for [{}]".format(renderer)) mapped = _get_template_id(renderer) - self.log.info("got id [{}]".format(mapped)) + self.log.debug("got id [{}]".format(mapped)) return self._templates.get(mapped) def _submit(self, payload): @@ -454,8 +454,8 @@ class MayaSubmitMuster(pyblish.api.InstancePlugin): self.preflight_check(instance) - self.log.info("Submitting ...") - self.log.info(json.dumps(payload, indent=4, sort_keys=True)) + self.log.debug("Submitting ...") + self.log.debug(json.dumps(payload, indent=4, sort_keys=True)) response = self._submit(payload) # response = requests.post(url, json=payload) diff --git a/openpype/hosts/maya/plugins/publish/validate_assembly_name.py b/openpype/hosts/maya/plugins/publish/validate_assembly_name.py index bcc40760e0..00588cd300 100644 --- a/openpype/hosts/maya/plugins/publish/validate_assembly_name.py +++ b/openpype/hosts/maya/plugins/publish/validate_assembly_name.py @@ -20,7 +20,7 @@ class ValidateAssemblyName(pyblish.api.InstancePlugin): @classmethod def get_invalid(cls, instance): - cls.log.info("Checking name of {}".format(instance.name)) + cls.log.debug("Checking name of {}".format(instance.name)) content_instance = instance.data.get("setMembers", None) if not content_instance: diff --git a/openpype/hosts/maya/plugins/publish/validate_assembly_namespaces.py b/openpype/hosts/maya/plugins/publish/validate_assembly_namespaces.py index 41ef78aab4..06577f38f7 100644 --- a/openpype/hosts/maya/plugins/publish/validate_assembly_namespaces.py +++ b/openpype/hosts/maya/plugins/publish/validate_assembly_namespaces.py @@ -23,7 +23,7 @@ class ValidateAssemblyNamespaces(pyblish.api.InstancePlugin): def process(self, instance): - self.log.info("Checking namespace for %s" % instance.name) + self.log.debug("Checking namespace for %s" % instance.name) if self.get_invalid(instance): raise PublishValidationError("Nested namespaces found") diff --git a/openpype/hosts/maya/plugins/publish/validate_frame_range.py b/openpype/hosts/maya/plugins/publish/validate_frame_range.py index c6184ed348..a7043b8407 100644 --- a/openpype/hosts/maya/plugins/publish/validate_frame_range.py +++ b/openpype/hosts/maya/plugins/publish/validate_frame_range.py @@ -47,10 +47,10 @@ class ValidateFrameRange(pyblish.api.InstancePlugin, context = instance.context if instance.data.get("tileRendering"): - self.log.info(( + self.log.debug( "Skipping frame range validation because " "tile rendering is enabled." - )) + ) return frame_start_handle = int(context.data.get("frameStartHandle")) diff --git a/openpype/hosts/maya/plugins/publish/validate_glsl_material.py b/openpype/hosts/maya/plugins/publish/validate_glsl_material.py index 10c48da404..3b386c3def 100644 --- a/openpype/hosts/maya/plugins/publish/validate_glsl_material.py +++ b/openpype/hosts/maya/plugins/publish/validate_glsl_material.py @@ -75,7 +75,7 @@ class ValidateGLSLMaterial(pyblish.api.InstancePlugin): """ meshes = cmds.ls(instance, type="mesh", long=True) - cls.log.info("meshes: {}".format(meshes)) + cls.log.debug("meshes: {}".format(meshes)) # load the glsl shader plugin cmds.loadPlugin("glslShader", quiet=True) @@ -96,8 +96,8 @@ class ValidateGLSLMaterial(pyblish.api.InstancePlugin): cls.log.warning("ogsfx shader file " "not found in {}".format(ogsfx_path)) - cls.log.info("Find the ogsfx shader file in " - "default maya directory...") + cls.log.debug("Searching the ogsfx shader file in " + "default maya directory...") # re-direct to search the ogsfx path in maya_dir ogsfx_path = os.getenv("MAYA_APP_DIR") + ogsfx_path if not os.path.exists(ogsfx_path): @@ -130,8 +130,8 @@ class ValidateGLSLMaterial(pyblish.api.InstancePlugin): @classmethod def pbs_shader_conversion(cls, main_shader, glsl): - cls.log.info("StringrayPBS detected " - "-> Can do texture conversion") + cls.log.debug("StringrayPBS detected " + "-> Can do texture conversion") for shader in main_shader: # get the file textures related to the PBS Shader @@ -168,8 +168,8 @@ class ValidateGLSLMaterial(pyblish.api.InstancePlugin): @classmethod def arnold_shader_conversion(cls, main_shader, glsl): - cls.log.info("aiStandardSurface detected " - "-> Can do texture conversion") + cls.log.debug("aiStandardSurface detected " + "-> Can do texture conversion") for shader in main_shader: # get the file textures related to the PBS Shader diff --git a/openpype/hosts/maya/plugins/publish/validate_instancer_content.py b/openpype/hosts/maya/plugins/publish/validate_instancer_content.py index 2f14693ef2..236adfb03d 100644 --- a/openpype/hosts/maya/plugins/publish/validate_instancer_content.py +++ b/openpype/hosts/maya/plugins/publish/validate_instancer_content.py @@ -21,7 +21,7 @@ class ValidateInstancerContent(pyblish.api.InstancePlugin): members = instance.data['setMembers'] export_members = instance.data['exactExportMembers'] - self.log.info("Contents {0}".format(members)) + self.log.debug("Contents {0}".format(members)) if not len(members) == len(cmds.ls(members, type="instancer")): self.log.error("Instancer can only contain instancers") diff --git a/openpype/hosts/maya/plugins/publish/validate_instancer_frame_ranges.py b/openpype/hosts/maya/plugins/publish/validate_instancer_frame_ranges.py index fcfcdce8b6..714c6229d6 100644 --- a/openpype/hosts/maya/plugins/publish/validate_instancer_frame_ranges.py +++ b/openpype/hosts/maya/plugins/publish/validate_instancer_frame_ranges.py @@ -5,8 +5,6 @@ import pyblish.api from openpype.pipeline.publish import PublishValidationError -VERBOSE = False - def is_cache_resource(resource): """Return whether resource is a cacheFile resource""" @@ -73,9 +71,6 @@ class ValidateInstancerFrameRanges(pyblish.api.InstancePlugin): xml = all_files.pop(0) assert xml.endswith(".xml") - if VERBOSE: - cls.log.info("Checking: {0}".format(all_files)) - # Ensure all files exist (including ticks) # The remainder file paths should be the .mcx or .mcc files valdidate_files(all_files) @@ -129,8 +124,8 @@ class ValidateInstancerFrameRanges(pyblish.api.InstancePlugin): # for the frames required by the time range. if ticks: ticks = list(sorted(ticks)) - cls.log.info("Found ticks: {0} " - "(substeps: {1})".format(ticks, len(ticks))) + cls.log.debug("Found ticks: {0} " + "(substeps: {1})".format(ticks, len(ticks))) # Check all frames except the last since we don't # require subframes after our time range. diff --git a/openpype/hosts/maya/plugins/publish/validate_model_name.py b/openpype/hosts/maya/plugins/publish/validate_model_name.py index 6948dcf724..f4c1aa39c7 100644 --- a/openpype/hosts/maya/plugins/publish/validate_model_name.py +++ b/openpype/hosts/maya/plugins/publish/validate_model_name.py @@ -125,7 +125,7 @@ class ValidateModelName(pyblish.api.InstancePlugin, r = re.compile(regex) for obj in filtered: - cls.log.info("testing: {}".format(obj)) + cls.log.debug("testing: {}".format(obj)) m = r.match(obj) if m is None: cls.log.error("invalid name on: {}".format(obj)) diff --git a/openpype/hosts/maya/plugins/publish/validate_mvlook_contents.py b/openpype/hosts/maya/plugins/publish/validate_mvlook_contents.py index 68784a165d..ad0fcafc56 100644 --- a/openpype/hosts/maya/plugins/publish/validate_mvlook_contents.py +++ b/openpype/hosts/maya/plugins/publish/validate_mvlook_contents.py @@ -35,12 +35,12 @@ class ValidateMvLookContents(pyblish.api.InstancePlugin, publishMipMap = instance.data["publishMipMap"] enforced = True if intent in self.enforced_intents: - self.log.info("This validation will be enforced: '{}'" - .format(intent)) + self.log.debug("This validation will be enforced: '{}'" + .format(intent)) else: enforced = False - self.log.info("This validation will NOT be enforced: '{}'" - .format(intent)) + self.log.debug("This validation will NOT be enforced: '{}'" + .format(intent)) if not instance[:]: raise PublishValidationError("Instance is empty") @@ -75,8 +75,9 @@ class ValidateMvLookContents(pyblish.api.InstancePlugin, self.log.warning(msg) if invalid: - raise PublishValidationError("'{}' has invalid look " - "content".format(instance.name)) + raise PublishValidationError( + "'{}' has invalid look content".format(instance.name) + ) def valid_file(self, fname): self.log.debug("Checking validity of '{}'".format(fname)) diff --git a/openpype/hosts/maya/plugins/publish/validate_skeletalmesh_hierarchy.py b/openpype/hosts/maya/plugins/publish/validate_skeletalmesh_hierarchy.py index 398b6fb7bf..9084374c76 100644 --- a/openpype/hosts/maya/plugins/publish/validate_skeletalmesh_hierarchy.py +++ b/openpype/hosts/maya/plugins/publish/validate_skeletalmesh_hierarchy.py @@ -28,7 +28,7 @@ class ValidateSkeletalMeshHierarchy(pyblish.api.InstancePlugin): parent.split("|")[1] for parent in (joints_parents + geo_parents) } - self.log.info(parents_set) + self.log.debug(parents_set) if len(set(parents_set)) > 2: raise PublishXmlValidationError( diff --git a/openpype/hosts/maya/plugins/publish/validate_unreal_staticmesh_naming.py b/openpype/hosts/maya/plugins/publish/validate_unreal_staticmesh_naming.py index b2cb2ebda2..5ba256f9f5 100644 --- a/openpype/hosts/maya/plugins/publish/validate_unreal_staticmesh_naming.py +++ b/openpype/hosts/maya/plugins/publish/validate_unreal_staticmesh_naming.py @@ -140,12 +140,12 @@ class ValidateUnrealStaticMeshName(pyblish.api.InstancePlugin, return if not self.validate_mesh and not self.validate_collision: - self.log.info("Validation of both mesh and collision names" - "is disabled.") + self.log.debug("Validation of both mesh and collision names" + "is disabled.") return if not instance.data.get("collisionMembers", None): - self.log.info("There are no collision objects to validate") + self.log.debug("There are no collision objects to validate") return invalid = self.get_invalid(instance) diff --git a/openpype/hosts/maya/plugins/publish/validate_vray_distributed_rendering.py b/openpype/hosts/maya/plugins/publish/validate_vray_distributed_rendering.py index a71849da00..14571203ea 100644 --- a/openpype/hosts/maya/plugins/publish/validate_vray_distributed_rendering.py +++ b/openpype/hosts/maya/plugins/publish/validate_vray_distributed_rendering.py @@ -52,6 +52,6 @@ class ValidateVRayDistributedRendering(pyblish.api.InstancePlugin): renderlayer = instance.data.get("renderlayer") with lib.renderlayer(renderlayer): - cls.log.info("Enabling Distributed Rendering " - "ignore in batch mode..") + cls.log.debug("Enabling Distributed Rendering " + "ignore in batch mode..") cmds.setAttr(cls.ignored_attr, True) diff --git a/openpype/hosts/maya/plugins/publish/validate_yeti_renderscript_callbacks.py b/openpype/hosts/maya/plugins/publish/validate_yeti_renderscript_callbacks.py index 06250f5779..a8085418e7 100644 --- a/openpype/hosts/maya/plugins/publish/validate_yeti_renderscript_callbacks.py +++ b/openpype/hosts/maya/plugins/publish/validate_yeti_renderscript_callbacks.py @@ -54,7 +54,7 @@ class ValidateYetiRenderScriptCallbacks(pyblish.api.InstancePlugin): # has any yeti callback set or not since if the callback # is there it wouldn't error and if it weren't then # nothing happens because there are no yeti nodes. - cls.log.info( + cls.log.debug( "Yeti is loaded but no yeti nodes were found. " "Callback validation skipped.." ) @@ -62,7 +62,7 @@ class ValidateYetiRenderScriptCallbacks(pyblish.api.InstancePlugin): renderer = instance.data["renderer"] if renderer == "redshift": - cls.log.info("Redshift ignores any pre and post render callbacks") + cls.log.debug("Redshift ignores any pre and post render callbacks") return False callback_lookup = cls.callbacks.get(renderer, {}) diff --git a/openpype/hosts/maya/plugins/publish/validate_yeti_rig_input_in_instance.py b/openpype/hosts/maya/plugins/publish/validate_yeti_rig_input_in_instance.py index 96fb475a0a..50a27589ad 100644 --- a/openpype/hosts/maya/plugins/publish/validate_yeti_rig_input_in_instance.py +++ b/openpype/hosts/maya/plugins/publish/validate_yeti_rig_input_in_instance.py @@ -37,8 +37,8 @@ class ValidateYetiRigInputShapesInInstance(pyblish.api.Validator): # Allow publish without input meshes. if not shapes: - cls.log.info("Found no input meshes for %s, skipping ..." - % instance) + cls.log.debug("Found no input meshes for %s, skipping ..." + % instance) return [] # check if input node is part of groomRig instance From eec1d82db2b605186d58fb5f860fcf89cea142c9 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 30 Aug 2023 09:54:37 +0200 Subject: [PATCH 064/154] Deadline: Tweak logging for artist-facing reports in publisher --- .../publish/collect_deadline_server_from_instance.py | 2 +- .../deadline/plugins/publish/submit_celaction_deadline.py | 6 +++--- .../deadline/plugins/publish/submit_fusion_deadline.py | 4 ++-- .../deadline/plugins/publish/submit_harmony_deadline.py | 2 +- .../plugins/publish/submit_houdini_remote_publish.py | 2 +- .../deadline/plugins/publish/submit_maya_deadline.py | 6 +++--- .../deadline/plugins/publish/submit_nuke_deadline.py | 8 ++++---- .../deadline/plugins/publish/submit_publish_job.py | 4 ++-- .../plugins/publish/validate_deadline_connection.py | 2 +- .../deadline/plugins/publish/validate_deadline_pools.py | 4 ++-- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/openpype/modules/deadline/plugins/publish/collect_deadline_server_from_instance.py b/openpype/modules/deadline/plugins/publish/collect_deadline_server_from_instance.py index eadfc3c83e..98ecb019c5 100644 --- a/openpype/modules/deadline/plugins/publish/collect_deadline_server_from_instance.py +++ b/openpype/modules/deadline/plugins/publish/collect_deadline_server_from_instance.py @@ -23,7 +23,7 @@ class CollectDeadlineServerFromInstance(pyblish.api.InstancePlugin): instance.data["deadlineUrl"] = self._collect_deadline_url(instance) instance.data["deadlineUrl"] = \ instance.data["deadlineUrl"].strip().rstrip("/") - self.log.info( + self.log.debug( "Using {} for submission.".format(instance.data["deadlineUrl"])) def _collect_deadline_url(self, render_instance): diff --git a/openpype/modules/deadline/plugins/publish/submit_celaction_deadline.py b/openpype/modules/deadline/plugins/publish/submit_celaction_deadline.py index ee28612b44..5a6537a767 100644 --- a/openpype/modules/deadline/plugins/publish/submit_celaction_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_celaction_deadline.py @@ -183,10 +183,10 @@ class CelactionSubmitDeadline(pyblish.api.InstancePlugin): } plugin = payload["JobInfo"]["Plugin"] - self.log.info("using render plugin : {}".format(plugin)) + self.log.debug("using render plugin : {}".format(plugin)) - self.log.info("Submitting..") - self.log.info(json.dumps(payload, indent=4, sort_keys=True)) + self.log.debug("Submitting..") + self.log.debug(json.dumps(payload, indent=4, sort_keys=True)) # adding expectied files to instance.data self.expected_files(instance, render_path) diff --git a/openpype/modules/deadline/plugins/publish/submit_fusion_deadline.py b/openpype/modules/deadline/plugins/publish/submit_fusion_deadline.py index a48596c6bf..70aa12956d 100644 --- a/openpype/modules/deadline/plugins/publish/submit_fusion_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_fusion_deadline.py @@ -233,8 +233,8 @@ class FusionSubmitDeadline( ) for index, key in enumerate(environment) }) - self.log.info("Submitting..") - self.log.info(json.dumps(payload, indent=4, sort_keys=True)) + self.log.debug("Submitting..") + self.log.debug(json.dumps(payload, indent=4, sort_keys=True)) # E.g. http://192.168.0.1:8082/api/jobs url = "{}/api/jobs".format(deadline_url) diff --git a/openpype/modules/deadline/plugins/publish/submit_harmony_deadline.py b/openpype/modules/deadline/plugins/publish/submit_harmony_deadline.py index 2c37268f04..9f8579cd23 100644 --- a/openpype/modules/deadline/plugins/publish/submit_harmony_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_harmony_deadline.py @@ -369,7 +369,7 @@ class HarmonySubmitDeadline( # rendering, we need to unzip it. published_scene = Path( self.from_published_scene(False)) - self.log.info(f"Processing {published_scene.as_posix()}") + self.log.debug(f"Processing {published_scene.as_posix()}") xstage_path = self._unzip_scene_file(published_scene) render_path = xstage_path.parent / "renders" diff --git a/openpype/modules/deadline/plugins/publish/submit_houdini_remote_publish.py b/openpype/modules/deadline/plugins/publish/submit_houdini_remote_publish.py index 68aa653804..39c0c3afe4 100644 --- a/openpype/modules/deadline/plugins/publish/submit_houdini_remote_publish.py +++ b/openpype/modules/deadline/plugins/publish/submit_houdini_remote_publish.py @@ -162,7 +162,7 @@ class HoudiniSubmitPublishDeadline(pyblish.api.ContextPlugin): ) # Submit - self.log.info("Submitting..") + self.log.debug("Submitting..") self.log.debug(json.dumps(payload, indent=4, sort_keys=True)) # E.g. http://192.168.0.1:8082/api/jobs diff --git a/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py b/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py index 75d24b28f0..615d167a9f 100644 --- a/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py @@ -434,7 +434,7 @@ class MayaSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, new_job_info.update(tiles_data["JobInfo"]) new_plugin_info.update(tiles_data["PluginInfo"]) - self.log.info("hashing {} - {}".format(file_index, file)) + self.log.debug("hashing {} - {}".format(file_index, file)) job_hash = hashlib.sha256( ("{}_{}".format(file_index, file)).encode("utf-8")) @@ -450,7 +450,7 @@ class MayaSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, ) file_index += 1 - self.log.info( + self.log.debug( "Submitting tile job(s) [{}] ...".format(len(frame_payloads))) # Submit frame tile jobs @@ -560,7 +560,7 @@ class MayaSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, assembly_job_ids = [] num_assemblies = len(assembly_payloads) for i, payload in enumerate(assembly_payloads): - self.log.info( + self.log.debug( "submitting assembly job {} of {}".format(i + 1, num_assemblies) ) diff --git a/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py b/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py index cfdeb4968b..ffa203e922 100644 --- a/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_nuke_deadline.py @@ -244,7 +244,7 @@ class NukeSubmitDeadline(pyblish.api.InstancePlugin, # resolve any limit groups limit_groups = self.get_limit_groups() - self.log.info("Limit groups: `{}`".format(limit_groups)) + self.log.debug("Limit groups: `{}`".format(limit_groups)) payload = { "JobInfo": { @@ -387,10 +387,10 @@ class NukeSubmitDeadline(pyblish.api.InstancePlugin, }) plugin = payload["JobInfo"]["Plugin"] - self.log.info("using render plugin : {}".format(plugin)) + self.log.debug("using render plugin : {}".format(plugin)) - self.log.info("Submitting..") - self.log.info(json.dumps(payload, indent=4, sort_keys=True)) + self.log.debug("Submitting..") + self.log.debug(json.dumps(payload, indent=4, sort_keys=True)) # adding expectied files to instance.data self.expected_files( diff --git a/openpype/modules/deadline/plugins/publish/submit_publish_job.py b/openpype/modules/deadline/plugins/publish/submit_publish_job.py index bf4411ef43..20bebe583f 100644 --- a/openpype/modules/deadline/plugins/publish/submit_publish_job.py +++ b/openpype/modules/deadline/plugins/publish/submit_publish_job.py @@ -317,7 +317,7 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin, # remove secondary pool payload["JobInfo"].pop("SecondaryPool", None) - self.log.info("Submitting Deadline job ...") + self.log.debug("Submitting Deadline publish job ...") url = "{}/api/jobs".format(self.deadline_url) response = requests.post(url, json=payload, timeout=10) @@ -454,7 +454,7 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin, import getpass render_job = {} - self.log.info("Faking job data ...") + self.log.debug("Faking job data ...") render_job["Props"] = {} # Render job doesn't exist because we do not have prior submission. # We still use data from it so lets fake it. diff --git a/openpype/modules/deadline/plugins/publish/validate_deadline_connection.py b/openpype/modules/deadline/plugins/publish/validate_deadline_connection.py index a30401e7dc..d8933a191f 100644 --- a/openpype/modules/deadline/plugins/publish/validate_deadline_connection.py +++ b/openpype/modules/deadline/plugins/publish/validate_deadline_connection.py @@ -18,7 +18,7 @@ class ValidateDeadlineConnection(pyblish.api.InstancePlugin): # if custom one is set in instance, use that if instance.data.get("deadlineUrl"): deadline_url = instance.data.get("deadlineUrl") - self.log.info( + self.log.debug( "We have deadline URL on instance {}".format( deadline_url)) assert deadline_url, "Requires Deadline Webservice URL" diff --git a/openpype/modules/deadline/plugins/publish/validate_deadline_pools.py b/openpype/modules/deadline/plugins/publish/validate_deadline_pools.py index 594f0ef866..1179b9cee9 100644 --- a/openpype/modules/deadline/plugins/publish/validate_deadline_pools.py +++ b/openpype/modules/deadline/plugins/publish/validate_deadline_pools.py @@ -32,9 +32,9 @@ class ValidateDeadlinePools(OptionalPyblishPluginMixin, # get default deadline webservice url from deadline module deadline_url = instance.context.data["defaultDeadline"] - self.log.info("deadline_url::{}".format(deadline_url)) + self.log.debug("deadline_url::{}".format(deadline_url)) pools = DeadlineModule.get_deadline_pools(deadline_url, log=self.log) - self.log.info("pools::{}".format(pools)) + self.log.debug("pools::{}".format(pools)) formatting_data = { "pools_str": ",".join(pools) From 63923ff4d8c65fde9b984ac8f0e1d8973d127ef6 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 30 Aug 2023 10:10:33 +0200 Subject: [PATCH 065/154] Global: Tweak logging for artist-facing reports in publisher --- openpype/plugins/publish/cleanup.py | 6 +++-- openpype/plugins/publish/cleanup_farm.py | 8 +++--- openpype/plugins/publish/collect_audio.py | 8 +++--- openpype/plugins/publish/collect_hierarchy.py | 2 +- .../plugins/publish/collect_rendered_files.py | 12 ++++----- openpype/plugins/publish/extract_burnin.py | 18 ++++++------- .../publish/extract_color_transcode.py | 2 +- .../publish/extract_colorspace_data.py | 2 +- .../publish/extract_hierarchy_avalon.py | 2 +- .../publish/extract_hierarchy_to_ayon.py | 4 +-- .../plugins/publish/extract_review_slate.py | 4 +-- .../plugins/publish/extract_scanline_exr.py | 12 ++++----- openpype/plugins/publish/extract_thumbnail.py | 26 +++++++++---------- .../publish/extract_thumbnail_from_source.py | 14 +++++----- .../publish/extract_trim_video_audio.py | 6 ++--- openpype/plugins/publish/integrate.py | 6 ++--- .../plugins/publish/integrate_hero_version.py | 6 ++--- .../plugins/publish/integrate_thumbnail.py | 8 +++--- .../publish/integrate_thumbnail_ayon.py | 6 ++--- .../plugins/publish/validate_asset_docs.py | 4 +-- .../publish/validate_editorial_asset_name.py | 2 +- 21 files changed, 81 insertions(+), 77 deletions(-) diff --git a/openpype/plugins/publish/cleanup.py b/openpype/plugins/publish/cleanup.py index 573cd829e4..f9f504dd4f 100644 --- a/openpype/plugins/publish/cleanup.py +++ b/openpype/plugins/publish/cleanup.py @@ -69,7 +69,7 @@ class CleanUp(pyblish.api.InstancePlugin): skip_cleanup_filepaths.add(os.path.normpath(path)) if self.remove_temp_renders: - self.log.info("Cleaning renders new...") + self.log.debug("Cleaning renders new...") self.clean_renders(instance, skip_cleanup_filepaths) if [ef for ef in self.exclude_families @@ -95,7 +95,9 @@ class CleanUp(pyblish.api.InstancePlugin): return if instance.data.get("stagingDir_persistent"): - self.log.info("Staging dir: %s should be persistent" % staging_dir) + self.log.debug( + "Staging dir {} should be persistent".format(staging_dir) + ) return self.log.info("Removing staging directory {}".format(staging_dir)) diff --git a/openpype/plugins/publish/cleanup_farm.py b/openpype/plugins/publish/cleanup_farm.py index 8052f13734..e655437ced 100644 --- a/openpype/plugins/publish/cleanup_farm.py +++ b/openpype/plugins/publish/cleanup_farm.py @@ -26,10 +26,10 @@ class CleanUpFarm(pyblish.api.ContextPlugin): # Skip process if is not in list of source hosts in which this # plugin should run if src_host_name not in self.allowed_hosts: - self.log.info(( + self.log.debug( "Source host \"{}\" is not in list of enabled hosts {}." - " Skipping" - ).format(str(src_host_name), str(self.allowed_hosts))) + " Skipping".format(src_host_name, self.allowed_hosts) + ) return self.log.debug("Preparing filepaths to remove") @@ -47,7 +47,7 @@ class CleanUpFarm(pyblish.api.ContextPlugin): dirpaths_to_remove.add(os.path.normpath(staging_dir)) if not dirpaths_to_remove: - self.log.info("Nothing to remove. Skipping") + self.log.debug("Nothing to remove. Skipping") return self.log.debug("Filepaths to remove are:\n{}".format( diff --git a/openpype/plugins/publish/collect_audio.py b/openpype/plugins/publish/collect_audio.py index 3a0ddb3281..6aaadfc568 100644 --- a/openpype/plugins/publish/collect_audio.py +++ b/openpype/plugins/publish/collect_audio.py @@ -53,8 +53,8 @@ class CollectAudio(pyblish.api.ContextPlugin): ): # Skip instances that already have audio filled if instance.data.get("audio"): - self.log.info( - "Skipping Audio collecion. It is already collected" + self.log.debug( + "Skipping Audio collection. It is already collected" ) continue filtered_instances.append(instance) @@ -70,7 +70,7 @@ class CollectAudio(pyblish.api.ContextPlugin): instances_by_asset_name[asset_name].append(instance) asset_names = set(instances_by_asset_name.keys()) - self.log.info(( + self.log.debug(( "Searching for audio subset '{subset}' in assets {assets}" ).format( subset=self.audio_subset_name, @@ -100,7 +100,7 @@ class CollectAudio(pyblish.api.ContextPlugin): "offset": 0, "filename": repre_path }] - self.log.info("Audio Data added to instance ...") + self.log.debug("Audio Data added to instance ...") def query_representations(self, project_name, asset_names): """Query representations related to audio subsets for passed assets. diff --git a/openpype/plugins/publish/collect_hierarchy.py b/openpype/plugins/publish/collect_hierarchy.py index 687397be8a..b5fd1e4bb9 100644 --- a/openpype/plugins/publish/collect_hierarchy.py +++ b/openpype/plugins/publish/collect_hierarchy.py @@ -24,7 +24,7 @@ class CollectHierarchy(pyblish.api.ContextPlugin): final_context[project_name]['entity_type'] = 'Project' for instance in context: - self.log.info("Processing instance: `{}` ...".format(instance)) + self.log.debug("Processing instance: `{}` ...".format(instance)) # shot data dict shot_data = {} diff --git a/openpype/plugins/publish/collect_rendered_files.py b/openpype/plugins/publish/collect_rendered_files.py index 6c8d1e9ca5..aaf290ace7 100644 --- a/openpype/plugins/publish/collect_rendered_files.py +++ b/openpype/plugins/publish/collect_rendered_files.py @@ -91,12 +91,12 @@ class CollectRenderedFiles(pyblish.api.ContextPlugin): # now we can just add instances from json file and we are done for instance_data in data.get("instances"): - self.log.info(" - processing instance for {}".format( + self.log.debug(" - processing instance for {}".format( instance_data.get("subset"))) instance = self._context.create_instance( instance_data.get("subset") ) - self.log.info("Filling stagingDir...") + self.log.debug("Filling stagingDir...") self._fill_staging_dir(instance_data, anatomy) instance.data.update(instance_data) @@ -121,7 +121,7 @@ class CollectRenderedFiles(pyblish.api.ContextPlugin): "offset": 0 }] }) - self.log.info( + self.log.debug( f"Adding audio to instance: {instance.data['audio']}") def process(self, context): @@ -137,11 +137,11 @@ class CollectRenderedFiles(pyblish.api.ContextPlugin): # Using already collected Anatomy anatomy = context.data["anatomy"] - self.log.info("Getting root setting for project \"{}\"".format( + self.log.debug("Getting root setting for project \"{}\"".format( anatomy.project_name )) - self.log.info("anatomy: {}".format(anatomy.roots)) + self.log.debug("anatomy: {}".format(anatomy.roots)) try: session_is_set = False for path in paths: @@ -156,7 +156,7 @@ class CollectRenderedFiles(pyblish.api.ContextPlugin): if remapped: session_data["AVALON_WORKDIR"] = remapped - self.log.info("Setting session using data from file") + self.log.debug("Setting session using data from file") legacy_io.Session.update(session_data) os.environ.update(session_data) session_is_set = True diff --git a/openpype/plugins/publish/extract_burnin.py b/openpype/plugins/publish/extract_burnin.py index e5b37ee3b4..dc8aab6ce4 100644 --- a/openpype/plugins/publish/extract_burnin.py +++ b/openpype/plugins/publish/extract_burnin.py @@ -83,7 +83,7 @@ class ExtractBurnin(publish.Extractor): return if not instance.data.get("representations"): - self.log.info( + self.log.debug( "Instance does not have filled representations. Skipping") return @@ -135,11 +135,11 @@ class ExtractBurnin(publish.Extractor): burnin_defs, repre["tags"] ) if not repre_burnin_defs: - self.log.info(( + self.log.debug( "Skipped representation. All burnin definitions from" - " selected profile does not match to representation's" - " tags. \"{}\"" - ).format(str(repre["tags"]))) + " selected profile do not match to representation's" + " tags. \"{}\"".format(repre["tags"]) + ) continue filtered_repres.append((repre, repre_burnin_defs)) @@ -164,7 +164,7 @@ class ExtractBurnin(publish.Extractor): logger=self.log) if not profile: - self.log.info(( + self.log.debug(( "Skipped instance. None of profiles in presets are for" " Host: \"{}\" | Families: \"{}\" | Task \"{}\"" " | Task type \"{}\" | Subset \"{}\" " @@ -176,7 +176,7 @@ class ExtractBurnin(publish.Extractor): # Pre-filter burnin definitions by instance families burnin_defs = self.filter_burnins_defs(profile, instance) if not burnin_defs: - self.log.info(( + self.log.debug(( "Skipped instance. Burnin definitions are not set for profile" " Host: \"{}\" | Families: \"{}\" | Task \"{}\"" " | Profile \"{}\"" @@ -223,10 +223,10 @@ class ExtractBurnin(publish.Extractor): # If result is None the requirement of conversion can't be # determined if do_convert is None: - self.log.info(( + self.log.debug( "Can't determine if representation requires conversion." " Skipped." - )) + ) continue # Do conversion if needed diff --git a/openpype/plugins/publish/extract_color_transcode.py b/openpype/plugins/publish/extract_color_transcode.py index f7c8af9318..dbf1b6c8a6 100644 --- a/openpype/plugins/publish/extract_color_transcode.py +++ b/openpype/plugins/publish/extract_color_transcode.py @@ -320,7 +320,7 @@ class ExtractOIIOTranscode(publish.Extractor): logger=self.log) if not profile: - self.log.info(( + self.log.debug(( "Skipped instance. None of profiles in presets are for" " Host: \"{}\" | Families: \"{}\" | Task \"{}\"" " | Task type \"{}\" | Subset \"{}\" " diff --git a/openpype/plugins/publish/extract_colorspace_data.py b/openpype/plugins/publish/extract_colorspace_data.py index 363df28fb5..8873dcd637 100644 --- a/openpype/plugins/publish/extract_colorspace_data.py +++ b/openpype/plugins/publish/extract_colorspace_data.py @@ -30,7 +30,7 @@ class ExtractColorspaceData(publish.Extractor, def process(self, instance): representations = instance.data.get("representations") if not representations: - self.log.info("No representations at instance : `{}`".format( + self.log.debug("No representations at instance : `{}`".format( instance)) return diff --git a/openpype/plugins/publish/extract_hierarchy_avalon.py b/openpype/plugins/publish/extract_hierarchy_avalon.py index 1d57545bc0..d70f0cbdd7 100644 --- a/openpype/plugins/publish/extract_hierarchy_avalon.py +++ b/openpype/plugins/publish/extract_hierarchy_avalon.py @@ -21,7 +21,7 @@ class ExtractHierarchyToAvalon(pyblish.api.ContextPlugin): return if "hierarchyContext" not in context.data: - self.log.info("skipping IntegrateHierarchyToAvalon") + self.log.debug("skipping ExtractHierarchyToAvalon") return if not legacy_io.Session: diff --git a/openpype/plugins/publish/extract_hierarchy_to_ayon.py b/openpype/plugins/publish/extract_hierarchy_to_ayon.py index 915650ae41..bb0081b7a5 100644 --- a/openpype/plugins/publish/extract_hierarchy_to_ayon.py +++ b/openpype/plugins/publish/extract_hierarchy_to_ayon.py @@ -27,13 +27,13 @@ class ExtractHierarchyToAYON(pyblish.api.ContextPlugin): hierarchy_context = context.data.get("hierarchyContext") if not hierarchy_context: - self.log.info("Skipping") + self.log.debug("Skipping ExtractHierarchyToAYON") return project_name = context.data["projectName"] hierarchy_context = self._filter_hierarchy(context) if not hierarchy_context: - self.log.info("All folders were filtered out") + self.log.debug("All folders were filtered out") return self.log.debug("Hierarchy_context: {}".format( diff --git a/openpype/plugins/publish/extract_review_slate.py b/openpype/plugins/publish/extract_review_slate.py index 886384fee6..8b1a06b6b8 100644 --- a/openpype/plugins/publish/extract_review_slate.py +++ b/openpype/plugins/publish/extract_review_slate.py @@ -46,7 +46,7 @@ class ExtractReviewSlate(publish.Extractor): "*": inst_data["slateFrame"] } - self.log.info("_ slates_data: {}".format(pformat(slates_data))) + self.log.debug("_ slates_data: {}".format(pformat(slates_data))) if "reviewToWidth" in inst_data: use_legacy_code = True @@ -76,7 +76,7 @@ class ExtractReviewSlate(publish.Extractor): ) # get slate data slate_path = self._get_slate_path(input_file, slates_data) - self.log.info("_ slate_path: {}".format(slate_path)) + self.log.debug("_ slate_path: {}".format(slate_path)) slate_width, slate_height = self._get_slates_resolution(slate_path) diff --git a/openpype/plugins/publish/extract_scanline_exr.py b/openpype/plugins/publish/extract_scanline_exr.py index 9f22794a79..747155689b 100644 --- a/openpype/plugins/publish/extract_scanline_exr.py +++ b/openpype/plugins/publish/extract_scanline_exr.py @@ -29,24 +29,24 @@ class ExtractScanlineExr(pyblish.api.InstancePlugin): representations_new = [] for repre in representations: - self.log.info( + self.log.debug( "Processing representation {}".format(repre.get("name"))) tags = repre.get("tags", []) if "toScanline" not in tags: - self.log.info(" - missing toScanline tag") + self.log.debug(" - missing toScanline tag") continue # run only on exrs if repre.get("ext") != "exr": - self.log.info("- not EXR files") + self.log.debug("- not EXR files") continue if not isinstance(repre['files'], (list, tuple)): input_files = [repre['files']] - self.log.info("We have a single frame") + self.log.debug("We have a single frame") else: input_files = repre['files'] - self.log.info("We have a sequence") + self.log.debug("We have a sequence") stagingdir = os.path.normpath(repre.get("stagingDir")) @@ -68,7 +68,7 @@ class ExtractScanlineExr(pyblish.api.InstancePlugin): ] subprocess_exr = " ".join(oiio_cmd) - self.log.info(f"running: {subprocess_exr}") + self.log.debug(f"running: {subprocess_exr}") run_subprocess(subprocess_exr, logger=self.log) # raise error if there is no ouptput diff --git a/openpype/plugins/publish/extract_thumbnail.py b/openpype/plugins/publish/extract_thumbnail.py index b72a6d02ad..cc2892213a 100644 --- a/openpype/plugins/publish/extract_thumbnail.py +++ b/openpype/plugins/publish/extract_thumbnail.py @@ -43,12 +43,12 @@ class ExtractThumbnail(pyblish.api.InstancePlugin): # Skip if instance have 'review' key in data set to 'False' if not self._is_review_instance(instance): - self.log.info("Skipping - no review set on instance.") + self.log.debug("Skipping - no review set on instance.") return # Check if already has thumbnail created if self._already_has_thumbnail(instance_repres): - self.log.info("Thumbnail representation already present.") + self.log.debug("Thumbnail representation already present.") return # skip crypto passes. @@ -58,15 +58,15 @@ class ExtractThumbnail(pyblish.api.InstancePlugin): # representation that can be determined much earlier and # with better precision. if "crypto" in subset_name.lower(): - self.log.info("Skipping crypto passes.") + self.log.debug("Skipping crypto passes.") return filtered_repres = self._get_filtered_repres(instance) if not filtered_repres: - self.log.info(( - "Instance don't have representations" - " that can be used as source for thumbnail. Skipping" - )) + self.log.info( + "Instance doesn't have representations that can be used " + "as source for thumbnail. Skipping thumbnail extraction." + ) return # Create temp directory for thumbnail @@ -107,10 +107,10 @@ class ExtractThumbnail(pyblish.api.InstancePlugin): # oiiotool isn't available if not thumbnail_created: if oiio_supported: - self.log.info(( + self.log.debug( "Converting with FFMPEG because input" " can't be read by OIIO." - )) + ) thumbnail_created = self.create_thumbnail_ffmpeg( full_input_path, full_output_path @@ -165,8 +165,8 @@ class ExtractThumbnail(pyblish.api.InstancePlugin): continue if not repre.get("files"): - self.log.info(( - "Representation \"{}\" don't have files. Skipping" + self.log.debug(( + "Representation \"{}\" doesn't have files. Skipping" ).format(repre["name"])) continue @@ -174,7 +174,7 @@ class ExtractThumbnail(pyblish.api.InstancePlugin): return filtered_repres def create_thumbnail_oiio(self, src_path, dst_path): - self.log.info("Extracting thumbnail {}".format(dst_path)) + self.log.debug("Extracting thumbnail with OIIO: {}".format(dst_path)) oiio_cmd = get_oiio_tool_args( "oiiotool", "-a", src_path, @@ -192,7 +192,7 @@ class ExtractThumbnail(pyblish.api.InstancePlugin): return False def create_thumbnail_ffmpeg(self, src_path, dst_path): - self.log.info("outputting {}".format(dst_path)) + self.log.debug("Extracting thumbnail with FFMPEG: {}".format(dst_path)) ffmpeg_path_args = get_ffmpeg_tool_args("ffmpeg") ffmpeg_args = self.ffmpeg_args or {} diff --git a/openpype/plugins/publish/extract_thumbnail_from_source.py b/openpype/plugins/publish/extract_thumbnail_from_source.py index 1b9f0a8bae..c1f271a8cc 100644 --- a/openpype/plugins/publish/extract_thumbnail_from_source.py +++ b/openpype/plugins/publish/extract_thumbnail_from_source.py @@ -49,7 +49,7 @@ class ExtractThumbnailFromSource(pyblish.api.InstancePlugin): # Check if already has thumbnail created if self._instance_has_thumbnail(instance): - self.log.info("Thumbnail representation already present.") + self.log.debug("Thumbnail representation already present.") return dst_filepath = self._create_thumbnail( @@ -98,7 +98,7 @@ class ExtractThumbnailFromSource(pyblish.api.InstancePlugin): thumbnail_created = False oiio_supported = is_oiio_supported() - self.log.info("Thumbnail source: {}".format(thumbnail_source)) + self.log.debug("Thumbnail source: {}".format(thumbnail_source)) src_basename = os.path.basename(thumbnail_source) dst_filename = os.path.splitext(src_basename)[0] + "_thumb.jpg" full_output_path = os.path.join(dst_staging, dst_filename) @@ -115,10 +115,10 @@ class ExtractThumbnailFromSource(pyblish.api.InstancePlugin): # oiiotool isn't available if not thumbnail_created: if oiio_supported: - self.log.info(( + self.log.info( "Converting with FFMPEG because input" " can't be read by OIIO." - )) + ) thumbnail_created = self.create_thumbnail_ffmpeg( thumbnail_source, full_output_path @@ -143,14 +143,14 @@ class ExtractThumbnailFromSource(pyblish.api.InstancePlugin): return False def create_thumbnail_oiio(self, src_path, dst_path): - self.log.info("outputting {}".format(dst_path)) + self.log.debug("Outputting thumbnail with OIIO: {}".format(dst_path)) oiio_cmd = get_oiio_tool_args( "oiiotool", "-a", src_path, "--ch", "R,G,B", "-o", dst_path ) - self.log.info("Running: {}".format(" ".join(oiio_cmd))) + self.log.debug("Running: {}".format(" ".join(oiio_cmd))) try: run_subprocess(oiio_cmd, logger=self.log) return True @@ -173,7 +173,7 @@ class ExtractThumbnailFromSource(pyblish.api.InstancePlugin): dst_path ) - self.log.info("Running: {}".format(" ".join(ffmpeg_cmd))) + self.log.debug("Running: {}".format(" ".join(ffmpeg_cmd))) try: run_subprocess(ffmpeg_cmd, logger=self.log) return True diff --git a/openpype/plugins/publish/extract_trim_video_audio.py b/openpype/plugins/publish/extract_trim_video_audio.py index 2907ae1839..5e00cfc96f 100644 --- a/openpype/plugins/publish/extract_trim_video_audio.py +++ b/openpype/plugins/publish/extract_trim_video_audio.py @@ -36,7 +36,7 @@ class ExtractTrimVideoAudio(publish.Extractor): # get staging dir staging_dir = self.staging_dir(instance) - self.log.info("Staging dir set to: `{}`".format(staging_dir)) + self.log.debug("Staging dir set to: `{}`".format(staging_dir)) # Generate mov file. fps = instance.data["fps"] @@ -59,7 +59,7 @@ class ExtractTrimVideoAudio(publish.Extractor): extensions = [output_file_type] for ext in extensions: - self.log.info("Processing ext: `{}`".format(ext)) + self.log.debug("Processing ext: `{}`".format(ext)) if not ext.startswith("."): ext = "." + ext @@ -98,7 +98,7 @@ class ExtractTrimVideoAudio(publish.Extractor): ffmpeg_args.append(clip_trimed_path) joined_args = " ".join(ffmpeg_args) - self.log.info(f"Processing: {joined_args}") + self.log.debug(f"Processing: {joined_args}") run_subprocess( ffmpeg_args, logger=self.log ) diff --git a/openpype/plugins/publish/integrate.py b/openpype/plugins/publish/integrate.py index be07cffe72..0c18ab4466 100644 --- a/openpype/plugins/publish/integrate.py +++ b/openpype/plugins/publish/integrate.py @@ -155,13 +155,13 @@ class IntegrateAsset(pyblish.api.InstancePlugin): # Instance should be integrated on a farm if instance.data.get("farm"): - self.log.info( + self.log.debug( "Instance is marked to be processed on farm. Skipping") return # Instance is marked to not get integrated if not instance.data.get("integrate", True): - self.log.info("Instance is marked to skip integrating. Skipping") + self.log.debug("Instance is marked to skip integrating. Skipping") return filtered_repres = self.filter_representations(instance) @@ -306,7 +306,7 @@ class IntegrateAsset(pyblish.api.InstancePlugin): # increase if the file transaction takes a long time. op_session.commit() - self.log.info("Subset {subset[name]} and Version {version[name]} " + self.log.info("Subset '{subset[name]}' and Version {version[name]} " "written to database..".format(subset=subset, version=version)) diff --git a/openpype/plugins/publish/integrate_hero_version.py b/openpype/plugins/publish/integrate_hero_version.py index 6c21664b78..9f0f7fe7f3 100644 --- a/openpype/plugins/publish/integrate_hero_version.py +++ b/openpype/plugins/publish/integrate_hero_version.py @@ -275,10 +275,10 @@ class IntegrateHeroVersion(pyblish.api.InstancePlugin): backup_hero_publish_dir = _backup_hero_publish_dir break except Exception: - self.log.info(( + self.log.info( "Could not remove previous backup folder." - " Trying to add index to folder name" - )) + " Trying to add index to folder name." + ) _backup_hero_publish_dir = ( backup_hero_publish_dir + str(idx) diff --git a/openpype/plugins/publish/integrate_thumbnail.py b/openpype/plugins/publish/integrate_thumbnail.py index 9929d8f754..0c12255d38 100644 --- a/openpype/plugins/publish/integrate_thumbnail.py +++ b/openpype/plugins/publish/integrate_thumbnail.py @@ -41,7 +41,9 @@ class IntegrateThumbnails(pyblish.api.ContextPlugin): def process(self, context): if AYON_SERVER_ENABLED: - self.log.info("AYON is enabled. Skipping v3 thumbnail integration") + self.log.debug( + "AYON is enabled. Skipping v3 thumbnail integration" + ) return # Filter instances which can be used for integration @@ -74,14 +76,14 @@ class IntegrateThumbnails(pyblish.api.ContextPlugin): thumbnail_template = anatomy.templates["publish"]["thumbnail"] if not thumbnail_template: - self.log.info("Thumbnail template is not filled. Skipping.") + self.log.debug("Thumbnail template is not filled. Skipping.") return if ( not thumbnail_root and thumbnail_root_format_key in thumbnail_template ): - self.log.warning(("{} is not set. Skipping.").format(env_key)) + self.log.warning("{} is not set. Skipping.".format(env_key)) return # Collect verion ids from all filtered instance diff --git a/openpype/plugins/publish/integrate_thumbnail_ayon.py b/openpype/plugins/publish/integrate_thumbnail_ayon.py index ba5664c69f..cf05327ce8 100644 --- a/openpype/plugins/publish/integrate_thumbnail_ayon.py +++ b/openpype/plugins/publish/integrate_thumbnail_ayon.py @@ -35,13 +35,13 @@ class IntegrateThumbnailsAYON(pyblish.api.ContextPlugin): def process(self, context): if not AYON_SERVER_ENABLED: - self.log.info("AYON is not enabled. Skipping") + self.log.debug("AYON is not enabled. Skipping") return # Filter instances which can be used for integration filtered_instance_items = self._prepare_instances(context) if not filtered_instance_items: - self.log.info( + self.log.debug( "All instances were filtered. Thumbnail integration skipped." ) return @@ -110,7 +110,7 @@ class IntegrateThumbnailsAYON(pyblish.api.ContextPlugin): # Skip instance if thumbnail path is not available for it if not thumbnail_path: - self.log.info(( + self.log.debug(( "Skipping thumbnail integration for instance \"{}\"." " Instance and context" " thumbnail paths are not available." diff --git a/openpype/plugins/publish/validate_asset_docs.py b/openpype/plugins/publish/validate_asset_docs.py index 9a1ca5b8de..8dfd783c39 100644 --- a/openpype/plugins/publish/validate_asset_docs.py +++ b/openpype/plugins/publish/validate_asset_docs.py @@ -22,11 +22,11 @@ class ValidateAssetDocs(pyblish.api.InstancePlugin): return if instance.data.get("assetEntity"): - self.log.info("Instance has set asset document in its data.") + self.log.debug("Instance has set asset document in its data.") elif instance.data.get("newAssetPublishing"): # skip if it is editorial - self.log.info("Editorial instance is no need to check...") + self.log.debug("Editorial instance has no need to check...") else: raise PublishValidationError(( diff --git a/openpype/plugins/publish/validate_editorial_asset_name.py b/openpype/plugins/publish/validate_editorial_asset_name.py index 4f8a1abf2e..fca0d8e7f5 100644 --- a/openpype/plugins/publish/validate_editorial_asset_name.py +++ b/openpype/plugins/publish/validate_editorial_asset_name.py @@ -56,7 +56,7 @@ class ValidateEditorialAssetName(pyblish.api.ContextPlugin): } continue - self.log.info("correct asset: {}".format(asset)) + self.log.debug("correct asset: {}".format(asset)) if assets_missing_name: wrong_names = {} From 7243f7e7219cd59aebb5c970666bb5d8552d378b Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 30 Aug 2023 10:11:30 +0200 Subject: [PATCH 066/154] Fix context not being reported correctly if it was already set on `context.data` prior to collector --- openpype/plugins/publish/collect_current_context.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/openpype/plugins/publish/collect_current_context.py b/openpype/plugins/publish/collect_current_context.py index 166d75e5de..8b12a3f77f 100644 --- a/openpype/plugins/publish/collect_current_context.py +++ b/openpype/plugins/publish/collect_current_context.py @@ -39,5 +39,12 @@ class CollectCurrentContext(pyblish.api.ContextPlugin): # - 'task' -> 'taskName' self.log.info(( - "Collected project context\nProject: {}\nAsset: {}\nTask: {}" - ).format(project_name, asset_name, task_name)) + "Collected project context\n" + "Project: {project_name}\n" + "Asset: {asset_name}\n" + "Task: {task_name}" + ).format( + project_name=context.data["projectName"], + asset_name=context.data["asset"], + task_name=context.data["task"] + )) From d03d0564cdd471ce8ac3c0fdcf85db4841c69508 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 30 Aug 2023 10:13:07 +0200 Subject: [PATCH 067/154] Fix typo `thubmnail` -> `thumbnail` --- openpype/plugins/publish/extract_thumbnail.py | 2 +- openpype/plugins/publish/extract_thumbnail_from_source.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openpype/plugins/publish/extract_thumbnail.py b/openpype/plugins/publish/extract_thumbnail.py index cc2892213a..de101ac7ac 100644 --- a/openpype/plugins/publish/extract_thumbnail.py +++ b/openpype/plugins/publish/extract_thumbnail.py @@ -225,7 +225,7 @@ class ExtractThumbnail(pyblish.api.InstancePlugin): return True except Exception: self.log.warning( - "Failed to create thubmnail using ffmpeg", + "Failed to create thumbnail using ffmpeg", exc_info=True ) return False diff --git a/openpype/plugins/publish/extract_thumbnail_from_source.py b/openpype/plugins/publish/extract_thumbnail_from_source.py index c1f271a8cc..401a5d615d 100644 --- a/openpype/plugins/publish/extract_thumbnail_from_source.py +++ b/openpype/plugins/publish/extract_thumbnail_from_source.py @@ -156,7 +156,7 @@ class ExtractThumbnailFromSource(pyblish.api.InstancePlugin): return True except Exception: self.log.warning( - "Failed to create thubmnail using oiiotool", + "Failed to create thumbnail using oiiotool", exc_info=True ) return False @@ -179,7 +179,7 @@ class ExtractThumbnailFromSource(pyblish.api.InstancePlugin): return True except Exception: self.log.warning( - "Failed to create thubmnail using ffmpeg", + "Failed to create thumbnail using ffmpeg", exc_info=True ) return False From 2ba42fe376bb6b0fec30cc1a37fb634b7ba69318 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 30 Aug 2023 10:14:53 +0200 Subject: [PATCH 068/154] Tweak logging level --- openpype/hosts/fusion/plugins/publish/collect_instances.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/fusion/plugins/publish/collect_instances.py b/openpype/hosts/fusion/plugins/publish/collect_instances.py index 6016baa2a9..4d6da79b77 100644 --- a/openpype/hosts/fusion/plugins/publish/collect_instances.py +++ b/openpype/hosts/fusion/plugins/publish/collect_instances.py @@ -85,5 +85,5 @@ class CollectInstanceData(pyblish.api.InstancePlugin): # Add review family if the instance is marked as 'review' # This could be done through a 'review' Creator attribute. if instance.data.get("review", False): - self.log.info("Adding review family..") + self.log.debug("Adding review family..") instance.data["families"].append("review") From ca8305a0cf2a48bb5c9965c6cab9b4bc14aaf549 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 30 Aug 2023 10:16:37 +0200 Subject: [PATCH 069/154] Tweak logging level of removal of directory in tempdir to debug since artist doesn't care about seeing that in artist facing report --- openpype/plugins/publish/cleanup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/plugins/publish/cleanup.py b/openpype/plugins/publish/cleanup.py index f9f504dd4f..6c122ddf09 100644 --- a/openpype/plugins/publish/cleanup.py +++ b/openpype/plugins/publish/cleanup.py @@ -100,7 +100,7 @@ class CleanUp(pyblish.api.InstancePlugin): ) return - self.log.info("Removing staging directory {}".format(staging_dir)) + self.log.debug("Removing staging directory {}".format(staging_dir)) shutil.rmtree(staging_dir) def clean_renders(self, instance, skip_cleanup_filepaths): From e9cb011c2a38084bc2318e4b15d011e2278f0c38 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 30 Aug 2023 10:31:06 +0200 Subject: [PATCH 070/154] Remove unused attribute --- openpype/hosts/maya/plugins/publish/collect_history.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/collect_history.py b/openpype/hosts/maya/plugins/publish/collect_history.py index 71f0169971..d4e8c6298b 100644 --- a/openpype/hosts/maya/plugins/publish/collect_history.py +++ b/openpype/hosts/maya/plugins/publish/collect_history.py @@ -18,7 +18,6 @@ class CollectMayaHistory(pyblish.api.InstancePlugin): hosts = ["maya"] label = "Maya History" families = ["rig"] - verbose = False def process(self, instance): From 97f9cd4377e83cfec48ae8d18bcc90d783185e60 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 30 Aug 2023 14:14:33 +0200 Subject: [PATCH 071/154] Do not warn about renderlayer instance being empty --- openpype/hosts/maya/plugins/publish/collect_instances.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/collect_instances.py b/openpype/hosts/maya/plugins/publish/collect_instances.py index 5f914b40d7..5058da3d01 100644 --- a/openpype/hosts/maya/plugins/publish/collect_instances.py +++ b/openpype/hosts/maya/plugins/publish/collect_instances.py @@ -28,6 +28,8 @@ class CollectNewInstances(pyblish.api.InstancePlugin): order = pyblish.api.CollectorOrder hosts = ["maya"] + valid_empty_families = {"workfile", "renderlayer"} + def process(self, instance): objset = instance.data.get("instance_node") @@ -58,7 +60,7 @@ class CollectNewInstances(pyblish.api.InstancePlugin): instance[:] = members_hierarchy - elif instance.data["family"] != "workfile": + elif instance.data["family"] not in self.valid_empty_families: self.log.warning("Empty instance: \"%s\" " % objset) # Store the exact members of the object set instance.data["setMembers"] = members From 0fa081dddb6e6295748f338daa822e1e2cd61d40 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 30 Aug 2023 14:16:27 +0200 Subject: [PATCH 072/154] Ignore arnold attribute check if arnold is not loaded --- .../maya/plugins/publish/validate_mesh_arnold_attributes.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py b/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py index 55624726ea..59ba326d45 100644 --- a/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py +++ b/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py @@ -109,6 +109,10 @@ class ValidateMeshArnoldAttributes(pyblish.api.InstancePlugin, if not self.is_active(instance.data): return + if not cmds.pluginInfo("mtoa", query=True, loaded=True): + # Arnold attributes only exist if plug-in is loaded + return + invalid = self.get_invalid_attributes(instance, compute=True) if invalid: raise PublishValidationError( From 17f83a0eccb99a35ba44faaf876ad3604b342932 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 30 Aug 2023 14:17:16 +0200 Subject: [PATCH 073/154] Avoid iterating over `None` if `ai` attributes for some reason do not exist --- .../maya/plugins/publish/validate_mesh_arnold_attributes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py b/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py index 59ba326d45..ddb8d2bf9d 100644 --- a/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py +++ b/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py @@ -51,7 +51,7 @@ class ValidateMeshArnoldAttributes(pyblish.api.InstancePlugin, tmp.append(transform) mesh = cmds.createNode("mesh", parent=transform) - for attr in cmds.listAttr(mesh, string="ai*"): + for attr in cmds.listAttr(mesh, string="ai*") or []: plug = "{}.{}".format(mesh, attr) try: defaults[attr] = get_attribute(plug) From 861b9849cb11b82ad70ef99806c1c0498ec30b1b Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 30 Aug 2023 14:20:56 +0200 Subject: [PATCH 074/154] Ensure we only iterate `ai*` attributes that come from a plugin --- .../maya/plugins/publish/validate_mesh_arnold_attributes.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py b/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py index ddb8d2bf9d..849d60653a 100644 --- a/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py +++ b/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py @@ -51,7 +51,10 @@ class ValidateMeshArnoldAttributes(pyblish.api.InstancePlugin, tmp.append(transform) mesh = cmds.createNode("mesh", parent=transform) - for attr in cmds.listAttr(mesh, string="ai*") or []: + arnold_attributes = cmds.listAttr(mesh, + string="ai*", + fromPlugin=True) or [] + for attr in arnold_attributes: plug = "{}.{}".format(mesh, attr) try: defaults[attr] = get_attribute(plug) From 3ee28bd1aa092f90e5b807dc63eea135eb913a8b Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 30 Aug 2023 14:22:11 +0200 Subject: [PATCH 075/154] Avoid selection changes --- .../maya/plugins/publish/validate_mesh_arnold_attributes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py b/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py index 849d60653a..d50e1a56c7 100644 --- a/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py +++ b/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py @@ -47,10 +47,10 @@ class ValidateMeshArnoldAttributes(pyblish.api.InstancePlugin, # Get default arnold attribute values for mesh type. defaults = {} with delete_after() as tmp: - transform = cmds.createNode("transform") + transform = cmds.createNode("transform", skipSelect=True) tmp.append(transform) - mesh = cmds.createNode("mesh", parent=transform) + mesh = cmds.createNode("mesh", parent=transform, skipSelect=True) arnold_attributes = cmds.listAttr(mesh, string="ai*", fromPlugin=True) or [] From 3b8df1ac2bad6df683ae4417e2b2e0b59944f729 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 30 Aug 2023 14:29:40 +0200 Subject: [PATCH 076/154] Cache arnold mesh attribute defaults so multiple "model" instance don't try and retrieve the default values every time. --- .../plugins/publish/validate_mesh_arnold_attributes.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py b/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py index d50e1a56c7..526ebbac99 100644 --- a/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py +++ b/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py @@ -36,6 +36,9 @@ class ValidateMeshArnoldAttributes(pyblish.api.InstancePlugin, optional = True + # cache (will be `dict` when cached) + arnold_mesh_defaults = None + @classmethod def apply_settings(cls, project_settings, system_settings): # todo: this should not be done this way @@ -44,6 +47,11 @@ class ValidateMeshArnoldAttributes(pyblish.api.InstancePlugin, @classmethod def get_default_attributes(cls): + + if cls.arnold_mesh_defaults is not None: + # Use from cache + return cls.arnold_mesh_defaults + # Get default arnold attribute values for mesh type. defaults = {} with delete_after() as tmp: @@ -61,6 +69,7 @@ class ValidateMeshArnoldAttributes(pyblish.api.InstancePlugin, except PublishValidationError: cls.log.debug("Ignoring arnold attribute: {}".format(attr)) + cls.arnold_mesh_defaults = defaults # assign cache return defaults @classmethod From 689da974c4d22161797862f2a9e77d8aeee65656 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 30 Aug 2023 14:42:46 +0200 Subject: [PATCH 077/154] Removed `apply_settings` override to fix plugin settings actually being applied This makes it so again that it's up to the studio admin to enable or disable the plug-in per project instead of whether the modeler's workfile just happened to have the current renderer set to arnold or not. Note that the plug-in is currently disabled by default in project settings. --- .../maya/plugins/publish/validate_mesh_arnold_attributes.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py b/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py index 526ebbac99..bde78a98b8 100644 --- a/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py +++ b/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py @@ -39,12 +39,6 @@ class ValidateMeshArnoldAttributes(pyblish.api.InstancePlugin, # cache (will be `dict` when cached) arnold_mesh_defaults = None - @classmethod - def apply_settings(cls, project_settings, system_settings): - # todo: this should not be done this way - attr = "defaultRenderGlobals.currentRenderer" - cls.active = cmds.getAttr(attr).lower() == "arnold" - @classmethod def get_default_attributes(cls): From 9e19f2f8ca1e7e848a7cebde4432df1fde3d3897 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 30 Aug 2023 22:09:33 +0200 Subject: [PATCH 078/154] implemented multiselection EnumDef --- openpype/lib/attribute_definitions.py | 30 +++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/openpype/lib/attribute_definitions.py b/openpype/lib/attribute_definitions.py index 6054d2a92a..0af701a93a 100644 --- a/openpype/lib/attribute_definitions.py +++ b/openpype/lib/attribute_definitions.py @@ -434,7 +434,9 @@ class EnumDef(AbstractAttrDef): type = "enum" - def __init__(self, key, items, default=None, **kwargs): + def __init__( + self, key, items, default=None, multiselection=False, **kwargs + ): if not items: raise ValueError(( "Empty 'items' value. {} must have" @@ -443,7 +445,10 @@ class EnumDef(AbstractAttrDef): items = self.prepare_enum_items(items) item_values = [item["value"] for item in items] - if default not in item_values: + if multiselection and default is None: + default = [] + + if not multiselection and default not in item_values: for value in item_values: default = value break @@ -452,21 +457,34 @@ class EnumDef(AbstractAttrDef): self.items = items self._item_values = set(item_values) + self.multiselection = multiselection def __eq__(self, other): if not super(EnumDef, self).__eq__(other): return False - return self.items == other.items + return ( + self.items == other.items + and self.multiselection == other.multiselection + ) def convert_value(self, value): - if value in self._item_values: - return value - return self.default + if not self.multiselection: + if value in self._item_values: + return value + return self.default + + if value is None: + return copy.deepcopy(self.default) + new_value = set(value) + rem = new_value - self._item_values + return list(new_value - rem) + def serialize(self): data = super(EnumDef, self).serialize() data["items"] = copy.deepcopy(self.items) + data["multiselection"] = self.multiselection return data @staticmethod From ebec7236aae738a2ffd9fd2738b9f402ead42c2e Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 30 Aug 2023 22:09:51 +0200 Subject: [PATCH 079/154] implemented multiselection combobox --- openpype/tools/utils/__init__.py | 3 + .../tools/utils/multiselection_combobox.py | 383 ++++++++++++++++++ 2 files changed, 386 insertions(+) create mode 100644 openpype/tools/utils/multiselection_combobox.py diff --git a/openpype/tools/utils/__init__.py b/openpype/tools/utils/__init__.py index f35bfaee70..d343353112 100644 --- a/openpype/tools/utils/__init__.py +++ b/openpype/tools/utils/__init__.py @@ -38,6 +38,7 @@ from .models import ( from .overlay_messages import ( MessageOverlayObject, ) +from .multiselection_combobox import MultiSelectionComboBox __all__ = ( @@ -78,4 +79,6 @@ __all__ = ( "RecursiveSortFilterProxyModel", "MessageOverlayObject", + + "MultiSelectionComboBox", ) diff --git a/openpype/tools/utils/multiselection_combobox.py b/openpype/tools/utils/multiselection_combobox.py new file mode 100644 index 0000000000..27576a449a --- /dev/null +++ b/openpype/tools/utils/multiselection_combobox.py @@ -0,0 +1,383 @@ +from qtpy import QtCore, QtGui, QtWidgets + +from .lib import ( + checkstate_int_to_enum, + checkstate_enum_to_int, +) +from .constants import ( + CHECKED_INT, + UNCHECKED_INT, + ITEM_IS_USER_TRISTATE, +) + + +class ComboItemDelegate(QtWidgets.QStyledItemDelegate): + """ + Helper styled delegate (mostly based on existing private Qt's + delegate used by the QtWidgets.QComboBox). Used to style the popup like a + list view (e.g windows style). + """ + + def paint(self, painter, option, index): + option = QtWidgets.QStyleOptionViewItem(option) + option.showDecorationSelected = True + + # option.state &= ( + # ~QtWidgets.QStyle.State_HasFocus + # & ~QtWidgets.QStyle.State_MouseOver + # ) + super(ComboItemDelegate, self).paint(painter, option, index) + + +class MultiSelectionComboBox(QtWidgets.QComboBox): + value_changed = QtCore.Signal() + focused_in = QtCore.Signal() + + ignored_keys = { + QtCore.Qt.Key_Up, + QtCore.Qt.Key_Down, + QtCore.Qt.Key_PageDown, + QtCore.Qt.Key_PageUp, + QtCore.Qt.Key_Home, + QtCore.Qt.Key_End, + } + + top_bottom_padding = 2 + left_right_padding = 3 + left_offset = 4 + top_bottom_margins = 2 + item_spacing = 5 + + item_bg_color = QtGui.QColor("#31424e") + + def __init__( + self, parent=None, placeholder="", separator=", ", **kwargs + ): + super(MultiSelectionComboBox, self).__init__(parent=parent, **kwargs) + self.setObjectName("MultiSelectionComboBox") + self.setFocusPolicy(QtCore.Qt.StrongFocus) + + self._popup_is_shown = False + self._block_mouse_release_timer = QtCore.QTimer(self, singleShot=True) + self._initial_mouse_pos = None + self._separator = separator + self._placeholder_text = placeholder + delegate = ComboItemDelegate(self) + self.setItemDelegate(delegate) + + self._lines = {} + self._item_height = None + self._custom_text = None + self._delegate = delegate + + def get_placeholder_text(self): + return self._placeholder_text + + def set_placeholder_text(self, text): + self._placeholder_text = text + + def set_custom_text(self, text): + self._custom_text = text + self.update() + self.updateGeometry() + + def focusInEvent(self, event): + self.focused_in.emit() + return super(MultiSelectionComboBox, self).focusInEvent(event) + + def mousePressEvent(self, event): + """Reimplemented.""" + self._popup_is_shown = False + super(MultiSelectionComboBox, self).mousePressEvent(event) + if self._popup_is_shown: + self._initial_mouse_pos = self.mapToGlobal(event.pos()) + self._block_mouse_release_timer.start( + QtWidgets.QApplication.doubleClickInterval() + ) + + def showPopup(self): + """Reimplemented.""" + super(MultiSelectionComboBox, self).showPopup() + view = self.view() + view.installEventFilter(self) + view.viewport().installEventFilter(self) + self._popup_is_shown = True + + def hidePopup(self): + """Reimplemented.""" + self.view().removeEventFilter(self) + self.view().viewport().removeEventFilter(self) + self._popup_is_shown = False + self._initial_mouse_pos = None + super(MultiSelectionComboBox, self).hidePopup() + self.view().clearFocus() + + def _event_popup_shown(self, obj, event): + if not self._popup_is_shown: + return + + current_index = self.view().currentIndex() + model = self.model() + + if event.type() == QtCore.QEvent.MouseMove: + if ( + self.view().isVisible() + and self._initial_mouse_pos is not None + and self._block_mouse_release_timer.isActive() + ): + diff = obj.mapToGlobal(event.pos()) - self._initial_mouse_pos + if diff.manhattanLength() > 9: + self._block_mouse_release_timer.stop() + return + + index_flags = current_index.flags() + state = checkstate_int_to_enum( + current_index.data(QtCore.Qt.CheckStateRole) + ) + new_state = None + + if event.type() == QtCore.QEvent.MouseButtonRelease: + if ( + self._block_mouse_release_timer.isActive() + or not current_index.isValid() + or not self.view().isVisible() + or not self.view().rect().contains(event.pos()) + or not index_flags & QtCore.Qt.ItemIsSelectable + or not index_flags & QtCore.Qt.ItemIsEnabled + or not index_flags & QtCore.Qt.ItemIsUserCheckable + ): + return + + if state == QtCore.Qt.Unchecked: + new_state = CHECKED_INT + else: + new_state = UNCHECKED_INT + + elif event.type() == QtCore.QEvent.KeyPress: + # TODO: handle QtCore.Qt.Key_Enter, Key_Return? + if event.key() == QtCore.Qt.Key_Space: + if ( + index_flags & QtCore.Qt.ItemIsUserCheckable + and index_flags & ITEM_IS_USER_TRISTATE + ): + new_state = (checkstate_enum_to_int(state) + 1) % 3 + + elif index_flags & QtCore.Qt.ItemIsUserCheckable: + # toggle the current items check state + if state != QtCore.Qt.Checked: + new_state = CHECKED_INT + else: + new_state = UNCHECKED_INT + + if new_state is not None: + model.setData(current_index, new_state, QtCore.Qt.CheckStateRole) + self.view().update(current_index) + self._update_size_hint() + self.value_changed.emit() + return True + + def eventFilter(self, obj, event): + """Reimplemented.""" + result = self._event_popup_shown(obj, event) + if result is not None: + return result + + return super(MultiSelectionComboBox, self).eventFilter(obj, event) + + def addItem(self, *args, **kwargs): + idx = self.count() + super(MultiSelectionComboBox, self).addItem(*args, **kwargs) + self.model().item(idx).setCheckable(True) + + def paintEvent(self, event): + """Reimplemented.""" + painter = QtWidgets.QStylePainter(self) + option = QtWidgets.QStyleOptionComboBox() + self.initStyleOption(option) + painter.drawComplexControl(QtWidgets.QStyle.CC_ComboBox, option) + + items = self.checked_items_text() + # draw the icon and text + draw_text = True + combotext = None + if self._custom_text is not None: + combotext = self._custom_text + elif not items: + combotext = self._placeholder_text + else: + draw_text = False + if draw_text: + option.currentText = combotext + option.palette.setCurrentColorGroup(QtGui.QPalette.Disabled) + painter.drawControl(QtWidgets.QStyle.CE_ComboBoxLabel, option) + return + + font_metricts = self.fontMetrics() + + if self._item_height is None: + self.updateGeometry() + self.update() + return + + for line, items in self._lines.items(): + top_y = ( + option.rect.top() + + (line * self._item_height) + + self.top_bottom_margins + ) + left_x = option.rect.left() + self.left_offset + for item in items: + label_rect = font_metricts.boundingRect(item) + label_height = label_rect.height() + + label_rect.moveTop(top_y) + label_rect.moveLeft(left_x) + label_rect.setHeight(self._item_height) + label_rect.setWidth( + label_rect.width() + self.left_right_padding + ) + + bg_rect = QtCore.QRectF(label_rect) + bg_rect.setWidth( + label_rect.width() + self.left_right_padding + ) + left_x = bg_rect.right() + self.item_spacing + + label_rect.moveLeft(label_rect.x() + self.left_right_padding) + + bg_rect.setHeight(label_height + (2 * self.top_bottom_padding)) + bg_rect.moveTop(bg_rect.top() + self.top_bottom_margins) + + path = QtGui.QPainterPath() + path.addRoundedRect(bg_rect, 5, 5) + + painter.fillPath(path, self.item_bg_color) + + painter.drawText( + label_rect, + QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter, + item + ) + + def resizeEvent(self, *args, **kwargs): + super(MultiSelectionComboBox, self).resizeEvent(*args, **kwargs) + self._update_size_hint() + + def _update_size_hint(self): + if self._custom_text is not None: + self.update() + return + self._lines = {} + + items = self.checked_items_text() + if not items: + self.update() + return + + option = QtWidgets.QStyleOptionComboBox() + self.initStyleOption(option) + btn_rect = self.style().subControlRect( + QtWidgets.QStyle.CC_ComboBox, + option, + QtWidgets.QStyle.SC_ComboBoxArrow + ) + total_width = option.rect.width() - btn_rect.width() + + line = 0 + self._lines = {line: []} + + font_metricts = self.fontMetrics() + default_left_x = 0 + self.left_offset + left_x = int(default_left_x) + for item in items: + rect = font_metricts.boundingRect(item) + width = rect.width() + (2 * self.left_right_padding) + right_x = left_x + width + if right_x > total_width: + left_x = int(default_left_x) + if self._lines.get(line): + line += 1 + self._lines[line] = [item] + left_x += width + else: + self._lines[line] = [item] + line += 1 + else: + if line in self._lines: + self._lines[line].append(item) + else: + self._lines[line] = [item] + left_x = left_x + width + self.item_spacing + + self.update() + self.updateGeometry() + + def sizeHint(self): + value = super(MultiSelectionComboBox, self).sizeHint() + lines = 1 + if self._custom_text is None: + lines = len(self._lines) + if lines == 0: + lines = 1 + + if self._item_height is None: + self._item_height = ( + self.fontMetrics().height() + + (2 * self.top_bottom_padding) + + (2 * self.top_bottom_margins) + ) + value.setHeight( + (lines * self._item_height) + + (2 * self.top_bottom_margins) + ) + return value + + def setItemCheckState(self, index, state): + self.setItemData(index, state, QtCore.Qt.CheckStateRole) + + def set_value(self, values): + for idx in range(self.count()): + value = self.itemData(idx, role=QtCore.Qt.UserRole) + if value in values: + check_state = CHECKED_INT + else: + check_state = UNCHECKED_INT + self.setItemData(idx, check_state, QtCore.Qt.CheckStateRole) + self._update_size_hint() + + def value(self): + items = list() + for idx in range(self.count()): + state = checkstate_int_to_enum( + self.itemData(idx, role=QtCore.Qt.CheckStateRole) + ) + if state == QtCore.Qt.Checked: + items.append( + self.itemData(idx, role=QtCore.Qt.UserRole) + ) + return items + + def checked_items_text(self): + items = list() + for idx in range(self.count()): + state = checkstate_int_to_enum( + self.itemData(idx, role=QtCore.Qt.CheckStateRole) + ) + if state == QtCore.Qt.Checked: + items.append(self.itemText(idx)) + return items + + def wheelEvent(self, event): + event.ignore() + + def keyPressEvent(self, event): + if ( + event.key() == QtCore.Qt.Key_Down + and event.modifiers() & QtCore.Qt.AltModifier + ): + return self.showPopup() + + if event.key() in self.ignored_keys: + return event.ignore() + + return super(MultiSelectionComboBox, self).keyPressEvent(event) From 2d04efba93c50e6832059ae92d49bee9aab641fb Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 30 Aug 2023 22:10:14 +0200 Subject: [PATCH 080/154] implemented multuselection EnumAttrDef widget --- openpype/tools/attribute_defs/widgets.py | 55 +++++++++++++++++++----- 1 file changed, 45 insertions(+), 10 deletions(-) diff --git a/openpype/tools/attribute_defs/widgets.py b/openpype/tools/attribute_defs/widgets.py index 7967416e9f..e08ca17225 100644 --- a/openpype/tools/attribute_defs/widgets.py +++ b/openpype/tools/attribute_defs/widgets.py @@ -19,6 +19,7 @@ from openpype.tools.utils import ( CustomTextComboBox, FocusSpinBox, FocusDoubleSpinBox, + MultiSelectionComboBox, ) from openpype.widgets.nice_checkbox import NiceCheckbox @@ -412,10 +413,19 @@ class EnumAttrWidget(_BaseAttrDefWidget): self._multivalue = False super(EnumAttrWidget, self).__init__(*args, **kwargs) + @property + def multiselection(self): + return self.attr_def.multiselection + def _ui_init(self): - input_widget = CustomTextComboBox(self) - combo_delegate = QtWidgets.QStyledItemDelegate(input_widget) - input_widget.setItemDelegate(combo_delegate) + if self.multiselection: + input_widget = MultiSelectionComboBox(self) + + else: + input_widget = CustomTextComboBox(self) + combo_delegate = QtWidgets.QStyledItemDelegate(input_widget) + input_widget.setItemDelegate(combo_delegate) + self._combo_delegate = combo_delegate if self.attr_def.tooltip: input_widget.setToolTip(self.attr_def.tooltip) @@ -427,9 +437,11 @@ class EnumAttrWidget(_BaseAttrDefWidget): if idx >= 0: input_widget.setCurrentIndex(idx) - input_widget.currentIndexChanged.connect(self._on_value_change) + if self.multiselection: + input_widget.value_changed.connect(self._on_value_change) + else: + input_widget.currentIndexChanged.connect(self._on_value_change) - self._combo_delegate = combo_delegate self._input_widget = input_widget self.main_layout.addWidget(input_widget, 0) @@ -442,17 +454,40 @@ class EnumAttrWidget(_BaseAttrDefWidget): self.value_changed.emit(new_value, self.attr_def.id) def current_value(self): + if self.multiselection: + return self._input_widget.value() idx = self._input_widget.currentIndex() return self._input_widget.itemData(idx) def set_value(self, value, multivalue=False): if multivalue: - set_value = set(value) - if len(set_value) == 1: - multivalue = False - value = tuple(set_value)[0] + if self.multiselection: + _value = None + are_same = True + for v in value: + _v = set(v) + if _value is None: + _value = _v + elif not are_same or _value != _v: + _value |= _v + are_same = False + if _value is None: + _value = [] + else: + value = list(_value) + multivalue = not are_same + else: + set_value = set(value) + if len(set_value) == 1: + multivalue = False + value = tuple(set_value)[0] - if not multivalue: + if self.multiselection: + self._input_widget.blockSignals(True) + self._input_widget.set_value(value) + self._input_widget.blockSignals(False) + + elif not multivalue: idx = self._input_widget.findData(value) cur_idx = self._input_widget.currentIndex() if idx != cur_idx and idx >= 0: From 7ebec6b8bcd737b6d393d9a50b9f4744a2e841b0 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 30 Aug 2023 22:55:44 +0200 Subject: [PATCH 081/154] simplified few lines --- openpype/lib/attribute_definitions.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/openpype/lib/attribute_definitions.py b/openpype/lib/attribute_definitions.py index 0af701a93a..44aa8dee48 100644 --- a/openpype/lib/attribute_definitions.py +++ b/openpype/lib/attribute_definitions.py @@ -445,18 +445,19 @@ class EnumDef(AbstractAttrDef): items = self.prepare_enum_items(items) item_values = [item["value"] for item in items] - if multiselection and default is None: - default = [] + item_values_set = set(item_values) + if multiselection: + if default is None: + default = [] + default = list(item_values_set.intersection(default)) - if not multiselection and default not in item_values: - for value in item_values: - default = value - break + elif default not in item_values: + default = next(iter(item_values), None) super(EnumDef, self).__init__(key, default=default, **kwargs) self.items = items - self._item_values = set(item_values) + self._item_values = item_values_set self.multiselection = multiselection def __eq__(self, other): @@ -476,9 +477,7 @@ class EnumDef(AbstractAttrDef): if value is None: return copy.deepcopy(self.default) - new_value = set(value) - rem = new_value - self._item_values - return list(new_value - rem) + return list(self._item_values.intersection(value)) def serialize(self): From 8cf4c9c6515c7eb6d9db92c57d48a21acf3821f9 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 30 Aug 2023 23:03:45 +0200 Subject: [PATCH 082/154] move multiselection multivalue handling to separated method --- openpype/tools/attribute_defs/widgets.py | 28 ++++++++++++------------ 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/openpype/tools/attribute_defs/widgets.py b/openpype/tools/attribute_defs/widgets.py index e08ca17225..adb29dcbd3 100644 --- a/openpype/tools/attribute_defs/widgets.py +++ b/openpype/tools/attribute_defs/widgets.py @@ -459,23 +459,23 @@ class EnumAttrWidget(_BaseAttrDefWidget): idx = self._input_widget.currentIndex() return self._input_widget.itemData(idx) + def _multiselection_multivalue_prep(self, values): + final = None + are_same = True + for value in values: + value = set(value) + if final is None: + final = value + elif not are_same or final != value: + final |= value + are_same = False + return list(final), not are_same + def set_value(self, value, multivalue=False): if multivalue: if self.multiselection: - _value = None - are_same = True - for v in value: - _v = set(v) - if _value is None: - _value = _v - elif not are_same or _value != _v: - _value |= _v - are_same = False - if _value is None: - _value = [] - else: - value = list(_value) - multivalue = not are_same + value, multivalue = self._multiselection_multivalue_prep( + value) else: set_value = set(value) if len(set_value) == 1: From 5b4bdeb6259dc5bd69ec773ba717a1efad17a695 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 30 Aug 2023 23:14:54 +0200 Subject: [PATCH 083/154] avoid unnecessary negative checks --- openpype/tools/attribute_defs/widgets.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openpype/tools/attribute_defs/widgets.py b/openpype/tools/attribute_defs/widgets.py index adb29dcbd3..d9c55f4a64 100644 --- a/openpype/tools/attribute_defs/widgets.py +++ b/openpype/tools/attribute_defs/widgets.py @@ -461,15 +461,15 @@ class EnumAttrWidget(_BaseAttrDefWidget): def _multiselection_multivalue_prep(self, values): final = None - are_same = True + multivalue = False for value in values: value = set(value) if final is None: final = value - elif not are_same or final != value: + elif multivalue or final != value: final |= value - are_same = False - return list(final), not are_same + multivalue = True + return list(final), multivalue def set_value(self, value, multivalue=False): if multivalue: From 055e8250007731c3ac516ae7dbee7736629d393b Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 31 Aug 2023 15:41:33 +0800 Subject: [PATCH 084/154] bigroy comment on the camera setup on validation --- openpype/hosts/max/plugins/publish/collect_render.py | 3 +++ .../max/plugins/publish/validate_viewport_camera.py | 12 +++++------- .../deadline/plugins/publish/submit_max_deadline.py | 8 ++++++-- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/openpype/hosts/max/plugins/publish/collect_render.py b/openpype/hosts/max/plugins/publish/collect_render.py index db5c84fad9..7df71799d3 100644 --- a/openpype/hosts/max/plugins/publish/collect_render.py +++ b/openpype/hosts/max/plugins/publish/collect_render.py @@ -34,6 +34,9 @@ class CollectRender(pyblish.api.InstancePlugin): aovs = RenderProducts().get_aovs(instance.name) files_by_aov.update(aovs) + camera = rt.viewport.GetCamera() + instance.data["cameras"] = [camera.name] or None + if "expectedFiles" not in instance.data: instance.data["expectedFiles"] = list() instance.data["files"] = list() diff --git a/openpype/hosts/max/plugins/publish/validate_viewport_camera.py b/openpype/hosts/max/plugins/publish/validate_viewport_camera.py index b35ba482a9..533b55f969 100644 --- a/openpype/hosts/max/plugins/publish/validate_viewport_camera.py +++ b/openpype/hosts/max/plugins/publish/validate_viewport_camera.py @@ -13,8 +13,7 @@ class ValidateViewportCamera(pyblish.api.InstancePlugin, OptionalPyblishPluginMixin): """Validates Viewport Camera - Check if the renderable camera in scene used as viewport - camera for rendering + Check if the renderable camera used for rendering """ order = pyblish.api.ValidatorOrder @@ -27,11 +26,9 @@ class ValidateViewportCamera(pyblish.api.InstancePlugin, def process(self, instance): if not self.is_active(instance.data): return - cameras_in_scene = [c for c in rt.Objects - if rt.classOf(c) in rt.Camera.Classes] - if rt.viewport.getCamera() not in cameras_in_scene: + if not instance.data["cameras"]: raise PublishValidationError( - "Cameras in Scene not used as viewport camera" + "No renderable Camera found in scene." ) @classmethod @@ -39,10 +36,11 @@ class ValidateViewportCamera(pyblish.api.InstancePlugin, rt.viewport.setType(rt.Name("view_camera")) camera = rt.viewport.GetCamera() - cls.log.info(f"Camera {camera} set as viewport camera") + cls.log.info(f"Camera {camera} set as renderable camera") renderer_class = get_current_renderer() renderer = str(renderer_class).split(":")[0] if renderer == "Arnold": arv = rt.MAXToAOps.ArnoldRenderView() arv.setOption("Camera", str(camera)) arv.close() + instance.data["cameras"] = [camera.name] diff --git a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py index d8725e853c..6b42270d05 100644 --- a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py @@ -31,6 +31,7 @@ class MaxPluginInfo(object): Version = attr.ib(default=None) # Mandatory for Deadline SaveFile = attr.ib(default=True) IgnoreInputs = attr.ib(default=True) + Camera = attr.ib(default=None) class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, @@ -154,7 +155,8 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, SceneFile=self.scene_path, Version=instance.data["maxversion"], SaveFile=True, - IgnoreInputs=True + IgnoreInputs=True, + Camera=instance.data["cameras"][0] ) plugin_payload = attr.asdict(plugin_info) @@ -238,7 +240,9 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, if renderer == "Redshift_Renderer": plugin_data["redshift_SeparateAovFiles"] = instance.data.get( "separateAovFiles") - + if instance.data["cameras"]: + plugin_info["Camera0"] = None + plugin_info["Camera1"] = instance.data["cameras"][0] self.log.debug("plugin data:{}".format(plugin_data)) plugin_info.update(plugin_data) From 72d7a9191baca344498f6c686c44adaf0d570f26 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 31 Aug 2023 16:00:22 +0800 Subject: [PATCH 085/154] bug fix the camera instance data collection --- openpype/hosts/max/plugins/publish/collect_render.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/max/plugins/publish/collect_render.py b/openpype/hosts/max/plugins/publish/collect_render.py index 7df71799d3..e7730369b6 100644 --- a/openpype/hosts/max/plugins/publish/collect_render.py +++ b/openpype/hosts/max/plugins/publish/collect_render.py @@ -35,7 +35,9 @@ class CollectRender(pyblish.api.InstancePlugin): files_by_aov.update(aovs) camera = rt.viewport.GetCamera() - instance.data["cameras"] = [camera.name] or None + instance.data["cameras"] = None + if camera: + instance.data["cameras"] = [camera.name] if "expectedFiles" not in instance.data: instance.data["expectedFiles"] = list() From b9fb4ce9e9669cfd6773fde30139243e77981a3c Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 31 Aug 2023 16:05:02 +0800 Subject: [PATCH 086/154] rename the validator --- .../publish/validate_renderable_camera.py | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 openpype/hosts/max/plugins/publish/validate_renderable_camera.py diff --git a/openpype/hosts/max/plugins/publish/validate_renderable_camera.py b/openpype/hosts/max/plugins/publish/validate_renderable_camera.py new file mode 100644 index 0000000000..61321661b5 --- /dev/null +++ b/openpype/hosts/max/plugins/publish/validate_renderable_camera.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +import pyblish.api +from openpype.pipeline import ( + PublishValidationError, + OptionalPyblishPluginMixin) +from openpype.pipeline.publish import RepairAction +from openpype.hosts.max.api.lib import get_current_renderer + +from pymxs import runtime as rt + + +class ValidateRenderableCamera(pyblish.api.InstancePlugin, + OptionalPyblishPluginMixin): + """Validates Renderable Camera + + Check if the renderable camera used for rendering + """ + + order = pyblish.api.ValidatorOrder + families = ["maxrender"] + hosts = ["max"] + label = "Renderable Camera" + optional = True + actions = [RepairAction] + + def process(self, instance): + if not self.is_active(instance.data): + return + if not instance.data["cameras"]: + raise PublishValidationError( + "No renderable Camera found in scene." + ) + + @classmethod + def repair(cls, instance): + + rt.viewport.setType(rt.Name("view_camera")) + camera = rt.viewport.GetCamera() + cls.log.info(f"Camera {camera} set as renderable camera") + renderer_class = get_current_renderer() + renderer = str(renderer_class).split(":")[0] + if renderer == "Arnold": + arv = rt.MAXToAOps.ArnoldRenderView() + arv.setOption("Camera", str(camera)) + arv.close() + instance.data["cameras"] = [camera.name] From 4e88f705ee67af7ba1c0a6e920288759be006fd5 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 31 Aug 2023 16:12:36 +0800 Subject: [PATCH 087/154] remove the duplicated validator --- .../publish/validate_viewport_camera.py | 46 ------------------- 1 file changed, 46 deletions(-) delete mode 100644 openpype/hosts/max/plugins/publish/validate_viewport_camera.py diff --git a/openpype/hosts/max/plugins/publish/validate_viewport_camera.py b/openpype/hosts/max/plugins/publish/validate_viewport_camera.py deleted file mode 100644 index 533b55f969..0000000000 --- a/openpype/hosts/max/plugins/publish/validate_viewport_camera.py +++ /dev/null @@ -1,46 +0,0 @@ -# -*- coding: utf-8 -*- -import pyblish.api -from openpype.pipeline import ( - PublishValidationError, - OptionalPyblishPluginMixin) -from openpype.pipeline.publish import RepairAction -from openpype.hosts.max.api.lib import get_current_renderer - -from pymxs import runtime as rt - - -class ValidateViewportCamera(pyblish.api.InstancePlugin, - OptionalPyblishPluginMixin): - """Validates Viewport Camera - - Check if the renderable camera used for rendering - """ - - order = pyblish.api.ValidatorOrder - families = ["maxrender"] - hosts = ["max"] - label = "Viewport Camera" - optional = True - actions = [RepairAction] - - def process(self, instance): - if not self.is_active(instance.data): - return - if not instance.data["cameras"]: - raise PublishValidationError( - "No renderable Camera found in scene." - ) - - @classmethod - def repair(cls, instance): - - rt.viewport.setType(rt.Name("view_camera")) - camera = rt.viewport.GetCamera() - cls.log.info(f"Camera {camera} set as renderable camera") - renderer_class = get_current_renderer() - renderer = str(renderer_class).split(":")[0] - if renderer == "Arnold": - arv = rt.MAXToAOps.ArnoldRenderView() - arv.setOption("Camera", str(camera)) - arv.close() - instance.data["cameras"] = [camera.name] From 5685e2a1681d2ea74ac481bfa31de6f0a370d55f Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 31 Aug 2023 16:48:52 +0800 Subject: [PATCH 088/154] introduce imprint function for correct version in hda loader --- openpype/hosts/houdini/plugins/load/load_hda.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openpype/hosts/houdini/plugins/load/load_hda.py b/openpype/hosts/houdini/plugins/load/load_hda.py index 57edc341a3..9630716253 100644 --- a/openpype/hosts/houdini/plugins/load/load_hda.py +++ b/openpype/hosts/houdini/plugins/load/load_hda.py @@ -59,6 +59,9 @@ class HdaLoader(load.LoaderPlugin): def_paths = [d.libraryFilePath() for d in defs] new = def_paths.index(file_path) defs[new].setIsPreferred(True) + hda_node.setParms({ + "representation": str(representation["_id"]) + }) def remove(self, container): node = container["node"] From f6c2be8b2a57559418077a68054e9ae3dfdbd76e Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Thu, 31 Aug 2023 11:15:37 +0200 Subject: [PATCH 089/154] force repaint --- openpype/tools/utils/multiselection_combobox.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openpype/tools/utils/multiselection_combobox.py b/openpype/tools/utils/multiselection_combobox.py index 27576a449a..13b396a059 100644 --- a/openpype/tools/utils/multiselection_combobox.py +++ b/openpype/tools/utils/multiselection_combobox.py @@ -266,12 +266,14 @@ class MultiSelectionComboBox(QtWidgets.QComboBox): def _update_size_hint(self): if self._custom_text is not None: self.update() + self.repaint() return self._lines = {} items = self.checked_items_text() if not items: self.update() + self.repaint() return option = QtWidgets.QStyleOptionComboBox() @@ -311,6 +313,7 @@ class MultiSelectionComboBox(QtWidgets.QComboBox): self.update() self.updateGeometry() + self.repaint() def sizeHint(self): value = super(MultiSelectionComboBox, self).sizeHint() From b412e221646b56b57a911f9bab312756d360f640 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Thu, 31 Aug 2023 11:17:25 +0200 Subject: [PATCH 090/154] remove multiselection combobox from settings --- .../tools/settings/settings/item_widgets.py | 2 +- .../settings/multiselection_combobox.py | 356 ------------------ 2 files changed, 1 insertion(+), 357 deletions(-) delete mode 100644 openpype/tools/settings/settings/multiselection_combobox.py diff --git a/openpype/tools/settings/settings/item_widgets.py b/openpype/tools/settings/settings/item_widgets.py index 117eca7d6b..2fd13cbbd8 100644 --- a/openpype/tools/settings/settings/item_widgets.py +++ b/openpype/tools/settings/settings/item_widgets.py @@ -4,6 +4,7 @@ from qtpy import QtWidgets, QtCore, QtGui from openpype.widgets.sliders import NiceSlider from openpype.tools.settings import CHILD_OFFSET +from openpype.tools.utils import MultiSelectionComboBox from openpype.settings.entities.exceptions import BaseInvalidValue from .widgets import ( @@ -15,7 +16,6 @@ from .widgets import ( SettingsNiceCheckbox, SettingsLineEdit ) -from .multiselection_combobox import MultiSelectionComboBox from .wrapper_widgets import ( WrapperWidget, CollapsibleWrapper, diff --git a/openpype/tools/settings/settings/multiselection_combobox.py b/openpype/tools/settings/settings/multiselection_combobox.py deleted file mode 100644 index d64fc83745..0000000000 --- a/openpype/tools/settings/settings/multiselection_combobox.py +++ /dev/null @@ -1,356 +0,0 @@ -from qtpy import QtCore, QtGui, QtWidgets -from openpype.tools.utils.lib import ( - checkstate_int_to_enum, - checkstate_enum_to_int, -) -from openpype.tools.utils.constants import ( - CHECKED_INT, - UNCHECKED_INT, - ITEM_IS_USER_TRISTATE, -) - - -class ComboItemDelegate(QtWidgets.QStyledItemDelegate): - """ - Helper styled delegate (mostly based on existing private Qt's - delegate used by the QtWidgets.QComboBox). Used to style the popup like a - list view (e.g windows style). - """ - - def paint(self, painter, option, index): - option = QtWidgets.QStyleOptionViewItem(option) - option.showDecorationSelected = True - - # option.state &= ( - # ~QtWidgets.QStyle.State_HasFocus - # & ~QtWidgets.QStyle.State_MouseOver - # ) - super(ComboItemDelegate, self).paint(painter, option, index) - - -class MultiSelectionComboBox(QtWidgets.QComboBox): - value_changed = QtCore.Signal() - focused_in = QtCore.Signal() - - ignored_keys = { - QtCore.Qt.Key_Up, - QtCore.Qt.Key_Down, - QtCore.Qt.Key_PageDown, - QtCore.Qt.Key_PageUp, - QtCore.Qt.Key_Home, - QtCore.Qt.Key_End, - } - - top_bottom_padding = 2 - left_right_padding = 3 - left_offset = 4 - top_bottom_margins = 2 - item_spacing = 5 - - item_bg_color = QtGui.QColor("#31424e") - - def __init__( - self, parent=None, placeholder="", separator=", ", **kwargs - ): - super(MultiSelectionComboBox, self).__init__(parent=parent, **kwargs) - self.setObjectName("MultiSelectionComboBox") - self.setFocusPolicy(QtCore.Qt.StrongFocus) - - self._popup_is_shown = False - self._block_mouse_release_timer = QtCore.QTimer(self, singleShot=True) - self._initial_mouse_pos = None - self._separator = separator - self.placeholder_text = placeholder - self.delegate = ComboItemDelegate(self) - self.setItemDelegate(self.delegate) - - self.lines = {} - self.item_height = None - - def focusInEvent(self, event): - self.focused_in.emit() - return super(MultiSelectionComboBox, self).focusInEvent(event) - - def mousePressEvent(self, event): - """Reimplemented.""" - self._popup_is_shown = False - super(MultiSelectionComboBox, self).mousePressEvent(event) - if self._popup_is_shown: - self._initial_mouse_pos = self.mapToGlobal(event.pos()) - self._block_mouse_release_timer.start( - QtWidgets.QApplication.doubleClickInterval() - ) - - def showPopup(self): - """Reimplemented.""" - super(MultiSelectionComboBox, self).showPopup() - view = self.view() - view.installEventFilter(self) - view.viewport().installEventFilter(self) - self._popup_is_shown = True - - def hidePopup(self): - """Reimplemented.""" - self.view().removeEventFilter(self) - self.view().viewport().removeEventFilter(self) - self._popup_is_shown = False - self._initial_mouse_pos = None - super(MultiSelectionComboBox, self).hidePopup() - self.view().clearFocus() - - def _event_popup_shown(self, obj, event): - if not self._popup_is_shown: - return - - current_index = self.view().currentIndex() - model = self.model() - - if event.type() == QtCore.QEvent.MouseMove: - if ( - self.view().isVisible() - and self._initial_mouse_pos is not None - and self._block_mouse_release_timer.isActive() - ): - diff = obj.mapToGlobal(event.pos()) - self._initial_mouse_pos - if diff.manhattanLength() > 9: - self._block_mouse_release_timer.stop() - return - - index_flags = current_index.flags() - state = checkstate_int_to_enum( - current_index.data(QtCore.Qt.CheckStateRole) - ) - new_state = None - - if event.type() == QtCore.QEvent.MouseButtonRelease: - if ( - self._block_mouse_release_timer.isActive() - or not current_index.isValid() - or not self.view().isVisible() - or not self.view().rect().contains(event.pos()) - or not index_flags & QtCore.Qt.ItemIsSelectable - or not index_flags & QtCore.Qt.ItemIsEnabled - or not index_flags & QtCore.Qt.ItemIsUserCheckable - ): - return - - if state == QtCore.Qt.Unchecked: - new_state = CHECKED_INT - else: - new_state = UNCHECKED_INT - - elif event.type() == QtCore.QEvent.KeyPress: - # TODO: handle QtCore.Qt.Key_Enter, Key_Return? - if event.key() == QtCore.Qt.Key_Space: - if ( - index_flags & QtCore.Qt.ItemIsUserCheckable - and index_flags & ITEM_IS_USER_TRISTATE - ): - new_state = (checkstate_enum_to_int(state) + 1) % 3 - - elif index_flags & QtCore.Qt.ItemIsUserCheckable: - # toggle the current items check state - if state != QtCore.Qt.Checked: - new_state = CHECKED_INT - else: - new_state = UNCHECKED_INT - - if new_state is not None: - model.setData(current_index, new_state, QtCore.Qt.CheckStateRole) - self.view().update(current_index) - self.update_size_hint() - self.value_changed.emit() - return True - - def eventFilter(self, obj, event): - """Reimplemented.""" - result = self._event_popup_shown(obj, event) - if result is not None: - return result - - return super(MultiSelectionComboBox, self).eventFilter(obj, event) - - def addItem(self, *args, **kwargs): - idx = self.count() - super(MultiSelectionComboBox, self).addItem(*args, **kwargs) - self.model().item(idx).setCheckable(True) - - def paintEvent(self, event): - """Reimplemented.""" - painter = QtWidgets.QStylePainter(self) - option = QtWidgets.QStyleOptionComboBox() - self.initStyleOption(option) - painter.drawComplexControl(QtWidgets.QStyle.CC_ComboBox, option) - - # draw the icon and text - items = self.checked_items_text() - if not items: - option.currentText = self.placeholder_text - option.palette.setCurrentColorGroup(QtGui.QPalette.Disabled) - painter.drawControl(QtWidgets.QStyle.CE_ComboBoxLabel, option) - return - - font_metricts = self.fontMetrics() - - if self.item_height is None: - self.updateGeometry() - self.update() - return - - for line, items in self.lines.items(): - top_y = ( - option.rect.top() - + (line * self.item_height) - + self.top_bottom_margins - ) - left_x = option.rect.left() + self.left_offset - for item in items: - label_rect = font_metricts.boundingRect(item) - label_height = label_rect.height() - - label_rect.moveTop(top_y) - label_rect.moveLeft(left_x) - label_rect.setHeight(self.item_height) - label_rect.setWidth( - label_rect.width() + self.left_right_padding - ) - - bg_rect = QtCore.QRectF(label_rect) - bg_rect.setWidth( - label_rect.width() + self.left_right_padding - ) - left_x = bg_rect.right() + self.item_spacing - - label_rect.moveLeft(label_rect.x() + self.left_right_padding) - - bg_rect.setHeight(label_height + (2 * self.top_bottom_padding)) - bg_rect.moveTop(bg_rect.top() + self.top_bottom_margins) - - path = QtGui.QPainterPath() - path.addRoundedRect(bg_rect, 5, 5) - - painter.fillPath(path, self.item_bg_color) - - painter.drawText( - label_rect, - QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter, - item - ) - - def resizeEvent(self, *args, **kwargs): - super(MultiSelectionComboBox, self).resizeEvent(*args, **kwargs) - self.update_size_hint() - - def update_size_hint(self): - self.lines = {} - - items = self.checked_items_text() - if not items: - self.update() - return - - option = QtWidgets.QStyleOptionComboBox() - self.initStyleOption(option) - btn_rect = self.style().subControlRect( - QtWidgets.QStyle.CC_ComboBox, - option, - QtWidgets.QStyle.SC_ComboBoxArrow - ) - total_width = option.rect.width() - btn_rect.width() - - line = 0 - self.lines = {line: []} - - font_metricts = self.fontMetrics() - default_left_x = 0 + self.left_offset - left_x = int(default_left_x) - for item in items: - rect = font_metricts.boundingRect(item) - width = rect.width() + (2 * self.left_right_padding) - right_x = left_x + width - if right_x > total_width: - left_x = int(default_left_x) - if self.lines.get(line): - line += 1 - self.lines[line] = [item] - left_x += width - else: - self.lines[line] = [item] - line += 1 - else: - if line in self.lines: - self.lines[line].append(item) - else: - self.lines[line] = [item] - left_x = left_x + width + self.item_spacing - - self.update() - self.updateGeometry() - - def sizeHint(self): - value = super(MultiSelectionComboBox, self).sizeHint() - lines = len(self.lines) - if lines == 0: - lines = 1 - - if self.item_height is None: - self.item_height = ( - self.fontMetrics().height() - + (2 * self.top_bottom_padding) - + (2 * self.top_bottom_margins) - ) - value.setHeight( - (lines * self.item_height) - + (2 * self.top_bottom_margins) - ) - return value - - def setItemCheckState(self, index, state): - self.setItemData(index, state, QtCore.Qt.CheckStateRole) - - def set_value(self, values): - for idx in range(self.count()): - value = self.itemData(idx, role=QtCore.Qt.UserRole) - if value in values: - check_state = CHECKED_INT - else: - check_state = UNCHECKED_INT - self.setItemData(idx, check_state, QtCore.Qt.CheckStateRole) - self.update_size_hint() - - def value(self): - items = list() - for idx in range(self.count()): - state = checkstate_int_to_enum( - self.itemData(idx, role=QtCore.Qt.CheckStateRole) - ) - if state == QtCore.Qt.Checked: - items.append( - self.itemData(idx, role=QtCore.Qt.UserRole) - ) - return items - - def checked_items_text(self): - items = list() - for idx in range(self.count()): - state = checkstate_int_to_enum( - self.itemData(idx, role=QtCore.Qt.CheckStateRole) - ) - if state == QtCore.Qt.Checked: - items.append(self.itemText(idx)) - return items - - def wheelEvent(self, event): - event.ignore() - - def keyPressEvent(self, event): - if ( - event.key() == QtCore.Qt.Key_Down - and event.modifiers() & QtCore.Qt.AltModifier - ): - return self.showPopup() - - if event.key() in self.ignored_keys: - return event.ignore() - - return super(MultiSelectionComboBox, self).keyPressEvent(event) From cbc622c46f52fb784c6dc8c49d37c3b3d65f0c85 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Thu, 31 Aug 2023 11:23:38 +0200 Subject: [PATCH 091/154] update docstrings --- openpype/lib/attribute_definitions.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/openpype/lib/attribute_definitions.py b/openpype/lib/attribute_definitions.py index 44aa8dee48..a71709cace 100644 --- a/openpype/lib/attribute_definitions.py +++ b/openpype/lib/attribute_definitions.py @@ -427,9 +427,12 @@ class EnumDef(AbstractAttrDef): """Enumeration of single item from items. Args: - items: Items definition that can be converted using - 'prepare_enum_items'. - default: Default value. Must be one key(value) from passed items. + items (Union[list[str], list[dict[str, Any]]): Items definition that + can be converted using 'prepare_enum_items'. + default (Optional[Any]): Default value. Must be one key(value) from + passed items or list of values for multiselection. + multiselection (Optional[bool]): If True, multiselection is allowed. + Output is list of selected items. """ type = "enum" From d3c1b84835aed4579ef7909e52631ab0732d6796 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 31 Aug 2023 12:07:23 +0200 Subject: [PATCH 092/154] fixing paths slashes in nuke api --- openpype/hosts/nuke/api/lib.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py index 2a6c1fb12c..d6a5e67ba0 100644 --- a/openpype/hosts/nuke/api/lib.py +++ b/openpype/hosts/nuke/api/lib.py @@ -2107,8 +2107,9 @@ class WorkfileSettings(object): # set ocio config path if config_data: + config_path = config_data["path"].replace("\\", "/") log.info("OCIO config path found: `{}`".format( - config_data["path"])) + config_path)) # check if there's a mismatch between environment and settings correct_settings = self._is_settings_matching_environment( @@ -2233,7 +2234,7 @@ Reopening Nuke should synchronize these paths and resolve any discrepancies. Returns: str: OCIO config path with environment variable TCL expression """ - config_path = config_data["path"] + config_path = config_data["path"].replace("\\", "/") config_template = config_data["template"] included_vars = self._get_included_vars(config_template) From e9c3a84916a87ef8df717b4f75b698f55b7cd5dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Je=C5=BEek?= Date: Thu, 31 Aug 2023 12:11:22 +0200 Subject: [PATCH 093/154] Update openpype/hosts/nuke/api/lib.py Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- openpype/hosts/nuke/api/lib.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py index cedbe6d5e6..157300d150 100644 --- a/openpype/hosts/nuke/api/lib.py +++ b/openpype/hosts/nuke/api/lib.py @@ -3371,10 +3371,9 @@ def create_viewer_profile_string(viewer, display=None, path_like=False): Returns: str: viewer config string """ - if display: - if path_like: - return "{}/{}".format(display, viewer) - else: - return "{} ({})".format(viewer, display) - else: + if not display: return viewer + + if path_like: + return "{}/{}".format(display, viewer) + return "{} ({})".format(viewer, display) From 33e18661241a59a612a06558fbc19f5de264220b Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 31 Aug 2023 13:30:33 +0200 Subject: [PATCH 094/154] separating code into own function for monitor lut settings --- openpype/hosts/nuke/api/lib.py | 64 ++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 22 deletions(-) diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py index 157300d150..95e945057c 100644 --- a/openpype/hosts/nuke/api/lib.py +++ b/openpype/hosts/nuke/api/lib.py @@ -2092,30 +2092,14 @@ class WorkfileSettings(object): workfile_settings.pop("colorManagement", None) workfile_settings.pop("OCIO_config", None) - # treat monitor lut separately + # get monitor lut from settings respecting Nuke version differences monitor_lut = workfile_settings.pop("monitorLut", None) - m_display, m_viewer = get_viewer_config_from_string(monitor_lut) - v_display, v_viewer = get_viewer_config_from_string( - viewer_process_settings - ) + monitor_lut_data = self._get_monitor_settings( + viewer_process_settings, monitor_lut) - # set monitor lut differently for nuke version 14 - if nuke.NUKE_VERSION_MAJOR >= 14: - workfile_settings["monitorOutLUT"] = create_viewer_profile_string( - m_viewer, m_display, path_like=False) - # monitorLut=thumbnails - viewerProcess makes more sense - workfile_settings["monitorLut"] = create_viewer_profile_string( - v_viewer, v_display, path_like=False) - - if nuke.NUKE_VERSION_MAJOR == 13: - workfile_settings["monitorOutLUT"] = create_viewer_profile_string( - m_viewer, m_display, path_like=False) - # monitorLut=thumbnails - viewerProcess makes more sense - workfile_settings["monitorLut"] = create_viewer_profile_string( - v_viewer, v_display, path_like=True) - if nuke.NUKE_VERSION_MAJOR <= 12: - workfile_settings["monitorLut"] = create_viewer_profile_string( - m_viewer, m_display, path_like=True) + # set monitor related knobs luts (MonitorOut, Thumbnails) + for knob, value_ in monitor_lut_data.items(): + workfile_settings[knob] = value_ # then set the rest for knob, value_ in workfile_settings.items(): @@ -2144,6 +2128,42 @@ class WorkfileSettings(object): if correct_settings: self._set_ocio_config_path_to_workfile(config_data) + def _get_monitor_settings(self, viewer_lut, monitor_lut): + """ Get monitor settings from viewer and monitor lut + + Args: + viewer_lut (str): viewer lut string + monitor_lut (str): monitor lut string + + Returns: + dict: monitor settings + """ + output_data = {} + m_display, m_viewer = get_viewer_config_from_string(monitor_lut) + v_display, v_viewer = get_viewer_config_from_string( + viewer_lut + ) + + # set monitor lut differently for nuke version 14 + if nuke.NUKE_VERSION_MAJOR >= 14: + output_data["monitorOutLUT"] = create_viewer_profile_string( + m_viewer, m_display, path_like=False) + # monitorLut=thumbnails - viewerProcess makes more sense + output_data["monitorLut"] = create_viewer_profile_string( + v_viewer, v_display, path_like=False) + + if nuke.NUKE_VERSION_MAJOR == 13: + output_data["monitorOutLUT"] = create_viewer_profile_string( + m_viewer, m_display, path_like=False) + # monitorLut=thumbnails - viewerProcess makes more sense + output_data["monitorLut"] = create_viewer_profile_string( + v_viewer, v_display, path_like=True) + if nuke.NUKE_VERSION_MAJOR <= 12: + output_data["monitorLut"] = create_viewer_profile_string( + m_viewer, m_display, path_like=True) + + return output_data + def _is_settings_matching_environment(self, config_data): """ Check if OCIO config path is different from environment From 82b50dcfc2698e60b1ffb45723a4112a0865f8e4 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 31 Aug 2023 14:00:13 +0200 Subject: [PATCH 095/154] adding comments --- .../plugins/publish/validate_rendered_frames.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/nuke/plugins/publish/validate_rendered_frames.py b/openpype/hosts/nuke/plugins/publish/validate_rendered_frames.py index ef3d4d0bb5..e316c6ff6e 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_rendered_frames.py +++ b/openpype/hosts/nuke/plugins/publish/validate_rendered_frames.py @@ -17,18 +17,23 @@ class RepairActionBase(pyblish.api.Action): def repair_knob(self, context, instances, state): create_context = context.data["create_context"] for instance in instances: - files_remove = [ + files_to_remove = [ + # create full path to file os.path.join(instance.data["outputDir"], f_) + # iterate representations from instance data for r_ in instance.data.get("representations", []) + # make sure that the representation has files in list + if r_.get("files") and isinstance(r_.get("files"), list) + # iterate files from representation files list for f_ in r_.get("files", []) ] - self.log.info("Files to be removed: {}".format(files_remove)) - for f_ in files_remove: + self.log.info("Files to be removed: {}".format(files_to_remove)) + for f_ in files_to_remove: os.remove(f_) self.log.debug("removing file: {}".format(f_)) # Reset the render knob - instance_id = instance.data["instance_id"] + instance_id = instance.data.get("instance_id") created_instance = create_context.get_instance_by_id( instance_id ) From 4d94bec464349db6e5277ae9d9615f15bf73e991 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 31 Aug 2023 22:55:59 +0800 Subject: [PATCH 096/154] oscar's comment on cameras implemenetation --- openpype/hosts/max/plugins/publish/collect_render.py | 4 +--- .../modules/deadline/plugins/publish/submit_max_deadline.py | 5 ++--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/max/plugins/publish/collect_render.py b/openpype/hosts/max/plugins/publish/collect_render.py index e7730369b6..8ee2f43103 100644 --- a/openpype/hosts/max/plugins/publish/collect_render.py +++ b/openpype/hosts/max/plugins/publish/collect_render.py @@ -35,9 +35,7 @@ class CollectRender(pyblish.api.InstancePlugin): files_by_aov.update(aovs) camera = rt.viewport.GetCamera() - instance.data["cameras"] = None - if camera: - instance.data["cameras"] = [camera.name] + instance.data["cameras"] = [camera.name] if camera else None # noqa if "expectedFiles" not in instance.data: instance.data["expectedFiles"] = list() diff --git a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py index 6b42270d05..01132662d4 100644 --- a/openpype/modules/deadline/plugins/publish/submit_max_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_max_deadline.py @@ -31,7 +31,6 @@ class MaxPluginInfo(object): Version = attr.ib(default=None) # Mandatory for Deadline SaveFile = attr.ib(default=True) IgnoreInputs = attr.ib(default=True) - Camera = attr.ib(default=None) class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, @@ -155,8 +154,7 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, SceneFile=self.scene_path, Version=instance.data["maxversion"], SaveFile=True, - IgnoreInputs=True, - Camera=instance.data["cameras"][0] + IgnoreInputs=True ) plugin_payload = attr.asdict(plugin_info) @@ -242,6 +240,7 @@ class MaxSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, "separateAovFiles") if instance.data["cameras"]: plugin_info["Camera0"] = None + plugin_info["Camera"] = instance.data["cameras"][0] plugin_info["Camera1"] = instance.data["cameras"][0] self.log.debug("plugin data:{}".format(plugin_data)) plugin_info.update(plugin_data) From e2e3bb3a68309c13e9f53fb5713baea6df6704dd Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 31 Aug 2023 17:23:38 +0200 Subject: [PATCH 097/154] AYON: Fill entities during editorial (2) (#5549) * fix appending of instances by asset name * skip disabled instances * formatting fix --- openpype/plugins/publish/extract_hierarchy_to_ayon.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openpype/plugins/publish/extract_hierarchy_to_ayon.py b/openpype/plugins/publish/extract_hierarchy_to_ayon.py index de9a70c233..36a7042ba5 100644 --- a/openpype/plugins/publish/extract_hierarchy_to_ayon.py +++ b/openpype/plugins/publish/extract_hierarchy_to_ayon.py @@ -42,13 +42,16 @@ class ExtractHierarchyToAYON(pyblish.api.ContextPlugin): def _fill_instance_entities(self, context, project_name): instances_by_asset_name = collections.defaultdict(list) for instance in context: + if instance.data.get("publish") is False: + continue + instance_entity = instance.data.get("assetEntity") if instance_entity: continue # Skip if instance asset does not match instance_asset_name = instance.data.get("asset") - instances_by_asset_name[instance_asset_name] = instance + instances_by_asset_name[instance_asset_name].append(instance) project_doc = context.data["projectEntity"] asset_docs = get_assets( From cf8919dbc5336e29e121020a7506d70277386834 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 31 Aug 2023 17:24:52 +0200 Subject: [PATCH 098/154] AYON: Update settings (#5544) * added 3dsmax settings conversion * added conversion of reposition knobs * fixed matching defaults * updated core settings * updated aftereffects settings model --- openpype/settings/ayon_settings.py | 29 ++++++++++ .../server/settings/creator_plugins.py | 2 +- .../aftereffects/server/settings/main.py | 2 +- server_addon/aftereffects/server/version.py | 2 +- server_addon/core/server/settings/main.py | 53 +++++++++++++++++-- server_addon/core/server/version.py | 2 +- .../max/server/settings/render_settings.py | 2 +- server_addon/maya/server/settings/creators.py | 4 +- .../server/settings/simple_creators.py | 17 ++++++ 9 files changed, 104 insertions(+), 9 deletions(-) diff --git a/openpype/settings/ayon_settings.py b/openpype/settings/ayon_settings.py index 50abfe4839..9a4f0607e0 100644 --- a/openpype/settings/ayon_settings.py +++ b/openpype/settings/ayon_settings.py @@ -616,6 +616,23 @@ def _convert_maya_project_settings(ayon_settings, output): output["maya"] = ayon_maya +def _convert_3dsmax_project_settings(ayon_settings, output): + if "max" not in ayon_settings: + return + + ayon_max = ayon_settings["max"] + _convert_host_imageio(ayon_max) + if "PointCloud" in ayon_max: + point_cloud_attribute = ayon_max["PointCloud"]["attribute"] + new_point_cloud_attribute = { + item["name"]: item["value"] + for item in point_cloud_attribute + } + ayon_max["PointCloud"]["attribute"] = new_point_cloud_attribute + + output["max"] = ayon_max + + def _convert_nuke_knobs(knobs): new_knobs = [] for knob in knobs: @@ -737,6 +754,17 @@ def _convert_nuke_project_settings(ayon_settings, output): item_filter["subsets"] = item_filter.pop("product_names") item_filter["families"] = item_filter.pop("product_types") + reformat_nodes_config = item.get("reformat_nodes_config") or {} + reposition_nodes = reformat_nodes_config.get( + "reposition_nodes") or [] + + for reposition_node in reposition_nodes: + if "knobs" not in reposition_node: + continue + reposition_node["knobs"] = _convert_nuke_knobs( + reposition_node["knobs"] + ) + name = item.pop("name") new_review_data_outputs[name] = item ayon_publish["ExtractReviewDataMov"]["outputs"] = new_review_data_outputs @@ -1261,6 +1289,7 @@ def convert_project_settings(ayon_settings, default_settings): _convert_flame_project_settings(ayon_settings, output) _convert_fusion_project_settings(ayon_settings, output) _convert_maya_project_settings(ayon_settings, output) + _convert_3dsmax_project_settings(ayon_settings, output) _convert_nuke_project_settings(ayon_settings, output) _convert_hiero_project_settings(ayon_settings, output) _convert_photoshop_project_settings(ayon_settings, output) diff --git a/server_addon/aftereffects/server/settings/creator_plugins.py b/server_addon/aftereffects/server/settings/creator_plugins.py index ee52fadd40..9cb03b0b26 100644 --- a/server_addon/aftereffects/server/settings/creator_plugins.py +++ b/server_addon/aftereffects/server/settings/creator_plugins.py @@ -5,7 +5,7 @@ from ayon_server.settings import BaseSettingsModel class CreateRenderPlugin(BaseSettingsModel): mark_for_review: bool = Field(True, title="Review") - defaults: list[str] = Field( + default_variants: list[str] = Field( default_factory=list, title="Default Variants" ) diff --git a/server_addon/aftereffects/server/settings/main.py b/server_addon/aftereffects/server/settings/main.py index 04d2e51cc9..4edc46d259 100644 --- a/server_addon/aftereffects/server/settings/main.py +++ b/server_addon/aftereffects/server/settings/main.py @@ -40,7 +40,7 @@ DEFAULT_AFTEREFFECTS_SETTING = { "create": { "RenderCreator": { "mark_for_review": True, - "defaults": [ + "default_variants": [ "Main" ] } diff --git a/server_addon/aftereffects/server/version.py b/server_addon/aftereffects/server/version.py index a242f0e757..df0c92f1e2 100644 --- a/server_addon/aftereffects/server/version.py +++ b/server_addon/aftereffects/server/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring addon version.""" -__version__ = "0.1.1" +__version__ = "0.1.2" diff --git a/server_addon/core/server/settings/main.py b/server_addon/core/server/settings/main.py index d19d732e71..ca8f7e63ed 100644 --- a/server_addon/core/server/settings/main.py +++ b/server_addon/core/server/settings/main.py @@ -4,6 +4,7 @@ from ayon_server.settings import ( BaseSettingsModel, MultiplatformPathListModel, ensure_unique_names, + task_types_enum, ) from ayon_server.exceptions import BadRequestException @@ -38,13 +39,52 @@ class CoreImageIOConfigModel(BaseSettingsModel): class CoreImageIOBaseModel(BaseSettingsModel): activate_global_color_management: bool = Field( False, - title="Override global OCIO config" + title="Enable Color Management" ) ocio_config: CoreImageIOConfigModel = Field( - default_factory=CoreImageIOConfigModel, title="OCIO config" + default_factory=CoreImageIOConfigModel, + title="OCIO config" ) file_rules: CoreImageIOFileRulesModel = Field( - default_factory=CoreImageIOFileRulesModel, title="File Rules" + default_factory=CoreImageIOFileRulesModel, + title="File Rules" + ) + + +class VersionStartCategoryProfileModel(BaseSettingsModel): + _layout = "expanded" + host_names: list[str] = Field( + default_factory=list, + title="Host names" + ) + task_types: list[str] = Field( + default_factory=list, + title="Task types", + enum_resolver=task_types_enum + ) + task_names: list[str] = Field( + default_factory=list, + title="Task names" + ) + product_types: list[str] = Field( + default_factory=list, + title="Product types" + ) + product_names: list[str] = Field( + default_factory=list, + title="Product names" + ) + version_start: int = Field( + 1, + title="Version Start", + ge=0 + ) + + +class VersionStartCategoryModel(BaseSettingsModel): + profiles: list[VersionStartCategoryProfileModel] = Field( + default_factory=list, + title="Profiles" ) @@ -61,6 +101,10 @@ class CoreSettings(BaseSettingsModel): default_factory=GlobalToolsModel, title="Tools" ) + version_start_category: VersionStartCategoryModel = Field( + default_factory=VersionStartCategoryModel, + title="Version start" + ) imageio: CoreImageIOBaseModel = Field( default_factory=CoreImageIOBaseModel, title="Color Management (ImageIO)" @@ -131,6 +175,9 @@ DEFAULT_VALUES = { "studio_code": "", "environments": "{}", "tools": DEFAULT_TOOLS_VALUES, + "version_start_category": { + "profiles": [] + }, "publish": DEFAULT_PUBLISH_VALUES, "project_folder_structure": json.dumps({ "__project_root__": { diff --git a/server_addon/core/server/version.py b/server_addon/core/server/version.py index 485f44ac21..b3f4756216 100644 --- a/server_addon/core/server/version.py +++ b/server_addon/core/server/version.py @@ -1 +1 @@ -__version__ = "0.1.1" +__version__ = "0.1.2" diff --git a/server_addon/max/server/settings/render_settings.py b/server_addon/max/server/settings/render_settings.py index 6c236d9f12..c00cb5e436 100644 --- a/server_addon/max/server/settings/render_settings.py +++ b/server_addon/max/server/settings/render_settings.py @@ -44,6 +44,6 @@ class RenderSettingsModel(BaseSettingsModel): DEFAULT_RENDER_SETTINGS = { "default_render_image_folder": "renders/3dsmax", "aov_separator": "underscore", - "image_format": "png", + "image_format": "exr", "multipass": True } diff --git a/server_addon/maya/server/settings/creators.py b/server_addon/maya/server/settings/creators.py index 9b97b92e59..11e2b8a36c 100644 --- a/server_addon/maya/server/settings/creators.py +++ b/server_addon/maya/server/settings/creators.py @@ -252,7 +252,9 @@ DEFAULT_CREATORS_SETTINGS = { }, "CreateUnrealSkeletalMesh": { "enabled": True, - "default_variants": [], + "default_variants": [ + "Main", + ], "joint_hints": "jnt_org" }, "CreateMultiverseLook": { diff --git a/server_addon/traypublisher/server/settings/simple_creators.py b/server_addon/traypublisher/server/settings/simple_creators.py index 94d6602738..8335b9d34e 100644 --- a/server_addon/traypublisher/server/settings/simple_creators.py +++ b/server_addon/traypublisher/server/settings/simple_creators.py @@ -288,5 +288,22 @@ DEFAULT_SIMPLE_CREATORS = [ "allow_multiple_items": True, "allow_version_control": False, "extensions": [] + }, + { + "product_type": "audio", + "identifier": "", + "label": "Audio ", + "icon": "fa5s.file-audio", + "default_variants": [ + "Main" + ], + "description": "Audio product", + "detailed_description": "Audio files for review or final delivery", + "allow_sequences": False, + "allow_multiple_items": False, + "allow_version_control": False, + "extensions": [ + ".wav" + ] } ] From 13d1b407199e7012aa309a6072a405a2d35cf657 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Je=C5=BEek?= Date: Thu, 31 Aug 2023 17:38:47 +0200 Subject: [PATCH 099/154] Update openpype/hosts/nuke/api/lib.py Co-authored-by: Roy Nieterau --- openpype/hosts/nuke/api/lib.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py index 95e945057c..91a9294740 100644 --- a/openpype/hosts/nuke/api/lib.py +++ b/openpype/hosts/nuke/api/lib.py @@ -2140,9 +2140,7 @@ class WorkfileSettings(object): """ output_data = {} m_display, m_viewer = get_viewer_config_from_string(monitor_lut) - v_display, v_viewer = get_viewer_config_from_string( - viewer_lut - ) + v_display, v_viewer = get_viewer_config_from_string(viewer_lut) # set monitor lut differently for nuke version 14 if nuke.NUKE_VERSION_MAJOR >= 14: From 24cbaefe953589b39f681bf4b93cc992cbb9fa19 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 31 Aug 2023 22:29:18 +0200 Subject: [PATCH 100/154] removing redundant action it was residual approach from old workflow --- .../plugins/publish/validate_rendered_frames.py | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/openpype/hosts/nuke/plugins/publish/validate_rendered_frames.py b/openpype/hosts/nuke/plugins/publish/validate_rendered_frames.py index e316c6ff6e..9a35b61a0e 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_rendered_frames.py +++ b/openpype/hosts/nuke/plugins/publish/validate_rendered_frames.py @@ -17,29 +17,14 @@ class RepairActionBase(pyblish.api.Action): def repair_knob(self, context, instances, state): create_context = context.data["create_context"] for instance in instances: - files_to_remove = [ - # create full path to file - os.path.join(instance.data["outputDir"], f_) - # iterate representations from instance data - for r_ in instance.data.get("representations", []) - # make sure that the representation has files in list - if r_.get("files") and isinstance(r_.get("files"), list) - # iterate files from representation files list - for f_ in r_.get("files", []) - ] - self.log.info("Files to be removed: {}".format(files_to_remove)) - for f_ in files_to_remove: - os.remove(f_) - self.log.debug("removing file: {}".format(f_)) - # Reset the render knob instance_id = instance.data.get("instance_id") created_instance = create_context.get_instance_by_id( instance_id ) created_instance.creator_attributes["render_target"] = state - self.log.info("Rendering toggled to `{}`".format(state)) + create_context.save_changes() From ec8a0f49480c8359f6b501f73626d770c12fe931 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 31 Aug 2023 22:44:36 +0200 Subject: [PATCH 101/154] simplification of spaghetti code and improving logic --- .../plugins/publish/collect_farm_target.py | 40 +++++++------------ 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/openpype/plugins/publish/collect_farm_target.py b/openpype/plugins/publish/collect_farm_target.py index 78410835dd..adcd842b48 100644 --- a/openpype/plugins/publish/collect_farm_target.py +++ b/openpype/plugins/publish/collect_farm_target.py @@ -15,31 +15,21 @@ class CollectFarmTarget(pyblish.api.InstancePlugin): return context = instance.context - try: - deadline_module = context.data.get("openPypeModules")["deadline"] - if deadline_module.enabled: - instance.data["toBeRenderedOn"] = "deadline" - self.log.debug("Collected render target: deadline") - except AttributeError: - self.log.error("Cannot get OpenPype Deadline module.") - raise AssertionError("OpenPype Deadline module not found.") - try: - royalrender_module = \ - context.data.get("openPypeModules")["royalrender"] - if royalrender_module.enabled: - instance.data["toBeRenderedOn"] = "royalrender" - self.log.debug("Collected render target: royalrender") + farm_name = "" + op_modules = context.data.get("openPypeModules") - except AttributeError: - self.log.error("Cannot get OpenPype RoyalRender module.") - raise AssertionError("OpenPype RoyalRender module not found.") + for farm_renderer in ["deadline", "royalrender", "muster"]: + op_module = op_modules.get(farm_renderer, False) - try: - muster_module = context.data.get("openPypeModules")["muster"] - if muster_module.enabled: - instance.data["toBeRenderedOn"] = "muster" - self.log.debug("Collected render target: muster") - except AttributeError: - self.log.error("Cannot get OpenPype Muster module.") - raise AssertionError("OpenPype Muster module not found.") + if op_module and op_module.enabled: + farm_name = farm_renderer + elif not op_module: + self.log.error("Cannot get OpenPype {0} module.".format( + farm_renderer)) + + if farm_name: + self.log.debug("Collected render target: {0}".format(farm_name)) + instance.data["toBeRenderedOn"] = farm_name + else: + AssertionError("No OpenPype renderer module found") From 78b5ae149a89223cb2f5c8a59464510685a8d67a Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 1 Sep 2023 15:54:42 +0200 Subject: [PATCH 102/154] only project settings are passed by default to create plugin --- openpype/pipeline/create/context.py | 19 ++++++++++------- openpype/pipeline/create/creator_plugins.py | 23 ++++++++++++++------- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/openpype/pipeline/create/context.py b/openpype/pipeline/create/context.py index 3076efcde7..e0e2c09f96 100644 --- a/openpype/pipeline/create/context.py +++ b/openpype/pipeline/create/context.py @@ -16,6 +16,7 @@ from openpype.settings import ( get_system_settings, get_project_settings ) +from openpype.lib import is_func_signature_supported from openpype.lib.attribute_definitions import ( UnknownDef, serialize_attr_defs, @@ -1774,7 +1775,7 @@ class CreateContext: self.creator_discover_result = report for creator_class in report.plugins: if inspect.isabstract(creator_class): - self.log.info( + self.log.debug( "Skipping abstract Creator {}".format(str(creator_class)) ) continue @@ -1798,12 +1799,16 @@ class CreateContext: ).format(creator_class.host_name, self.host_name)) continue - creator = creator_class( - project_settings, - system_settings, - self, - self.headless - ) + if is_func_signature_supported( + creator_class, project_settings, self, self.headless + ): + creator = creator_class(project_settings, self, self.headless) + else: + # Backwards compatibility to pass system settings to creators + creator = creator_class( + project_settings, system_settings, self, self.headless + ) + if not creator.enabled: disabled_creators[creator_identifier] = creator continue diff --git a/openpype/pipeline/create/creator_plugins.py b/openpype/pipeline/create/creator_plugins.py index 38d6b6f465..a1a6a73236 100644 --- a/openpype/pipeline/create/creator_plugins.py +++ b/openpype/pipeline/create/creator_plugins.py @@ -10,7 +10,7 @@ from abc import ( import six from openpype.settings import get_system_settings, get_project_settings -from openpype.lib import Logger +from openpype.lib import Logger, is_func_signature_supported from openpype.pipeline.plugin_discover import ( discover, register_plugin, @@ -161,7 +161,6 @@ class BaseCreator: Args: project_settings (Dict[str, Any]): Project settings. - system_settings (Dict[str, Any]): System settings. create_context (CreateContext): Context which initialized creator. headless (bool): Running in headless mode. """ @@ -197,9 +196,7 @@ class BaseCreator: # QUESTION make this required? host_name = None - def __init__( - self, project_settings, system_settings, create_context, headless=False - ): + def __init__(self, project_settings, create_context, headless=False): # Reference to CreateContext self.create_context = create_context self.project_settings = project_settings @@ -208,10 +205,20 @@ class BaseCreator: # - we may use UI inside processing this attribute should be checked self.headless = headless - self.apply_settings(project_settings, system_settings) + if is_func_signature_supported( + self.apply_settings, project_settings + ): + self.apply_settings(project_settings) + else: + # Backwards compatibility for system settings + self.apply_settings(project_settings, {}) - def apply_settings(self, project_settings, system_settings): - """Method called on initialization of plugin to apply settings.""" + def apply_settings(self, project_settings): + """Method called on initialization of plugin to apply settings. + + Args: + project_settings (dict[str, Any]): Project settings. + """ pass From 1f6df907eb4934d471dcbad96b10d1c08566d5ca Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 1 Sep 2023 16:54:05 +0200 Subject: [PATCH 103/154] fixed typehints --- openpype/lib/python_module_tools.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/lib/python_module_tools.py b/openpype/lib/python_module_tools.py index a10263f991..bedf19562d 100644 --- a/openpype/lib/python_module_tools.py +++ b/openpype/lib/python_module_tools.py @@ -270,8 +270,8 @@ def is_func_signature_supported(func, *args, **kwargs): Args: func (function): A function where the signature should be tested. - *args (tuple[Any]): Positional arguments for function signature. - **kwargs (dict[str, Any]): Keyword arguments for function signature. + *args (Any): Positional arguments for function signature. + **kwargs (Any): Keyword arguments for function signature. Returns: bool: Function can pass in arguments. From fee3c950d3a728ef9d22bfc857eb14a15620ce5b Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 1 Sep 2023 17:00:14 +0200 Subject: [PATCH 104/154] removed deprecated 'abstractproperty' --- openpype/pipeline/create/creator_plugins.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/openpype/pipeline/create/creator_plugins.py b/openpype/pipeline/create/creator_plugins.py index a1a6a73236..b38c1199e6 100644 --- a/openpype/pipeline/create/creator_plugins.py +++ b/openpype/pipeline/create/creator_plugins.py @@ -1,11 +1,7 @@ import copy import collections -from abc import ( - ABCMeta, - abstractmethod, - abstractproperty -) +from abc import ABCMeta, abstractmethod import six @@ -84,7 +80,8 @@ class SubsetConvertorPlugin(object): def host(self): return self._create_context.host - @abstractproperty + @property + @abstractmethod def identifier(self): """Converted identifier. @@ -231,7 +228,8 @@ class BaseCreator: return self.family - @abstractproperty + @property + @abstractmethod def family(self): """Family that plugin represents.""" From e2c60831c2a32e260615f9842e7ecf50109b48a1 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 1 Sep 2023 17:07:28 +0200 Subject: [PATCH 105/154] apply settings in TVPaint does not expect system settings --- openpype/hosts/tvpaint/plugins/create/create_render.py | 2 +- openpype/hosts/tvpaint/plugins/create/create_review.py | 2 +- openpype/hosts/tvpaint/plugins/create/create_workfile.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/tvpaint/plugins/create/create_render.py b/openpype/hosts/tvpaint/plugins/create/create_render.py index 2369c7329f..656ea5d80b 100644 --- a/openpype/hosts/tvpaint/plugins/create/create_render.py +++ b/openpype/hosts/tvpaint/plugins/create/create_render.py @@ -139,7 +139,7 @@ class CreateRenderlayer(TVPaintCreator): # - Mark by default instance for review mark_for_review = True - def apply_settings(self, project_settings, system_settings): + def apply_settings(self, project_settings): plugin_settings = ( project_settings["tvpaint"]["create"]["create_render_layer"] ) diff --git a/openpype/hosts/tvpaint/plugins/create/create_review.py b/openpype/hosts/tvpaint/plugins/create/create_review.py index 886dae7c39..7bb7510a8e 100644 --- a/openpype/hosts/tvpaint/plugins/create/create_review.py +++ b/openpype/hosts/tvpaint/plugins/create/create_review.py @@ -12,7 +12,7 @@ class TVPaintReviewCreator(TVPaintAutoCreator): # Settings active_on_create = True - def apply_settings(self, project_settings, system_settings): + def apply_settings(self, project_settings): plugin_settings = ( project_settings["tvpaint"]["create"]["create_review"] ) diff --git a/openpype/hosts/tvpaint/plugins/create/create_workfile.py b/openpype/hosts/tvpaint/plugins/create/create_workfile.py index 41347576d5..c3982c0eca 100644 --- a/openpype/hosts/tvpaint/plugins/create/create_workfile.py +++ b/openpype/hosts/tvpaint/plugins/create/create_workfile.py @@ -9,7 +9,7 @@ class TVPaintWorkfileCreator(TVPaintAutoCreator): label = "Workfile" icon = "fa.file-o" - def apply_settings(self, project_settings, system_settings): + def apply_settings(self, project_settings): plugin_settings = ( project_settings["tvpaint"]["create"]["create_workfile"] ) From 21d5d4cad2705edc8aadc593356a796a14a155e1 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 1 Sep 2023 17:08:13 +0200 Subject: [PATCH 106/154] removed system settings usage from traypublisher --- .../hosts/traypublisher/plugins/create/create_movie_batch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/traypublisher/plugins/create/create_movie_batch.py b/openpype/hosts/traypublisher/plugins/create/create_movie_batch.py index 1bed07f785..3454b6e135 100644 --- a/openpype/hosts/traypublisher/plugins/create/create_movie_batch.py +++ b/openpype/hosts/traypublisher/plugins/create/create_movie_batch.py @@ -36,7 +36,7 @@ class BatchMovieCreator(TrayPublishCreator): # Position batch creator after simple creators order = 110 - def apply_settings(self, project_settings, system_settings): + def apply_settings(self, project_settings): creator_settings = ( project_settings["traypublisher"]["create"]["BatchMovieCreator"] ) From cb3ef02fc377ad375ebf2ccf061da735414d7703 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 1 Sep 2023 17:10:07 +0200 Subject: [PATCH 107/154] fusion creator does not expect system settings --- openpype/hosts/fusion/plugins/create/create_saver.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/openpype/hosts/fusion/plugins/create/create_saver.py b/openpype/hosts/fusion/plugins/create/create_saver.py index 04898d0a45..344deffb42 100644 --- a/openpype/hosts/fusion/plugins/create/create_saver.py +++ b/openpype/hosts/fusion/plugins/create/create_saver.py @@ -250,11 +250,7 @@ class CreateSaver(NewCreator): label="Review", ) - def apply_settings( - self, - project_settings, - system_settings - ): + def apply_settings(self, project_settings): """Method called on initialization of plugin to apply settings.""" # plugin settings From 09d31e81ef01fd94b64d6bcd14dde61960c44a91 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 1 Sep 2023 17:10:26 +0200 Subject: [PATCH 108/154] removed duplicated attribute --- openpype/hosts/fusion/plugins/create/create_saver.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/openpype/hosts/fusion/plugins/create/create_saver.py b/openpype/hosts/fusion/plugins/create/create_saver.py index 344deffb42..39edca4de3 100644 --- a/openpype/hosts/fusion/plugins/create/create_saver.py +++ b/openpype/hosts/fusion/plugins/create/create_saver.py @@ -30,10 +30,6 @@ class CreateSaver(NewCreator): instance_attributes = [ "reviewable" ] - default_variants = [ - "Main", - "Mask" - ] # TODO: This should be renamed together with Nuke so it is aligned temp_rendering_path_template = ( From 3ba7939222c920367a68153a46c8a4ded8684369 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 1 Sep 2023 17:10:40 +0200 Subject: [PATCH 109/154] removed usage of system settings from after effects --- openpype/hosts/aftereffects/plugins/create/create_render.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/aftereffects/plugins/create/create_render.py b/openpype/hosts/aftereffects/plugins/create/create_render.py index dcf424b44f..fbe600ae68 100644 --- a/openpype/hosts/aftereffects/plugins/create/create_render.py +++ b/openpype/hosts/aftereffects/plugins/create/create_render.py @@ -164,7 +164,7 @@ class RenderCreator(Creator): api.get_stub().rename_item(comp_id, new_comp_name) - def apply_settings(self, project_settings, system_settings): + def apply_settings(self, project_settings): plugin_settings = ( project_settings["aftereffects"]["create"]["RenderCreator"] ) From 539120f71861569dfce8e1e2bc39a87fe408f9aa Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 1 Sep 2023 17:11:21 +0200 Subject: [PATCH 110/154] removed usage of system settings from houdini --- openpype/hosts/houdini/api/plugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/houdini/api/plugin.py b/openpype/hosts/houdini/api/plugin.py index 70c837205e..730a627dc3 100644 --- a/openpype/hosts/houdini/api/plugin.py +++ b/openpype/hosts/houdini/api/plugin.py @@ -296,7 +296,7 @@ class HoudiniCreator(NewCreator, HoudiniCreatorBase): """ return [hou.ropNodeTypeCategory()] - def apply_settings(self, project_settings, system_settings): + def apply_settings(self, project_settings): """Method called on initialization of plugin to apply settings.""" settings_name = self.settings_name From cb3e83118b29e48b430da8a5eaf124e928bad3bc Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 1 Sep 2023 17:14:39 +0200 Subject: [PATCH 111/154] maya create plugins do not expecte system settings --- openpype/hosts/maya/api/plugin.py | 2 +- openpype/hosts/maya/plugins/create/create_animation.py | 6 ++---- openpype/hosts/maya/plugins/create/create_render.py | 2 +- .../hosts/maya/plugins/create/create_unreal_skeletalmesh.py | 2 +- .../hosts/maya/plugins/create/create_unreal_staticmesh.py | 2 +- openpype/hosts/maya/plugins/create/create_vrayscene.py | 2 +- 6 files changed, 7 insertions(+), 9 deletions(-) diff --git a/openpype/hosts/maya/api/plugin.py b/openpype/hosts/maya/api/plugin.py index 00d6602ef9..3f383fafb8 100644 --- a/openpype/hosts/maya/api/plugin.py +++ b/openpype/hosts/maya/api/plugin.py @@ -260,7 +260,7 @@ class MayaCreator(NewCreator, MayaCreatorBase): default=True) ] - def apply_settings(self, project_settings, system_settings): + def apply_settings(self, project_settings): """Method called on initialization of plugin to apply settings.""" settings_name = self.settings_name diff --git a/openpype/hosts/maya/plugins/create/create_animation.py b/openpype/hosts/maya/plugins/create/create_animation.py index 214ac18aef..115c73c0d3 100644 --- a/openpype/hosts/maya/plugins/create/create_animation.py +++ b/openpype/hosts/maya/plugins/create/create_animation.py @@ -81,10 +81,8 @@ class CreateAnimation(plugin.MayaHiddenCreator): return defs - def apply_settings(self, project_settings, system_settings): - super(CreateAnimation, self).apply_settings( - project_settings, system_settings - ) + def apply_settings(self, project_settings): + super(CreateAnimation, self).apply_settings(project_settings) # Hardcoding creator to be enabled due to existing settings would # disable the creator causing the creator plugin to not be # discoverable. diff --git a/openpype/hosts/maya/plugins/create/create_render.py b/openpype/hosts/maya/plugins/create/create_render.py index cc5c1eb205..6266689af4 100644 --- a/openpype/hosts/maya/plugins/create/create_render.py +++ b/openpype/hosts/maya/plugins/create/create_render.py @@ -34,7 +34,7 @@ class CreateRenderlayer(plugin.RenderlayerCreator): render_settings = {} @classmethod - def apply_settings(cls, project_settings, system_settings): + def apply_settings(cls, project_settings): cls.render_settings = project_settings["maya"]["RenderSettings"] def create(self, subset_name, instance_data, pre_create_data): diff --git a/openpype/hosts/maya/plugins/create/create_unreal_skeletalmesh.py b/openpype/hosts/maya/plugins/create/create_unreal_skeletalmesh.py index 4e2a99eced..3c9a79156a 100644 --- a/openpype/hosts/maya/plugins/create/create_unreal_skeletalmesh.py +++ b/openpype/hosts/maya/plugins/create/create_unreal_skeletalmesh.py @@ -21,7 +21,7 @@ class CreateUnrealSkeletalMesh(plugin.MayaCreator): # Defined in settings joint_hints = set() - def apply_settings(self, project_settings, system_settings): + def apply_settings(self, project_settings): """Apply project settings to creator""" settings = ( project_settings["maya"]["create"]["CreateUnrealSkeletalMesh"] diff --git a/openpype/hosts/maya/plugins/create/create_unreal_staticmesh.py b/openpype/hosts/maya/plugins/create/create_unreal_staticmesh.py index 3f96d91a54..025b39fa55 100644 --- a/openpype/hosts/maya/plugins/create/create_unreal_staticmesh.py +++ b/openpype/hosts/maya/plugins/create/create_unreal_staticmesh.py @@ -16,7 +16,7 @@ class CreateUnrealStaticMesh(plugin.MayaCreator): # Defined in settings collision_prefixes = [] - def apply_settings(self, project_settings, system_settings): + def apply_settings(self, project_settings): """Apply project settings to creator""" settings = project_settings["maya"]["create"]["CreateUnrealStaticMesh"] self.collision_prefixes = settings["collision_prefixes"] diff --git a/openpype/hosts/maya/plugins/create/create_vrayscene.py b/openpype/hosts/maya/plugins/create/create_vrayscene.py index d601dceb54..2726979d30 100644 --- a/openpype/hosts/maya/plugins/create/create_vrayscene.py +++ b/openpype/hosts/maya/plugins/create/create_vrayscene.py @@ -22,7 +22,7 @@ class CreateVRayScene(plugin.RenderlayerCreator): singleton_node_name = "vraysceneMain" @classmethod - def apply_settings(cls, project_settings, system_settings): + def apply_settings(cls, project_settings): cls.render_settings = project_settings["maya"]["RenderSettings"] def create(self, subset_name, instance_data, pre_create_data): From 9338c163057d6c644bb6e113b51ed05170f8a951 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 1 Sep 2023 17:18:10 +0200 Subject: [PATCH 112/154] photoshop create plugins do not expect system settings --- openpype/hosts/photoshop/plugins/create/create_flatten_image.py | 2 +- openpype/hosts/photoshop/plugins/create/create_image.py | 2 +- openpype/hosts/photoshop/plugins/create/create_review.py | 2 +- openpype/hosts/photoshop/plugins/create/create_workfile.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/photoshop/plugins/create/create_flatten_image.py b/openpype/hosts/photoshop/plugins/create/create_flatten_image.py index 3bc61c8184..9d4189a1a3 100644 --- a/openpype/hosts/photoshop/plugins/create/create_flatten_image.py +++ b/openpype/hosts/photoshop/plugins/create/create_flatten_image.py @@ -98,7 +98,7 @@ class AutoImageCreator(PSAutoCreator): ) ] - def apply_settings(self, project_settings, system_settings): + def apply_settings(self, project_settings): plugin_settings = ( project_settings["photoshop"]["create"]["AutoImageCreator"] ) diff --git a/openpype/hosts/photoshop/plugins/create/create_image.py b/openpype/hosts/photoshop/plugins/create/create_image.py index f3165fca57..8d3ac9f459 100644 --- a/openpype/hosts/photoshop/plugins/create/create_image.py +++ b/openpype/hosts/photoshop/plugins/create/create_image.py @@ -171,7 +171,7 @@ class ImageCreator(Creator): ) ] - def apply_settings(self, project_settings, system_settings): + def apply_settings(self, project_settings): plugin_settings = ( project_settings["photoshop"]["create"]["ImageCreator"] ) diff --git a/openpype/hosts/photoshop/plugins/create/create_review.py b/openpype/hosts/photoshop/plugins/create/create_review.py index 064485d465..63751d94e4 100644 --- a/openpype/hosts/photoshop/plugins/create/create_review.py +++ b/openpype/hosts/photoshop/plugins/create/create_review.py @@ -18,7 +18,7 @@ class ReviewCreator(PSAutoCreator): it will get recreated in next publish either way). """ - def apply_settings(self, project_settings, system_settings): + def apply_settings(self, project_settings): plugin_settings = ( project_settings["photoshop"]["create"]["ReviewCreator"] ) diff --git a/openpype/hosts/photoshop/plugins/create/create_workfile.py b/openpype/hosts/photoshop/plugins/create/create_workfile.py index d498f0549c..1b255de3a3 100644 --- a/openpype/hosts/photoshop/plugins/create/create_workfile.py +++ b/openpype/hosts/photoshop/plugins/create/create_workfile.py @@ -19,7 +19,7 @@ class WorkfileCreator(PSAutoCreator): in next publish automatically). """ - def apply_settings(self, project_settings, system_settings): + def apply_settings(self, project_settings): plugin_settings = ( project_settings["photoshop"]["create"]["WorkfileCreator"] ) From 7441d2617ab118db431b0ce57079ea25ffd8209b Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 1 Sep 2023 17:19:30 +0200 Subject: [PATCH 113/154] add missing tvpaint creators --- openpype/hosts/tvpaint/plugins/create/create_render.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/tvpaint/plugins/create/create_render.py b/openpype/hosts/tvpaint/plugins/create/create_render.py index 656ea5d80b..b7a7c208d9 100644 --- a/openpype/hosts/tvpaint/plugins/create/create_render.py +++ b/openpype/hosts/tvpaint/plugins/create/create_render.py @@ -387,7 +387,7 @@ class CreateRenderPass(TVPaintCreator): # Settings mark_for_review = True - def apply_settings(self, project_settings, system_settings): + def apply_settings(self, project_settings): plugin_settings = ( project_settings["tvpaint"]["create"]["create_render_pass"] ) @@ -690,7 +690,7 @@ class TVPaintAutoDetectRenderCreator(TVPaintCreator): group_idx_offset = 10 group_idx_padding = 3 - def apply_settings(self, project_settings, system_settings): + def apply_settings(self, project_settings): plugin_settings = ( project_settings ["tvpaint"] @@ -1029,7 +1029,7 @@ class TVPaintSceneRenderCreator(TVPaintAutoCreator): mark_for_review = True active_on_create = False - def apply_settings(self, project_settings, system_settings): + def apply_settings(self, project_settings): plugin_settings = ( project_settings["tvpaint"]["create"]["create_render_scene"] ) From ce3e9a52401fdd85a6574b6fafc0d23351e69135 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 1 Sep 2023 17:19:39 +0200 Subject: [PATCH 114/154] nuke create plugins do not expect system settings --- openpype/hosts/nuke/api/plugin.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/openpype/hosts/nuke/api/plugin.py b/openpype/hosts/nuke/api/plugin.py index 6d48c09d60..a0e1525cd0 100644 --- a/openpype/hosts/nuke/api/plugin.py +++ b/openpype/hosts/nuke/api/plugin.py @@ -379,11 +379,7 @@ class NukeWriteCreator(NukeCreator): sys.exc_info()[2] ) - def apply_settings( - self, - project_settings, - system_settings - ): + def apply_settings(self, project_settings): """Method called on initialization of plugin to apply settings.""" # plugin settings From 34d7a4f477c109ec419a2048d72cdc657bae7e51 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Fri, 1 Sep 2023 17:24:01 +0200 Subject: [PATCH 115/154] removed unnecessary line Co-authored-by: Roy Nieterau --- openpype/lib/attribute_definitions.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/lib/attribute_definitions.py b/openpype/lib/attribute_definitions.py index a71709cace..095b096255 100644 --- a/openpype/lib/attribute_definitions.py +++ b/openpype/lib/attribute_definitions.py @@ -482,7 +482,6 @@ class EnumDef(AbstractAttrDef): return copy.deepcopy(self.default) return list(self._item_values.intersection(value)) - def serialize(self): data = super(EnumDef, self).serialize() data["items"] = copy.deepcopy(self.items) From 5de86cb6df5c852b590a83f72d4b3bfe1cdf1ebb Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 1 Sep 2023 17:33:57 +0200 Subject: [PATCH 116/154] do not override scale factor rounding policy if has defined value through env variable --- openpype/tools/utils/lib.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/openpype/tools/utils/lib.py b/openpype/tools/utils/lib.py index 2df46c1eae..723e71e7aa 100644 --- a/openpype/tools/utils/lib.py +++ b/openpype/tools/utils/lib.py @@ -170,8 +170,12 @@ def get_openpype_qt_app(): if attr is not None: QtWidgets.QApplication.setAttribute(attr) - if hasattr( - QtWidgets.QApplication, "setHighDpiScaleFactorRoundingPolicy" + policy = os.getenv("QT_SCALE_FACTOR_ROUNDING_POLICY") + if ( + hasattr( + QtWidgets.QApplication, "setHighDpiScaleFactorRoundingPolicy" + ) + and not policy ): QtWidgets.QApplication.setHighDpiScaleFactorRoundingPolicy( QtCore.Qt.HighDpiScaleFactorRoundingPolicy.PassThrough From 88ab56db12f21a6aabf558bf1c9b1ab8471a4011 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 1 Sep 2023 18:16:54 +0200 Subject: [PATCH 117/154] backwards compatibility is kept with waring message --- openpype/pipeline/create/context.py | 16 ++++++---------- openpype/pipeline/create/creator_plugins.py | 19 +++++++++++++++++-- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/openpype/pipeline/create/context.py b/openpype/pipeline/create/context.py index e0e2c09f96..f9e3f86652 100644 --- a/openpype/pipeline/create/context.py +++ b/openpype/pipeline/create/context.py @@ -16,7 +16,6 @@ from openpype.settings import ( get_system_settings, get_project_settings ) -from openpype.lib import is_func_signature_supported from openpype.lib.attribute_definitions import ( UnknownDef, serialize_attr_defs, @@ -1799,15 +1798,12 @@ class CreateContext: ).format(creator_class.host_name, self.host_name)) continue - if is_func_signature_supported( - creator_class, project_settings, self, self.headless - ): - creator = creator_class(project_settings, self, self.headless) - else: - # Backwards compatibility to pass system settings to creators - creator = creator_class( - project_settings, system_settings, self, self.headless - ) + creator = creator_class( + project_settings, + system_settings, + self, + self.headless + ) if not creator.enabled: disabled_creators[creator_identifier] = creator diff --git a/openpype/pipeline/create/creator_plugins.py b/openpype/pipeline/create/creator_plugins.py index b38c1199e6..bd9d1d16c3 100644 --- a/openpype/pipeline/create/creator_plugins.py +++ b/openpype/pipeline/create/creator_plugins.py @@ -193,7 +193,9 @@ class BaseCreator: # QUESTION make this required? host_name = None - def __init__(self, project_settings, create_context, headless=False): + def __init__( + self, project_settings, system_settings, create_context, headless=False + ): # Reference to CreateContext self.create_context = create_context self.project_settings = project_settings @@ -202,13 +204,26 @@ class BaseCreator: # - we may use UI inside processing this attribute should be checked self.headless = headless + expect_system_settings = False if is_func_signature_supported( self.apply_settings, project_settings ): self.apply_settings(project_settings) else: + expect_system_settings = True # Backwards compatibility for system settings - self.apply_settings(project_settings, {}) + self.apply_settings(project_settings, system_settings) + + init_overriden = self.__class__.__init__ is not BaseCreator.__init__ + if init_overriden or expect_system_settings: + self.log.warning(( + "WARNING: Source - Create plugin {}." + " System settings argument will not be passed to" + " '__init__' and 'apply_settings' methods in future versions" + " of OpenPype. Planned version to drop the support" + " is 3.15.6 or 3.16.0. Please contact Ynput core team if you" + " need to keep system settings." + ).format(self.__class__.__name__)) def apply_settings(self, project_settings): """Method called on initialization of plugin to apply settings. From 1b8d8e68f2b7e41f3f141a3ad8570b49ae0d7be5 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Fri, 1 Sep 2023 18:23:45 +0200 Subject: [PATCH 118/154] Harmony: refresh code for current Deadline (#5493) * Explicitly set Python3 for Harmony OP plugin * Fix method call Without it it would always return True * Explicitly set render instance to farm * Added Harmony 22 executable This plugin might not be necessary anymore for current Harmonies (at least for 22 works original Harmony plugin in DL) * Removed logging * fix - remove explicit disabling of review instance.data["review"] could be False only if review shouldn't be explicitly done. This is not possible in old publisher. TODO must be implemented in NP. --- .../plugins/publish/collect_farm_render.py | 2 +- .../publish/submit_harmony_deadline.py | 2 +- .../HarmonyOpenPype/HarmonyOpenPype.param | 20 ++++++++++++++++++- .../HarmonyOpenPype/HarmonyOpenPype.py | 1 + 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/harmony/plugins/publish/collect_farm_render.py b/openpype/hosts/harmony/plugins/publish/collect_farm_render.py index 5daa93cddb..af825c052a 100644 --- a/openpype/hosts/harmony/plugins/publish/collect_farm_render.py +++ b/openpype/hosts/harmony/plugins/publish/collect_farm_render.py @@ -147,13 +147,13 @@ class CollectFarmRender(publish.AbstractCollectRender): attachTo=False, setMembers=[node], publish=info[4], - review=False, renderer=None, priority=50, name=node.split("/")[1], family="render.farm", families=["render.farm"], + farm=True, resolutionWidth=context.data["resolutionWidth"], resolutionHeight=context.data["resolutionHeight"], diff --git a/openpype/modules/deadline/plugins/publish/submit_harmony_deadline.py b/openpype/modules/deadline/plugins/publish/submit_harmony_deadline.py index 2c37268f04..16e703fc91 100644 --- a/openpype/modules/deadline/plugins/publish/submit_harmony_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_harmony_deadline.py @@ -265,7 +265,7 @@ class HarmonySubmitDeadline( job_info.SecondaryPool = self._instance.data.get("secondaryPool") job_info.ChunkSize = self.chunk_size batch_name = os.path.basename(self._instance.data["source"]) - if is_in_tests: + if is_in_tests(): batch_name += datetime.now().strftime("%d%m%Y%H%M%S") job_info.BatchName = batch_name job_info.Department = self.department diff --git a/openpype/modules/deadline/repository/custom/plugins/HarmonyOpenPype/HarmonyOpenPype.param b/openpype/modules/deadline/repository/custom/plugins/HarmonyOpenPype/HarmonyOpenPype.param index ff2949766c..43a54a464e 100644 --- a/openpype/modules/deadline/repository/custom/plugins/HarmonyOpenPype/HarmonyOpenPype.param +++ b/openpype/modules/deadline/repository/custom/plugins/HarmonyOpenPype/HarmonyOpenPype.param @@ -77,4 +77,22 @@ CategoryOrder=0 Index=4 Label=Harmony 20 Render Executable Description=The path to the Harmony Render executable file used for rendering. Enter alternative paths on separate lines. -Default=c:\Program Files (x86)\Toon Boom Animation\Toon Boom Harmony 20 Premium\win64\bin\HarmonyPremium.exe;/Applications/Toon Boom Harmony 20 Premium/Harmony Premium.app/Contents/MacOS/Harmony Premium;/usr/local/ToonBoomAnimation/harmonyPremium_20/lnx86_64/bin/HarmonyPremium \ No newline at end of file +Default=c:\Program Files (x86)\Toon Boom Animation\Toon Boom Harmony 20 Premium\win64\bin\HarmonyPremium.exe;/Applications/Toon Boom Harmony 20 Premium/Harmony Premium.app/Contents/MacOS/Harmony Premium;/usr/local/ToonBoomAnimation/harmonyPremium_20/lnx86_64/bin/HarmonyPremium + +[Harmony_RenderExecutable_21] +Type=multilinemultifilename +Category=Render Executables +CategoryOrder=0 +Index=4 +Label=Harmony 21 Render Executable +Description=The path to the Harmony Render executable file used for rendering. Enter alternative paths on separate lines. +Default=c:\Program Files (x86)\Toon Boom Animation\Toon Boom Harmony 21 Premium\win64\bin\HarmonyPremium.exe;/Applications/Toon Boom Harmony 21 Premium/Harmony Premium.app/Contents/MacOS/Harmony Premium;/usr/local/ToonBoomAnimation/harmonyPremium_21/lnx86_64/bin/HarmonyPremium + +[Harmony_RenderExecutable_22] +Type=multilinemultifilename +Category=Render Executables +CategoryOrder=0 +Index=4 +Label=Harmony 22 Render Executable +Description=The path to the Harmony Render executable file used for rendering. Enter alternative paths on separate lines. +Default=c:\Program Files (x86)\Toon Boom Animation\Toon Boom Harmony 22 Premium\win64\bin\HarmonyPremium.exe;/Applications/Toon Boom Harmony 22 Premium/Harmony Premium.app/Contents/MacOS/Harmony Premium;/usr/local/ToonBoomAnimation/harmonyPremium_22/lnx86_64/bin/HarmonyPremium diff --git a/openpype/modules/deadline/repository/custom/plugins/HarmonyOpenPype/HarmonyOpenPype.py b/openpype/modules/deadline/repository/custom/plugins/HarmonyOpenPype/HarmonyOpenPype.py index 2f6e9cf379..32ed76b58d 100644 --- a/openpype/modules/deadline/repository/custom/plugins/HarmonyOpenPype/HarmonyOpenPype.py +++ b/openpype/modules/deadline/repository/custom/plugins/HarmonyOpenPype/HarmonyOpenPype.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 from System import * from System.Diagnostics import * from System.IO import * From 0cf8f8f42dc0f3b348c55ee02d7e8cdc784838e2 Mon Sep 17 00:00:00 2001 From: Ynbot Date: Sat, 2 Sep 2023 03:24:31 +0000 Subject: [PATCH 119/154] [Automated] Bump version --- openpype/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/version.py b/openpype/version.py index 12f797228b..7de6fd752b 100644 --- a/openpype/version.py +++ b/openpype/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring Pype version.""" -__version__ = "3.16.5-nightly.3" +__version__ = "3.16.5-nightly.4" From dc684b65f38ddeb6900343f35a8d005049307798 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 2 Sep 2023 03:25:07 +0000 Subject: [PATCH 120/154] chore(): update bug report / version --- .github/ISSUE_TEMPLATE/bug_report.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 669bf391cd..83a4b6a8d4 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -35,6 +35,7 @@ body: label: Version description: What version are you running? Look to OpenPype Tray options: + - 3.16.5-nightly.4 - 3.16.5-nightly.3 - 3.16.5-nightly.2 - 3.16.5-nightly.1 @@ -134,7 +135,6 @@ body: - 3.14.9-nightly.1 - 3.14.8 - 3.14.8-nightly.4 - - 3.14.8-nightly.3 validations: required: true - type: dropdown From 115dd54733c83744548643e720b108d00ef1e529 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 4 Sep 2023 10:56:30 +0200 Subject: [PATCH 121/154] fix repaint when custom text changed --- openpype/tools/utils/multiselection_combobox.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/openpype/tools/utils/multiselection_combobox.py b/openpype/tools/utils/multiselection_combobox.py index 13b396a059..34361fca17 100644 --- a/openpype/tools/utils/multiselection_combobox.py +++ b/openpype/tools/utils/multiselection_combobox.py @@ -75,11 +75,11 @@ class MultiSelectionComboBox(QtWidgets.QComboBox): def set_placeholder_text(self, text): self._placeholder_text = text + self._update_size_hint() def set_custom_text(self, text): self._custom_text = text - self.update() - self.updateGeometry() + self._update_size_hint() def focusInEvent(self, event): self.focused_in.emit() @@ -266,7 +266,6 @@ class MultiSelectionComboBox(QtWidgets.QComboBox): def _update_size_hint(self): if self._custom_text is not None: self.update() - self.repaint() return self._lines = {} @@ -313,7 +312,6 @@ class MultiSelectionComboBox(QtWidgets.QComboBox): self.update() self.updateGeometry() - self.repaint() def sizeHint(self): value = super(MultiSelectionComboBox, self).sizeHint() From 6b1d060a8133643cebbf92e8c3e1fe93c84fbed9 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 4 Sep 2023 11:00:00 +0200 Subject: [PATCH 122/154] updated docstring --- openpype/lib/attribute_definitions.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openpype/lib/attribute_definitions.py b/openpype/lib/attribute_definitions.py index 095b096255..a71d6cc72a 100644 --- a/openpype/lib/attribute_definitions.py +++ b/openpype/lib/attribute_definitions.py @@ -424,7 +424,10 @@ class TextDef(AbstractAttrDef): class EnumDef(AbstractAttrDef): - """Enumeration of single item from items. + """Enumeration of items. + + Enumeration of single item from items. Or list of items if multiselection + is enabled. Args: items (Union[list[str], list[dict[str, Any]]): Items definition that From 0f39ccf0168d8e24ffed0d12287db8a15d99a38f Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Mon, 4 Sep 2023 11:05:27 +0200 Subject: [PATCH 123/154] Fix - files on representation cannot be single item list (#5545) Further logic expects that single item files will be only 'string' not 'list' (eg. repre["files"] = "abc.exr" not repre["files"] = ["abc.exr"]. This would cause an issue in ExtractReview later. --- .../plugins/publish/validate_expected_and_rendered_files.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openpype/modules/deadline/plugins/publish/validate_expected_and_rendered_files.py b/openpype/modules/deadline/plugins/publish/validate_expected_and_rendered_files.py index 9f1f7bc518..5d37e7357e 100644 --- a/openpype/modules/deadline/plugins/publish/validate_expected_and_rendered_files.py +++ b/openpype/modules/deadline/plugins/publish/validate_expected_and_rendered_files.py @@ -70,7 +70,10 @@ class ValidateExpectedFiles(pyblish.api.InstancePlugin): # Update the representation expected files self.log.info("Update range from actual job range " "to frame list: {}".format(frame_list)) - repre["files"] = sorted(job_expected_files) + # single item files must be string not list + repre["files"] = (sorted(job_expected_files) + if len(job_expected_files) > 1 else + list(job_expected_files)[0]) # Update the expected files expected_files = job_expected_files From 35074e8db892d07bfd43ea3860e660ab10843346 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Mon, 4 Sep 2023 11:49:14 +0200 Subject: [PATCH 124/154] Fix versions in deprecated message --- openpype/pipeline/create/creator_plugins.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/pipeline/create/creator_plugins.py b/openpype/pipeline/create/creator_plugins.py index bd9d1d16c3..de9cc7cff3 100644 --- a/openpype/pipeline/create/creator_plugins.py +++ b/openpype/pipeline/create/creator_plugins.py @@ -221,7 +221,7 @@ class BaseCreator: " System settings argument will not be passed to" " '__init__' and 'apply_settings' methods in future versions" " of OpenPype. Planned version to drop the support" - " is 3.15.6 or 3.16.0. Please contact Ynput core team if you" + " is 3.16.6 or 3.17.0. Please contact Ynput core team if you" " need to keep system settings." ).format(self.__class__.__name__)) From 0c8ad276e409840ce665ecd7c8c3655a545cc500 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 4 Sep 2023 18:02:32 +0800 Subject: [PATCH 125/154] Oscar's and BigRoy's comment respectively on namespace function --- openpype/hosts/max/api/lib.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openpype/hosts/max/api/lib.py b/openpype/hosts/max/api/lib.py index 034307e72a..8287341456 100644 --- a/openpype/hosts/max/api/lib.py +++ b/openpype/hosts/max/api/lib.py @@ -316,7 +316,6 @@ def set_timeline(frameStart, frameEnd): def unique_namespace(namespace, format="%02d", prefix="", suffix="", con_suffix="CON"): - from pymxs import runtime as rt """Return unique namespace Arguments: @@ -336,7 +335,7 @@ def unique_namespace(namespace, format="%02d", def current_namespace(): current = namespace - # When inside a namespace Maya adds no trailing : + # When inside a namespace Max adds no trailing : if not current.endswith(":"): current += ":" return current From 646d4f6db2850a3faefb32e5635074ae84cd44c3 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 4 Sep 2023 19:19:39 +0800 Subject: [PATCH 126/154] oscar comment on the import custom attribute data --- openpype/hosts/max/api/pipeline.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/openpype/hosts/max/api/pipeline.py b/openpype/hosts/max/api/pipeline.py index 161e2bdc7b..695169894f 100644 --- a/openpype/hosts/max/api/pipeline.py +++ b/openpype/hosts/max/api/pipeline.py @@ -197,19 +197,18 @@ def import_custom_attribute_data(container: str, selections: list): rt.addModifier(container, modifier) container.modifiers[0].name = "OP Data" rt.custAttributes.add(container.modifiers[0], attrs) - node_list = [] - sel_list = [] + nodes = {} for i in selections: - node_ref = rt.NodeTransformMonitor(node=i) - node_list.append(node_ref) - sel_list.append(str(i)) + nodes = { + str(i) : rt.NodeTransformMonitor(node=i), + } # Setting the property rt.setProperty( container.modifiers[0].openPypeData, - "all_handles", node_list) + "all_handles", nodes.values()) rt.setProperty( container.modifiers[0].openPypeData, - "sel_list", sel_list) + "sel_list", nodes.keys()) def update_custom_attribute_data(container: str, selections: list): From 4e3d0d7eacc63e2ac4892cecbcefc595905df933 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 4 Sep 2023 19:20:42 +0800 Subject: [PATCH 127/154] hound --- openpype/hosts/max/api/pipeline.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/max/api/pipeline.py b/openpype/hosts/max/api/pipeline.py index 695169894f..d9a66c60f5 100644 --- a/openpype/hosts/max/api/pipeline.py +++ b/openpype/hosts/max/api/pipeline.py @@ -200,7 +200,7 @@ def import_custom_attribute_data(container: str, selections: list): nodes = {} for i in selections: nodes = { - str(i) : rt.NodeTransformMonitor(node=i), + str(i): rt.NodeTransformMonitor(node=i), } # Setting the property rt.setProperty( From 3c911f9f5d2995e866fa7f0b5fe41c6eff100bef Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 4 Sep 2023 13:24:07 +0200 Subject: [PATCH 128/154] removed export maya ass job script --- openpype/scripts/export_maya_ass_job.py | 105 ------------------ openpype/scripts/export_maya_ass_sequence.mel | 67 ----------- 2 files changed, 172 deletions(-) delete mode 100644 openpype/scripts/export_maya_ass_job.py delete mode 100644 openpype/scripts/export_maya_ass_sequence.mel diff --git a/openpype/scripts/export_maya_ass_job.py b/openpype/scripts/export_maya_ass_job.py deleted file mode 100644 index 16e841ce96..0000000000 --- a/openpype/scripts/export_maya_ass_job.py +++ /dev/null @@ -1,105 +0,0 @@ -"""This module is used for command line exporting of ASS files. - -WARNING: -This need to be rewriten to be able use it in Pype 3! -""" - -import os -import argparse -import logging -import subprocess -import platform - -try: - from shutil import which -except ImportError: - # we are in python < 3.3 - def which(command): - path = os.getenv('PATH') - for p in path.split(os.path.pathsep): - p = os.path.join(p, command) - if os.path.exists(p) and os.access(p, os.X_OK): - return p - -handler = logging.basicConfig() -log = logging.getLogger("Publish Image Sequences") -log.setLevel(logging.DEBUG) - -error_format = "Failed {plugin.__name__}: {error} -- {error.traceback}" - - -def __main__(): - parser = argparse.ArgumentParser() - parser.add_argument("--paths", - nargs="*", - default=[], - help="The filepaths to publish. This can be a " - "directory or a path to a .json publish " - "configuration.") - parser.add_argument("--gui", - default=False, - action="store_true", - help="Whether to run Pyblish in GUI mode.") - - parser.add_argument("--pype", help="Pype root") - - kwargs, args = parser.parse_known_args() - - print("Running pype ...") - auto_pype_root = os.path.dirname(os.path.abspath(__file__)) - auto_pype_root = os.path.abspath(auto_pype_root + "../../../../..") - - auto_pype_root = os.environ.get('OPENPYPE_SETUP_PATH') or auto_pype_root - if os.environ.get('OPENPYPE_SETUP_PATH'): - print("Got Pype location from environment: {}".format( - os.environ.get('OPENPYPE_SETUP_PATH'))) - - pype_command = "openpype.ps1" - if platform.system().lower() == "linux": - pype_command = "pype" - elif platform.system().lower() == "windows": - pype_command = "openpype.bat" - - if kwargs.pype: - pype_root = kwargs.pype - else: - # test if pype.bat / pype is in the PATH - # if it is, which() will return its path and we use that. - # if not, we use auto_pype_root path. Caveat of that one is - # that it can be UNC path and that will not work on windows. - - pype_path = which(pype_command) - - if pype_path: - pype_root = os.path.dirname(pype_path) - else: - pype_root = auto_pype_root - - print("Set pype root to: {}".format(pype_root)) - print("Paths: {}".format(kwargs.paths or [os.getcwd()])) - - # paths = kwargs.paths or [os.environ.get("OPENPYPE_METADATA_FILE")] or [os.getcwd()] # noqa - - mayabatch = os.environ.get("AVALON_APP_NAME").replace("maya", "mayabatch") - args = [ - os.path.join(pype_root, pype_command), - "launch", - "--app", - mayabatch, - "-script", - os.path.join(pype_root, "repos", "pype", - "pype", "scripts", "export_maya_ass_sequence.mel") - ] - - print("Pype command: {}".format(" ".join(args))) - # Forcing forwaring the environment because environment inheritance does - # not always work. - # Cast all values in environment to str to be safe - env = {k: str(v) for k, v in os.environ.items()} - exit_code = subprocess.call(args, env=env) - if exit_code != 0: - raise RuntimeError("Publishing failed.") - - -if __name__ == '__main__': - __main__() diff --git a/openpype/scripts/export_maya_ass_sequence.mel b/openpype/scripts/export_maya_ass_sequence.mel deleted file mode 100644 index b3b9a8543e..0000000000 --- a/openpype/scripts/export_maya_ass_sequence.mel +++ /dev/null @@ -1,67 +0,0 @@ -/* - Script to export specified layer as ass files. - -Attributes: - - scene_file (str): Name of the scene to load. - start (int): Start frame. - end (int): End frame. - step (int): Step size. - output_path (str): File output path. - render_layer (str): Name of render layer. - -*/ - -$scene_file=`getenv "OPENPYPE_ASS_EXPORT_SCENE_FILE"`; -$step=`getenv "OPENPYPE_ASS_EXPORT_STEP"`; -$start=`getenv "OPENPYPE_ASS_EXPORT_START"`; -$end=`getenv "OPENPYPE_ASS_EXPORT_END"`; -$file_path=`getenv "OPENPYPE_ASS_EXPORT_OUTPUT"`; -$render_layer = `getenv "OPENPYPE_ASS_EXPORT_RENDER_LAYER"`; - -print("*** ASS Export Plugin\n"); - -if ($scene_file == "") { - print("!!! cannot determine scene file\n"); - quit -a -ex -1; -} - -if ($step == "") { - print("!!! cannot determine step size\n"); - quit -a -ex -1; -} - -if ($start == "") { - print("!!! cannot determine start frame\n"); - quit -a -ex -1; -} - -if ($end == "") { - print("!!! cannot determine end frame\n"); - quit -a -ex -1; -} - -if ($file_path == "") { - print("!!! cannot determine output file\n"); - quit -a -ex -1; -} - -if ($render_layer == "") { - print("!!! cannot determine render layer\n"); - quit -a -ex -1; -} - - -print(">>> Opening Scene [ " + $scene_file + " ]\n"); - -// open scene -file -o -f $scene_file; - -// switch to render layer -print(">>> Switching layer [ "+ $render_layer + " ]\n"); -editRenderLayerGlobals -currentRenderLayer $render_layer; - -// export -print(">>> Exporting to [ " + $file_path + " ]\n"); -arnoldExportAss -mask 255 -sl 1 -ll 1 -bb 1 -sf $start -se $end -b -fs $step; -print("--- Done\n"); From aa9846dcbde067e63aa2089752b76840417870bb Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 4 Sep 2023 13:25:35 +0200 Subject: [PATCH 129/154] removed logic where the script is used --- .../plugins/publish/submit_maya_deadline.py | 53 ------------------- 1 file changed, 53 deletions(-) diff --git a/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py b/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py index 34f3905a17..24052f23d5 100644 --- a/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py +++ b/openpype/modules/deadline/plugins/publish/submit_maya_deadline.py @@ -334,12 +334,6 @@ class MayaSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, payload = self._get_vray_render_payload(payload_data) - elif "assscene" in instance.data["families"]: - self.log.debug("Submitting Arnold .ass standalone render..") - ass_export_payload = self._get_arnold_export_payload(payload_data) - export_job = self.submit(ass_export_payload) - - payload = self._get_arnold_render_payload(payload_data) else: self.log.debug("Submitting MayaBatch render..") payload = self._get_maya_payload(payload_data) @@ -635,53 +629,6 @@ class MayaSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline, return job_info, attr.asdict(plugin_info) - def _get_arnold_export_payload(self, data): - - try: - from openpype.scripts import export_maya_ass_job - except Exception: - raise AssertionError( - "Expected module 'export_maya_ass_job' to be available") - - module_path = export_maya_ass_job.__file__ - if module_path.endswith(".pyc"): - module_path = module_path[: -len(".pyc")] + ".py" - - script = os.path.normpath(module_path) - - job_info = copy.deepcopy(self.job_info) - job_info.Name = self._job_info_label("Export") - - # Force a single frame Python job - job_info.Plugin = "Python" - job_info.Frames = 1 - - renderlayer = self._instance.data["setMembers"] - - # add required env vars for the export script - envs = { - "AVALON_APP_NAME": os.environ.get("AVALON_APP_NAME"), - "OPENPYPE_ASS_EXPORT_RENDER_LAYER": renderlayer, - "OPENPYPE_ASS_EXPORT_SCENE_FILE": self.scene_path, - "OPENPYPE_ASS_EXPORT_OUTPUT": job_info.OutputFilename[0], - "OPENPYPE_ASS_EXPORT_START": int(self._instance.data["frameStartHandle"]), # noqa - "OPENPYPE_ASS_EXPORT_END": int(self._instance.data["frameEndHandle"]), # noqa - "OPENPYPE_ASS_EXPORT_STEP": 1 - } - for key, value in envs.items(): - if not value: - continue - job_info.EnvironmentKeyValue[key] = value - - plugin_info = PythonPluginInfo( - ScriptFile=script, - Version="3.6", - Arguments="", - SingleFrameOnly="True" - ) - - return job_info, attr.asdict(plugin_info) - def _get_vray_render_payload(self, data): # Job Info From 90bfd0a79a8ef5fcee474340594949e44f657ab2 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 4 Sep 2023 13:26:36 +0200 Subject: [PATCH 130/154] Yeti Cache: Include viewport preview settings --- .../plugins/publish/collect_yeti_cache.py | 36 ++++++++++++------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/collect_yeti_cache.py b/openpype/hosts/maya/plugins/publish/collect_yeti_cache.py index e6b5ca4260..4dcda29050 100644 --- a/openpype/hosts/maya/plugins/publish/collect_yeti_cache.py +++ b/openpype/hosts/maya/plugins/publish/collect_yeti_cache.py @@ -4,12 +4,23 @@ import pyblish.api from openpype.hosts.maya.api import lib -SETTINGS = {"renderDensity", - "renderWidth", - "renderLength", - "increaseRenderBounds", - "imageSearchPath", - "cbId"} + +SETTINGS = { + # Preview + "displayOutput", + "colorR", "colorG", "colorB", + "viewportDensity", + "viewportWidth", + "viewportLength", + # Render attributes + "renderDensity", + "renderWidth", + "renderLength", + "increaseRenderBounds", + "imageSearchPath", + # Pipeline specific + "cbId" +} class CollectYetiCache(pyblish.api.InstancePlugin): @@ -39,10 +50,6 @@ class CollectYetiCache(pyblish.api.InstancePlugin): # Get yeti nodes and their transforms yeti_shapes = cmds.ls(instance, type="pgYetiMaya") for shape in yeti_shapes: - shape_data = {"transform": None, - "name": shape, - "cbId": lib.get_id(shape), - "attrs": None} # Get specific node attributes attr_data = {} @@ -58,9 +65,12 @@ class CollectYetiCache(pyblish.api.InstancePlugin): parent = cmds.listRelatives(shape, parent=True)[0] transform_data = {"name": parent, "cbId": lib.get_id(parent)} - # Store collected data - shape_data["attrs"] = attr_data - shape_data["transform"] = transform_data + shape_data = { + "transform": transform_data, + "name": shape, + "cbId": lib.get_id(shape), + "attrs": attr_data, + } settings["nodes"].append(shape_data) From 26ef5812b7428f792e81de4a2bfa61867e73f834 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 4 Sep 2023 13:42:01 +0200 Subject: [PATCH 131/154] Skip viewport attributes on 'update' but preserve what artist tweaked after initial load --- .../hosts/maya/plugins/load/load_yeti_cache.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/load/load_yeti_cache.py b/openpype/hosts/maya/plugins/load/load_yeti_cache.py index 5cded13d4e..4a11ea9a2c 100644 --- a/openpype/hosts/maya/plugins/load/load_yeti_cache.py +++ b/openpype/hosts/maya/plugins/load/load_yeti_cache.py @@ -15,6 +15,16 @@ from openpype.hosts.maya.api import lib from openpype.hosts.maya.api.pipeline import containerise +# Do not reset these values on update but only apply on first load +# to preserve any potential local overrides +SKIP_UPDATE_ATTRS = { + "displayOutput", + "viewportDensity", + "viewportWidth", + "viewportLength", +} + + def set_attribute(node, attr, value): """Wrapper of set attribute which ignores None values""" if value is None: @@ -205,6 +215,8 @@ class YetiCacheLoader(load.LoaderPlugin): yeti_node = yeti_nodes[0] for attr, value in node_settings["attrs"].items(): + if attr in SKIP_UPDATE_ATTRS: + continue set_attribute(attr, value, yeti_node) cmds.setAttr("{}.representation".format(container_node), @@ -311,7 +323,6 @@ class YetiCacheLoader(load.LoaderPlugin): # Update attributes with defaults attributes = node_settings["attrs"] attributes.update({ - "viewportDensity": 0.1, "verbosity": 2, "fileMode": 1, @@ -321,6 +332,9 @@ class YetiCacheLoader(load.LoaderPlugin): "visibleInRefractions": True }) + if "viewportDensity" not in attributes: + attributes["viewportDensity"] = 0.1 + # Apply attributes to pgYetiMaya node for attr, value in attributes.items(): set_attribute(attr, value, yeti_node) From c2722344e052565413914a6e7118024d03dee745 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 4 Sep 2023 20:38:18 +0800 Subject: [PATCH 132/154] update attribute should be correct --- openpype/hosts/max/api/pipeline.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/openpype/hosts/max/api/pipeline.py b/openpype/hosts/max/api/pipeline.py index d9a66c60f5..72163f5ecf 100644 --- a/openpype/hosts/max/api/pipeline.py +++ b/openpype/hosts/max/api/pipeline.py @@ -197,19 +197,20 @@ def import_custom_attribute_data(container: str, selections: list): rt.addModifier(container, modifier) container.modifiers[0].name = "OP Data" rt.custAttributes.add(container.modifiers[0], attrs) - nodes = {} + node_list = [] + sel_list = [] for i in selections: - nodes = { - str(i): rt.NodeTransformMonitor(node=i), - } + node_ref = rt.NodeTransformMonitor(node=i) + node_list.append(node_ref) + sel_list.append(str(i)) + # Setting the property rt.setProperty( container.modifiers[0].openPypeData, - "all_handles", nodes.values()) + "all_handles", node_list) rt.setProperty( container.modifiers[0].openPypeData, - "sel_list", nodes.keys()) - + "sel_list", sel_list) def update_custom_attribute_data(container: str, selections: list): """Updating the Openpype/AYON custom parameter built by the creator From 167527f2bf1b8fed25f38d84d08f0edca6bb718c Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 4 Sep 2023 23:55:41 +0200 Subject: [PATCH 133/154] Fix Houdini not showing outdated containers pop-up on scene open when launching with last workfile argument --- openpype/hosts/houdini/api/pipeline.py | 48 ++++++++++++++++---------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/openpype/hosts/houdini/api/pipeline.py b/openpype/hosts/houdini/api/pipeline.py index 3c325edfa7..c9ae801af5 100644 --- a/openpype/hosts/houdini/api/pipeline.py +++ b/openpype/hosts/houdini/api/pipeline.py @@ -303,6 +303,28 @@ def on_save(): lib.set_id(node, new_id, overwrite=False) +def _show_outdated_content_popup(): + # Get main window + parent = lib.get_main_window() + if parent is None: + log.info("Skipping outdated content pop-up " + "because Houdini window can't be found.") + else: + from openpype.widgets import popup + + # Show outdated pop-up + def _on_show_inventory(): + from openpype.tools.utils import host_tools + host_tools.show_scene_inventory(parent=parent) + + dialog = popup.Popup(parent=parent) + dialog.setWindowTitle("Houdini scene has outdated content") + dialog.setMessage("There are outdated containers in " + "your Houdini scene.") + dialog.on_clicked.connect(_on_show_inventory) + dialog.show() + + def on_open(): if not hou.isUIAvailable(): @@ -316,28 +338,18 @@ def on_open(): lib.validate_fps() if any_outdated_containers(): - from openpype.widgets import popup - - log.warning("Scene has outdated content.") - - # Get main window parent = lib.get_main_window() if parent is None: - log.info("Skipping outdated content pop-up " - "because Houdini window can't be found.") + # When opening Houdini with last workfile on launch the UI hasn't + # initialized yet completely when the `on_open` callback triggers. + # We defer the dialog popup to wait for the UI to become available. + # We assume it will open because `hou.isUIAvailable()` returns True + import hdefereval + hdefereval.executeDeferred(_show_outdated_content_popup) else: + _show_outdated_content_popup() - # Show outdated pop-up - def _on_show_inventory(): - from openpype.tools.utils import host_tools - host_tools.show_scene_inventory(parent=parent) - - dialog = popup.Popup(parent=parent) - dialog.setWindowTitle("Houdini scene has outdated content") - dialog.setMessage("There are outdated containers in " - "your Houdini scene.") - dialog.on_clicked.connect(_on_show_inventory) - dialog.show() + log.warning("Scene has outdated content.") def on_new(): From 7c29aa2f7b72dd0a94a5a3531bc8a65c6d1cd3bb Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 5 Sep 2023 00:00:03 +0200 Subject: [PATCH 134/154] Improve errors e.g. raise PublishValidationError or cosmetics --- .../houdini/plugins/publish/collect_output_node.py | 6 ++++-- .../plugins/publish/validate_animation_settings.py | 3 ++- .../plugins/publish/validate_remote_publish.py | 11 +++++------ .../publish/validate_usd_render_product_names.py | 2 +- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/openpype/hosts/houdini/plugins/publish/collect_output_node.py b/openpype/hosts/houdini/plugins/publish/collect_output_node.py index 601ed17b39..0b27678ed0 100644 --- a/openpype/hosts/houdini/plugins/publish/collect_output_node.py +++ b/openpype/hosts/houdini/plugins/publish/collect_output_node.py @@ -1,5 +1,7 @@ import pyblish.api +from openpype.pipeline.publish import KnownPublishError + class CollectOutputSOPPath(pyblish.api.InstancePlugin): """Collect the out node's SOP/COP Path value.""" @@ -58,8 +60,8 @@ class CollectOutputSOPPath(pyblish.api.InstancePlugin): elif node_type == "Redshift_Proxy_Output": out_node = node.parm("RS_archive_sopPath").evalAsNode() else: - raise ValueError( - "ROP node type '%s' is" " not supported." % node_type + raise KnownPublishError( + "ROP node type '{}' is not supported.".format(node_type) ) if not out_node: diff --git a/openpype/hosts/houdini/plugins/publish/validate_animation_settings.py b/openpype/hosts/houdini/plugins/publish/validate_animation_settings.py index 4878738ed3..79387fbef5 100644 --- a/openpype/hosts/houdini/plugins/publish/validate_animation_settings.py +++ b/openpype/hosts/houdini/plugins/publish/validate_animation_settings.py @@ -1,5 +1,6 @@ import pyblish.api +from openpype.pipeline.publish import PublishValidationError from openpype.hosts.houdini.api import lib import hou @@ -30,7 +31,7 @@ class ValidateAnimationSettings(pyblish.api.InstancePlugin): invalid = self.get_invalid(instance) if invalid: - raise RuntimeError( + raise PublishValidationError( "Output settings do no match for '%s'" % instance ) diff --git a/openpype/hosts/houdini/plugins/publish/validate_remote_publish.py b/openpype/hosts/houdini/plugins/publish/validate_remote_publish.py index 4e8e5fc0e8..4f71d79382 100644 --- a/openpype/hosts/houdini/plugins/publish/validate_remote_publish.py +++ b/openpype/hosts/houdini/plugins/publish/validate_remote_publish.py @@ -36,11 +36,11 @@ class ValidateRemotePublishOutNode(pyblish.api.ContextPlugin): if node.parm("shellexec").eval(): self.raise_error("Must not execute in shell") if node.parm("prerender").eval() != cmd: - self.raise_error(("REMOTE_PUBLISH node does not have " - "correct prerender script.")) + self.raise_error("REMOTE_PUBLISH node does not have " + "correct prerender script.") if node.parm("lprerender").eval() != "python": - self.raise_error(("REMOTE_PUBLISH node prerender script " - "type not set to 'python'")) + self.raise_error("REMOTE_PUBLISH node prerender script " + "type not set to 'python'") @classmethod def repair(cls, context): @@ -48,5 +48,4 @@ class ValidateRemotePublishOutNode(pyblish.api.ContextPlugin): lib.create_remote_publish_node(force=True) def raise_error(self, message): - self.log.error(message) - raise PublishValidationError(message, title=self.label) + raise PublishValidationError(message) diff --git a/openpype/hosts/houdini/plugins/publish/validate_usd_render_product_names.py b/openpype/hosts/houdini/plugins/publish/validate_usd_render_product_names.py index 02c44ab94e..1daa96f2b9 100644 --- a/openpype/hosts/houdini/plugins/publish/validate_usd_render_product_names.py +++ b/openpype/hosts/houdini/plugins/publish/validate_usd_render_product_names.py @@ -24,7 +24,7 @@ class ValidateUSDRenderProductNames(pyblish.api.InstancePlugin): if not os.path.isabs(filepath): invalid.append( - "Output file path is not " "absolute path: %s" % filepath + "Output file path is not absolute path: %s" % filepath ) if invalid: From 0e580ad3190f9cfa15243ebde5e99f02e3c95e71 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 5 Sep 2023 00:02:59 +0200 Subject: [PATCH 135/154] Fix invalid import `openpype.action` does not exist + raise KnownPublishError --- .../houdini/plugins/publish/increment_current_file.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/openpype/hosts/houdini/plugins/publish/increment_current_file.py b/openpype/hosts/houdini/plugins/publish/increment_current_file.py index 2493b28bc1..3569de7693 100644 --- a/openpype/hosts/houdini/plugins/publish/increment_current_file.py +++ b/openpype/hosts/houdini/plugins/publish/increment_current_file.py @@ -2,7 +2,7 @@ import pyblish.api from openpype.lib import version_up from openpype.pipeline import registered_host -from openpype.action import get_errored_plugins_from_data +from openpype.pipeline.publish import get_errored_plugins_from_context from openpype.hosts.houdini.api import HoudiniHost from openpype.pipeline.publish import KnownPublishError @@ -27,7 +27,7 @@ class IncrementCurrentFile(pyblish.api.ContextPlugin): def process(self, context): - errored_plugins = get_errored_plugins_from_data(context) + errored_plugins = get_errored_plugins_from_context(context) if any( plugin.__name__ == "HoudiniSubmitPublishDeadline" for plugin in errored_plugins @@ -40,9 +40,10 @@ class IncrementCurrentFile(pyblish.api.ContextPlugin): # Filename must not have changed since collecting host = registered_host() # type: HoudiniHost current_file = host.current_file() - assert ( - context.data["currentFile"] == current_file - ), "Collected filename mismatches from current scene name." + if context.data["currentFile"] != current_file: + raise KnownPublishError( + "Collected filename mismatches from current scene name." + ) new_filepath = version_up(current_file) host.save_workfile(new_filepath) From 10dd15444ad9244618e4e89e4a176d3aaaa2ef58 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 5 Sep 2023 09:03:54 +0200 Subject: [PATCH 136/154] Log collected scene version as debug - artists don't care --- openpype/plugins/publish/collect_scene_version.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openpype/plugins/publish/collect_scene_version.py b/openpype/plugins/publish/collect_scene_version.py index 70a0aca296..7920c1e82b 100644 --- a/openpype/plugins/publish/collect_scene_version.py +++ b/openpype/plugins/publish/collect_scene_version.py @@ -63,4 +63,6 @@ class CollectSceneVersion(pyblish.api.ContextPlugin): "filename: {}".format(filename)) context.data['version'] = int(version) - self.log.info('Scene Version: %s' % context.data.get('version')) + self.log.debug( + "Collected scene version: {}".format(context.data.get('version')) + ) From 43902c0b118019fc770affc9217a751cd6a98c07 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 5 Sep 2023 09:04:13 +0200 Subject: [PATCH 137/154] Add debug log about the skipped input --- .../publish/collect_input_representations_to_versions.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/openpype/plugins/publish/collect_input_representations_to_versions.py b/openpype/plugins/publish/collect_input_representations_to_versions.py index 54a3214647..2b8c745d3d 100644 --- a/openpype/plugins/publish/collect_input_representations_to_versions.py +++ b/openpype/plugins/publish/collect_input_representations_to_versions.py @@ -46,3 +46,10 @@ class CollectInputRepresentationsToVersions(pyblish.api.ContextPlugin): version_id = representation_id_to_version_id.get(repre_id) if version_id: input_versions.append(version_id) + else: + self.log.debug( + "Representation id {} skipped because its version is " + "not found in current project. Likely it is loaded " + "from a library project or uses a deleted " + "representation or version.".format(repre_id) + ) From 97bb0de1a93c92e17be7ff31cc80c3a59cc8300e Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 5 Sep 2023 09:04:40 +0200 Subject: [PATCH 138/154] Raise KnownPublishError --- openpype/plugins/publish/extract_review_slate.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/openpype/plugins/publish/extract_review_slate.py b/openpype/plugins/publish/extract_review_slate.py index 8b1a06b6b8..2ff7fbe7fa 100644 --- a/openpype/plugins/publish/extract_review_slate.py +++ b/openpype/plugins/publish/extract_review_slate.py @@ -14,10 +14,13 @@ from openpype.lib import ( get_ffmpeg_codec_args, get_ffmpeg_format_args, ) -from openpype.pipeline import publish +from openpype.pipeline.publish import ( + Extractor, + KnownPublishError +) -class ExtractReviewSlate(publish.Extractor): +class ExtractReviewSlate(Extractor): """ Will add slate frame at the start of the video files """ @@ -93,9 +96,10 @@ class ExtractReviewSlate(publish.Extractor): # Raise exception of any stream didn't define input resolution if input_width is None: - raise AssertionError(( + raise KnownPublishError( "FFprobe couldn't read resolution from input file: \"{}\"" - ).format(input_path)) + .format(input_path) + ) ( audio_codec, From 84960826a6250897e262f3c468aadc5a94d23c1a Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 5 Sep 2023 09:05:07 +0200 Subject: [PATCH 139/154] Tweak grammar + log what representations got created --- openpype/plugins/publish/integrate.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/openpype/plugins/publish/integrate.py b/openpype/plugins/publish/integrate.py index 0c18ab4466..7e48155b9e 100644 --- a/openpype/plugins/publish/integrate.py +++ b/openpype/plugins/publish/integrate.py @@ -306,7 +306,7 @@ class IntegrateAsset(pyblish.api.InstancePlugin): # increase if the file transaction takes a long time. op_session.commit() - self.log.info("Subset '{subset[name]}' and Version {version[name]} " + self.log.info("Subset '{subset[name]}' version {version[name]} " "written to database..".format(subset=subset, version=version)) @@ -392,8 +392,13 @@ class IntegrateAsset(pyblish.api.InstancePlugin): p["representation"]["_id"]: p for p in prepared_representations } - self.log.info("Registered {} representations" - "".format(len(prepared_representations))) + self.log.info( + "Registered {} representations: {}".format( + len(prepared_representations), + ", ".join(p["representation"]["name"] + for p in prepared_representations) + ) + ) def prepare_subset(self, instance, op_session, project_name): asset_doc = instance.data["assetEntity"] From 4749ac80400346fd4b8ac27f3de4346ba526ba25 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 5 Sep 2023 09:05:40 +0200 Subject: [PATCH 140/154] Raise PublishValidationError --- openpype/plugins/publish/validate_file_saved.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openpype/plugins/publish/validate_file_saved.py b/openpype/plugins/publish/validate_file_saved.py index 448eaccf57..94aadc9358 100644 --- a/openpype/plugins/publish/validate_file_saved.py +++ b/openpype/plugins/publish/validate_file_saved.py @@ -1,5 +1,7 @@ import pyblish.api +from openpype.pipeline.publish import PublishValidationError + class ValidateCurrentSaveFile(pyblish.api.ContextPlugin): """File must be saved before publishing""" @@ -12,4 +14,4 @@ class ValidateCurrentSaveFile(pyblish.api.ContextPlugin): current_file = context.data["currentFile"] if not current_file: - raise RuntimeError("File not saved") + raise PublishValidationError("File not saved") From 68ab2fc934e6a11995884ad1472cb04567f7c271 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 5 Sep 2023 09:06:07 +0200 Subject: [PATCH 141/154] Raise PublishValidationError --- .../plugins/publish/validate_filesequences.py | 5 ++++- openpype/plugins/publish/validate_intent.py | 10 ++++------ .../plugins/publish/validate_publish_dir.py | 17 +++++++++-------- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/openpype/plugins/publish/validate_filesequences.py b/openpype/plugins/publish/validate_filesequences.py index 8a877d79bb..0ac281022d 100644 --- a/openpype/plugins/publish/validate_filesequences.py +++ b/openpype/plugins/publish/validate_filesequences.py @@ -1,5 +1,7 @@ import pyblish.api +from openpype.pipeline.publish import PublishValidationError + class ValidateFileSequences(pyblish.api.ContextPlugin): """Validates whether any file sequences were collected.""" @@ -10,4 +12,5 @@ class ValidateFileSequences(pyblish.api.ContextPlugin): label = "Validate File Sequences" def process(self, context): - assert context, "Nothing collected." + if not context: + raise PublishValidationError("Nothing collected.") diff --git a/openpype/plugins/publish/validate_intent.py b/openpype/plugins/publish/validate_intent.py index 23d57bb2b7..832c7cc0a1 100644 --- a/openpype/plugins/publish/validate_intent.py +++ b/openpype/plugins/publish/validate_intent.py @@ -1,7 +1,7 @@ -import os import pyblish.api from openpype.lib import filter_profiles +from openpype.pipeline.publish import PublishValidationError class ValidateIntent(pyblish.api.ContextPlugin): @@ -51,12 +51,10 @@ class ValidateIntent(pyblish.api.ContextPlugin): )) return - msg = ( - "Please make sure that you select the intent of this publish." - ) - intent = context.data.get("intent") or {} self.log.debug(str(intent)) intent_value = intent.get("value") if not intent_value: - raise AssertionError(msg) + raise PublishValidationError( + "Please make sure that you select the intent of this publish." + ) diff --git a/openpype/plugins/publish/validate_publish_dir.py b/openpype/plugins/publish/validate_publish_dir.py index ad5fd34434..0eb93da583 100644 --- a/openpype/plugins/publish/validate_publish_dir.py +++ b/openpype/plugins/publish/validate_publish_dir.py @@ -47,15 +47,16 @@ class ValidatePublishDir(pyblish.api.InstancePlugin): # original_dirname must be convertable to rootless path # in other case it is path inside of root folder for the project success, _ = anatomy.find_root_template_from_path(original_dirname) - - formatting_data = { - "original_dirname": original_dirname, - } - msg = "Path '{}' not in project folder.".format(original_dirname) + \ - " Please publish from inside of project folder." if not success: - raise PublishXmlValidationError(self, msg, key="not_in_dir", - formatting_data=formatting_data) + raise PublishXmlValidationError( + plugin=self, + message=( + "Path '{}' not in project folder. Please publish from " + "inside of project folder.".format(original_dirname) + ), + key="not_in_dir", + formatting_data={"original_dirname": original_dirname} + ) def _get_template_name_from_instance(self, instance): """Find template which will be used during integration.""" From d46f610e4d110a504991c9669fef644ec7e5c747 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Tue, 5 Sep 2023 11:21:46 +0200 Subject: [PATCH 142/154] removed switch_ui script from fusion with related script in 'scripts' --- .../deploy/Scripts/Comp/OpenPype/switch_ui.py | 200 --------------- openpype/scripts/fusion_switch_shot.py | 241 ------------------ 2 files changed, 441 deletions(-) delete mode 100644 openpype/hosts/fusion/deploy/Scripts/Comp/OpenPype/switch_ui.py delete mode 100644 openpype/scripts/fusion_switch_shot.py diff --git a/openpype/hosts/fusion/deploy/Scripts/Comp/OpenPype/switch_ui.py b/openpype/hosts/fusion/deploy/Scripts/Comp/OpenPype/switch_ui.py deleted file mode 100644 index 87322235f5..0000000000 --- a/openpype/hosts/fusion/deploy/Scripts/Comp/OpenPype/switch_ui.py +++ /dev/null @@ -1,200 +0,0 @@ -import os -import sys -import glob -import logging - -from qtpy import QtWidgets, QtCore - -import qtawesome as qta - -from openpype.client import get_assets -from openpype import style -from openpype.pipeline import ( - install_host, - get_current_project_name, -) -from openpype.hosts.fusion import api -from openpype.pipeline.context_tools import get_workdir_from_session - -log = logging.getLogger("Fusion Switch Shot") - - -class App(QtWidgets.QWidget): - - def __init__(self, parent=None): - - ################################################ - # |---------------------| |------------------| # - # |Comp | |Asset | # - # |[..][ v]| |[ v]| # - # |---------------------| |------------------| # - # | Update existing comp [ ] | # - # |------------------------------------------| # - # | Switch | # - # |------------------------------------------| # - ################################################ - - QtWidgets.QWidget.__init__(self, parent) - - layout = QtWidgets.QVBoxLayout() - - # Comp related input - comp_hlayout = QtWidgets.QHBoxLayout() - comp_label = QtWidgets.QLabel("Comp file") - comp_label.setFixedWidth(50) - comp_box = QtWidgets.QComboBox() - - button_icon = qta.icon("fa.folder", color="white") - open_from_dir = QtWidgets.QPushButton() - open_from_dir.setIcon(button_icon) - - comp_box.setFixedHeight(25) - open_from_dir.setFixedWidth(25) - open_from_dir.setFixedHeight(25) - - comp_hlayout.addWidget(comp_label) - comp_hlayout.addWidget(comp_box) - comp_hlayout.addWidget(open_from_dir) - - # Asset related input - asset_hlayout = QtWidgets.QHBoxLayout() - asset_label = QtWidgets.QLabel("Shot") - asset_label.setFixedWidth(50) - - asset_box = QtWidgets.QComboBox() - asset_box.setLineEdit(QtWidgets.QLineEdit()) - asset_box.setFixedHeight(25) - - refresh_icon = qta.icon("fa.refresh", color="white") - refresh_btn = QtWidgets.QPushButton() - refresh_btn.setIcon(refresh_icon) - - asset_box.setFixedHeight(25) - refresh_btn.setFixedWidth(25) - refresh_btn.setFixedHeight(25) - - asset_hlayout.addWidget(asset_label) - asset_hlayout.addWidget(asset_box) - asset_hlayout.addWidget(refresh_btn) - - # Options - options = QtWidgets.QHBoxLayout() - options.setAlignment(QtCore.Qt.AlignLeft) - - current_comp_check = QtWidgets.QCheckBox() - current_comp_check.setChecked(True) - current_comp_label = QtWidgets.QLabel("Use current comp") - - options.addWidget(current_comp_label) - options.addWidget(current_comp_check) - - accept_btn = QtWidgets.QPushButton("Switch") - - layout.addLayout(options) - layout.addLayout(comp_hlayout) - layout.addLayout(asset_hlayout) - layout.addWidget(accept_btn) - - self._open_from_dir = open_from_dir - self._comps = comp_box - self._assets = asset_box - self._use_current = current_comp_check - self._accept_btn = accept_btn - self._refresh_btn = refresh_btn - - self.setWindowTitle("Fusion Switch Shot") - self.setLayout(layout) - - self.resize(260, 140) - self.setMinimumWidth(260) - self.setFixedHeight(140) - - self.connections() - - # Update ui to correct state - self._on_use_current_comp() - self._refresh() - - def connections(self): - self._use_current.clicked.connect(self._on_use_current_comp) - self._open_from_dir.clicked.connect(self._on_open_from_dir) - self._refresh_btn.clicked.connect(self._refresh) - self._accept_btn.clicked.connect(self._on_switch) - - def _on_use_current_comp(self): - state = self._use_current.isChecked() - self._open_from_dir.setEnabled(not state) - self._comps.setEnabled(not state) - - def _on_open_from_dir(self): - - start_dir = get_workdir_from_session() - comp_file, _ = QtWidgets.QFileDialog.getOpenFileName( - self, "Choose comp", start_dir) - - if not comp_file: - return - - # Create completer - self.populate_comp_box([comp_file]) - self._refresh() - - def _refresh(self): - # Clear any existing items - self._assets.clear() - - asset_names = self.collect_asset_names() - completer = QtWidgets.QCompleter(asset_names) - - self._assets.setCompleter(completer) - self._assets.addItems(asset_names) - - def _on_switch(self): - - if not self._use_current.isChecked(): - file_name = self._comps.itemData(self._comps.currentIndex()) - else: - comp = api.get_current_comp() - file_name = comp.GetAttrs("COMPS_FileName") - - asset = self._assets.currentText() - - import colorbleed.scripts.fusion_switch_shot as switch_shot - switch_shot.switch(asset_name=asset, filepath=file_name, new=True) - - def collect_slap_comps(self, directory): - items = glob.glob("{}/*.comp".format(directory)) - return items - - def collect_asset_names(self): - project_name = get_current_project_name() - asset_docs = get_assets(project_name, fields=["name"]) - asset_names = { - asset_doc["name"] - for asset_doc in asset_docs - } - return list(asset_names) - - def populate_comp_box(self, files): - """Ensure we display the filename only but the path is stored as well - - Args: - files (list): list of full file path [path/to/item/item.ext,] - - Returns: - None - """ - - for f in files: - filename = os.path.basename(f) - self._comps.addItem(filename, userData=f) - - -if __name__ == '__main__': - install_host(api) - - app = QtWidgets.QApplication(sys.argv) - window = App() - window.setStyleSheet(style.load_stylesheet()) - window.show() - sys.exit(app.exec_()) diff --git a/openpype/scripts/fusion_switch_shot.py b/openpype/scripts/fusion_switch_shot.py deleted file mode 100644 index 1cc728226f..0000000000 --- a/openpype/scripts/fusion_switch_shot.py +++ /dev/null @@ -1,241 +0,0 @@ -import os -import re -import sys -import logging - -from openpype.client import get_asset_by_name, get_versions - -# Pipeline imports -from openpype.hosts.fusion import api -import openpype.hosts.fusion.api.lib as fusion_lib - -# Config imports -from openpype.lib import version_up -from openpype.pipeline import ( - install_host, - registered_host, - legacy_io, - get_current_project_name, -) - -from openpype.pipeline.context_tools import get_workdir_from_session -from openpype.pipeline.version_start import get_versioning_start - -log = logging.getLogger("Update Slap Comp") - - -def _format_version_folder(folder): - """Format a version folder based on the filepath - - Args: - folder: file path to a folder - - Returns: - str: new version folder name - """ - - new_version = get_versioning_start( - get_current_project_name(), - "fusion", - family="workfile" - ) - if os.path.isdir(folder): - re_version = re.compile(r"v\d+$") - versions = [i for i in os.listdir(folder) if os.path.isdir(i) - and re_version.match(i)] - if versions: - # ensure the "v" is not included - new_version = int(max(versions)[1:]) + 1 - - version_folder = "v{:03d}".format(new_version) - - return version_folder - - -def _get_fusion_instance(): - fusion = getattr(sys.modules["__main__"], "fusion", None) - if fusion is None: - try: - # Support for FuScript.exe, BlackmagicFusion module for py2 only - import BlackmagicFusion as bmf - fusion = bmf.scriptapp("Fusion") - except ImportError: - raise RuntimeError("Could not find a Fusion instance") - return fusion - - -def _format_filepath(session): - - project = session["AVALON_PROJECT"] - asset = session["AVALON_ASSET"] - - # Save updated slap comp - work_path = get_workdir_from_session(session) - walk_to_dir = os.path.join(work_path, "scenes", "slapcomp") - slapcomp_dir = os.path.abspath(walk_to_dir) - - # Ensure destination exists - if not os.path.isdir(slapcomp_dir): - log.warning("Folder did not exist, creating folder structure") - os.makedirs(slapcomp_dir) - - # Compute output path - new_filename = "{}_{}_slapcomp_v001.comp".format(project, asset) - new_filepath = os.path.join(slapcomp_dir, new_filename) - - # Create new unqiue filepath - if os.path.exists(new_filepath): - new_filepath = version_up(new_filepath) - - return new_filepath - - -def _update_savers(comp, session): - """Update all savers of the current comp to ensure the output is correct - - Args: - comp (object): current comp instance - session (dict): the current Avalon session - - Returns: - None - """ - - new_work = get_workdir_from_session(session) - renders = os.path.join(new_work, "renders") - version_folder = _format_version_folder(renders) - renders_version = os.path.join(renders, version_folder) - - comp.Print("New renders to: %s\n" % renders) - - with api.comp_lock_and_undo_chunk(comp): - savers = comp.GetToolList(False, "Saver").values() - for saver in savers: - filepath = saver.GetAttrs("TOOLST_Clip_Name")[1.0] - filename = os.path.basename(filepath) - new_path = os.path.join(renders_version, filename) - saver["Clip"] = new_path - - -def update_frame_range(comp, representations): - """Update the frame range of the comp and render length - - The start and end frame are based on the lowest start frame and the highest - end frame - - Args: - comp (object): current focused comp - representations (list) collection of dicts - - Returns: - None - - """ - - version_ids = [r["parent"] for r in representations] - project_name = get_current_project_name() - versions = list(get_versions(project_name, version_ids=version_ids)) - - start = min(v["data"]["frameStart"] for v in versions) - end = max(v["data"]["frameEnd"] for v in versions) - - fusion_lib.update_frame_range(start, end, comp=comp) - - -def switch(asset_name, filepath=None, new=True): - """Switch the current containers of the file to the other asset (shot) - - Args: - filepath (str): file path of the comp file - asset_name (str): name of the asset (shot) - new (bool): Save updated comp under a different name - - Returns: - comp path (str): new filepath of the updated comp - - """ - - # If filepath provided, ensure it is valid absolute path - if filepath is not None: - if not os.path.isabs(filepath): - filepath = os.path.abspath(filepath) - - assert os.path.exists(filepath), "%s must exist " % filepath - - # Assert asset name exists - # It is better to do this here then to wait till switch_shot does it - project_name = get_current_project_name() - asset = get_asset_by_name(project_name, asset_name) - assert asset, "Could not find '%s' in the database" % asset_name - - # Go to comp - if not filepath: - current_comp = api.get_current_comp() - assert current_comp is not None, "Could not find current comp" - else: - fusion = _get_fusion_instance() - current_comp = fusion.LoadComp(filepath, quiet=True) - assert current_comp is not None, "Fusion could not load '%s'" % filepath - - host = registered_host() - containers = list(host.ls()) - assert containers, "Nothing to update" - - representations = [] - for container in containers: - try: - representation = fusion_lib.switch_item(container, - asset_name=asset_name) - representations.append(representation) - except Exception as e: - current_comp.Print("Error in switching! %s\n" % e.message) - - message = "Switched %i Loaders of the %i\n" % (len(representations), - len(containers)) - current_comp.Print(message) - - # Build the session to switch to - switch_to_session = legacy_io.Session.copy() - switch_to_session["AVALON_ASSET"] = asset['name'] - - if new: - comp_path = _format_filepath(switch_to_session) - - # Update savers output based on new session - _update_savers(current_comp, switch_to_session) - else: - comp_path = version_up(filepath) - - current_comp.Print(comp_path) - - current_comp.Print("\nUpdating frame range") - update_frame_range(current_comp, representations) - - current_comp.Save(comp_path) - - return comp_path - - -if __name__ == '__main__': - - import argparse - - parser = argparse.ArgumentParser(description="Switch to a shot within an" - "existing comp file") - - parser.add_argument("--file_path", - type=str, - default=True, - help="File path of the comp to use") - - parser.add_argument("--asset_name", - type=str, - default=True, - help="Name of the asset (shot) to switch") - - args, unknown = parser.parse_args() - - install_host(api) - switch(args.asset_name, args.file_path) - - sys.exit(0) From 2b8ec005fcc39f54e5a9f14a0352f98f6997034e Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Tue, 5 Sep 2023 11:27:31 +0200 Subject: [PATCH 143/154] removed remaining scripts after discussion with @BigRoy --- .../32bit/backgrounds_selected_to32bit.py | 16 -------- .../OpenPype/32bit/backgrounds_to32bit.py | 16 -------- .../32bit/loaders_selected_to32bit.py | 16 -------- .../Comp/OpenPype/32bit/loaders_to32bit.py | 16 -------- .../Comp/OpenPype/update_loader_ranges.py | 40 ------------------- 5 files changed, 104 deletions(-) delete mode 100644 openpype/hosts/fusion/deploy/Scripts/Comp/OpenPype/32bit/backgrounds_selected_to32bit.py delete mode 100644 openpype/hosts/fusion/deploy/Scripts/Comp/OpenPype/32bit/backgrounds_to32bit.py delete mode 100644 openpype/hosts/fusion/deploy/Scripts/Comp/OpenPype/32bit/loaders_selected_to32bit.py delete mode 100644 openpype/hosts/fusion/deploy/Scripts/Comp/OpenPype/32bit/loaders_to32bit.py delete mode 100644 openpype/hosts/fusion/deploy/Scripts/Comp/OpenPype/update_loader_ranges.py diff --git a/openpype/hosts/fusion/deploy/Scripts/Comp/OpenPype/32bit/backgrounds_selected_to32bit.py b/openpype/hosts/fusion/deploy/Scripts/Comp/OpenPype/32bit/backgrounds_selected_to32bit.py deleted file mode 100644 index 1a0a9911ea..0000000000 --- a/openpype/hosts/fusion/deploy/Scripts/Comp/OpenPype/32bit/backgrounds_selected_to32bit.py +++ /dev/null @@ -1,16 +0,0 @@ -from openpype.hosts.fusion.api import ( - comp_lock_and_undo_chunk, - get_current_comp -) - - -def main(): - comp = get_current_comp() - """Set all selected backgrounds to 32 bit""" - with comp_lock_and_undo_chunk(comp, 'Selected Backgrounds to 32bit'): - tools = comp.GetToolList(True, "Background").values() - for tool in tools: - tool.Depth = 5 - - -main() diff --git a/openpype/hosts/fusion/deploy/Scripts/Comp/OpenPype/32bit/backgrounds_to32bit.py b/openpype/hosts/fusion/deploy/Scripts/Comp/OpenPype/32bit/backgrounds_to32bit.py deleted file mode 100644 index c2eea505e5..0000000000 --- a/openpype/hosts/fusion/deploy/Scripts/Comp/OpenPype/32bit/backgrounds_to32bit.py +++ /dev/null @@ -1,16 +0,0 @@ -from openpype.hosts.fusion.api import ( - comp_lock_and_undo_chunk, - get_current_comp -) - - -def main(): - comp = get_current_comp() - """Set all backgrounds to 32 bit""" - with comp_lock_and_undo_chunk(comp, 'Backgrounds to 32bit'): - tools = comp.GetToolList(False, "Background").values() - for tool in tools: - tool.Depth = 5 - - -main() diff --git a/openpype/hosts/fusion/deploy/Scripts/Comp/OpenPype/32bit/loaders_selected_to32bit.py b/openpype/hosts/fusion/deploy/Scripts/Comp/OpenPype/32bit/loaders_selected_to32bit.py deleted file mode 100644 index 2118767f4d..0000000000 --- a/openpype/hosts/fusion/deploy/Scripts/Comp/OpenPype/32bit/loaders_selected_to32bit.py +++ /dev/null @@ -1,16 +0,0 @@ -from openpype.hosts.fusion.api import ( - comp_lock_and_undo_chunk, - get_current_comp -) - - -def main(): - comp = get_current_comp() - """Set all selected loaders to 32 bit""" - with comp_lock_and_undo_chunk(comp, 'Selected Loaders to 32bit'): - tools = comp.GetToolList(True, "Loader").values() - for tool in tools: - tool.Depth = 5 - - -main() diff --git a/openpype/hosts/fusion/deploy/Scripts/Comp/OpenPype/32bit/loaders_to32bit.py b/openpype/hosts/fusion/deploy/Scripts/Comp/OpenPype/32bit/loaders_to32bit.py deleted file mode 100644 index 7dd1f66a5e..0000000000 --- a/openpype/hosts/fusion/deploy/Scripts/Comp/OpenPype/32bit/loaders_to32bit.py +++ /dev/null @@ -1,16 +0,0 @@ -from openpype.hosts.fusion.api import ( - comp_lock_and_undo_chunk, - get_current_comp -) - - -def main(): - comp = get_current_comp() - """Set all loaders to 32 bit""" - with comp_lock_and_undo_chunk(comp, 'Loaders to 32bit'): - tools = comp.GetToolList(False, "Loader").values() - for tool in tools: - tool.Depth = 5 - - -main() diff --git a/openpype/hosts/fusion/deploy/Scripts/Comp/OpenPype/update_loader_ranges.py b/openpype/hosts/fusion/deploy/Scripts/Comp/OpenPype/update_loader_ranges.py deleted file mode 100644 index 3d2d1ecfa6..0000000000 --- a/openpype/hosts/fusion/deploy/Scripts/Comp/OpenPype/update_loader_ranges.py +++ /dev/null @@ -1,40 +0,0 @@ -"""Forces Fusion to 'retrigger' the Loader to update. - -Warning: - This might change settings like 'Reverse', 'Loop', trims and other - settings of the Loader. So use this at your own risk. - -""" -from openpype.hosts.fusion.api.pipeline import ( - get_current_comp, - comp_lock_and_undo_chunk -) - - -def update_loader_ranges(): - comp = get_current_comp() - with comp_lock_and_undo_chunk(comp, "Reload clip time ranges"): - tools = comp.GetToolList(True, "Loader").values() - for tool in tools: - - # Get tool attributes - tool_a = tool.GetAttrs() - clipTable = tool_a['TOOLST_Clip_Name'] - altclipTable = tool_a['TOOLST_AltClip_Name'] - startTime = tool_a['TOOLNT_Clip_Start'] - old_global_in = tool.GlobalIn[comp.CurrentTime] - - # Reapply - for index, _ in clipTable.items(): - time = startTime[index] - tool.Clip[time] = tool.Clip[time] - - for index, _ in altclipTable.items(): - time = startTime[index] - tool.ProxyFilename[time] = tool.ProxyFilename[time] - - tool.GlobalIn[comp.CurrentTime] = old_global_in - - -if __name__ == '__main__': - update_loader_ranges() From bde5a560a207dfb28839cb336b30fb59bb0762f0 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Tue, 5 Sep 2023 11:28:25 +0200 Subject: [PATCH 144/154] Removed ';OpenPype:Scripts' from prefs file --- openpype/hosts/fusion/deploy/fusion_shared.prefs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/fusion/deploy/fusion_shared.prefs b/openpype/hosts/fusion/deploy/fusion_shared.prefs index b379ea7c66..93b08aa886 100644 --- a/openpype/hosts/fusion/deploy/fusion_shared.prefs +++ b/openpype/hosts/fusion/deploy/fusion_shared.prefs @@ -5,7 +5,7 @@ Global = { Map = { ["OpenPype:"] = "$(OPENPYPE_FUSION)/deploy", ["Config:"] = "UserPaths:Config;OpenPype:Config", - ["Scripts:"] = "UserPaths:Scripts;Reactor:System/Scripts;OpenPype:Scripts", + ["Scripts:"] = "UserPaths:Scripts;Reactor:System/Scripts", }, }, Script = { From 564cb31cbe700aef687f6b11969eb530973e60d9 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 5 Sep 2023 12:05:40 +0200 Subject: [PATCH 145/154] Fix base `Extractor` being picked up as a plug-in to process --- openpype/plugins/publish/extract_review_slate.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/openpype/plugins/publish/extract_review_slate.py b/openpype/plugins/publish/extract_review_slate.py index 2ff7fbe7fa..d89fbb90c4 100644 --- a/openpype/plugins/publish/extract_review_slate.py +++ b/openpype/plugins/publish/extract_review_slate.py @@ -14,13 +14,11 @@ from openpype.lib import ( get_ffmpeg_codec_args, get_ffmpeg_format_args, ) -from openpype.pipeline.publish import ( - Extractor, - KnownPublishError -) +from openpype.pipeline import publish +from openpype.pipeline.publish import KnownPublishError -class ExtractReviewSlate(Extractor): +class ExtractReviewSlate(publish.Extractor): """ Will add slate frame at the start of the video files """ From e2c3a0f5be2be18ab71cfbd65632f66f1a8b218e Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Tue, 5 Sep 2023 17:33:25 +0200 Subject: [PATCH 146/154] better check of overriden '__init__' method --- openpype/pipeline/create/creator_plugins.py | 30 ++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/openpype/pipeline/create/creator_plugins.py b/openpype/pipeline/create/creator_plugins.py index de9cc7cff3..ab0d36e67e 100644 --- a/openpype/pipeline/create/creator_plugins.py +++ b/openpype/pipeline/create/creator_plugins.py @@ -214,7 +214,7 @@ class BaseCreator: # Backwards compatibility for system settings self.apply_settings(project_settings, system_settings) - init_overriden = self.__class__.__init__ is not BaseCreator.__init__ + init_overriden = self._method_is_overriden("__init__") if init_overriden or expect_system_settings: self.log.warning(( "WARNING: Source - Create plugin {}." @@ -225,6 +225,19 @@ class BaseCreator: " need to keep system settings." ).format(self.__class__.__name__)) + def _method_is_overriden(self, method_name): + """Check if method is overriden on objects class. + + Implemented for deprecation warning validation on init. + + Returns: + bool: True if method is overriden on objects class. + """ + + cls_method = getattr(BaseCreator, method_name) + obj_method = getattr(self.__class__, method_name) + return cls_method is not obj_method + def apply_settings(self, project_settings): """Method called on initialization of plugin to apply settings. @@ -578,6 +591,11 @@ class Creator(BaseCreator): ) super(Creator, self).__init__(*args, **kwargs) + def _method_is_overriden(self, method_name): + cls_method = getattr(Creator, method_name) + obj_method = getattr(self.__class__, method_name) + return cls_method is not obj_method + @property def show_order(self): """Order in which is creator shown in UI. @@ -720,6 +738,11 @@ class HiddenCreator(BaseCreator): def create(self, instance_data, source_data): pass + def _method_is_overriden(self, method_name): + cls_method = getattr(HiddenCreator, method_name) + obj_method = getattr(self.__class__, method_name) + return cls_method is not obj_method + class AutoCreator(BaseCreator): """Creator which is automatically triggered without user interaction. @@ -731,6 +754,11 @@ class AutoCreator(BaseCreator): """Skip removement.""" pass + def _method_is_overriden(self, method_name): + cls_method = getattr(AutoCreator, method_name) + obj_method = getattr(self.__class__, method_name) + return cls_method is not obj_method + def discover_creator_plugins(*args, **kwargs): return discover(BaseCreator, *args, **kwargs) From c3847aec5186d26414f220369a89234f70740706 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Tue, 5 Sep 2023 17:55:37 +0200 Subject: [PATCH 147/154] removed '_method_is_overriden' and use explicit class checks --- openpype/pipeline/create/creator_plugins.py | 40 ++++++--------------- 1 file changed, 10 insertions(+), 30 deletions(-) diff --git a/openpype/pipeline/create/creator_plugins.py b/openpype/pipeline/create/creator_plugins.py index ab0d36e67e..6aa08cae70 100644 --- a/openpype/pipeline/create/creator_plugins.py +++ b/openpype/pipeline/create/creator_plugins.py @@ -214,8 +214,16 @@ class BaseCreator: # Backwards compatibility for system settings self.apply_settings(project_settings, system_settings) - init_overriden = self._method_is_overriden("__init__") - if init_overriden or expect_system_settings: + init_use_base = any( + self.__class__.__init__ is cls.__init__ + for cls in { + BaseCreator, + Creator, + HiddenCreator, + AutoCreator, + } + ) + if not init_use_base or expect_system_settings: self.log.warning(( "WARNING: Source - Create plugin {}." " System settings argument will not be passed to" @@ -225,19 +233,6 @@ class BaseCreator: " need to keep system settings." ).format(self.__class__.__name__)) - def _method_is_overriden(self, method_name): - """Check if method is overriden on objects class. - - Implemented for deprecation warning validation on init. - - Returns: - bool: True if method is overriden on objects class. - """ - - cls_method = getattr(BaseCreator, method_name) - obj_method = getattr(self.__class__, method_name) - return cls_method is not obj_method - def apply_settings(self, project_settings): """Method called on initialization of plugin to apply settings. @@ -591,11 +586,6 @@ class Creator(BaseCreator): ) super(Creator, self).__init__(*args, **kwargs) - def _method_is_overriden(self, method_name): - cls_method = getattr(Creator, method_name) - obj_method = getattr(self.__class__, method_name) - return cls_method is not obj_method - @property def show_order(self): """Order in which is creator shown in UI. @@ -738,11 +728,6 @@ class HiddenCreator(BaseCreator): def create(self, instance_data, source_data): pass - def _method_is_overriden(self, method_name): - cls_method = getattr(HiddenCreator, method_name) - obj_method = getattr(self.__class__, method_name) - return cls_method is not obj_method - class AutoCreator(BaseCreator): """Creator which is automatically triggered without user interaction. @@ -754,11 +739,6 @@ class AutoCreator(BaseCreator): """Skip removement.""" pass - def _method_is_overriden(self, method_name): - cls_method = getattr(AutoCreator, method_name) - obj_method = getattr(self.__class__, method_name) - return cls_method is not obj_method - def discover_creator_plugins(*args, **kwargs): return discover(BaseCreator, *args, **kwargs) From 1b7e1aeed7c09014855f5d16bef37f22f917f3f0 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 5 Sep 2023 18:12:49 +0200 Subject: [PATCH 148/154] Fix attribute definitions for `CreateYetiCache` --- openpype/hosts/maya/plugins/create/create_yeti_cache.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/maya/plugins/create/create_yeti_cache.py b/openpype/hosts/maya/plugins/create/create_yeti_cache.py index 395aa62325..ca002392d4 100644 --- a/openpype/hosts/maya/plugins/create/create_yeti_cache.py +++ b/openpype/hosts/maya/plugins/create/create_yeti_cache.py @@ -13,8 +13,7 @@ class CreateYetiCache(plugin.MayaCreator): family = "yeticache" icon = "pagelines" - def __init__(self, *args, **kwargs): - super(CreateYetiCache, self).__init__(*args, **kwargs) + def get_instance_attr_defs(self): defs = [ NumberDef("preroll", @@ -36,3 +35,5 @@ class CreateYetiCache(plugin.MayaCreator): default=3, decimals=0) ) + + return defs From 896b80322cec4158124a8e43c5c5036059393c0b Mon Sep 17 00:00:00 2001 From: Ynbot Date: Wed, 6 Sep 2023 03:25:11 +0000 Subject: [PATCH 149/154] [Automated] Bump version --- openpype/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/version.py b/openpype/version.py index 7de6fd752b..466f9ce033 100644 --- a/openpype/version.py +++ b/openpype/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring Pype version.""" -__version__ = "3.16.5-nightly.4" +__version__ = "3.16.5-nightly.5" From 83f4c2ea39012f3dc15890dddf421e86606a4dd4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 6 Sep 2023 03:25:50 +0000 Subject: [PATCH 150/154] chore(): update bug report / version --- .github/ISSUE_TEMPLATE/bug_report.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 83a4b6a8d4..f6d1a25dc2 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -35,6 +35,7 @@ body: label: Version description: What version are you running? Look to OpenPype Tray options: + - 3.16.5-nightly.5 - 3.16.5-nightly.4 - 3.16.5-nightly.3 - 3.16.5-nightly.2 @@ -134,7 +135,6 @@ body: - 3.14.9-nightly.2 - 3.14.9-nightly.1 - 3.14.8 - - 3.14.8-nightly.4 validations: required: true - type: dropdown From caad3e57e67f3f54854c33dd19c6d482fe977f54 Mon Sep 17 00:00:00 2001 From: Ynbot Date: Wed, 6 Sep 2023 08:00:16 +0000 Subject: [PATCH 151/154] [Automated] Release --- CHANGELOG.md | 673 ++++++++++++++++++++++++++++++++++++++++++++ openpype/version.py | 2 +- pyproject.toml | 2 +- 3 files changed, 675 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f1948b1a3f..c4f9ff57ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,679 @@ # Changelog +## [3.16.5](https://github.com/ynput/OpenPype/tree/3.16.5) + + +[Full Changelog](https://github.com/ynput/OpenPype/compare/3.16.4...3.16.5) + +### **🆕 New features** + + +
+Attribute Definitions: Multiselection enum def #5547 + +Added `multiselection` option to `EnumDef`. + + +___ + +
+ +### **🚀 Enhancements** + + +
+Farm: adding target collector #5494 + +Enhancing farm publishing workflow. + + +___ + +
+ + +
+Maya: Optimize validate plug-in path attributes #5522 + +- Optimize query (use `cmds.ls` once) +- Add Select Invalid action +- Improve validation report +- Avoid "Unknown object type" errors + + +___ + +
+ + +
+Maya: Remove Validate Instance Attributes plug-in #5525 + +Remove Validate Instance Attributes plug-in. + + +___ + +
+ + +
+Enhancement: Tweak logging for artist facing reports #5537 + +Tweak the logging of publishing for global, deadline, maya and a fusion plugin to have a cleaner artist-facing report. +- Fix context being reported correctly from CollectContext +- Fix ValidateMeshArnoldAttributes: fix when arnold is not loaded, fix applying settings, fix for when ai attributes do not exist + + +___ + +
+ + +
+AYON: Update settings #5544 + +Updated settings in AYON addons and conversion of AYON settings in OpenPype. + + +___ + +
+ + +
+Chore: Removed Ass export script #5560 + +Removed Arnold render script, which was obsolete and unused. + + +___ + +
+ + +
+Nuke: Allow for knob values to be validated against multiple values. #5042 + +Knob values can now be validated against multiple values, so you can allow write nodes to be `exr` and `png`, or `16-bit` and `32-bit`. + + +___ + +
+ + +
+Enhancement: Cosmetics for Higher version of publish already exists validation error #5190 + +Fix double spaces in message.Example output **after** the PR: + + +___ + +
+ + +
+Nuke: publish existing frames on farm #5409 + +This PR proposes adding a fourth option in Nuke render publish called "Use Existing Frames - Farm". This would be useful when the farm is busy or when the artist lacks enough farm licenses. Additionally, some artists prefer rendering on the farm but still want to check frames before publishing.By adding the "Use Existing Frames - Farm" option, artists will have more flexibility and control over their render publishing process. This enhancement will streamline the workflow and improve efficiency for Nuke users. + + +___ + +
+ + +
+Unreal: Create project in temp location and move to final when done #5476 + +Create Unreal project in local temporary folder and when done, move it to final destination. + + +___ + +
+ + +
+TrayPublisher: adding audio product type into default presets #5489 + +Adding Audio product type into default presets so anybody can publish audio to their shots. + + +___ + +
+ + +
+Global: avoiding cleanup of flagged representation #5502 + +Publishing folder can be flagged as persistent at representation level. + + +___ + +
+ + +
+General: missing tag could raise error #5511 + +- avoiding potential situation where missing Tag key could raise error + + +___ + +
+ + +
+Chore: Queued event system #5514 + +Implemented event system with more expected behavior of event system. If an event is triggered during other event callback, it is not processed immediately but waits until all callbacks of previous events are done. The event system also allows to not trigger events directly once `emit_event` is called which gives option to process events in custom loops. + + +___ + +
+ + +
+Publisher: Tweak log message to provide plugin name after "Plugin" #5521 + +Fix logged message for settings automatically applied to plugin attributes + + +___ + +
+ + +
+Houdini: Improve VDB Selection #5523 + +Improves VDB selection if selection is `SopNode`: return the selected sop nodeif selection is `ObjNode`: get the output node with the minimum 'outputidx' or the node with display flag + + +___ + +
+ + +
+Maya: Refactor/tweak Validate Instance In same Context plug-in #5526 + +- Chore/Refactor: Re-use existing select invalid and repair actions +- Enhancement: provide more elaborate PublishValidationError report +- Bugfix: fix "optional" support by using `OptionalPyblishPluginMixin` base class. + + +___ + +
+ + +
+Enhancement: Update houdini main menu #5527 + +This PR adds two updates: +- dynamic main menu +- dynamic asset name and task + + +___ + +
+ + +
+Houdini: Reset FPS when clicking Set Frame Range #5528 + +_Similar to Maya,_ Make `Set Frame Range` resets FPS, issue https://github.com/ynput/OpenPype/issues/5516 + + +___ + +
+ + +
+Enhancement: Deadline plugins optimize, cleanup and fix optional support for validate deadline pools #5531 + +- Fix optional support of validate deadline pools +- Query deadline webservice only once per URL for verification, and once for available deadline pools instead of for every instance +- Use `deadlineUrl` in `instance.data` when validating pools if it is set. +- Code cleanup: Re-use existing `requests_get` implementation + + +___ + +
+ + +
+Chore: PowerShell script for docker build #5535 + +Added PowerShell script to run docker build. + + +___ + +
+ + +
+AYON: Deadline expand userpaths in executables list #5540 + +Expande `~` paths in executables list. + + +___ + +
+ + +
+Chore: Use correct git url #5542 + +Fixed github url in README.md. + + +___ + +
+ + +
+Chore: Create plugin does not expect system settings #5553 + +System settings are not passed to initialization of create plugin initialization (and `apply_settings`). + + +___ + +
+ + +
+Chore: Allow custom Qt scale factor rounding policy #5555 + +Do not force `PassThrough` rounding policy if different policy is defined via env variable. + + +___ + +
+ + +
+Houdini: Fix outdated containers pop-up on opening last workfile on launch #5567 + +Fix Houdini not showing outdated containers pop-up on scene open when launching with last workfile argument + + +___ + +
+ + +
+Houdini: Improve errors e.g. raise PublishValidationError or cosmetics #5568 + +Improve errors e.g. raise PublishValidationError or cosmeticsThis also fixes the Increment Current File plug-in since due to an invalid import it was previously broken + + +___ + +
+ + +
+Fusion: Code updates #5569 + +Update fusion code which contains obsolete code. Removed `switch_ui.py` script from fusion with related script in scripts. + + +___ + +
+ +### **🐛 Bug fixes** + + +
+Maya: Validate Shape Zero fix repair action + provide informational artist-facing report #5524 + +Refactor to PublishValidationError to allow the RepairAction to work + provide informational report message + + +___ + +
+ + +
+Maya: Fix attribute definitions for `CreateYetiCache` #5574 + +Fix attribute definitions for `CreateYetiCache` + + +___ + +
+ + +
+Max: Optional Renderable Camera Validator for Render Instance #5286 + +Optional validation to check on renderable camera being set up correctly for deadline submission.If not being set up correctly, it wont pass the validation and user can perform repair actions. + + +___ + +
+ + +
+Max: Adding custom modifiers back to the loaded objects #5378 + +The custom parameters OpenpypeData doesn't show in the loaded container when it is being loaded through the loader. + + +___ + +
+ + +
+Houdini: Use default_variant to Houdini Node TAB Creator #5421 + +Use the default variant of the creator plugins on the interactive creator from the TAB node search instead of hard-coding it to `Main`. + + +___ + +
+ + +
+Nuke: adding inherited colorspace from instance #5454 + +Thumbnails are extracted with inherited colorspace collected from rendering write node. + + +___ + +
+ + +
+Add kitsu credentials to deadline publish job #5455 + +This PR hopefully fixes this issue #5440 + + +___ + +
+ + +
+AYON: Fill entities during editorial #5475 + +Fill entities and update template data on instances during extract AYON hierarchy. + + +___ + +
+ + +
+Ftrack: Fix version 0 when integrating to Ftrack - OP-6595 #5477 + +Fix publishing version 0 to Ftrack. + + +___ + +
+ + +
+OCIO: windows unc path support in Nuke and Hiero #5479 + +Hiero and Nuke is not supporting windows unc path formatting in OCIO environment variable. + + +___ + +
+ + +
+Deadline: Added super call to init #5480 + +DL 10.3 requires plugin inheriting from DeadlinePlugin to call super's **init** explicitly. + + +___ + +
+ + +
+Nuke: fixing thumbnail and monitor out root attributes #5483 + +Nuke Root Colorspace settings for Thumbnail and Monitor Out schema was gradually changed between version 12, 13, 14 and we needed to address those changes individually for particular version. + + +___ + +
+ + +
+Nuke: fixing missing `instance_id` error #5484 + +Workfiles with Instances created in old publisher workflow were rising error during converting method since they were missing `instance_id` key introduced in new publisher workflow. + + +___ + +
+ + +
+Nuke: existing frames validator is repairing render target #5486 + +Nuke is now correctly repairing render target after the existing frames validator finds missing frames and repair action is used. + + +___ + +
+ + +
+added UE to extract burnins families #5487 + +This PR fixes missing burnins in reviewables when rendering from UE. +___ + +
+ + +
+Harmony: refresh code for current Deadline #5493 + +- Added support in Deadline Plug-in for new versions of Harmony, in particular version 21 and 22. +- Remove review=False flag on render instance +- Add farm=True flag on render instance +- Fix is_in_tests function call in Harmony Deadline submission plugin +- Force HarmonyOpenPype.py Deadline Python plug-in to py3 +- Fix cosmetics/hound in HarmonyOpenPype.py Deadline Python plug-in + + +___ + +
+ + +
+Publisher: Fix multiselection value #5505 + +Selection of multiple instances in Publisher does not cause that all instances change all publish attributes to the same value. + + +___ + +
+ + +
+Publisher: Avoid warnings on thumbnails if source image also has alpha channel #5510 + +Avoids the following warning from `ExtractThumbnailFromSource`: +``` +// pyblish.ExtractThumbnailFromSource : oiiotool WARNING: -o : Can't save 4 channels to jpeg... saving only R,G,B +``` + + + +___ + +
+ + +
+Update ayon-python-api #5512 + +Update ayon python api and related callbacks. + + +___ + +
+ + +
+Max: Fixing the bug of falling back to use workfile for Arnold or any renderers except Redshift #5520 + +Fix the bug of falling back to use workfile for Arnold + + +___ + +
+ + +
+General: Fix Validate Publish Dir Validator #5534 + +Nonsensical "family" key was used instead of real value (as 'render' etc.) which would result in wrong translation of intermediate family names.Updated docstring. + + +___ + +
+ + +
+have the addons loading respect a custom AYON_ADDONS_DIR #5539 + +When using a custom AYON_ADDONS_DIR environment variable that variable is used in the launcher correctly and downloads and extracts addons to there, however when running Ayon does not respect this environment variable + + +___ + +
+ + +
+Deadline: files on representation cannot be single item list #5545 + +Further logic expects that single item files will be only 'string' not 'list' (eg. repre["files"] = "abc.exr" not repre["files"] = ["abc.exr"].This would cause an issue in ExtractReview later.This could happen if DL rendered single frame file with different frame value. + + +___ + +
+ + +
+Webpublisher: better encode list values for click #5546 + +Targets could be a list, original implementation pushed it as a separate items, it must be added as `--targets webpulish --targets filepublish`.`wepublish_routes` handles triggering from UI, changes in `publish_functions` handle triggering from cmd (for tests, api access). + + +___ + +
+ + +
+Houdini: Introduce imprint function for correct version in hda loader #5548 + +Resolve #5478 + + +___ + +
+ + +
+AYON: Fill entities during editorial (2) #5549 + +Fix changes made in https://github.com/ynput/OpenPype/pull/5475. + + +___ + +
+ + +
+Max: OP Data updates in Loaders #5563 + +Fix the bug on the loaders not being able to load the objects when iterating key and values with the dict.Max prefers list over the list in dict. + + +___ + +
+ + +
+Create Plugins: Better check of overriden '__init__' method #5571 + +Create plugins do not log warning messages about each create plugin because of wrong `__init__` method check. + + +___ + +
+ +### **Merged pull requests** + + +
+Tests: fix unit tests #5533 + +Fixed failing tests.Updated Unreal's validator to match removed general one which had a couple of issues fixed. + + +___ + +
+ + + + ## [3.16.4](https://github.com/ynput/OpenPype/tree/3.16.4) diff --git a/openpype/version.py b/openpype/version.py index 466f9ce033..d5d46bab0c 100644 --- a/openpype/version.py +++ b/openpype/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring Pype version.""" -__version__ = "3.16.5-nightly.5" +__version__ = "3.16.5" diff --git a/pyproject.toml b/pyproject.toml index a07c547123..68fbf19c91 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "OpenPype" -version = "3.16.4" # OpenPype +version = "3.16.5" # OpenPype description = "Open VFX and Animation pipeline with support." authors = ["OpenPype Team "] license = "MIT License" From 1c667f91f90dbd3f34df971ece4453efc57ff0a4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 6 Sep 2023 08:01:23 +0000 Subject: [PATCH 152/154] chore(): update bug report / version --- .github/ISSUE_TEMPLATE/bug_report.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index f6d1a25dc2..a35dbf1a17 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -35,6 +35,7 @@ body: label: Version description: What version are you running? Look to OpenPype Tray options: + - 3.16.5 - 3.16.5-nightly.5 - 3.16.5-nightly.4 - 3.16.5-nightly.3 @@ -134,7 +135,6 @@ body: - 3.14.9-nightly.3 - 3.14.9-nightly.2 - 3.14.9-nightly.1 - - 3.14.8 validations: required: true - type: dropdown From 135cb285120495c250a8cbbace25a8581445fb1e Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 6 Sep 2023 22:17:21 +0200 Subject: [PATCH 153/154] Add deprecation warning to usage of `fname` on Loader plugins --- openpype/pipeline/load/plugins.py | 13 +++++++++++++ openpype/pipeline/load/utils.py | 3 ++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/openpype/pipeline/load/plugins.py b/openpype/pipeline/load/plugins.py index f87fb3312d..8acfcfdb6c 100644 --- a/openpype/pipeline/load/plugins.py +++ b/openpype/pipeline/load/plugins.py @@ -234,6 +234,19 @@ class LoaderPlugin(list): """ return cls.options or [] + @property + def fname(self): + """Backwards compatibility with deprecation warning""" + + self.log.warning(( + "DEPRECATION WARNING: Source - Loader plugin {}." + " The 'fname' property on the Loader plugin will be removed in" + " future versions of OpenPype. Planned version to drop the support" + " is 3.16.6 or 3.17.0." + ).format(self.__class__.__name__)) + if hasattr(self, "_fname"): + return self._fname + class SubsetLoaderPlugin(LoaderPlugin): """Load subset into host application diff --git a/openpype/pipeline/load/utils.py b/openpype/pipeline/load/utils.py index 42418be40e..b10d6032b3 100644 --- a/openpype/pipeline/load/utils.py +++ b/openpype/pipeline/load/utils.py @@ -318,7 +318,8 @@ def load_with_repre_context( # Backwards compatibility: Originally the loader's __init__ required the # representation context to set `fname` attribute to the filename to load - loader.fname = get_representation_path_from_context(repre_context) + # Deprecated - to be removed in OpenPype 3.16.6 or 3.17.0. + loader._fname = get_representation_path_from_context(repre_context) return loader.load(repre_context, name, namespace, options) From f954c877023f902a7ab28d2d86401829883734c0 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 6 Sep 2023 22:17:56 +0200 Subject: [PATCH 154/154] Refactor usage of deprecated `self.fname` to new style --- openpype/hosts/blender/plugins/load/load_blend.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/blender/plugins/load/load_blend.py b/openpype/hosts/blender/plugins/load/load_blend.py index 99f291a5a7..fa41f4374b 100644 --- a/openpype/hosts/blender/plugins/load/load_blend.py +++ b/openpype/hosts/blender/plugins/load/load_blend.py @@ -119,7 +119,7 @@ class BlendLoader(plugin.AssetLoader): context: Full parenthood of representation to load options: Additional settings dictionary """ - libpath = self.fname + libpath = self.filepath_from_context(context) asset = context["asset"]["name"] subset = context["subset"]["name"]