diff --git a/openpype/hosts/max/plugins/publish/extract_camera_abc.py b/openpype/hosts/max/plugins/publish/extract_camera_abc.py index 8c23ff9878..b4f294fbf9 100644 --- a/openpype/hosts/max/plugins/publish/extract_camera_abc.py +++ b/openpype/hosts/max/plugins/publish/extract_camera_abc.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 ) @@ -29,8 +28,6 @@ class ExtractCameraAlembic(publish.Extractor, start = float(instance.data.get("frameStartHandle", 1)) end = float(instance.data.get("frameEndHandle", 1)) - container = instance.data["instance_node"] - self.log.info("Extracting Camera ...") stagingdir = self.staging_dir(instance) @@ -38,8 +35,7 @@ class ExtractCameraAlembic(publish.Extractor, path = os.path.join(stagingdir, filename) # We run the render - self.log.info("Writing alembic '%s' to '%s'" % (filename, - stagingdir)) + self.log.info(f"Writing alembic '{filename}' to '{stagingdir}'") export_cmd = ( f""" @@ -57,8 +53,8 @@ exportFile @"{path}" #noPrompt selectedOnly:on using:AlembicExport with maintained_selection(): # select and export - rt.select(get_all_children(rt.getNodeByName(container))) - rt.execute(export_cmd) + rt.Select(instance.data["members"]) + rt.Execute(export_cmd) self.log.info("Performing Extraction ...") if "representations" not in instance.data: @@ -71,5 +67,4 @@ exportFile @"{path}" #noPrompt selectedOnly:on using:AlembicExport "stagingDir": stagingdir, } instance.data["representations"].append(representation) - self.log.info("Extracted instance '%s' to: %s" % (instance.name, - path)) + self.log.info(f"Extracted instance '{instance.name}' to: {path}") diff --git a/openpype/hosts/max/plugins/publish/extract_camera_fbx.py b/openpype/hosts/max/plugins/publish/extract_camera_fbx.py index 7e92f355ed..ffbd281c67 100644 --- a/openpype/hosts/max/plugins/publish/extract_camera_fbx.py +++ b/openpype/hosts/max/plugins/publish/extract_camera_fbx.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 ) @@ -26,15 +25,13 @@ class ExtractCameraFbx(publish.Extractor, def process(self, instance): if not self.is_active(instance.data): return - container = instance.data["instance_node"] self.log.info("Extracting Camera ...") stagingdir = self.staging_dir(instance) filename = "{name}.fbx".format(**instance.data) filepath = os.path.join(stagingdir, filename) - self.log.info("Writing fbx file '%s' to '%s'" % (filename, - filepath)) + self.log.info(f"Writing fbx file '{filename}' to '{filepath}'") # Need to export: # Animation = True @@ -57,8 +54,8 @@ exportFile @"{filepath}" #noPrompt selectedOnly:true using:FBXEXP with maintained_selection(): # select and export - rt.select(get_all_children(rt.getNodeByName(container))) - rt.execute(fbx_export_cmd) + rt.Select(instance.data["members"]) + rt.Execute(fbx_export_cmd) self.log.info("Performing Extraction ...") if "representations" not in instance.data: @@ -71,5 +68,4 @@ exportFile @"{filepath}" #noPrompt selectedOnly:true using:FBXEXP "stagingDir": stagingdir, } instance.data["representations"].append(representation) - self.log.info("Extracted instance '%s' to: %s" % (instance.name, - filepath)) + self.log.info(f"Extracted instance '{instance.name}' to: {filepath}") diff --git a/openpype/hosts/max/plugins/publish/extract_max_scene_raw.py b/openpype/hosts/max/plugins/publish/extract_max_scene_raw.py index c14fcdbd0b..ed98922462 100644 --- a/openpype/hosts/max/plugins/publish/extract_max_scene_raw.py +++ b/openpype/hosts/max/plugins/publish/extract_max_scene_raw.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 ) @@ -28,7 +27,6 @@ class ExtractMaxSceneRaw(publish.Extractor, def process(self, instance): if not self.is_active(instance.data): return - container = instance.data["instance_node"] # publish the raw scene for camera self.log.info("Extracting Raw Max Scene ...") @@ -37,8 +35,7 @@ class ExtractMaxSceneRaw(publish.Extractor, filename = "{name}.max".format(**instance.data) max_path = os.path.join(stagingdir, filename) - self.log.info("Writing max file '%s' to '%s'" % (filename, - max_path)) + self.log.info(f"Writing max file '{filename}' to '{max_path}'") if "representations" not in instance.data: instance.data["representations"] = [] @@ -46,8 +43,8 @@ class ExtractMaxSceneRaw(publish.Extractor, # saving max scene with maintained_selection(): # need to figure out how to select the camera - rt.select(get_all_children(rt.getNodeByName(container))) - rt.execute(f'saveNodes selection "{max_path}" quiet:true') + rt.Select(instance.data["members"]) + rt.Execute(f'saveNodes selection "{max_path}" quiet:true') self.log.info("Performing Extraction ...") @@ -58,5 +55,4 @@ class ExtractMaxSceneRaw(publish.Extractor, "stagingDir": stagingdir, } instance.data["representations"].append(representation) - self.log.info("Extracted instance '%s' to: %s" % (instance.name, - max_path)) + self.log.info(f"Extracted instance '{instance.name}' to: {max_path}") diff --git a/openpype/hosts/max/plugins/publish/extract_model.py b/openpype/hosts/max/plugins/publish/extract_model.py index 710ad5f97d..d0f7bb0410 100644 --- a/openpype/hosts/max/plugins/publish/extract_model.py +++ b/openpype/hosts/max/plugins/publish/extract_model.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 ) @@ -27,8 +26,6 @@ class ExtractModel(publish.Extractor, if not self.is_active(instance.data): return - container = instance.data["instance_node"] - self.log.info("Extracting Geometry ...") stagingdir = self.staging_dir(instance) @@ -36,8 +33,7 @@ class ExtractModel(publish.Extractor, filepath = os.path.join(stagingdir, filename) # We run the render - self.log.info("Writing alembic '%s' to '%s'" % (filename, - stagingdir)) + self.log.info(f"Writing alembic '{filename}' to '{stagingdir}'") export_cmd = ( f""" @@ -56,8 +52,8 @@ exportFile @"{filepath}" #noPrompt selectedOnly:on using:AlembicExport with maintained_selection(): # select and export - rt.select(get_all_children(rt.getNodeByName(container))) - rt.execute(export_cmd) + rt.Select(instance.data["members"]) + rt.Execute(export_cmd) self.log.info("Performing Extraction ...") if "representations" not in instance.data: @@ -70,5 +66,4 @@ exportFile @"{filepath}" #noPrompt selectedOnly:on using:AlembicExport "stagingDir": stagingdir, } instance.data["representations"].append(representation) - self.log.info("Extracted instance '%s' to: %s" % (instance.name, - filepath)) + self.log.info(f"Extracted instance '{instance.name}' to: {filepath}") diff --git a/openpype/hosts/max/plugins/publish/extract_model_fbx.py b/openpype/hosts/max/plugins/publish/extract_model_fbx.py index ce58e8cc17..696974a703 100644 --- a/openpype/hosts/max/plugins/publish/extract_model_fbx.py +++ b/openpype/hosts/max/plugins/publish/extract_model_fbx.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 ) @@ -27,16 +26,13 @@ class ExtractModelFbx(publish.Extractor, if not self.is_active(instance.data): return - container = instance.data["instance_node"] - self.log.info("Extracting Geometry ...") stagingdir = self.staging_dir(instance) filename = "{name}.fbx".format(**instance.data) filepath = os.path.join(stagingdir, filename) - self.log.info("Writing FBX '%s' to '%s'" % (filepath, - stagingdir)) + self.log.info(f"Writing FBX '{filepath}' to '{stagingdir}'") export_fbx_cmd = ( f""" @@ -56,8 +52,8 @@ exportFile @"{filepath}" #noPrompt selectedOnly:true using:FBXEXP with maintained_selection(): # select and export - rt.select(get_all_children(rt.getNodeByName(container))) - rt.execute(export_fbx_cmd) + rt.Select(instance.data["members"]) + rt.Execute(export_fbx_cmd) self.log.info("Performing Extraction ...") if "representations" not in instance.data: @@ -70,5 +66,4 @@ exportFile @"{filepath}" #noPrompt selectedOnly:true using:FBXEXP "stagingDir": stagingdir, } instance.data["representations"].append(representation) - self.log.info("Extracted instance '%s' to: %s" % (instance.name, - filepath)) + self.log.info(f"Extracted instance '{instance.name}' to: {filepath}") diff --git a/openpype/hosts/max/plugins/publish/extract_model_obj.py b/openpype/hosts/max/plugins/publish/extract_model_obj.py index 7bda237880..93896eea02 100644 --- a/openpype/hosts/max/plugins/publish/extract_model_obj.py +++ b/openpype/hosts/max/plugins/publish/extract_model_obj.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 ) @@ -27,21 +26,18 @@ class ExtractModelObj(publish.Extractor, if not self.is_active(instance.data): return - container = instance.data["instance_node"] - self.log.info("Extracting Geometry ...") stagingdir = self.staging_dir(instance) filename = "{name}.obj".format(**instance.data) filepath = os.path.join(stagingdir, filename) - self.log.info("Writing OBJ '%s' to '%s'" % (filepath, - stagingdir)) + self.log.info(f"Writing OBJ '{filepath}' to '{stagingdir}'") with maintained_selection(): # select and export - rt.select(get_all_children(rt.getNodeByName(container))) - rt.execute(f'exportFile @"{filepath}" #noPrompt selectedOnly:true using:ObjExp') # noqa + rt.Select(instance.data["members"]) + rt.Execute(f'exportFile @"{filepath}" #noPrompt selectedOnly:true using:ObjExp') # noqa self.log.info("Performing Extraction ...") if "representations" not in instance.data: @@ -55,5 +51,4 @@ class ExtractModelObj(publish.Extractor, } instance.data["representations"].append(representation) - self.log.info("Extracted instance '%s' to: %s" % (instance.name, - filepath)) + self.log.info(f"Extracted instance '{instance.name}' to: {filepath}") diff --git a/openpype/hosts/max/plugins/publish/extract_model_usd.py b/openpype/hosts/max/plugins/publish/extract_model_usd.py index 0bed2d855e..ae250cae5a 100644 --- a/openpype/hosts/max/plugins/publish/extract_model_usd.py +++ b/openpype/hosts/max/plugins/publish/extract_model_usd.py @@ -26,31 +26,27 @@ class ExtractModelUSD(publish.Extractor, if not self.is_active(instance.data): return - container = instance.data["instance_node"] - self.log.info("Extracting Geometry ...") stagingdir = self.staging_dir(instance) asset_filename = "{name}.usda".format(**instance.data) asset_filepath = os.path.join(stagingdir, asset_filename) - self.log.info("Writing USD '%s' to '%s'" % (asset_filepath, - stagingdir)) + self.log.info(f"Writing USD '{asset_filepath}' to '{stagingdir}'") log_filename = "{name}.txt".format(**instance.data) log_filepath = os.path.join(stagingdir, log_filename) - self.log.info("Writing log '%s' to '%s'" % (log_filepath, - stagingdir)) + self.log.info(f"Writing log '{log_filepath}' to '{stagingdir}'") # get the nodes which need to be exported export_options = self.get_export_options(log_filepath) with maintained_selection(): # select and export - node_list = self.get_node_list(container) + node_list = instance.data["members"] rt.USDExporter.ExportFile(asset_filepath, exportOptions=export_options, - contentSource=rt.name("selected"), + contentSource=rt.Name("selected"), nodeList=node_list) self.log.info("Performing Extraction ...") @@ -73,25 +69,10 @@ class ExtractModelUSD(publish.Extractor, } instance.data["representations"].append(log_representation) - self.log.info("Extracted instance '%s' to: %s" % (instance.name, - asset_filepath)) + self.log.info(f"Extracted instance '{instance.name}' to: {asset_filepath}") - def get_node_list(self, container): - """ - Get the target nodes which are - the children of the container - """ - node_list = [] - - container_node = rt.getNodeByName(container) - target_node = container_node.Children - rt.select(target_node) - for sel in rt.selection: - node_list.append(sel) - - return node_list - - def get_export_options(self, log_path): + @staticmethod + def get_export_options(log_path): """Set Export Options for USD Exporter""" export_options = rt.USDExporter.createOptions() @@ -101,13 +82,13 @@ class ExtractModelUSD(publish.Extractor, export_options.Lights = False export_options.Cameras = False export_options.Materials = False - export_options.MeshFormat = rt.name('fromScene') - export_options.FileFormat = rt.name('ascii') - export_options.UpAxis = rt.name('y') - export_options.LogLevel = rt.name('info') + export_options.MeshFormat = rt.Name('fromScene') + export_options.FileFormat = rt.Name('ascii') + export_options.UpAxis = rt.Name('y') + export_options.LogLevel = rt.Name('info') export_options.LogPath = log_path export_options.PreserveEdgeOrientation = True - export_options.TimeMode = rt.name('current') + export_options.TimeMode = rt.Name('current') rt.USDexporter.UIOptions = export_options diff --git a/openpype/hosts/max/plugins/publish/extract_pointcache.py b/openpype/hosts/max/plugins/publish/extract_pointcache.py index 75d8a7972c..400d55d198 100644 --- a/openpype/hosts/max/plugins/publish/extract_pointcache.py +++ b/openpype/hosts/max/plugins/publish/extract_pointcache.py @@ -42,8 +42,7 @@ 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 + maintained_selection ) @@ -57,17 +56,14 @@ class ExtractAlembic(publish.Extractor): start = float(instance.data.get("frameStartHandle", 1)) end = float(instance.data.get("frameEndHandle", 1)) - container = instance.data["instance_node"] - self.log.info("Extracting pointcache ...") parent_dir = self.staging_dir(instance) file_name = "{name}.abc".format(**instance.data) path = os.path.join(parent_dir, file_name) - # We run the render - self.log.info("Writing alembic '%s' to '%s'" % (file_name, - parent_dir)) + self.log.info( + f"Writing alembic '{file_name}' to '{parent_dir}'") abc_export_cmd = ( f""" @@ -85,8 +81,8 @@ exportFile @"{path}" #noPrompt selectedOnly:on using:AlembicExport with maintained_selection(): # select and export - rt.select(get_all_children(rt.getNodeByName(container))) - rt.execute(abc_export_cmd) + rt.Select(instance.data["members"]) + rt.Execute(abc_export_cmd) if "representations" not in instance.data: instance.data["representations"] = [] diff --git a/openpype/hosts/max/plugins/publish/extract_pointcloud.py b/openpype/hosts/max/plugins/publish/extract_pointcloud.py index e8d58ab713..5a85915967 100644 --- a/openpype/hosts/max/plugins/publish/extract_pointcloud.py +++ b/openpype/hosts/max/plugins/publish/extract_pointcloud.py @@ -9,13 +9,6 @@ from openpype.settings import get_project_settings from openpype.pipeline import legacy_io -def get_setting(project_setting=None): - project_setting = get_project_settings( - legacy_io.Session["AVALON_PROJECT"] - ) - return (project_setting["max"]["PointCloud"]) - - class ExtractPointCloud(publish.Extractor): """ Extract PRT format with tyFlow operators @@ -24,19 +17,20 @@ class ExtractPointCloud(publish.Extractor): Currently only works for the default partition setting Args: - export_particle(): sets up all job arguments for attributes - to be exported in MAXscript + self.export_particle(): sets up all job arguments for attributes + to be exported in MAXscript - get_operators(): get the export_particle operator + self.get_operators(): get the export_particle operator - get_custom_attr(): get all custom channel attributes from Openpype - setting and sets it as job arguments before exporting + self.get_custom_attr(): get all custom channel attributes from Openpype + setting and sets it as job arguments before exporting - get_files(): get the files with tyFlow naming convention - before publishing + self.get_files(): get the files with tyFlow naming convention + before publishing - partition_output_name(): get the naming with partition settings. - get_partition(): get partition value + self.partition_output_name(): get the naming with partition settings. + + self.get_partition(): get partition value """ @@ -46,6 +40,7 @@ class ExtractPointCloud(publish.Extractor): families = ["pointcloud"] def process(self, instance): + self.settings = self.get_setting(instance) start = int(instance.context.data.get("frameStart")) end = int(instance.context.data.get("frameEnd")) container = instance.data["instance_node"] @@ -56,12 +51,12 @@ class ExtractPointCloud(publish.Extractor): path = os.path.join(stagingdir, filename) with maintained_selection(): - job_args = self.export_particle(container, + job_args = self.export_particle(instance.data["members"], start, end, path) for job in job_args: - rt.execute(job) + rt.Execute(job) self.log.info("Performing Extraction ...") if "representations" not in instance.data: @@ -69,7 +64,7 @@ class ExtractPointCloud(publish.Extractor): self.log.info("Writing PRT with TyFlow Plugin...") filenames = self.get_files(container, path, start, end) - self.log.debug("filenames: {0}".format(filenames)) + self.log.debug(f"filenames: {filenames}") partition = self.partition_output_name(container) @@ -81,67 +76,87 @@ class ExtractPointCloud(publish.Extractor): "outputName": partition # partition value } instance.data["representations"].append(representation) - self.log.info("Extracted instance '%s' to: %s" % (instance.name, - path)) + self.log.info(f"Extracted instance '{instance.name}' to: {path}") def export_particle(self, - container, + members, start, end, filepath): + """Sets up all job arguments for attributes. + + Those attributes are to be exported in MAX Script. + + Args: + members (list): Member nodes of the instance. + start (int): Start frame. + end (int): End frame. + filepath (str): Path to PRT file. + + Returns: + list of arguments for MAX Script. + + """ job_args = [] - opt_list = self.get_operators(container) + opt_list = self.get_operators(members) for operator in opt_list: - start_frame = "{0}.frameStart={1}".format(operator, - start) + start_frame = f"{operator}.frameStart={start}" job_args.append(start_frame) - end_frame = "{0}.frameEnd={1}".format(operator, - end) + end_frame = f"{operator}.frameEnd={end}" job_args.append(end_frame) filepath = filepath.replace("\\", "/") - prt_filename = '{0}.PRTFilename="{1}"'.format(operator, - filepath) + prt_filename = f"{operator}.PRTFilename={filepath}" job_args.append(prt_filename) # Partition - mode = "{0}.PRTPartitionsMode=2".format(operator) + mode = f"{operator}.PRTPartitionsMode=2" job_args.append(mode) additional_args = self.get_custom_attr(operator) - for args in additional_args: - job_args.append(args) - - prt_export = "{0}.exportPRT()".format(operator) + job_args.extend(iter(additional_args)) + prt_export = f"{operator}.exportPRT()" job_args.append(prt_export) return job_args - def get_operators(self, container): - """Get Export Particles Operator""" + @staticmethod + def get_operators(members): + """Get Export Particles Operator. + Args: + members (list): Instance members. + + Returns: + list of particle operators + + """ opt_list = [] - node = rt.getNodebyName(container) - selection_list = list(node.Children) - for sel in selection_list: - obj = sel.baseobject + for member in members: + obj = member.baseobject # TODO: to see if it can be used maxscript instead - anim_names = rt.getsubanimnames(obj) + anim_names = rt.GetSubAnimNames(obj) for anim_name in anim_names: - sub_anim = rt.getsubanim(obj, anim_name) - boolean = rt.isProperty(sub_anim, "Export_Particles") - event_name = sub_anim.name + sub_anim = rt.GetSubAnim(obj, anim_name) + boolean = rt.IsProperty(sub_anim, "Export_Particles") if boolean: - opt = "${0}.{1}.export_particles".format(sel.name, - event_name) + event_name = sub_anim.Name + opt = f"${member.Name}.{event_name}.export_particles" opt_list.append(opt) return opt_list + @staticmethod + def get_setting(instance): + project_setting = get_project_settings( + instance.context.data["projectName"] + ) + return project_setting["max"]["PointCloud"] + def get_custom_attr(self, operator): """Get Custom Attributes""" custom_attr_list = [] - attr_settings = get_setting()["attribute"] + attr_settings = self.settings["attribute"] for key, value in attr_settings.items(): custom_attr = "{0}.PRTChannels_{1}=True".format(operator, value) @@ -157,14 +172,25 @@ class ExtractPointCloud(publish.Extractor): path, start_frame, end_frame): - """ - Note: - Set the filenames accordingly to the tyFlow file - naming extension for the publishing purpose + """Get file names for tyFlow. - Actual File Output from tyFlow: + Set the filenames accordingly to the tyFlow file + naming extension for the publishing purpose + + Actual File Output from tyFlow:: __partof..prt + e.g. tyFlow_cloth_CCCS_blobbyFill_001__part1of1_00004.prt + + Args: + container: Instance node. + path (str): Output directory. + start_frame (int): Start frame. + end_frame (int): End frame. + + Returns: + list of filenames + """ filenames = [] filename = os.path.basename(path) @@ -181,27 +207,36 @@ class ExtractPointCloud(publish.Extractor): return filenames def partition_output_name(self, container): - """ - Notes: - Partition output name set for mapping - the published file output + """Get partition output name. + + Partition output name set for mapping + the published file output. + + Todo: + Customizes the setting for the output. + + Args: + container: Instance node. + + Returns: + str: Partition name. - todo: - Customizes the setting for the output """ partition_count, partition_start = self.get_partition(container) - partition = "_part{:03}of{}".format(partition_start, - partition_count) - - return partition + return f"_part{partition_start:03}of{partition_count}" def get_partition(self, container): - """ - Get Partition Value + """Get Partition value. + + Args: + container: Instance node. + """ opt_list = self.get_operators(container) + # TODO: This looks strange? Iterating over + # the opt_list but returning from inside? for operator in opt_list: - count = rt.execute(f'{operator}.PRTPartitionsCount') - start = rt.execute(f'{operator}.PRTPartitionsFrom') + count = rt.Execute(f'{operator}.PRTPartitionsCount') + start = rt.Execute(f'{operator}.PRTPartitionsFrom') return count, start diff --git a/openpype/hosts/max/plugins/publish/validate_camera_contents.py b/openpype/hosts/max/plugins/publish/validate_camera_contents.py index c81e28a61f..a858092abd 100644 --- a/openpype/hosts/max/plugins/publish/validate_camera_contents.py +++ b/openpype/hosts/max/plugins/publish/validate_camera_contents.py @@ -18,30 +18,24 @@ class ValidateCameraContent(pyblish.api.InstancePlugin): "$Physical_Camera", "$Target"] def process(self, instance): - invalid = self.get_invalid(instance) - if invalid: - raise PublishValidationError("Camera instance must only include" - "camera (and camera target)") + if invalid := self.get_invalid(instance): + raise PublishValidationError(("Camera instance must only include" + "camera (and camera target). " + f"Invalid content {invalid}")) def get_invalid(self, instance): """ Get invalid nodes if the instance is not camera """ - invalid = list() + invalid = [] container = instance.data["instance_node"] - self.log.info("Validating look content for " - "{}".format(container)) + self.log.info(f"Validating camera content for {container}") - con = rt.getNodeByName(container) - selection_list = list(con.Children) + selection_list = instance.data["members"] for sel in selection_list: # to avoid Attribute Error from pymxs wrapper sel_tmp = str(sel) - found = False - for cam in self.camera_type: - if sel_tmp.startswith(cam): - found = True - break + found = any(sel_tmp.startswith(cam) for cam in self.camera_type) if not found: self.log.error("Camera not found") invalid.append(sel) diff --git a/openpype/hosts/max/plugins/publish/validate_model_contents.py b/openpype/hosts/max/plugins/publish/validate_model_contents.py index dd782674ff..b21c0184b0 100644 --- a/openpype/hosts/max/plugins/publish/validate_model_contents.py +++ b/openpype/hosts/max/plugins/publish/validate_model_contents.py @@ -17,28 +17,26 @@ class ValidateModelContent(pyblish.api.InstancePlugin): label = "Model Contents" def process(self, instance): - invalid = self.get_invalid(instance) - if invalid: - raise PublishValidationError("Model instance must only include" - "Geometry and Editable Mesh") + if invalid := self.get_invalid(instance): + raise PublishValidationError(("Model instance must only include" + "Geometry and Editable Mesh. " + f"Invalid types on: {invalid}")) def get_invalid(self, instance): """ Get invalid nodes if the instance is not camera """ - invalid = list() + invalid = [] container = instance.data["instance_node"] - self.log.info("Validating look content for " - "{}".format(container)) + self.log.info(f"Validating model content for {container}") - con = rt.getNodeByName(container) - selection_list = list(con.Children) or rt.getCurrentSelection() + selection_list = instance.data["members"] for sel in selection_list: - if rt.classOf(sel) in rt.Camera.classes: + if rt.ClassOf(sel) in rt.Camera.classes: invalid.append(sel) - if rt.classOf(sel) in rt.Light.classes: + if rt.ClassOf(sel) in rt.Light.classes: invalid.append(sel) - if rt.classOf(sel) in rt.Shape.classes: + if rt.ClassOf(sel) in rt.Shape.classes: invalid.append(sel) return invalid diff --git a/openpype/hosts/max/plugins/publish/validate_no_max_content.py b/openpype/hosts/max/plugins/publish/validate_no_max_content.py index c20a1968ed..ba4a6882c2 100644 --- a/openpype/hosts/max/plugins/publish/validate_no_max_content.py +++ b/openpype/hosts/max/plugins/publish/validate_no_max_content.py @@ -18,6 +18,5 @@ class ValidateMaxContents(pyblish.api.InstancePlugin): label = "Max Scene Contents" def process(self, instance): - container = rt.getNodeByName(instance.data["instance_node"]) - if not list(container.Children): + if not instance.data["members"]: raise PublishValidationError("No content found in the container") diff --git a/openpype/hosts/max/plugins/publish/validate_pointcloud.py b/openpype/hosts/max/plugins/publish/validate_pointcloud.py index f654058648..38d8226e41 100644 --- a/openpype/hosts/max/plugins/publish/validate_pointcloud.py +++ b/openpype/hosts/max/plugins/publish/validate_pointcloud.py @@ -9,11 +9,11 @@ def get_setting(project_setting=None): project_setting = get_project_settings( legacy_io.Session["AVALON_PROJECT"] ) - return (project_setting["max"]["PointCloud"]) + return project_setting["max"]["PointCloud"] class ValidatePointCloud(pyblish.api.InstancePlugin): - """Validate that workfile was saved.""" + """Validate that work file was saved.""" order = pyblish.api.ValidatorOrder families = ["pointcloud"] @@ -34,39 +34,37 @@ class ValidatePointCloud(pyblish.api.InstancePlugin): of export_particle operator """ - invalid = self.get_tyFlow_object(instance) - if invalid: - raise PublishValidationError("Non tyFlow object " - "found: {}".format(invalid)) - invalid = self.get_tyFlow_operator(instance) - if invalid: - raise PublishValidationError("tyFlow ExportParticle operator " - "not found: {}".format(invalid)) + report = [] + if invalid := self.get_tyflow_object(instance): + report.append(f"Non tyFlow object found: {invalid}") - invalid = self.validate_export_mode(instance) - if invalid: - raise PublishValidationError("The export mode is not at PRT") + if invalid := self.get_tyflow_operator(instance): + report.append( + f"tyFlow ExportParticle operator not found: {invalid}") - invalid = self.validate_partition_value(instance) - if invalid: - raise PublishValidationError("tyFlow Partition setting is " - "not at the default value") - invalid = self.validate_custom_attribute(instance) - if invalid: - raise PublishValidationError("Custom Attribute not found " - ":{}".format(invalid)) + if self.validate_export_mode(instance): + report.append("The export mode is not at PRT") - def get_tyFlow_object(self, instance): + if self.validate_partition_value(instance): + report.append(("tyFlow Partition setting is " + "not at the default value")) + + if invalid := self.validate_custom_attribute(instance): + report.append(("Custom Attribute not found " + f":{invalid}")) + + if report: + raise PublishValidationError + + def get_tyflow_object(self, instance): invalid = [] container = instance.data["instance_node"] - self.log.info("Validating tyFlow container " - "for {}".format(container)) + self.log.info(f"Validating tyFlow container for {container}") - con = rt.getNodeByName(container) - selection_list = list(con.Children) + selection_list = instance.data["members"] for sel in selection_list: sel_tmp = str(sel) - if rt.classOf(sel) in [rt.tyFlow, + if rt.ClassOf(sel) in [rt.tyFlow, rt.Editable_Mesh]: if "tyFlow" not in sel_tmp: invalid.append(sel) @@ -75,23 +73,20 @@ class ValidatePointCloud(pyblish.api.InstancePlugin): return invalid - def get_tyFlow_operator(self, instance): + def get_tyflow_operator(self, instance): invalid = [] container = instance.data["instance_node"] - self.log.info("Validating tyFlow object " - "for {}".format(container)) - - con = rt.getNodeByName(container) - selection_list = list(con.Children) + self.log.info(f"Validating tyFlow object for {container}") + selection_list = instance.data["members"] bool_list = [] for sel in selection_list: obj = sel.baseobject - anim_names = rt.getsubanimnames(obj) + anim_names = rt.GetSubAnimNames(obj) for anim_name in anim_names: # get all the names of the related tyFlow nodes - sub_anim = rt.getsubanim(obj, anim_name) + sub_anim = rt.GetSubAnim(obj, anim_name) # check if there is export particle operator - boolean = rt.isProperty(sub_anim, "Export_Particles") + boolean = rt.IsProperty(sub_anim, "Export_Particles") bool_list.append(str(boolean)) # if the export_particles property is not there # it means there is not a "Export Particle" operator @@ -104,21 +99,18 @@ class ValidatePointCloud(pyblish.api.InstancePlugin): def validate_custom_attribute(self, instance): invalid = [] container = instance.data["instance_node"] - self.log.info("Validating tyFlow custom " - "attributes for {}".format(container)) + self.log.info( + f"Validating tyFlow custom attributes for {container}") - con = rt.getNodeByName(container) - selection_list = list(con.Children) + selection_list = instance.data["members"] for sel in selection_list: obj = sel.baseobject - anim_names = rt.getsubanimnames(obj) + anim_names = rt.GetSubAnimNames(obj) for anim_name in anim_names: # get all the names of the related tyFlow nodes - sub_anim = rt.getsubanim(obj, anim_name) - # check if there is export particle operator - boolean = rt.isProperty(sub_anim, "Export_Particles") - event_name = sub_anim.name - if boolean: + sub_anim = rt.GetSubAnim(obj, anim_name) + if rt.IsProperty(sub_anim, "Export_Particles"): + event_name = sub_anim.name opt = "${0}.{1}.export_particles".format(sel.name, event_name) attributes = get_setting()["attribute"] @@ -126,39 +118,36 @@ class ValidatePointCloud(pyblish.api.InstancePlugin): custom_attr = "{0}.PRTChannels_{1}".format(opt, value) try: - rt.execute(custom_attr) + rt.Execute(custom_attr) except RuntimeError: - invalid.add(key) + invalid.append(key) return invalid def validate_partition_value(self, instance): invalid = [] container = instance.data["instance_node"] - self.log.info("Validating tyFlow partition " - "value for {}".format(container)) + self.log.info( + f"Validating tyFlow partition value for {container}") - con = rt.getNodeByName(container) - selection_list = list(con.Children) + selection_list = instance.data["members"] for sel in selection_list: obj = sel.baseobject - anim_names = rt.getsubanimnames(obj) + anim_names = rt.GetSubAnimNames(obj) for anim_name in anim_names: # get all the names of the related tyFlow nodes - sub_anim = rt.getsubanim(obj, anim_name) - # check if there is export particle operator - boolean = rt.isProperty(sub_anim, "Export_Particles") - event_name = sub_anim.name - if boolean: + sub_anim = rt.GetSubAnim(obj, anim_name) + if rt.IsProperty(sub_anim, "Export_Particles"): + event_name = sub_anim.name opt = "${0}.{1}.export_particles".format(sel.name, event_name) - count = rt.execute(f'{opt}.PRTPartitionsCount') + count = rt.Execute(f'{opt}.PRTPartitionsCount') if count != 100: invalid.append(count) - start = rt.execute(f'{opt}.PRTPartitionsFrom') + start = rt.Execute(f'{opt}.PRTPartitionsFrom') if start != 1: invalid.append(start) - end = rt.execute(f'{opt}.PRTPartitionsTo') + end = rt.Execute(f'{opt}.PRTPartitionsTo') if end != 1: invalid.append(end) @@ -167,24 +156,23 @@ class ValidatePointCloud(pyblish.api.InstancePlugin): def validate_export_mode(self, instance): invalid = [] container = instance.data["instance_node"] - self.log.info("Validating tyFlow export " - "mode for {}".format(container)) + self.log.info( + f"Validating tyFlow export mode for {container}") - con = rt.getNodeByName(container) + con = rt.GetNodeByName(container) selection_list = list(con.Children) for sel in selection_list: obj = sel.baseobject - anim_names = rt.getsubanimnames(obj) + anim_names = rt.GetSubAnimNames(obj) for anim_name in anim_names: # get all the names of the related tyFlow nodes - sub_anim = rt.getsubanim(obj, anim_name) + sub_anim = rt.GetSubAnim(obj, anim_name) # check if there is export particle operator - boolean = rt.isProperty(sub_anim, "Export_Particles") + boolean = rt.IsProperty(sub_anim, "Export_Particles") event_name = sub_anim.name if boolean: - opt = "${0}.{1}.export_particles".format(sel.name, - event_name) - export_mode = rt.execute(f'{opt}.exportMode') + opt = f"${sel.name}.{event_name}.export_particles" + export_mode = rt.Execute(f'{opt}.exportMode') if export_mode != 1: invalid.append(export_mode) diff --git a/openpype/hosts/max/plugins/publish/validate_usd_plugin.py b/openpype/hosts/max/plugins/publish/validate_usd_plugin.py index 747147020a..8f11d72567 100644 --- a/openpype/hosts/max/plugins/publish/validate_usd_plugin.py +++ b/openpype/hosts/max/plugins/publish/validate_usd_plugin.py @@ -14,21 +14,20 @@ class ValidateUSDPlugin(pyblish.api.InstancePlugin): label = "USD Plugin" def process(self, instance): - plugin_mgr = rt.pluginManager + plugin_mgr = rt.PluginManager plugin_count = plugin_mgr.pluginDllCount plugin_info = self.get_plugins(plugin_mgr, plugin_count) usd_import = "usdimport.dli" if usd_import not in plugin_info: - raise PublishValidationError("USD Plugin {}" - " not found".format(usd_import)) + raise PublishValidationError(f"USD Plugin {usd_import} not found") usd_export = "usdexport.dle" if usd_export not in plugin_info: - raise PublishValidationError("USD Plugin {}" - " not found".format(usd_export)) + raise PublishValidationError(f"USD Plugin {usd_export} not found") - def get_plugins(self, manager, count): - plugin_info_list = list() + @staticmethod + def get_plugins(manager, count): + plugin_info_list = [] for p in range(1, count + 1): plugin_info = manager.pluginDllName(p) plugin_info_list.append(plugin_info)