From c104805830c349260b30756b19560836bd9866a6 Mon Sep 17 00:00:00 2001 From: moonyuet Date: Tue, 14 Mar 2023 16:17:17 +0100 Subject: [PATCH 01/22] adding creator, loader for redshift proxy in 3dsmax --- .../plugins/create/create_redshift_proxy.py | 26 +++++++ .../max/plugins/load/load_redshift_proxy.py | 59 ++++++++++++++ .../plugins/publish/extract_redshift_proxy.py | 78 +++++++++++++++++++ 3 files changed, 163 insertions(+) create mode 100644 openpype/hosts/max/plugins/create/create_redshift_proxy.py create mode 100644 openpype/hosts/max/plugins/load/load_redshift_proxy.py create mode 100644 openpype/hosts/max/plugins/publish/extract_redshift_proxy.py diff --git a/openpype/hosts/max/plugins/create/create_redshift_proxy.py b/openpype/hosts/max/plugins/create/create_redshift_proxy.py new file mode 100644 index 0000000000..83ddc3a193 --- /dev/null +++ b/openpype/hosts/max/plugins/create/create_redshift_proxy.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +"""Creator plugin for creating camera.""" +from openpype.hosts.max.api import plugin +from openpype.pipeline import CreatedInstance + + +class CreateRedshiftProxy(plugin.MaxCreator): + identifier = "io.openpype.creators.max.redshiftproxy" + label = "Redshift Proxy" + family = "redshiftproxy" + icon = "gear" + + def create(self, subset_name, instance_data, pre_create_data): + from pymxs import runtime as rt + sel_obj = list(rt.selection) + instance = super(CreateRedshiftProxy, self).create( + subset_name, + instance_data, + pre_create_data) # type: CreatedInstance + container = rt.getNodeByName(instance.data.get("instance_node")) + # TODO: Disable "Add to Containers?" Panel + # parent the selected cameras into the container + for obj in sel_obj: + obj.parent = container + # for additional work on the node: + # instance_node = rt.getNodeByName(instance.get("instance_node")) diff --git a/openpype/hosts/max/plugins/load/load_redshift_proxy.py b/openpype/hosts/max/plugins/load/load_redshift_proxy.py new file mode 100644 index 0000000000..7a5e94158f --- /dev/null +++ b/openpype/hosts/max/plugins/load/load_redshift_proxy.py @@ -0,0 +1,59 @@ +import os +import clique + +from openpype.pipeline import ( + load, + get_representation_path +) +from openpype.hosts.max.api.pipeline import containerise +from openpype.hosts.max.api import lib + + +class RedshiftProxyLoader(load.LoaderPlugin): + """Redshift Proxy Loader""" + + families = ["redshiftproxy"] + representations = ["rs"] + order = -9 + icon = "code-fork" + color = "white" + + def load(self, context, name=None, namespace=None, data=None): + from pymxs import runtime as rt + + filepath = os.path.normpath(self.fname) + rs_proxy = rt.RedshiftProxy() + rs_proxy.file = filepath + files_in_folder = os.listdir(os.path.dirname(filepath)) + collections, remainder = clique.assemble(files_in_folder) + if collections: + rs_proxy.is_sequence = True + + container = rt.container() + container.name = f"{name}" + rs_proxy.Parent = container + + asset = rt.getNodeByName(f"{name}") + + return containerise( + name, [asset], context, loader=self.__class__.__name__) + + def update(self, container, representation): + from pymxs import runtime as rt + + path = get_representation_path(representation) + node = rt.getNodeByName(container["instance_node"]) + + proxy_objects = self.get_container_children(node) + for proxy in proxy_objects: + proxy.source = path + + lib.imprint(container["instance_node"], { + "representation": str(representation["_id"]) + }) + + def remove(self, container): + from pymxs import runtime as rt + + node = rt.getNodeByName(container["instance_node"]) + rt.delete(node) diff --git a/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py b/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py new file mode 100644 index 0000000000..f9dd726ef4 --- /dev/null +++ b/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py @@ -0,0 +1,78 @@ +import os +import pyblish.api +from openpype.pipeline import ( + publish, + OptionalPyblishPluginMixin +) +from pymxs import runtime as rt +from openpype.hosts.max.api import ( + maintained_selection, + get_all_children +) + + +class ExtractCameraAlembic(publish.Extractor, + OptionalPyblishPluginMixin): + """ + Extract Camera with AlembicExport + """ + + order = pyblish.api.ExtractorOrder - 0.1 + label = "Extract RedShift Proxy" + hosts = ["max"] + families = ["redshiftproxy"] + + def process(self, instance): + container = instance.data["instance_node"] + start = int(instance.context.data.get("frameStart")) + end = int(instance.context.data.get("frameEnd")) + + self.log.info("Extracting Redshift Proxy...") + stagingdir = self.staging_dir(instance) + rs_filename = "{name}.rs".format(**instance.data) + + rs_filepath = os.path.join(stagingdir, rs_filename) + + # MaxScript command for export + export_cmd = ( + f""" +fn ProxyExport fp selected:true compress:false connectivity:false startFrame: endFrame: camera:undefined warnExisting:true transformPivotToOrigin:false = ( + if startFrame == unsupplied then ( + startFrame = (currentTime.frame as integer) + ) + + if endFrame == unsupplied then ( + endFrame = (currentTime.frame as integer) + ) + + ret = rsProxy fp selected compress connectivity startFrame endFrame camera warnExisting transformPivotToOrigin + + ret +) +execute = ProxyExport fp selected:true compress:false connectivity:false startFrame:{start} endFrame:{end} warnExisting:false transformPivotToOrigin:bTransformPivotToOrigin + + """) # noqa + + with maintained_selection(): + # select and export + rt.select(container.Children) + rt.execute(export_cmd) + + self.log.info("Performing Extraction ...") + if "representations" not in instance.data: + instance.data["representations"] = [] + + representation = { + 'name': 'rs', + 'ext': 'rs', + # need to count the files + 'files': rs_filename, + "stagingDir": stagingdir, + } + instance.data["representations"].append(representation) + self.log.info("Extracted instance '%s' to: %s" % (instance.name, + rs_filepath)) + + # TODO: set sequence + def get_rsfiles(self, container, startFrame, endFrame): + pass From 5af9867dedda3eb154fedd4aba0c93d8438b80df Mon Sep 17 00:00:00 2001 From: moonyuet Date: Tue, 14 Mar 2023 16:25:00 +0100 Subject: [PATCH 02/22] update fix --- openpype/hosts/max/plugins/publish/extract_redshift_proxy.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py b/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py index f9dd726ef4..85d249b020 100644 --- a/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py +++ b/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py @@ -6,8 +6,7 @@ from openpype.pipeline import ( ) from pymxs import runtime as rt from openpype.hosts.max.api import ( - maintained_selection, - get_all_children + maintained_selection ) From 9cbac449fded786bc033931a07c9e44dd18907e2 Mon Sep 17 00:00:00 2001 From: moonyuet Date: Tue, 14 Mar 2023 16:26:06 +0100 Subject: [PATCH 03/22] change the name --- openpype/hosts/max/plugins/publish/extract_redshift_proxy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py b/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py index 85d249b020..938a7e8c2c 100644 --- a/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py +++ b/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py @@ -10,7 +10,7 @@ from openpype.hosts.max.api import ( ) -class ExtractCameraAlembic(publish.Extractor, +class ExtractRedshiftProxy(publish.Extractor, OptionalPyblishPluginMixin): """ Extract Camera with AlembicExport From 119bb1a586548e6997f3e2724660c19e0d346a56 Mon Sep 17 00:00:00 2001 From: moonyuet Date: Tue, 14 Mar 2023 16:37:25 +0100 Subject: [PATCH 04/22] update the loader and creator --- openpype/hosts/max/plugins/create/create_redshift_proxy.py | 5 +---- openpype/hosts/max/plugins/load/load_redshift_proxy.py | 6 +++--- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/openpype/hosts/max/plugins/create/create_redshift_proxy.py b/openpype/hosts/max/plugins/create/create_redshift_proxy.py index 83ddc3a193..ca0891fc5b 100644 --- a/openpype/hosts/max/plugins/create/create_redshift_proxy.py +++ b/openpype/hosts/max/plugins/create/create_redshift_proxy.py @@ -18,9 +18,6 @@ class CreateRedshiftProxy(plugin.MaxCreator): instance_data, pre_create_data) # type: CreatedInstance container = rt.getNodeByName(instance.data.get("instance_node")) - # TODO: Disable "Add to Containers?" Panel - # parent the selected cameras into the container + for obj in sel_obj: obj.parent = container - # for additional work on the node: - # instance_node = rt.getNodeByName(instance.get("instance_node")) diff --git a/openpype/hosts/max/plugins/load/load_redshift_proxy.py b/openpype/hosts/max/plugins/load/load_redshift_proxy.py index 7a5e94158f..13003d764a 100644 --- a/openpype/hosts/max/plugins/load/load_redshift_proxy.py +++ b/openpype/hosts/max/plugins/load/load_redshift_proxy.py @@ -10,8 +10,8 @@ from openpype.hosts.max.api import lib class RedshiftProxyLoader(load.LoaderPlugin): - """Redshift Proxy Loader""" + label = "Load Redshift Proxy" families = ["redshiftproxy"] representations = ["rs"] order = -9 @@ -21,7 +21,7 @@ class RedshiftProxyLoader(load.LoaderPlugin): def load(self, context, name=None, namespace=None, data=None): from pymxs import runtime as rt - filepath = os.path.normpath(self.fname) + filepath = self.filepath_from_context(context) rs_proxy = rt.RedshiftProxy() rs_proxy.file = filepath files_in_folder = os.listdir(os.path.dirname(filepath)) @@ -30,7 +30,7 @@ class RedshiftProxyLoader(load.LoaderPlugin): rs_proxy.is_sequence = True container = rt.container() - container.name = f"{name}" + container.name = name rs_proxy.Parent = container asset = rt.getNodeByName(f"{name}") From f3bd329d5a40793a6e083198326b22b43a58c621 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 28 Mar 2023 18:48:58 +0800 Subject: [PATCH 05/22] add validator for checking if the current renderer is redshift before the extraction --- .../validate_renderer_redshift_proxy.py | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 openpype/hosts/max/plugins/publish/validate_renderer_redshift_proxy.py diff --git a/openpype/hosts/max/plugins/publish/validate_renderer_redshift_proxy.py b/openpype/hosts/max/plugins/publish/validate_renderer_redshift_proxy.py new file mode 100644 index 0000000000..3a921c386e --- /dev/null +++ b/openpype/hosts/max/plugins/publish/validate_renderer_redshift_proxy.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +import pyblish.api +from openpype.pipeline import PublishValidationError +from pymxs import runtime as rt +from openpype.pipeline.publish import RepairAction +from openpype.hosts.max.api.lib import get_current_renderer + + +class ValidateRendererRedshiftProxy(pyblish.api.InstancePlugin): + """ + Validates Redshift as the current renderer for creating + Redshift Proxy + """ + + order = pyblish.api.ValidatorOrder + families = ["redshiftproxy"] + hosts = ["max"] + label = "Redshift Renderer" + actions = [RepairAction] + + def process(self, instance): + invalid = self.get_all_renderer(instance) + if invalid: + raise PublishValidationError("Please install Redshift for 3dsMax" + " before using this!") + invalid = self.get_current_renderer(instance) + if invalid: + raise PublishValidationError("Current Renderer is not Redshift") + + def get_all_renderer(self, instance): + invalid = list() + max_renderers_list = str(rt.RendererClass.classes) + if "Redshift_Renderer" not in max_renderers_list: + invalid.append(max_renderers_list) + + return invalid + + def get_current_renderer(self, instance): + invalid = list() + renderer_class = get_current_renderer() + current_renderer = str(renderer_class).split(":")[0] + if current_renderer != "Redshift_Renderer": + invalid.append(current_renderer) + + return invalid + + @classmethod + def repair(cls, instance): + if "Redshift_Renderer" in str(rt.RendererClass.classes[2]()): + rt.renderers.production = rt.RendererClass.classes[2]() From 91abe54b01ce08856004b7e395735c9508ab8300 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 28 Mar 2023 22:35:02 +0800 Subject: [PATCH 06/22] add the extractor for redshift proxy --- .../plugins/publish/extract_redshift_proxy.py | 48 ++++++++----------- 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py b/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py index 938a7e8c2c..1616ead0ac 100644 --- a/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py +++ b/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py @@ -6,7 +6,8 @@ from openpype.pipeline import ( ) from pymxs import runtime as rt from openpype.hosts.max.api import ( - maintained_selection + maintained_selection, + get_all_children ) @@ -29,35 +30,22 @@ class ExtractRedshiftProxy(publish.Extractor, self.log.info("Extracting Redshift Proxy...") stagingdir = self.staging_dir(instance) rs_filename = "{name}.rs".format(**instance.data) - rs_filepath = os.path.join(stagingdir, rs_filename) + rs_filepath = rs_filepath.replace("\\", "/") - # MaxScript command for export - export_cmd = ( - f""" -fn ProxyExport fp selected:true compress:false connectivity:false startFrame: endFrame: camera:undefined warnExisting:true transformPivotToOrigin:false = ( - if startFrame == unsupplied then ( - startFrame = (currentTime.frame as integer) - ) - - if endFrame == unsupplied then ( - endFrame = (currentTime.frame as integer) - ) - - ret = rsProxy fp selected compress connectivity startFrame endFrame camera warnExisting transformPivotToOrigin - - ret -) -execute = ProxyExport fp selected:true compress:false connectivity:false startFrame:{start} endFrame:{end} warnExisting:false transformPivotToOrigin:bTransformPivotToOrigin - - """) # noqa + rs_filenames = self.get_rsfiles(instance, start, end) with maintained_selection(): # select and export - rt.select(container.Children) - rt.execute(export_cmd) + # con = rt.getNodeByName(container) + rt.select(get_all_children(rt.getNodeByName(container))) + # Redshift rsProxy command + # rsProxy fp selected compress connectivity startFrame endFrame + # camera warnExisting transformPivotToOrigin + rt.rsProxy(rs_filepath, 1, 0, 0, start, end, 0, 1, 1) self.log.info("Performing Extraction ...") + if "representations" not in instance.data: instance.data["representations"] = [] @@ -65,13 +53,19 @@ execute = ProxyExport fp selected:true compress:false connectivity:false startFr 'name': 'rs', 'ext': 'rs', # need to count the files - 'files': rs_filename, + 'files': rs_filenames if len(rs_filenames) > 1 else rs_filenames[0], "stagingDir": stagingdir, } instance.data["representations"].append(representation) self.log.info("Extracted instance '%s' to: %s" % (instance.name, - rs_filepath)) + stagingdir)) # TODO: set sequence - def get_rsfiles(self, container, startFrame, endFrame): - pass + def get_rsfiles(self, instance, startFrame, endFrame): + rs_filenames = [] + rs_name = instance.data["name"] + for frame in range(startFrame, endFrame + 1): + rs_filename = "%s.%04d.rs" % (rs_name, frame) + rs_filenames.append(rs_filename) + + return rs_filenames From be6813293c605d5b477af72fedcca047b6e7f0c0 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 28 Mar 2023 22:36:22 +0800 Subject: [PATCH 07/22] shut hound --- openpype/hosts/max/plugins/publish/extract_redshift_proxy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py b/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py index 1616ead0ac..8924242a93 100644 --- a/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py +++ b/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py @@ -53,7 +53,7 @@ class ExtractRedshiftProxy(publish.Extractor, 'name': 'rs', 'ext': 'rs', # need to count the files - 'files': rs_filenames if len(rs_filenames) > 1 else rs_filenames[0], + 'files': rs_filenames if len(rs_filenames) > 1 else rs_filenames[0], # noqa "stagingDir": stagingdir, } instance.data["representations"].append(representation) From f25b5d309ad212b273a2ba6ccdfa6b1d950e5a25 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 28 Mar 2023 22:42:28 +0800 Subject: [PATCH 08/22] cleanup --- .../max/plugins/publish/extract_redshift_proxy.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py b/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py index 8924242a93..bf16c8d4a9 100644 --- a/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py +++ b/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py @@ -1,9 +1,6 @@ import os import pyblish.api -from openpype.pipeline import ( - publish, - OptionalPyblishPluginMixin -) +from openpype.pipeline import publish from pymxs import runtime as rt from openpype.hosts.max.api import ( maintained_selection, @@ -11,10 +8,9 @@ from openpype.hosts.max.api import ( ) -class ExtractRedshiftProxy(publish.Extractor, - OptionalPyblishPluginMixin): +class ExtractRedshiftProxy(publish.Extractor): """ - Extract Camera with AlembicExport + Extract Redshift Proxy """ order = pyblish.api.ExtractorOrder - 0.1 From 6d51333a20e13b07d8f32ea69c299163b1c90fc4 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 28 Mar 2023 22:45:52 +0800 Subject: [PATCH 09/22] add docstrings --- openpype/hosts/max/plugins/publish/extract_redshift_proxy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py b/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py index bf16c8d4a9..c91391429d 100644 --- a/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py +++ b/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py @@ -10,7 +10,7 @@ from openpype.hosts.max.api import ( class ExtractRedshiftProxy(publish.Extractor): """ - Extract Redshift Proxy + Extract Redshift Proxy with rsProxy """ order = pyblish.api.ExtractorOrder - 0.1 From b9ec96fdd64b4d8e7f770dfc722e459f28cd596e Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 28 Mar 2023 22:48:21 +0800 Subject: [PATCH 10/22] add docstring for the rs loader --- openpype/hosts/max/plugins/load/load_redshift_proxy.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openpype/hosts/max/plugins/load/load_redshift_proxy.py b/openpype/hosts/max/plugins/load/load_redshift_proxy.py index 13003d764a..30879bca78 100644 --- a/openpype/hosts/max/plugins/load/load_redshift_proxy.py +++ b/openpype/hosts/max/plugins/load/load_redshift_proxy.py @@ -11,6 +11,8 @@ from openpype.hosts.max.api import lib class RedshiftProxyLoader(load.LoaderPlugin): + """Load rs files with Redshift Proxy""" + label = "Load Redshift Proxy" families = ["redshiftproxy"] representations = ["rs"] From 3ba7b9b1ffc8ba9877024f8175af8adcbd984e08 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 28 Mar 2023 23:05:25 +0800 Subject: [PATCH 11/22] fix selection of children --- openpype/hosts/max/plugins/publish/extract_redshift_proxy.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py b/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py index c91391429d..5aba257443 100644 --- a/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py +++ b/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py @@ -33,8 +33,8 @@ class ExtractRedshiftProxy(publish.Extractor): with maintained_selection(): # select and export - # con = rt.getNodeByName(container) - rt.select(get_all_children(rt.getNodeByName(container))) + con = rt.getNodeByName(container) + rt.select(con.Children) # Redshift rsProxy command # rsProxy fp selected compress connectivity startFrame endFrame # camera warnExisting transformPivotToOrigin From 35448073aba93b3ead99513b0d831accb00c76cb Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 28 Mar 2023 23:07:05 +0800 Subject: [PATCH 12/22] hound fix --- openpype/hosts/max/plugins/publish/extract_redshift_proxy.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py b/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py index 5aba257443..0a3579d687 100644 --- a/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py +++ b/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py @@ -2,10 +2,7 @@ import os import pyblish.api from openpype.pipeline import publish from pymxs import runtime as rt -from openpype.hosts.max.api import ( - maintained_selection, - get_all_children -) +from openpype.hosts.max.api import maintained_selection class ExtractRedshiftProxy(publish.Extractor): From 14b8139a5cfe92680233343d8e4120ae2253865f Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 3 Apr 2023 16:47:15 +0800 Subject: [PATCH 13/22] Roy's comment & fix the loader update --- openpype/hosts/max/plugins/load/load_redshift_proxy.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/openpype/hosts/max/plugins/load/load_redshift_proxy.py b/openpype/hosts/max/plugins/load/load_redshift_proxy.py index 30879bca78..fd79a2b97c 100644 --- a/openpype/hosts/max/plugins/load/load_redshift_proxy.py +++ b/openpype/hosts/max/plugins/load/load_redshift_proxy.py @@ -35,7 +35,7 @@ class RedshiftProxyLoader(load.LoaderPlugin): container.name = name rs_proxy.Parent = container - asset = rt.getNodeByName(f"{name}") + asset = rt.getNodeByName(name) return containerise( name, [asset], context, loader=self.__class__.__name__) @@ -45,10 +45,10 @@ class RedshiftProxyLoader(load.LoaderPlugin): path = get_representation_path(representation) node = rt.getNodeByName(container["instance_node"]) - - proxy_objects = self.get_container_children(node) - for proxy in proxy_objects: - proxy.source = path + for children in node.Children: + children_node = rt.getNodeByName(children.name) + for proxy in children_node.Children: + proxy.file = path lib.imprint(container["instance_node"], { "representation": str(representation["_id"]) From 6423479078a7305d9e73f55243eb42796acb7820 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 3 Apr 2023 16:50:33 +0800 Subject: [PATCH 14/22] add switch version in the loader --- openpype/hosts/max/plugins/load/load_redshift_proxy.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openpype/hosts/max/plugins/load/load_redshift_proxy.py b/openpype/hosts/max/plugins/load/load_redshift_proxy.py index fd79a2b97c..9451e5299b 100644 --- a/openpype/hosts/max/plugins/load/load_redshift_proxy.py +++ b/openpype/hosts/max/plugins/load/load_redshift_proxy.py @@ -54,6 +54,9 @@ class RedshiftProxyLoader(load.LoaderPlugin): "representation": str(representation["_id"]) }) + def switch(self, container, representation): + self.update(container, representation) + def remove(self, container): from pymxs import runtime as rt From 442236284bc87cf3a4aff4d3ae622beaaf946c4c Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 6 Apr 2023 17:53:42 +0800 Subject: [PATCH 15/22] add docs --- website/docs/artist_hosts_3dsmax.md | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/website/docs/artist_hosts_3dsmax.md b/website/docs/artist_hosts_3dsmax.md index 12c1f40181..fffab8ca5d 100644 --- a/website/docs/artist_hosts_3dsmax.md +++ b/website/docs/artist_hosts_3dsmax.md @@ -30,7 +30,7 @@ By clicking the icon ```OpenPype Menu``` rolls out. Choose ```OpenPype Menu > Launcher``` to open the ```Launcher``` window. -When opened you can **choose** the **project** to work in from the list. Then choose the particular **asset** you want to work on then choose **task** +When opened you can **choose** the **project** to work in from the list. Then choose the particular **asset** you want to work on then choose **task** and finally **run 3dsmax by its icon** in the tools. ![Menu OpenPype](assets/3dsmax_tray_OP.png) @@ -65,13 +65,13 @@ If not any workfile present simply hit ```Save As``` and keep ```Subversion``` e ![Save As Dialog](assets/3dsmax_SavingFirstFile_OP.png) -OpenPype correctly names it and add version to the workfile. This basically happens whenever user trigger ```Save As``` action. Resulting into incremental version numbers like +OpenPype correctly names it and add version to the workfile. This basically happens whenever user trigger ```Save As``` action. Resulting into incremental version numbers like ```workfileName_v001``` ```workfileName_v002``` - etc. + etc. Basically meaning user is free of guessing what is the correct naming and other necessities to keep everything in order and managed. @@ -105,13 +105,13 @@ Before proceeding further please check [Glossary](artist_concepts.md) and [What ### Intro -Current OpenPype integration (ver 3.15.0) supports only ```PointCache``` and ```Camera``` families now. +Current OpenPype integration (ver 3.15.0) supports only ```PointCache```, ```Camera```, ```Geometry``` and ```Redshift Proxy``` families now. **Pointcache** family being basically any geometry outputted as Alembic cache (.abc) format **Camera** family being 3dsmax Camera object with/without animation outputted as native .max, FBX, Alembic format - +**Redshift Proxy** family being Redshift Proxy object with/without animation outputted as rs format(Redshift Proxy's very own format) --- :::note Work in progress @@ -119,7 +119,3 @@ This part of documentation is still work in progress. ::: ## ...to be added - - - - From cdf9a10aa19b39c698a57b97abbb5858b6571de6 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 26 Apr 2023 19:10:55 +0800 Subject: [PATCH 16/22] roy's comment --- openpype/hosts/max/api/lib.py | 9 ++++++++- .../max/plugins/create/create_redshift_proxy.py | 7 ++++--- .../max/plugins/publish/extract_redshift_proxy.py | 3 +-- .../publish/validate_renderer_redshift_proxy.py | 14 +++++++++----- 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/openpype/hosts/max/api/lib.py b/openpype/hosts/max/api/lib.py index ad9a450cad..27d4598a3a 100644 --- a/openpype/hosts/max/api/lib.py +++ b/openpype/hosts/max/api/lib.py @@ -128,7 +128,14 @@ def get_all_children(parent, node_type=None): def get_current_renderer(): - """get current renderer""" + """ + Notes: + Get current renderer for Max + + Returns: + "{Current Renderer}:{Current Renderer}" + e.g. "Redshift_Renderer:Redshift_Renderer" + """ return rt.renderers.production diff --git a/openpype/hosts/max/plugins/create/create_redshift_proxy.py b/openpype/hosts/max/plugins/create/create_redshift_proxy.py index ca0891fc5b..1bddbdafae 100644 --- a/openpype/hosts/max/plugins/create/create_redshift_proxy.py +++ b/openpype/hosts/max/plugins/create/create_redshift_proxy.py @@ -18,6 +18,7 @@ class CreateRedshiftProxy(plugin.MaxCreator): instance_data, pre_create_data) # type: CreatedInstance container = rt.getNodeByName(instance.data.get("instance_node")) - - for obj in sel_obj: - obj.parent = container + if self.selected_nodes: + sel_obj = list(self.selected_nodes) + for obj in sel_obj: + obj.parent = container diff --git a/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py b/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py index 0a3579d687..eb1673c4fa 100644 --- a/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py +++ b/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py @@ -45,7 +45,6 @@ class ExtractRedshiftProxy(publish.Extractor): representation = { 'name': 'rs', 'ext': 'rs', - # need to count the files 'files': rs_filenames if len(rs_filenames) > 1 else rs_filenames[0], # noqa "stagingDir": stagingdir, } @@ -53,7 +52,7 @@ class ExtractRedshiftProxy(publish.Extractor): self.log.info("Extracted instance '%s' to: %s" % (instance.name, stagingdir)) - # TODO: set sequence + def get_rsfiles(self, instance, startFrame, endFrame): rs_filenames = [] rs_name = instance.data["name"] diff --git a/openpype/hosts/max/plugins/publish/validate_renderer_redshift_proxy.py b/openpype/hosts/max/plugins/publish/validate_renderer_redshift_proxy.py index 3a921c386e..c834f12ae2 100644 --- a/openpype/hosts/max/plugins/publish/validate_renderer_redshift_proxy.py +++ b/openpype/hosts/max/plugins/publish/validate_renderer_redshift_proxy.py @@ -22,12 +22,13 @@ class ValidateRendererRedshiftProxy(pyblish.api.InstancePlugin): invalid = self.get_all_renderer(instance) if invalid: raise PublishValidationError("Please install Redshift for 3dsMax" - " before using this!") + " before using the Redshift proxy instance") invalid = self.get_current_renderer(instance) if invalid: - raise PublishValidationError("Current Renderer is not Redshift") + raise PublishValidationError("The Redshift proxy extraction discontinued" + "since the current renderer is not Redshift") - def get_all_renderer(self, instance): + def get_redshift_renderer(self, instance): invalid = list() max_renderers_list = str(rt.RendererClass.classes) if "Redshift_Renderer" not in max_renderers_list: @@ -46,5 +47,8 @@ class ValidateRendererRedshiftProxy(pyblish.api.InstancePlugin): @classmethod def repair(cls, instance): - if "Redshift_Renderer" in str(rt.RendererClass.classes[2]()): - rt.renderers.production = rt.RendererClass.classes[2]() + renderer_count = len(rt.RendererClass.classes) + for r in range(renderer_count): + if "Redshift_Renderer" in str(rt.RendererClass.classes[r]()): + rt.renderers.production = rt.RendererClass.classes[r]() + break From a20d37c68045d73b5f442f503dcbaf31bb8892b5 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 26 Apr 2023 19:13:33 +0800 Subject: [PATCH 17/22] hound fix --- .../hosts/max/plugins/publish/extract_redshift_proxy.py | 1 - .../max/plugins/publish/validate_renderer_redshift_proxy.py | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py b/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py index eb1673c4fa..3b44099609 100644 --- a/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py +++ b/openpype/hosts/max/plugins/publish/extract_redshift_proxy.py @@ -52,7 +52,6 @@ class ExtractRedshiftProxy(publish.Extractor): self.log.info("Extracted instance '%s' to: %s" % (instance.name, stagingdir)) - def get_rsfiles(self, instance, startFrame, endFrame): rs_filenames = [] rs_name = instance.data["name"] diff --git a/openpype/hosts/max/plugins/publish/validate_renderer_redshift_proxy.py b/openpype/hosts/max/plugins/publish/validate_renderer_redshift_proxy.py index c834f12ae2..6f8a92a93c 100644 --- a/openpype/hosts/max/plugins/publish/validate_renderer_redshift_proxy.py +++ b/openpype/hosts/max/plugins/publish/validate_renderer_redshift_proxy.py @@ -22,11 +22,11 @@ class ValidateRendererRedshiftProxy(pyblish.api.InstancePlugin): invalid = self.get_all_renderer(instance) if invalid: raise PublishValidationError("Please install Redshift for 3dsMax" - " before using the Redshift proxy instance") + " before using the Redshift proxy instance") # noqa invalid = self.get_current_renderer(instance) if invalid: - raise PublishValidationError("The Redshift proxy extraction discontinued" - "since the current renderer is not Redshift") + raise PublishValidationError("The Redshift proxy extraction" + "discontinued since the current renderer is not Redshift") # noqa def get_redshift_renderer(self, instance): invalid = list() From edec4a2b1995adbeda6f5b681b9488f7fb3bcb08 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 26 Apr 2023 20:17:36 +0800 Subject: [PATCH 18/22] roy's comment --- .../publish/validate_renderer_redshift_proxy.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/openpype/hosts/max/plugins/publish/validate_renderer_redshift_proxy.py b/openpype/hosts/max/plugins/publish/validate_renderer_redshift_proxy.py index 6f8a92a93c..bc82f82f3b 100644 --- a/openpype/hosts/max/plugins/publish/validate_renderer_redshift_proxy.py +++ b/openpype/hosts/max/plugins/publish/validate_renderer_redshift_proxy.py @@ -19,7 +19,7 @@ class ValidateRendererRedshiftProxy(pyblish.api.InstancePlugin): actions = [RepairAction] def process(self, instance): - invalid = self.get_all_renderer(instance) + invalid = self.get_redshift_renderer(instance) if invalid: raise PublishValidationError("Please install Redshift for 3dsMax" " before using the Redshift proxy instance") # noqa @@ -47,8 +47,8 @@ class ValidateRendererRedshiftProxy(pyblish.api.InstancePlugin): @classmethod def repair(cls, instance): - renderer_count = len(rt.RendererClass.classes) - for r in range(renderer_count): - if "Redshift_Renderer" in str(rt.RendererClass.classes[r]()): - rt.renderers.production = rt.RendererClass.classes[r]() + for Renderer in rt.RendererClass.classes: + renderer = Renderer() + if "Redshift_Renderer" in str(renderer): + rt.renderers.production = renderer break From 86fcab6f8d423fd6d719f5ba50f63e72e278e056 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 8 May 2023 15:20:25 +0800 Subject: [PATCH 19/22] refractor the creator for custom modifiers --- .../hosts/max/plugins/create/create_redshift_proxy.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/openpype/hosts/max/plugins/create/create_redshift_proxy.py b/openpype/hosts/max/plugins/create/create_redshift_proxy.py index 1bddbdafae..8c71feb40f 100644 --- a/openpype/hosts/max/plugins/create/create_redshift_proxy.py +++ b/openpype/hosts/max/plugins/create/create_redshift_proxy.py @@ -12,13 +12,8 @@ class CreateRedshiftProxy(plugin.MaxCreator): def create(self, subset_name, instance_data, pre_create_data): from pymxs import runtime as rt - sel_obj = list(rt.selection) - instance = super(CreateRedshiftProxy, self).create( + + _ = super(CreateRedshiftProxy, self).create( subset_name, instance_data, pre_create_data) # type: CreatedInstance - container = rt.getNodeByName(instance.data.get("instance_node")) - if self.selected_nodes: - sel_obj = list(self.selected_nodes) - for obj in sel_obj: - obj.parent = container From e45098c2841c2390c42d7b46f2d1688a5220fa0a Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 8 May 2023 15:21:27 +0800 Subject: [PATCH 20/22] hound fix --- openpype/hosts/max/plugins/create/create_redshift_proxy.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/hosts/max/plugins/create/create_redshift_proxy.py b/openpype/hosts/max/plugins/create/create_redshift_proxy.py index 8c71feb40f..698ea82b69 100644 --- a/openpype/hosts/max/plugins/create/create_redshift_proxy.py +++ b/openpype/hosts/max/plugins/create/create_redshift_proxy.py @@ -11,7 +11,6 @@ class CreateRedshiftProxy(plugin.MaxCreator): icon = "gear" def create(self, subset_name, instance_data, pre_create_data): - from pymxs import runtime as rt _ = super(CreateRedshiftProxy, self).create( subset_name, From a4e9eaf3c38aaa4bb31784067d35d54656ae8333 Mon Sep 17 00:00:00 2001 From: Milan Kolar Date: Mon, 29 May 2023 23:24:48 +0200 Subject: [PATCH 21/22] Update openpype/hosts/max/plugins/load/load_redshift_proxy.py Co-authored-by: Roy Nieterau --- openpype/hosts/max/plugins/load/load_redshift_proxy.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/hosts/max/plugins/load/load_redshift_proxy.py b/openpype/hosts/max/plugins/load/load_redshift_proxy.py index 9451e5299b..31692f6367 100644 --- a/openpype/hosts/max/plugins/load/load_redshift_proxy.py +++ b/openpype/hosts/max/plugins/load/load_redshift_proxy.py @@ -10,7 +10,6 @@ from openpype.hosts.max.api import lib class RedshiftProxyLoader(load.LoaderPlugin): - """Load rs files with Redshift Proxy""" label = "Load Redshift Proxy" From d4a807194ebb0971a629f608f3fc2ecf84723394 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Thu, 1 Jun 2023 11:24:34 +0200 Subject: [PATCH 22/22] Resolve: Make sure scripts dir exists (#5078) * make sure scripts dir exists * use exist_ok in makedirs --- openpype/hosts/resolve/utils.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openpype/hosts/resolve/utils.py b/openpype/hosts/resolve/utils.py index 9a161f4865..1213fd9e7a 100644 --- a/openpype/hosts/resolve/utils.py +++ b/openpype/hosts/resolve/utils.py @@ -29,6 +29,9 @@ def setup(env): log.info("Utility Scripts Dir: `{}`".format(util_scripts_paths)) log.info("Utility Scripts: `{}`".format(scripts)) + # Make sure scripts dir exists + os.makedirs(util_scripts_dir, exist_ok=True) + # make sure no script file is in folder for script in os.listdir(util_scripts_dir): path = os.path.join(util_scripts_dir, script)