From 1a6e7aa041cfdaffbae58ddfada7e03c753b89b5 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 1 Aug 2023 22:05:16 +0800 Subject: [PATCH 01/30] 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 02/30] 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 03/30] 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 04/30] 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 38b905c6f92b7ff4b3b9977c27b77153a35f9e8d Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 8 Aug 2023 18:27:13 +0800 Subject: [PATCH 05/30] 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 67840465ab7cdd2c9f282b13324d53620cbce60d Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 14 Aug 2023 14:36:35 +0800 Subject: [PATCH 06/30] 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 07/30] 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 08/30] 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 09/30] 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 10/30] 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 11/30] 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 12/30] 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 13/30] 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 14/30] 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 15/30] 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 16/30] 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 17/30] 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 18/30] 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 19/30] 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 20/30] 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 f4e42e27ac01faa61c71b2dec930a78361645578 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Fri, 18 Aug 2023 18:43:13 +0800 Subject: [PATCH 21/30] 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 fa80317f6a6fb8ac5f65d11304444cf128b0567a Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 24 Aug 2023 17:08:37 +0800 Subject: [PATCH 22/30] 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 23/30] 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 24/30] 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 098bacddb9e87ac5eb7c8b9e5f1ef2d3f43fa74f Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Fri, 25 Aug 2023 11:54:44 +0800 Subject: [PATCH 25/30] 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 26/30] 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 1a61eb0c3e711cfcf856f7f1ef937949161e89f4 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Fri, 25 Aug 2023 21:29:34 +0800 Subject: [PATCH 27/30] 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 0c8ad276e409840ce665ecd7c8c3655a545cc500 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 4 Sep 2023 18:02:32 +0800 Subject: [PATCH 28/30] 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 29/30] 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 30/30] 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(