From 0e80eff9349fb61125a459f7993dba0a7e8eb5f0 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 22 Dec 2022 21:32:53 +0800 Subject: [PATCH 01/70] maya gltf texture convertor and validator --- .../plugins/publish/convert_gltf_shader.py | 83 ++++++++++++ .../publish/validate_gltf_textures_names.py | 125 ++++++++++++++++++ .../defaults/project_settings/maya.json | 5 + .../schemas/schema_maya_publish.json | 4 + 4 files changed, 217 insertions(+) create mode 100644 openpype/hosts/maya/plugins/publish/convert_gltf_shader.py create mode 100644 openpype/hosts/maya/plugins/publish/validate_gltf_textures_names.py diff --git a/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py b/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py new file mode 100644 index 0000000000..f62fb92f81 --- /dev/null +++ b/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py @@ -0,0 +1,83 @@ +import os +from maya import cmds +import pyblish.api + +from openpype.pipeline import publish + + +class ConvertGLSLShader(publish.Extractor): + """ + Converting StingrayPBS material to GLSL Shaders + specially for the glb export through Maya2GLTF plugin + + """ + order = pyblish.api.ExtractorOrder - 0.1 + hosts = ["maya"] + label = "Convert StingrayPBS to GLTF" + families = ["gltf"] + optional = True + + def process(self, instance): + meshes = cmds.ls(instance, type="mesh", long=True) + self.log.info("meshes: {}".format(meshes)) + # load the glsl shader plugin + cmds.loadPlugin("glslShader.mll", quiet=True) + + for mesh in meshes: + + # create glsl shader + glsl_shader = cmds.createNode('GLSLShader') + glsl_shadingGrp = cmds.sets(name=glsl_shader + "SG", empty=True, + renderable=True, noSurfaceShader=True) + cmds.connectAttr(glsl_shader + ".outColor", glsl_shadingGrp + ".surfaceShader") + + # load the maya2gltf shader + maya_dir = os.getenv("MAYA_APP_DIR") + ogsfx = maya_dir + "/maya2glTF/PBR/shaders/glTF_PBR.ogsfx" + cmds.setAttr(glsl_shader + ".shader", ogsfx, typ="string") + + # list the materials used for the assets + shading_grp = cmds.listConnections( + mesh, destination=True, type="shadingEngine" + ) + + # get the materials related to the selected assets + for material in shading_grp: + main_shader = cmds.listConnections( + material, destination=True, type="StingrayPBS" + ) + for shader in main_shader: + # get the file textures related to the PBS Shader + albedo = cmds.listConnections(shader + ".TEX_color_map")[0] + dif_output = albedo + ".outColor" + + orm_packed = cmds.listConnections(shader + ".TEX_ao_mapX")[0] + ao_output = orm_packed + ".outColorR" + rough_output = orm_packed + ".outColorG" + metallic_output = orm_packed + ".outColorB" + + nrm = cmds.listConnections(shader + ".TEX_normal_map")[0] + nrm_output = nrm + ".outColor" + + # get the glsl_shader input + # reconnect the file nodes to maya2gltf shader + glsl_dif = glsl_shader + ".u_BaseColorTexture" + glsl_nrm = glsl_shader + ".u_NormalTexture" + cmds.connectAttr(dif_output, glsl_dif) + cmds.connectAttr(nrm_output, glsl_nrm) + + rgb_list = ["R", "G", "B"] + for ch in rgb_list: + mtl = ".u_MetallicTexture.u_MetallicTexture{}".format(ch) + mtl = glsl_shader + mtl + ao = ".u_OcclusionTexture.u_OcclusionTexture{}".format(ch) + ao= glsl_shader + ao + rough = ".u_RoughnessTexture.u_RoughnessTexture{}".format(ch) + rough= glsl_shader + rough + + cmds.connectAttr(metallic_output, mtl) + cmds.connectAttr(ao_output, ao) + cmds.connectAttr(rough_output, rough) + + # assign the shader to the asset + cmds.sets(mesh, forceElement = str(glsl_shadingGrp)) diff --git a/openpype/hosts/maya/plugins/publish/validate_gltf_textures_names.py b/openpype/hosts/maya/plugins/publish/validate_gltf_textures_names.py new file mode 100644 index 0000000000..2b99defd1b --- /dev/null +++ b/openpype/hosts/maya/plugins/publish/validate_gltf_textures_names.py @@ -0,0 +1,125 @@ +from maya import cmds + +import pyblish.api +import openpype.hosts.maya.api.action +from openpype.pipeline.publish import ValidateContentsOrder + + +class ValidateGLTFTexturesNames(pyblish.api.InstancePlugin): + """ + Validate if the asset uses StingrayPBS material before conversion + of the GLSL Shader + Validate if the names of GLTF Textures follow + the packed ORM/ORMS standard. + + The texture naming conventions follows the UE5-style-guides: + https://github.com/Allar/ue5-style-guide#anc-textures-packing + + ORM: Occulsion Roughness Metallic + ORMS: Occulsion Roughness Metallic Specular + + Texture Naming Style: + + Albedo/Diffuse: {Name}_D.{imageExtension} or + {Name}_D..{imageExtension} + + Normal: {Name}_N.{imageExtension} or + {Name}_N..{imageExtension} + ORM: {Name}_ORM.{imageExtension} or + {Name}_ORM..{imageExtension} + + """ + + order = ValidateContentsOrder + families = ['gltf'] + hosts = ['maya'] + label = 'GLTF Textures Name' + actions = [openpype.hosts.maya.api.action.SelectInvalidAction] + + def process(self, instance): + """Process all the nodes in the instance""" + invalid = self.get_texture_shader_invalid(instance) + if invalid: + raise RuntimeError("Non PBS material found in " + "{0}".format(invalid)) + invalid = self.get_texture_node_invalid(instance) + if invalid: + raise RuntimeError("Related texture file " \ + "nodes not connected") + invalid = self.get_texture_name_invalid(instance) + if invalid: + raise RuntimeError("Invalid texture name(s) found: " + "{0}".format(invalid)) + + + def get_texture_name_invalid(self, instance): + + invalid = set() + shading_grp = self.shader_selection(instance) + + # get the materials related to the selected assets + # get the file textures related to the PBS Shader + # validate the names of the textures + for material in shading_grp: + main_shader = cmds.listConnections( + material, destination=True, type="StingrayPBS" + ) + for shader in main_shader: + albedo = cmds.listConnections(shader + ".TEX_color_map")[0] + dif_path = cmds.getAttr(albedo + ".fileTextureName") + dif = dif_path.split(".")[0] + # "_D" + if not dif.endswith("_D"): + invalid.add(dif_path) + orm_packed = cmds.listConnections(shader + ".TEX_ao_mapX")[0] + # "_ORM" + orm_path = cmds.getAttr(orm_packed + ".fileTextureName") + orm = orm_path.split(".")[0] + if not orm.endswith("_ORM"): + invalid.add(orm_path) + nrm = cmds.listConnections(shader + ".TEX_normal_map")[0] + nrm_path = cmds.getAttr(nrm + ".fileTextureName") + nrm_map = nrm_path.split(".")[0] + # "_N" + if not nrm_map.endswith("_N"): + invalid.add(nrm_path) + + return list(invalid) + + def get_texture_node_invalid(self, instance): + invalid = set() + shading_grp = self.shader_selection(instance) + for material in shading_grp: + main_shader = cmds.listConnections( + material, destination=True, type="StingrayPBS" + ) + for shader in main_shader: + # diffuse texture file node + albedo = cmds.listConnections(shader + ".TEX_color_map") + if not albedo: + invalid.add(albedo) + orm_packed = cmds.listConnections(shader + ".TEX_ao_mapX") + if not orm_packed: + invalid.add(orm_packed) + nrm = cmds.listConnections(shader + ".TEX_normal_map") + if not nrm: + invalid.add(nrm) + return list(invalid) + + def get_texture_shader_invalid(self, instance): + + invalid = set() + shading_grp = self.shader_selection(instance) + for shader in shading_grp: + if "StingrayPBS" not in shader: + invalid.add(shader) + return list(invalid) + + def shader_selection(self, instance): + shapes = cmds.ls(instance, type="mesh", long=True) + for shape in shapes: + shading_grp = cmds.listConnections( + shape, destination=True, type="shadingEngine" + ) + + return shading_grp diff --git a/openpype/settings/defaults/project_settings/maya.json b/openpype/settings/defaults/project_settings/maya.json index 5f40c2a10c..db64f388c8 100644 --- a/openpype/settings/defaults/project_settings/maya.json +++ b/openpype/settings/defaults/project_settings/maya.json @@ -349,6 +349,11 @@ "optional": false, "active": true }, + "ValidateGLTFTexturesNames": { + "enabled": true, + "optional": false, + "active": true + }, "ValidateRenderImageRule": { "enabled": true, "optional": false, diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json index 9aaff248ab..32280d1934 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json @@ -369,6 +369,10 @@ "key": "ValidateCurrentRenderLayerIsRenderable", "label": "Validate Current Render Layer Has Renderable Camera" }, + { + "key": "ValidateGLTFTexturesNames", + "label": "Validate GLTF Textures Names" + }, { "key": "ValidateRenderImageRule", "label": "Validate Images File Rule (Workspace)" From 92fd7658d985fcf8208048de458636c8792b805f Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 22 Dec 2022 21:59:24 +0800 Subject: [PATCH 02/70] maya gltf texture convertor and validator --- .../plugins/publish/convert_gltf_shader.py | 34 +++++++++---------- .../publish/validate_gltf_textures_names.py | 12 +++---- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py b/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py index f62fb92f81..8223b80c3c 100644 --- a/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py +++ b/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py @@ -26,26 +26,26 @@ class ConvertGLSLShader(publish.Extractor): for mesh in meshes: # create glsl shader - glsl_shader = cmds.createNode('GLSLShader') - glsl_shadingGrp = cmds.sets(name=glsl_shader + "SG", empty=True, + glsl = cmds.createNode('GLSLShader') + glsl_shadingGrp = cmds.sets(name=glsl + "SG", empty=True, renderable=True, noSurfaceShader=True) - cmds.connectAttr(glsl_shader + ".outColor", glsl_shadingGrp + ".surfaceShader") + cmds.connectAttr(glsl + ".outColor", glsl_shadingGrp + ".surfaceShader") # load the maya2gltf shader maya_dir = os.getenv("MAYA_APP_DIR") ogsfx = maya_dir + "/maya2glTF/PBR/shaders/glTF_PBR.ogsfx" - cmds.setAttr(glsl_shader + ".shader", ogsfx, typ="string") + cmds.setAttr(glsl + ".shader", ogsfx, typ="string") # list the materials used for the assets shading_grp = cmds.listConnections( - mesh, destination=True, type="shadingEngine" - ) + mesh, destination=True, + type="shadingEngine") # get the materials related to the selected assets for material in shading_grp: main_shader = cmds.listConnections( - material, destination=True, type="StingrayPBS" - ) + material, destination=True, + type="StingrayPBS") for shader in main_shader: # get the file textures related to the PBS Shader albedo = cmds.listConnections(shader + ".TEX_color_map")[0] @@ -61,23 +61,23 @@ class ConvertGLSLShader(publish.Extractor): # get the glsl_shader input # reconnect the file nodes to maya2gltf shader - glsl_dif = glsl_shader + ".u_BaseColorTexture" - glsl_nrm = glsl_shader + ".u_NormalTexture" + glsl_dif = glsl + ".u_BaseColorTexture" + glsl_nrm = glsl + ".u_NormalTexture" cmds.connectAttr(dif_output, glsl_dif) cmds.connectAttr(nrm_output, glsl_nrm) rgb_list = ["R", "G", "B"] for ch in rgb_list: - mtl = ".u_MetallicTexture.u_MetallicTexture{}".format(ch) - mtl = glsl_shader + mtl - ao = ".u_OcclusionTexture.u_OcclusionTexture{}".format(ch) - ao= glsl_shader + ao - rough = ".u_RoughnessTexture.u_RoughnessTexture{}".format(ch) - rough= glsl_shader + rough + mtl = ".u_MetallicTexture.u_MetallicTexture{}".format(ch) # noqa + mtl = glsl + mtl + ao = ".u_OcclusionTexture.u_OcclusionTexture{}".format(ch) # noqa + ao = glsl + ao + rough = ".u_RoughnessTexture.u_RoughnessTexture{}".format(ch) # noqa + rough = glsl + rough cmds.connectAttr(metallic_output, mtl) cmds.connectAttr(ao_output, ao) cmds.connectAttr(rough_output, rough) # assign the shader to the asset - cmds.sets(mesh, forceElement = str(glsl_shadingGrp)) + cmds.sets(mesh, forceElement=str(glsl_shadingGrp)) diff --git a/openpype/hosts/maya/plugins/publish/validate_gltf_textures_names.py b/openpype/hosts/maya/plugins/publish/validate_gltf_textures_names.py index 2b99defd1b..6ff8aba623 100644 --- a/openpype/hosts/maya/plugins/publish/validate_gltf_textures_names.py +++ b/openpype/hosts/maya/plugins/publish/validate_gltf_textures_names.py @@ -62,8 +62,8 @@ class ValidateGLTFTexturesNames(pyblish.api.InstancePlugin): # validate the names of the textures for material in shading_grp: main_shader = cmds.listConnections( - material, destination=True, type="StingrayPBS" - ) + material, destination=True, + type="StingrayPBS") for shader in main_shader: albedo = cmds.listConnections(shader + ".TEX_color_map")[0] dif_path = cmds.getAttr(albedo + ".fileTextureName") @@ -91,8 +91,8 @@ class ValidateGLTFTexturesNames(pyblish.api.InstancePlugin): shading_grp = self.shader_selection(instance) for material in shading_grp: main_shader = cmds.listConnections( - material, destination=True, type="StingrayPBS" - ) + material, destination=True, + type="StingrayPBS") for shader in main_shader: # diffuse texture file node albedo = cmds.listConnections(shader + ".TEX_color_map") @@ -119,7 +119,7 @@ class ValidateGLTFTexturesNames(pyblish.api.InstancePlugin): shapes = cmds.ls(instance, type="mesh", long=True) for shape in shapes: shading_grp = cmds.listConnections( - shape, destination=True, type="shadingEngine" - ) + shape, destination=True, + type="shadingEngine") return shading_grp From 96c80299975dae5e9418144c7f106a2461ef90e7 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 22 Dec 2022 22:05:09 +0800 Subject: [PATCH 03/70] maya gltf texture convertor and validator --- .../plugins/publish/convert_gltf_shader.py | 15 ++++++------- .../publish/validate_gltf_textures_names.py | 21 +++++++++---------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py b/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py index 8223b80c3c..6c1a7346e7 100644 --- a/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py +++ b/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py @@ -29,7 +29,8 @@ class ConvertGLSLShader(publish.Extractor): glsl = cmds.createNode('GLSLShader') glsl_shadingGrp = cmds.sets(name=glsl + "SG", empty=True, renderable=True, noSurfaceShader=True) - cmds.connectAttr(glsl + ".outColor", glsl_shadingGrp + ".surfaceShader") + cmds.connectAttr(glsl + ".outColor", + glsl_shadingGrp + ".surfaceShader") # load the maya2gltf shader maya_dir = os.getenv("MAYA_APP_DIR") @@ -37,15 +38,15 @@ class ConvertGLSLShader(publish.Extractor): cmds.setAttr(glsl + ".shader", ogsfx, typ="string") # list the materials used for the assets - shading_grp = cmds.listConnections( - mesh, destination=True, - type="shadingEngine") + shading_grp = cmds.listConnections(mesh, + destination=True, + type="shadingEngine") # get the materials related to the selected assets for material in shading_grp: - main_shader = cmds.listConnections( - material, destination=True, - type="StingrayPBS") + main_shader = cmds.listConnections(material, + destination=True, + type="StingrayPBS") for shader in main_shader: # get the file textures related to the PBS Shader albedo = cmds.listConnections(shader + ".TEX_color_map")[0] diff --git a/openpype/hosts/maya/plugins/publish/validate_gltf_textures_names.py b/openpype/hosts/maya/plugins/publish/validate_gltf_textures_names.py index 6ff8aba623..6e5e1a832d 100644 --- a/openpype/hosts/maya/plugins/publish/validate_gltf_textures_names.py +++ b/openpype/hosts/maya/plugins/publish/validate_gltf_textures_names.py @@ -44,14 +44,13 @@ class ValidateGLTFTexturesNames(pyblish.api.InstancePlugin): "{0}".format(invalid)) invalid = self.get_texture_node_invalid(instance) if invalid: - raise RuntimeError("Related texture file " \ + raise RuntimeError("Related texture file " "nodes not connected") invalid = self.get_texture_name_invalid(instance) if invalid: raise RuntimeError("Invalid texture name(s) found: " "{0}".format(invalid)) - def get_texture_name_invalid(self, instance): invalid = set() @@ -61,9 +60,9 @@ class ValidateGLTFTexturesNames(pyblish.api.InstancePlugin): # get the file textures related to the PBS Shader # validate the names of the textures for material in shading_grp: - main_shader = cmds.listConnections( - material, destination=True, - type="StingrayPBS") + main_shader = cmds.listConnections(material, + destination=True, + type="StingrayPBS") for shader in main_shader: albedo = cmds.listConnections(shader + ".TEX_color_map")[0] dif_path = cmds.getAttr(albedo + ".fileTextureName") @@ -90,9 +89,9 @@ class ValidateGLTFTexturesNames(pyblish.api.InstancePlugin): invalid = set() shading_grp = self.shader_selection(instance) for material in shading_grp: - main_shader = cmds.listConnections( - material, destination=True, - type="StingrayPBS") + main_shader = cmds.listConnections(material, + destination=True, + type="StingrayPBS") for shader in main_shader: # diffuse texture file node albedo = cmds.listConnections(shader + ".TEX_color_map") @@ -118,8 +117,8 @@ class ValidateGLTFTexturesNames(pyblish.api.InstancePlugin): def shader_selection(self, instance): shapes = cmds.ls(instance, type="mesh", long=True) for shape in shapes: - shading_grp = cmds.listConnections( - shape, destination=True, - type="shadingEngine") + shading_grp = cmds.listConnections(shape, + destination=True, + type="shadingEngine") return shading_grp From 7f02e8c72b89344076a7ca816daa4aacb027b349 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 22 Dec 2022 22:06:23 +0800 Subject: [PATCH 04/70] maya gltf texture convertor and validator --- openpype/hosts/maya/plugins/publish/convert_gltf_shader.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py b/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py index 6c1a7346e7..bbeeb38ef3 100644 --- a/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py +++ b/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py @@ -52,7 +52,8 @@ class ConvertGLSLShader(publish.Extractor): albedo = cmds.listConnections(shader + ".TEX_color_map")[0] dif_output = albedo + ".outColor" - orm_packed = cmds.listConnections(shader + ".TEX_ao_mapX")[0] + orm_packed = cmds.listConnections(shader + + ".TEX_ao_mapX")[0] ao_output = orm_packed + ".outColorR" rough_output = orm_packed + ".outColorG" metallic_output = orm_packed + ".outColorB" From b90e9b69c60ff03b165985350dd74b645793f824 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 16 Jan 2023 21:44:24 +0100 Subject: [PATCH 05/70] added more specific functions for current context into host integration --- openpype/host/host.py | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/openpype/host/host.py b/openpype/host/host.py index 94416bb39a..56d01c667a 100644 --- a/openpype/host/host.py +++ b/openpype/host/host.py @@ -100,6 +100,30 @@ class HostBase(object): pass + def get_current_project_name(self): + """ + Returns: + Union[str, None]: Current project name. + """ + + return os.environ.get("AVALON_PROJECT") + + def get_current_asset_name(self): + """ + Returns: + Union[str, None]: Current asset name. + """ + + return os.environ.get("AVALON_ASSET") + + def get_current_task_name(self): + """ + Returns: + Union[str, None]: Current task name. + """ + + return os.environ.get("AVALON_ASSET") + def get_current_context(self): """Get current context information. @@ -111,19 +135,14 @@ class HostBase(object): Default implementation returns values from 'legacy_io.Session'. Returns: - dict: Context with 3 keys 'project_name', 'asset_name' and - 'task_name'. All of them can be 'None'. + Dict[str, Union[str, None]]: Context with 3 keys 'project_name', + 'asset_name' and 'task_name'. All of them can be 'None'. """ - from openpype.pipeline import legacy_io - - if legacy_io.is_installed(): - legacy_io.install() - return { - "project_name": legacy_io.Session["AVALON_PROJECT"], - "asset_name": legacy_io.Session["AVALON_ASSET"], - "task_name": legacy_io.Session["AVALON_TASK"] + "project_name": self.get_current_project_name(), + "asset_name": self.get_current_asset_name(), + "task_name": self.get_current_task_name() } def get_context_title(self): From 2c35bda38146d35f84c3468abf64710c5fb02ba4 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 16 Jan 2023 21:45:09 +0100 Subject: [PATCH 06/70] added functions for global access to current context --- openpype/pipeline/context_tools.py | 44 +++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/openpype/pipeline/context_tools.py b/openpype/pipeline/context_tools.py index da0ce8ecf4..50ce827a39 100644 --- a/openpype/pipeline/context_tools.py +++ b/openpype/pipeline/context_tools.py @@ -306,6 +306,42 @@ def debug_host(): return host +def get_global_context(): + return { + "project_name": os.environ.get("AVALON_PROJECT"), + "asset_name": os.environ.get("AVALON_ASSET"), + "task_name": os.environ.get("AVALON_TASK"), + } + + +def get_current_context(): + host = registered_host() + if host is not None and hasattr(host, "get_current_context"): + return host.get_current_context() + return get_global_context() + + +def get_current_project_name(): + host = registered_host() + if host is not None and hasattr(host, "get_current_project_name"): + return host.get_current_project_name() + return get_global_context()["project_name"] + + +def get_current_asset_name(): + host = registered_host() + if host is not None and hasattr(host, "get_current_asset_name"): + return host.get_current_asset_name() + return get_global_context()["asset_name"] + + +def get_current_task_name(): + host = registered_host() + if host is not None and hasattr(host, "get_current_task_name"): + return host.get_current_task_name() + return get_global_context()["task_name"] + + def get_current_project(fields=None): """Helper function to get project document based on global Session. @@ -316,7 +352,7 @@ def get_current_project(fields=None): None: Project is not set. """ - project_name = legacy_io.active_project() + project_name = get_current_project_name() return get_project(project_name, fields=fields) @@ -341,12 +377,12 @@ def get_current_project_asset(asset_name=None, asset_id=None, fields=None): None: Asset is not set or not exist. """ - project_name = legacy_io.active_project() + project_name = get_current_project_name() if asset_id: return get_asset_by_id(project_name, asset_id, fields=fields) if not asset_name: - asset_name = legacy_io.Session.get("AVALON_ASSET") + asset_name = get_current_asset_name() # Skip if is not set even on context if not asset_name: return None @@ -363,7 +399,7 @@ def is_representation_from_latest(representation): bool: Whether the representation is of latest version. """ - project_name = legacy_io.active_project() + project_name = get_current_project_name() return version_is_latest(project_name, representation["parent"]) From b75768249c422665fdd380383424326829e00748 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 16 Jan 2023 21:45:17 +0100 Subject: [PATCH 07/70] added function to get current host name --- openpype/pipeline/context_tools.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/openpype/pipeline/context_tools.py b/openpype/pipeline/context_tools.py index 50ce827a39..06538dd91f 100644 --- a/openpype/pipeline/context_tools.py +++ b/openpype/pipeline/context_tools.py @@ -306,6 +306,22 @@ def debug_host(): return host +def get_current_host_name(): + """Current host name. + + Function is based on currently registered host integration or environment + variant 'AVALON_APP'. + + Returns: + Union[str, None]: Name of host integration in current process or None. + """ + + host = registered_host() + if host is not None and hasattr(host, "name"): + return host.name + return os.environ.get("AVALON_APP") + + def get_global_context(): return { "project_name": os.environ.get("AVALON_PROJECT"), From 48937de52ce9092d5718e9cb549764887be6c5c6 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 16 Jan 2023 22:07:25 +0100 Subject: [PATCH 08/70] added missing import --- openpype/host/host.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/host/host.py b/openpype/host/host.py index 56d01c667a..28d0a21b34 100644 --- a/openpype/host/host.py +++ b/openpype/host/host.py @@ -1,3 +1,4 @@ +import os import logging import contextlib from abc import ABCMeta, abstractproperty From 24d7de450b0f8906943638eb223b39f4fd83e70e Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 17 Jan 2023 15:39:23 +0800 Subject: [PATCH 09/70] improve the validator for gltf texture name --- .../plugins/publish/validate_gltf_textures_names.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_gltf_textures_names.py b/openpype/hosts/maya/plugins/publish/validate_gltf_textures_names.py index 6e5e1a832d..ed0ae9c6d5 100644 --- a/openpype/hosts/maya/plugins/publish/validate_gltf_textures_names.py +++ b/openpype/hosts/maya/plugins/publish/validate_gltf_textures_names.py @@ -38,6 +38,9 @@ class ValidateGLTFTexturesNames(pyblish.api.InstancePlugin): def process(self, instance): """Process all the nodes in the instance""" + pbs_shader = cmds.ls(type="StingrayPBS") + if not pbs_shader: + raise RuntimeError("No PBS Shader in the scene") invalid = self.get_texture_shader_invalid(instance) if invalid: raise RuntimeError("Non PBS material found in " @@ -109,9 +112,12 @@ class ValidateGLTFTexturesNames(pyblish.api.InstancePlugin): invalid = set() shading_grp = self.shader_selection(instance) - for shader in shading_grp: - if "StingrayPBS" not in shader: - invalid.add(shader) + for material in shading_grp: + main_shader = cmds.listConnections(material, + destination=True, + type="StingrayPBS") + if not main_shader: + invalid.add(material) return list(invalid) def shader_selection(self, instance): From 3dd02cec71ceeac49d52a3f85652548aef68e21f Mon Sep 17 00:00:00 2001 From: Kayla Man <64118225+moonyuet@users.noreply.github.com> Date: Tue, 17 Jan 2023 22:49:33 +0800 Subject: [PATCH 10/70] update the validator --- .../publish/validate_gltf_textures_names.py | 32 ++++++++----------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_gltf_textures_names.py b/openpype/hosts/maya/plugins/publish/validate_gltf_textures_names.py index ed0ae9c6d5..635a59a4be 100644 --- a/openpype/hosts/maya/plugins/publish/validate_gltf_textures_names.py +++ b/openpype/hosts/maya/plugins/publish/validate_gltf_textures_names.py @@ -47,8 +47,8 @@ class ValidateGLTFTexturesNames(pyblish.api.InstancePlugin): "{0}".format(invalid)) invalid = self.get_texture_node_invalid(instance) if invalid: - raise RuntimeError("Related texture file " - "nodes not connected") + raise RuntimeError("At least a Albedo texture file" + "nodes need to be connected") invalid = self.get_texture_name_invalid(instance) if invalid: raise RuntimeError("Invalid texture name(s) found: " @@ -74,17 +74,19 @@ class ValidateGLTFTexturesNames(pyblish.api.InstancePlugin): if not dif.endswith("_D"): invalid.add(dif_path) orm_packed = cmds.listConnections(shader + ".TEX_ao_mapX")[0] - # "_ORM" - orm_path = cmds.getAttr(orm_packed + ".fileTextureName") - orm = orm_path.split(".")[0] - if not orm.endswith("_ORM"): - invalid.add(orm_path) + if orm_packed: + # "_ORM" + orm_path = cmds.getAttr(orm_packed + ".fileTextureName") + orm = orm_path.split(".")[0] + if not orm.endswith("_ORM"): + invalid.add(orm_path) nrm = cmds.listConnections(shader + ".TEX_normal_map")[0] - nrm_path = cmds.getAttr(nrm + ".fileTextureName") - nrm_map = nrm_path.split(".")[0] - # "_N" - if not nrm_map.endswith("_N"): - invalid.add(nrm_path) + if nrm: + nrm_path = cmds.getAttr(nrm + ".fileTextureName") + nrm_map = nrm_path.split(".")[0] + # "_N" + if not nrm_map.endswith("_N"): + invalid.add(nrm_path) return list(invalid) @@ -100,12 +102,6 @@ class ValidateGLTFTexturesNames(pyblish.api.InstancePlugin): albedo = cmds.listConnections(shader + ".TEX_color_map") if not albedo: invalid.add(albedo) - orm_packed = cmds.listConnections(shader + ".TEX_ao_mapX") - if not orm_packed: - invalid.add(orm_packed) - nrm = cmds.listConnections(shader + ".TEX_normal_map") - if not nrm: - invalid.add(nrm) return list(invalid) def get_texture_shader_invalid(self, instance): From eb8c40a4e7b985cf5455081fe72301e1942f8480 Mon Sep 17 00:00:00 2001 From: Kayla Man <64118225+moonyuet@users.noreply.github.com> Date: Tue, 17 Jan 2023 23:50:27 +0800 Subject: [PATCH 11/70] update the validator for ORM --- openpype/hosts/maya/plugins/publish/convert_gltf_shader.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py b/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py index bbeeb38ef3..ceed4cb062 100644 --- a/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py +++ b/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py @@ -53,7 +53,7 @@ class ConvertGLSLShader(publish.Extractor): dif_output = albedo + ".outColor" orm_packed = cmds.listConnections(shader + - ".TEX_ao_mapX")[0] + ".TEX_ao_map")[0] ao_output = orm_packed + ".outColorR" rough_output = orm_packed + ".outColorG" metallic_output = orm_packed + ".outColorB" From ba45473f8ceee3a6c9d934b8ac6e5b71a4e273d9 Mon Sep 17 00:00:00 2001 From: Kayla Man <64118225+moonyuet@users.noreply.github.com> Date: Tue, 17 Jan 2023 23:51:28 +0800 Subject: [PATCH 12/70] update the texture conversion of ORM --- .../plugins/publish/convert_gltf_shader.py | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py b/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py index ceed4cb062..39597806bf 100644 --- a/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py +++ b/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py @@ -54,9 +54,7 @@ class ConvertGLSLShader(publish.Extractor): orm_packed = cmds.listConnections(shader + ".TEX_ao_map")[0] - ao_output = orm_packed + ".outColorR" - rough_output = orm_packed + ".outColorG" - metallic_output = orm_packed + ".outColorB" + orm_output = orm_packed + ".outColor" nrm = cmds.listConnections(shader + ".TEX_normal_map")[0] nrm_output = nrm + ".outColor" @@ -68,18 +66,17 @@ class ConvertGLSLShader(publish.Extractor): cmds.connectAttr(dif_output, glsl_dif) cmds.connectAttr(nrm_output, glsl_nrm) - rgb_list = ["R", "G", "B"] - for ch in rgb_list: - mtl = ".u_MetallicTexture.u_MetallicTexture{}".format(ch) # noqa - mtl = glsl + mtl - ao = ".u_OcclusionTexture.u_OcclusionTexture{}".format(ch) # noqa - ao = glsl + ao - rough = ".u_RoughnessTexture.u_RoughnessTexture{}".format(ch) # noqa - rough = glsl + rough - cmds.connectAttr(metallic_output, mtl) - cmds.connectAttr(ao_output, ao) - cmds.connectAttr(rough_output, rough) + mtl = ".u_MetallicTexture.u_MetallicTexture" + mtl = glsl + mtl + ao = ".u_OcclusionTexture.u_OcclusionTexture" + ao = glsl + ao + rough = ".u_RoughnessTexture.u_RoughnessTexture" + rough = glsl + rough + + cmds.connectAttr(orm_output, mtl) + cmds.connectAttr(orm_output, ao) + cmds.connectAttr(orm_output, rough) # assign the shader to the asset cmds.sets(mesh, forceElement=str(glsl_shadingGrp)) From 0af4f7d9fe21fe86426692308a98e868c79dabba Mon Sep 17 00:00:00 2001 From: Kayla Man <64118225+moonyuet@users.noreply.github.com> Date: Tue, 17 Jan 2023 23:52:26 +0800 Subject: [PATCH 13/70] Update convert_gltf_shader.py --- openpype/hosts/maya/plugins/publish/convert_gltf_shader.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py b/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py index 39597806bf..7d28bef840 100644 --- a/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py +++ b/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py @@ -66,7 +66,6 @@ class ConvertGLSLShader(publish.Extractor): cmds.connectAttr(dif_output, glsl_dif) cmds.connectAttr(nrm_output, glsl_nrm) - mtl = ".u_MetallicTexture.u_MetallicTexture" mtl = glsl + mtl ao = ".u_OcclusionTexture.u_OcclusionTexture" From 257859716fe99e3c1214f090b06bb7954c36f582 Mon Sep 17 00:00:00 2001 From: Kayla Man <64118225+moonyuet@users.noreply.github.com> Date: Tue, 17 Jan 2023 23:55:43 +0800 Subject: [PATCH 14/70] Update convert_gltf_shader.py --- .../hosts/maya/plugins/publish/convert_gltf_shader.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py b/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py index 7d28bef840..f7cfd33c0b 100644 --- a/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py +++ b/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py @@ -66,12 +66,9 @@ class ConvertGLSLShader(publish.Extractor): cmds.connectAttr(dif_output, glsl_dif) cmds.connectAttr(nrm_output, glsl_nrm) - mtl = ".u_MetallicTexture.u_MetallicTexture" - mtl = glsl + mtl - ao = ".u_OcclusionTexture.u_OcclusionTexture" - ao = glsl + ao - rough = ".u_RoughnessTexture.u_RoughnessTexture" - rough = glsl + rough + mtl = glsl + ".u_MetallicTexture" + ao = glsl + ".u_OcclusionTexture" + rough = glsl + "u_RoughnessTexture" cmds.connectAttr(orm_output, mtl) cmds.connectAttr(orm_output, ao) From bdc4a0963577af3fd90985afef88b5cbc1e62f76 Mon Sep 17 00:00:00 2001 From: Kayla Man <64118225+moonyuet@users.noreply.github.com> Date: Wed, 18 Jan 2023 00:00:08 +0800 Subject: [PATCH 15/70] Update convert_gltf_shader.py --- openpype/hosts/maya/plugins/publish/convert_gltf_shader.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py b/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py index f7cfd33c0b..0b084223fe 100644 --- a/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py +++ b/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py @@ -68,7 +68,7 @@ class ConvertGLSLShader(publish.Extractor): mtl = glsl + ".u_MetallicTexture" ao = glsl + ".u_OcclusionTexture" - rough = glsl + "u_RoughnessTexture" + rough = glsl + ".u_RoughnessTexture" cmds.connectAttr(orm_output, mtl) cmds.connectAttr(orm_output, ao) From 62ebd77fe1d7bfa20901f60f1bb5e494224e6d8f Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Wed, 18 Jan 2023 13:55:19 +0800 Subject: [PATCH 16/70] clean up the code for validator and add the config options for glsl shader --- .../plugins/publish/convert_gltf_shader.py | 17 ++++++++-- .../publish/validate_gltf_textures_names.py | 32 +++++++++++-------- .../defaults/project_settings/maya.json | 8 ++++- .../schemas/schema_maya_publish.json | 29 +++++++++++++++++ 4 files changed, 68 insertions(+), 18 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py b/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py index 0b084223fe..3b8ad9d672 100644 --- a/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py +++ b/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py @@ -21,7 +21,7 @@ class ConvertGLSLShader(publish.Extractor): meshes = cmds.ls(instance, type="mesh", long=True) self.log.info("meshes: {}".format(meshes)) # load the glsl shader plugin - cmds.loadPlugin("glslShader.mll", quiet=True) + cmds.loadPlugin("glslShader", quiet=True) for mesh in meshes: @@ -33,8 +33,19 @@ class ConvertGLSLShader(publish.Extractor): glsl_shadingGrp + ".surfaceShader") # load the maya2gltf shader - maya_dir = os.getenv("MAYA_APP_DIR") - ogsfx = maya_dir + "/maya2glTF/PBR/shaders/glTF_PBR.ogsfx" + maya_publish = ( + instance.context.data["project_settings"]["maya"]["publish"] + ) + ogsfx_path = maya_publish["ConvertGLSLShader"]["ogsfx_path"] + if not ogsfx_path: + maya_dir = os.getenv("MAYA_APP_DIR") + if not maya_dir: + raise RuntimeError("MAYA_APP_DIR not found") + ogsfx_path = maya_dir + "/maya2glTF/PBR/shaders/" + if not os.path.exists(ogsfx_path): + raise RuntimeError("the ogsfx file not found") + + ogsfx = ogsfx_path + "glTF_PBR.ogsfx" cmds.setAttr(glsl + ".shader", ogsfx, typ="string") # list the materials used for the assets diff --git a/openpype/hosts/maya/plugins/publish/validate_gltf_textures_names.py b/openpype/hosts/maya/plugins/publish/validate_gltf_textures_names.py index 635a59a4be..5c1f5d70fb 100644 --- a/openpype/hosts/maya/plugins/publish/validate_gltf_textures_names.py +++ b/openpype/hosts/maya/plugins/publish/validate_gltf_textures_names.py @@ -15,8 +15,8 @@ class ValidateGLTFTexturesNames(pyblish.api.InstancePlugin): The texture naming conventions follows the UE5-style-guides: https://github.com/Allar/ue5-style-guide#anc-textures-packing - ORM: Occulsion Roughness Metallic - ORMS: Occulsion Roughness Metallic Specular + ORM: Occlusion Roughness Metallic + ORMS: Occlusion Roughness Metallic Specular Texture Naming Style: @@ -34,7 +34,6 @@ class ValidateGLTFTexturesNames(pyblish.api.InstancePlugin): families = ['gltf'] hosts = ['maya'] label = 'GLTF Textures Name' - actions = [openpype.hosts.maya.api.action.SelectInvalidAction] def process(self, instance): """Process all the nodes in the instance""" @@ -43,7 +42,7 @@ class ValidateGLTFTexturesNames(pyblish.api.InstancePlugin): raise RuntimeError("No PBS Shader in the scene") invalid = self.get_texture_shader_invalid(instance) if invalid: - raise RuntimeError("Non PBS material found in " + raise RuntimeError("Non PBS material found" "{0}".format(invalid)) invalid = self.get_texture_node_invalid(instance) if invalid: @@ -57,7 +56,7 @@ class ValidateGLTFTexturesNames(pyblish.api.InstancePlugin): def get_texture_name_invalid(self, instance): invalid = set() - shading_grp = self.shader_selection(instance) + shading_grp = self.get_material_from_shapes(instance) # get the materials related to the selected assets # get the file textures related to the PBS Shader @@ -73,7 +72,7 @@ class ValidateGLTFTexturesNames(pyblish.api.InstancePlugin): # "_D" if not dif.endswith("_D"): invalid.add(dif_path) - orm_packed = cmds.listConnections(shader + ".TEX_ao_mapX")[0] + orm_packed = cmds.listConnections(shader + ".TEX_ao_map")[0] if orm_packed: # "_ORM" orm_path = cmds.getAttr(orm_packed + ".fileTextureName") @@ -92,7 +91,7 @@ class ValidateGLTFTexturesNames(pyblish.api.InstancePlugin): def get_texture_node_invalid(self, instance): invalid = set() - shading_grp = self.shader_selection(instance) + shading_grp = self.get_material_from_shapes(instance) for material in shading_grp: main_shader = cmds.listConnections(material, destination=True, @@ -107,16 +106,21 @@ class ValidateGLTFTexturesNames(pyblish.api.InstancePlugin): def get_texture_shader_invalid(self, instance): invalid = set() - shading_grp = self.shader_selection(instance) - for material in shading_grp: - main_shader = cmds.listConnections(material, - destination=True, - type="StingrayPBS") - if not main_shader: + shading_grp = self.get_material_from_shapes(instance) + for shading_group in shading_grp: + material_name = "{}.surfaceShader".format(shading_group) + material = cmds.listConnections(material_name, + source=True, + destination=False, + type="StingrayPBS") + + if not material: + # add material name + material = cmds.listConnections(material_name)[0] invalid.add(material) return list(invalid) - def shader_selection(self, instance): + def get_material_from_shapes(self, instance): shapes = cmds.ls(instance, type="mesh", long=True) for shape in shapes: shading_grp = cmds.listConnections(shape, diff --git a/openpype/settings/defaults/project_settings/maya.json b/openpype/settings/defaults/project_settings/maya.json index db64f388c8..c89b41a3e4 100644 --- a/openpype/settings/defaults/project_settings/maya.json +++ b/openpype/settings/defaults/project_settings/maya.json @@ -350,7 +350,7 @@ "active": true }, "ValidateGLTFTexturesNames": { - "enabled": true, + "enabled": false, "optional": false, "active": true }, @@ -829,6 +829,12 @@ } } }, + "ConvertGLSLShader": { + "enabled": false, + "optional": true, + "active": true, + "ogsfx_path": "" + }, "ExtractMayaSceneRaw": { "enabled": true, "add_for_families": [ diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json index 32280d1934..a124aec1b3 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json @@ -864,6 +864,35 @@ "type": "schema", "name": "schema_maya_capture" }, + { + "type": "dict", + "collapsible": true, + "key": "ConvertGLSLShader", + "label": "Convert PBS Shader to GLSL Shader", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "type": "boolean", + "key": "active", + "label": "Active" + }, + { + "type": "text", + "key": "ogsfx_path", + "label": "GLSL Shader Directory" + } + ] + }, { "type": "dict", "collapsible": true, From cf4df006bdf67fc935db649bbb27db8beef4f6af Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 19 Jan 2023 09:12:33 +0000 Subject: [PATCH 17/70] Clean up redundant lib code. --- openpype/hosts/maya/api/lib.py | 31 ------------------- .../plugins/publish/submit_maya_muster.py | 7 ++++- .../plugins/publish/validate_maya_units.py | 7 ++--- 3 files changed, 8 insertions(+), 37 deletions(-) diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py index dd5da275e8..71d890f46b 100644 --- a/openpype/hosts/maya/api/lib.py +++ b/openpype/hosts/maya/api/lib.py @@ -254,11 +254,6 @@ def read(node): return data -def _get_mel_global(name): - """Return the value of a mel global variable""" - return mel.eval("$%s = $%s;" % (name, name)) - - def matrix_equals(a, b, tolerance=1e-10): """ Compares two matrices with an imperfection tolerance @@ -691,11 +686,6 @@ class delete_after(object): cmds.delete(self._nodes) -def get_renderer(layer): - with renderlayer(layer): - return cmds.getAttr("defaultRenderGlobals.currentRenderer") - - def get_current_renderlayer(): return cmds.editRenderLayerGlobals(query=True, currentRenderLayer=True) @@ -1440,27 +1430,6 @@ def set_id(node, unique_id, overwrite=False): cmds.setAttr(attr, unique_id, type="string") -# endregion ID -def get_reference_node(path): - """ - Get the reference node when the path is found being used in a reference - Args: - path (str): the file path to check - - Returns: - node (str): name of the reference node in question - """ - try: - node = cmds.file(path, query=True, referenceNode=True) - except RuntimeError: - log.debug('File is not referenced : "{}"'.format(path)) - return - - reference_path = cmds.referenceQuery(path, filename=True) - if os.path.normpath(path) == os.path.normpath(reference_path): - return node - - def set_attribute(attribute, value, node): """Adjust attributes based on the value from the attribute data diff --git a/openpype/hosts/maya/plugins/publish/submit_maya_muster.py b/openpype/hosts/maya/plugins/publish/submit_maya_muster.py index 1a6463fb9d..8ae3e5124b 100644 --- a/openpype/hosts/maya/plugins/publish/submit_maya_muster.py +++ b/openpype/hosts/maya/plugins/publish/submit_maya_muster.py @@ -52,6 +52,11 @@ def _get_script(): return module_path +def get_renderer(layer): + with lib.renderlayer(layer): + return cmds.getAttr("defaultRenderGlobals.currentRenderer") + + def get_renderer_variables(renderlayer=None): """Retrieve the extension which has been set in the VRay settings @@ -66,7 +71,7 @@ def get_renderer_variables(renderlayer=None): dict """ - renderer = lib.get_renderer(renderlayer or lib.get_current_renderlayer()) + renderer = get_renderer(renderlayer or lib.get_current_renderlayer()) render_attrs = lib.RENDER_ATTRS.get(renderer, lib.RENDER_ATTRS["default"]) padding = cmds.getAttr("{}.{}".format(render_attrs["node"], diff --git a/openpype/hosts/maya/plugins/publish/validate_maya_units.py b/openpype/hosts/maya/plugins/publish/validate_maya_units.py index 5698d795ff..e6fabb1712 100644 --- a/openpype/hosts/maya/plugins/publish/validate_maya_units.py +++ b/openpype/hosts/maya/plugins/publish/validate_maya_units.py @@ -11,10 +11,6 @@ from openpype.pipeline.publish import ( ) -def float_round(num, places=0, direction=ceil): - return direction(num * (10**places)) / float(10**places) - - class ValidateMayaUnits(pyblish.api.ContextPlugin): """Check if the Maya units are set correct""" @@ -36,6 +32,7 @@ class ValidateMayaUnits(pyblish.api.ContextPlugin): # Collected units linearunits = context.data.get('linearUnits') angularunits = context.data.get('angularUnits') + # TODO(antirotor): This is hack as for framerates having multiple # decimal places. FTrack is ceiling decimal values on # fps to two decimal places but Maya 2019+ is reporting those fps @@ -43,7 +40,7 @@ class ValidateMayaUnits(pyblish.api.ContextPlugin): # rounding, we have to round those numbers coming from Maya. # NOTE: this must be revisited yet again as it seems that Ftrack is # now flooring the value? - fps = float_round(context.data.get('fps'), 2, ceil) + fps = mayalib.float_round(context.data.get('fps'), 2, ceil) # TODO repace query with using 'context.data["assetEntity"]' asset_doc = get_current_project_asset() From 7d7442590793dddc22e30e9b8661f68cc09fb2a2 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 26 Jan 2023 14:48:06 +0800 Subject: [PATCH 18/70] add extractors and validators for cameras --- .../hosts/max/plugins/create/create_camera.py | 26 +++++++ .../max/plugins/publish/extract_camera_abc.py | 69 +++++++++++++++++++ .../max/plugins/publish/extract_camera_fbx.py | 68 ++++++++++++++++++ .../plugins/publish/extract_max_scene_raw.py | 68 ++++++++++++++++++ .../max/plugins/publish/extract_pointcache.py | 2 +- .../publish/validate_camera_contents.py | 57 +++++++++++++++ 6 files changed, 289 insertions(+), 1 deletion(-) create mode 100644 openpype/hosts/max/plugins/create/create_camera.py create mode 100644 openpype/hosts/max/plugins/publish/extract_camera_abc.py create mode 100644 openpype/hosts/max/plugins/publish/extract_camera_fbx.py create mode 100644 openpype/hosts/max/plugins/publish/extract_max_scene_raw.py create mode 100644 openpype/hosts/max/plugins/publish/validate_camera_contents.py diff --git a/openpype/hosts/max/plugins/create/create_camera.py b/openpype/hosts/max/plugins/create/create_camera.py new file mode 100644 index 0000000000..45f437b7ee --- /dev/null +++ b/openpype/hosts/max/plugins/create/create_camera.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 CreateCamera(plugin.MaxCreator): + identifier = "io.openpype.creators.max.camera" + label = "Camera" + family = "camera" + icon = "gear" + + def create(self, subset_name, instance_data, pre_create_data): + from pymxs import runtime as rt + sel_obj = list(rt.selection) + _ = super(CreateCamera, self).create( + subset_name, + instance_data, + pre_create_data) # type: CreatedInstance + container = rt.getNodeByName(subset_name) + # 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/publish/extract_camera_abc.py b/openpype/hosts/max/plugins/publish/extract_camera_abc.py new file mode 100644 index 0000000000..83cf2c3a6e --- /dev/null +++ b/openpype/hosts/max/plugins/publish/extract_camera_abc.py @@ -0,0 +1,69 @@ +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 +) + + +class ExtractAlembicCamera(publish.Extractor): + """ + Extract Camera with AlembicExport + """ + + order = pyblish.api.ExtractorOrder - 0.1 + label = "Extract Almebic Camera" + hosts = ["max"] + families = ["camera"] + optional = True + + def process(self, instance): + 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) + filename = "{name}.abc".format(**instance.data) + path = os.path.join(stagingdir, filename) + + # We run the render + self.log.info("Writing alembic '%s' to '%s'" % (filename, + stagingdir)) + + export_cmd = ( + f""" +AlembicExport.ArchiveType = #ogawa +AlembicExport.CoordinateSystem = #maya +AlembicExport.StartFrame = {start} +AlembicExport.EndFrame = {end} +AlembicExport.CustomAttributes = true + +exportFile @"{path}" #noPrompt selectedOnly:on using:AlembicExport + + """) + + self.log.debug(f"Executing command: {export_cmd}") + + with maintained_selection(): + # select and export + rt.select(get_all_children(rt.getNodeByName(container))) + rt.execute(export_cmd) + + self.log.info("Performing Extraction ...") + if "representations" not in instance.data: + instance.data["representations"] = [] + + representation = { + 'name': 'abc', + 'ext': 'abc', + 'files': filename, + "stagingDir": stagingdir, + } + instance.data["representations"].append(representation) + self.log.info("Extracted instance '%s' to: %s" % (instance.name, + path)) diff --git a/openpype/hosts/max/plugins/publish/extract_camera_fbx.py b/openpype/hosts/max/plugins/publish/extract_camera_fbx.py new file mode 100644 index 0000000000..5a68edfbe8 --- /dev/null +++ b/openpype/hosts/max/plugins/publish/extract_camera_fbx.py @@ -0,0 +1,68 @@ +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 +) + + +class ExtractCameraFbx(publish.Extractor): + """ + Extract Camera with FbxExporter + """ + + order = pyblish.api.ExtractorOrder - 0.2 + label = "Extract Fbx Camera" + hosts = ["max"] + families = ["camera"] + + def process(self, instance): + 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)) + + # Need to export: + # Animation = True + # Cameras = True + # AxisConversionMethod + fbx_export_cmd = ( + f""" + +FBXExporterSetParam "Animation" true +FBXExporterSetParam "Cameras" true +FBXExporterSetParam "AxisConversionMethod" "Animation" +FbxExporterSetParam "UpAxis" "Y" +FbxExporterSetParam "Preserveinstances" true + +exportFile @"{filepath}" #noPrompt selectedOnly:true using:FBXEXP + + """) + + self.log.debug(f"Executing command: {fbx_export_cmd}") + + with maintained_selection(): + # select and export + rt.select(get_all_children(rt.getNodeByName(container))) + rt.execute(fbx_export_cmd) + + self.log.info("Performing Extraction ...") + if "representations" not in instance.data: + instance.data["representations"] = [] + + representation = { + 'name': 'fbx', + 'ext': 'fbx', + 'files': filename, + "stagingDir": stagingdir, + } + instance.data["representations"].append(representation) + self.log.info("Extracted instance '%s' to: %s" % (instance.name, + filepath)) \ No newline at end of file diff --git a/openpype/hosts/max/plugins/publish/extract_max_scene_raw.py b/openpype/hosts/max/plugins/publish/extract_max_scene_raw.py new file mode 100644 index 0000000000..4524609a02 --- /dev/null +++ b/openpype/hosts/max/plugins/publish/extract_max_scene_raw.py @@ -0,0 +1,68 @@ +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 +) + + +class ExtractMaxSceneRaw(publish.Extractor): + """ + Extract Raw Max Scene with SaveSelected + """ + + order = pyblish.api.ExtractorOrder - 0.2 + label = "Max Scene(Raw)" + hosts = ["max"] + families = ["camera"] + + def process(self, instance): + container = instance.data["instance_node"] + + # publish the raw scene for camera + self.log.info("Extracting Camera ...") + + stagingdir = self.staging_dir(instance) + 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)) + + if "representations" not in instance.data: + instance.data["representations"] = [] + + #add extra blacklash for saveNodes in MaxScript + re_max_path = stagingdir + "\\\\" + filename + # saving max scene + raw_export_cmd = ( + f""" +sel = getCurrentSelection() +for s in sel do +( + select s + f="{re_max_path}" + print f + saveNodes selection f quiet:true +) + """) + + self.log.debug(f"Executing Maxscript command: {raw_export_cmd}") + + with maintained_selection(): + # need to figure out how to select the camera + rt.select(get_all_children(rt.getNodeByName(container))) + rt.execute(raw_export_cmd) + + self.log.info("Performing Extraction ...") + representation = { + 'name': 'max', + 'ext': 'max', + 'files': filename, + "stagingDir": stagingdir, + } + instance.data["representations"].append(representation) + self.log.info("Extracted instance '%s' to: %s" % (instance.name, + max_path)) \ No newline at end of file diff --git a/openpype/hosts/max/plugins/publish/extract_pointcache.py b/openpype/hosts/max/plugins/publish/extract_pointcache.py index 904c1656da..75d8a7972c 100644 --- a/openpype/hosts/max/plugins/publish/extract_pointcache.py +++ b/openpype/hosts/max/plugins/publish/extract_pointcache.py @@ -51,7 +51,7 @@ class ExtractAlembic(publish.Extractor): order = pyblish.api.ExtractorOrder label = "Extract Pointcache" hosts = ["max"] - families = ["pointcache", "camera"] + families = ["pointcache"] def process(self, instance): start = float(instance.data.get("frameStartHandle", 1)) diff --git a/openpype/hosts/max/plugins/publish/validate_camera_contents.py b/openpype/hosts/max/plugins/publish/validate_camera_contents.py new file mode 100644 index 0000000000..3990103e61 --- /dev/null +++ b/openpype/hosts/max/plugins/publish/validate_camera_contents.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +import pyblish.api +from openpype.pipeline import PublishValidationError +from pymxs import runtime as rt +from openpype.hosts.max.api import get_all_children + + +class ValidateCameraContent(pyblish.api.InstancePlugin): + """Validates Camera instance contents. + + A Camera instance may only hold a SINGLE camera's transform + """ + + order = pyblish.api.ValidatorOrder + families = ["camera"] + hosts = ["max"] + label = "Camera Contents" + camera_type = ["$Free_Camera", "$Target_Camera", + "$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)") + + + def get_invalid(self, instance): + """ + Get invalid nodes if the instance is not camera + """ + invalid = list() + container = instance.data["instance_node"] + self.log.info("Validating look content for " + "'{}'".format(container)) + + con = rt.getNodeByName(container) + selection_list = self.list_children(con) + validation_msg = list() + for sel in selection_list: + # to avoid Attribute Error from pymxs wrapper + sel_tmp = str(sel) + for cam in self.camera_type: + if sel_tmp.startswith(cam): + validation_msg.append("Camera Found") + else: + validation_msg.append("Camera Not Found") + if "Camera Found" not in validation_msg: + invalid.append(sel) + # go through the camera type to see if there are same name + return invalid + + def list_children(self, node): + children = [] + for c in node.Children: + children.append(c) + return children From c4fe43a1f71adddb99e39e4c9d0c6f9874adc8fe Mon Sep 17 00:00:00 2001 From: Kayla Man <64118225+moonyuet@users.noreply.github.com> Date: Thu, 26 Jan 2023 15:07:40 +0800 Subject: [PATCH 19/70] Delete convert_gltf_shader.py --- .../plugins/publish/convert_gltf_shader.py | 89 ------------------- 1 file changed, 89 deletions(-) delete mode 100644 openpype/hosts/maya/plugins/publish/convert_gltf_shader.py diff --git a/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py b/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py deleted file mode 100644 index 3b8ad9d672..0000000000 --- a/openpype/hosts/maya/plugins/publish/convert_gltf_shader.py +++ /dev/null @@ -1,89 +0,0 @@ -import os -from maya import cmds -import pyblish.api - -from openpype.pipeline import publish - - -class ConvertGLSLShader(publish.Extractor): - """ - Converting StingrayPBS material to GLSL Shaders - specially for the glb export through Maya2GLTF plugin - - """ - order = pyblish.api.ExtractorOrder - 0.1 - hosts = ["maya"] - label = "Convert StingrayPBS to GLTF" - families = ["gltf"] - optional = True - - def process(self, instance): - meshes = cmds.ls(instance, type="mesh", long=True) - self.log.info("meshes: {}".format(meshes)) - # load the glsl shader plugin - cmds.loadPlugin("glslShader", quiet=True) - - for mesh in meshes: - - # create glsl shader - glsl = cmds.createNode('GLSLShader') - glsl_shadingGrp = cmds.sets(name=glsl + "SG", empty=True, - renderable=True, noSurfaceShader=True) - cmds.connectAttr(glsl + ".outColor", - glsl_shadingGrp + ".surfaceShader") - - # load the maya2gltf shader - maya_publish = ( - instance.context.data["project_settings"]["maya"]["publish"] - ) - ogsfx_path = maya_publish["ConvertGLSLShader"]["ogsfx_path"] - if not ogsfx_path: - maya_dir = os.getenv("MAYA_APP_DIR") - if not maya_dir: - raise RuntimeError("MAYA_APP_DIR not found") - ogsfx_path = maya_dir + "/maya2glTF/PBR/shaders/" - if not os.path.exists(ogsfx_path): - raise RuntimeError("the ogsfx file not found") - - ogsfx = ogsfx_path + "glTF_PBR.ogsfx" - cmds.setAttr(glsl + ".shader", ogsfx, typ="string") - - # list the materials used for the assets - shading_grp = cmds.listConnections(mesh, - destination=True, - type="shadingEngine") - - # get the materials related to the selected assets - for material in shading_grp: - main_shader = cmds.listConnections(material, - destination=True, - type="StingrayPBS") - for shader in main_shader: - # get the file textures related to the PBS Shader - albedo = cmds.listConnections(shader + ".TEX_color_map")[0] - dif_output = albedo + ".outColor" - - orm_packed = cmds.listConnections(shader + - ".TEX_ao_map")[0] - orm_output = orm_packed + ".outColor" - - nrm = cmds.listConnections(shader + ".TEX_normal_map")[0] - nrm_output = nrm + ".outColor" - - # get the glsl_shader input - # reconnect the file nodes to maya2gltf shader - glsl_dif = glsl + ".u_BaseColorTexture" - glsl_nrm = glsl + ".u_NormalTexture" - cmds.connectAttr(dif_output, glsl_dif) - cmds.connectAttr(nrm_output, glsl_nrm) - - mtl = glsl + ".u_MetallicTexture" - ao = glsl + ".u_OcclusionTexture" - rough = glsl + ".u_RoughnessTexture" - - cmds.connectAttr(orm_output, mtl) - cmds.connectAttr(orm_output, ao) - cmds.connectAttr(orm_output, rough) - - # assign the shader to the asset - cmds.sets(mesh, forceElement=str(glsl_shadingGrp)) From d370f8ac14a1918cdf24bc74cddcbeade437d913 Mon Sep 17 00:00:00 2001 From: Kayla Man <64118225+moonyuet@users.noreply.github.com> Date: Thu, 26 Jan 2023 15:08:23 +0800 Subject: [PATCH 20/70] Delete validate_gltf_textures_names.py --- .../publish/validate_gltf_textures_names.py | 130 ------------------ 1 file changed, 130 deletions(-) delete mode 100644 openpype/hosts/maya/plugins/publish/validate_gltf_textures_names.py diff --git a/openpype/hosts/maya/plugins/publish/validate_gltf_textures_names.py b/openpype/hosts/maya/plugins/publish/validate_gltf_textures_names.py deleted file mode 100644 index 5c1f5d70fb..0000000000 --- a/openpype/hosts/maya/plugins/publish/validate_gltf_textures_names.py +++ /dev/null @@ -1,130 +0,0 @@ -from maya import cmds - -import pyblish.api -import openpype.hosts.maya.api.action -from openpype.pipeline.publish import ValidateContentsOrder - - -class ValidateGLTFTexturesNames(pyblish.api.InstancePlugin): - """ - Validate if the asset uses StingrayPBS material before conversion - of the GLSL Shader - Validate if the names of GLTF Textures follow - the packed ORM/ORMS standard. - - The texture naming conventions follows the UE5-style-guides: - https://github.com/Allar/ue5-style-guide#anc-textures-packing - - ORM: Occlusion Roughness Metallic - ORMS: Occlusion Roughness Metallic Specular - - Texture Naming Style: - - Albedo/Diffuse: {Name}_D.{imageExtension} or - {Name}_D..{imageExtension} - - Normal: {Name}_N.{imageExtension} or - {Name}_N..{imageExtension} - ORM: {Name}_ORM.{imageExtension} or - {Name}_ORM..{imageExtension} - - """ - - order = ValidateContentsOrder - families = ['gltf'] - hosts = ['maya'] - label = 'GLTF Textures Name' - - def process(self, instance): - """Process all the nodes in the instance""" - pbs_shader = cmds.ls(type="StingrayPBS") - if not pbs_shader: - raise RuntimeError("No PBS Shader in the scene") - invalid = self.get_texture_shader_invalid(instance) - if invalid: - raise RuntimeError("Non PBS material found" - "{0}".format(invalid)) - invalid = self.get_texture_node_invalid(instance) - if invalid: - raise RuntimeError("At least a Albedo texture file" - "nodes need to be connected") - invalid = self.get_texture_name_invalid(instance) - if invalid: - raise RuntimeError("Invalid texture name(s) found: " - "{0}".format(invalid)) - - def get_texture_name_invalid(self, instance): - - invalid = set() - shading_grp = self.get_material_from_shapes(instance) - - # get the materials related to the selected assets - # get the file textures related to the PBS Shader - # validate the names of the textures - for material in shading_grp: - main_shader = cmds.listConnections(material, - destination=True, - type="StingrayPBS") - for shader in main_shader: - albedo = cmds.listConnections(shader + ".TEX_color_map")[0] - dif_path = cmds.getAttr(albedo + ".fileTextureName") - dif = dif_path.split(".")[0] - # "_D" - if not dif.endswith("_D"): - invalid.add(dif_path) - orm_packed = cmds.listConnections(shader + ".TEX_ao_map")[0] - if orm_packed: - # "_ORM" - orm_path = cmds.getAttr(orm_packed + ".fileTextureName") - orm = orm_path.split(".")[0] - if not orm.endswith("_ORM"): - invalid.add(orm_path) - nrm = cmds.listConnections(shader + ".TEX_normal_map")[0] - if nrm: - nrm_path = cmds.getAttr(nrm + ".fileTextureName") - nrm_map = nrm_path.split(".")[0] - # "_N" - if not nrm_map.endswith("_N"): - invalid.add(nrm_path) - - return list(invalid) - - def get_texture_node_invalid(self, instance): - invalid = set() - shading_grp = self.get_material_from_shapes(instance) - for material in shading_grp: - main_shader = cmds.listConnections(material, - destination=True, - type="StingrayPBS") - for shader in main_shader: - # diffuse texture file node - albedo = cmds.listConnections(shader + ".TEX_color_map") - if not albedo: - invalid.add(albedo) - return list(invalid) - - def get_texture_shader_invalid(self, instance): - - invalid = set() - shading_grp = self.get_material_from_shapes(instance) - for shading_group in shading_grp: - material_name = "{}.surfaceShader".format(shading_group) - material = cmds.listConnections(material_name, - source=True, - destination=False, - type="StingrayPBS") - - if not material: - # add material name - material = cmds.listConnections(material_name)[0] - invalid.add(material) - return list(invalid) - - def get_material_from_shapes(self, instance): - shapes = cmds.ls(instance, type="mesh", long=True) - for shape in shapes: - shading_grp = cmds.listConnections(shape, - destination=True, - type="shadingEngine") - - return shading_grp From 32b557efcb1bbd9cd184af6e71d7b5a86bdbe447 Mon Sep 17 00:00:00 2001 From: Kayla Man <64118225+moonyuet@users.noreply.github.com> Date: Thu, 26 Jan 2023 15:10:22 +0800 Subject: [PATCH 21/70] Delete maya.json --- .../defaults/project_settings/maya.json | 1054 ----------------- 1 file changed, 1054 deletions(-) delete mode 100644 openpype/settings/defaults/project_settings/maya.json diff --git a/openpype/settings/defaults/project_settings/maya.json b/openpype/settings/defaults/project_settings/maya.json deleted file mode 100644 index c89b41a3e4..0000000000 --- a/openpype/settings/defaults/project_settings/maya.json +++ /dev/null @@ -1,1054 +0,0 @@ -{ - "imageio": { - "colorManagementPreference_v2": { - "enabled": true, - "configFilePath": { - "windows": [], - "darwin": [], - "linux": [] - }, - "renderSpace": "ACEScg", - "displayName": "sRGB", - "viewName": "ACES 1.0 SDR-video" - }, - "colorManagementPreference": { - "configFilePath": { - "windows": [], - "darwin": [], - "linux": [] - }, - "renderSpace": "scene-linear Rec 709/sRGB", - "viewTransform": "sRGB gamma" - } - }, - "mel_workspace": "workspace -fr \"shaders\" \"renderData/shaders\";\nworkspace -fr \"images\" \"renders/maya\";\nworkspace -fr \"particles\" \"particles\";\nworkspace -fr \"mayaAscii\" \"\";\nworkspace -fr \"mayaBinary\" \"\";\nworkspace -fr \"scene\" \"\";\nworkspace -fr \"alembicCache\" \"cache/alembic\";\nworkspace -fr \"renderData\" \"renderData\";\nworkspace -fr \"sourceImages\" \"sourceimages\";\nworkspace -fr \"fileCache\" \"cache/nCache\";\n", - "ext_mapping": { - "model": "ma", - "mayaAscii": "ma", - "camera": "ma", - "rig": "ma", - "workfile": "ma", - "yetiRig": "ma" - }, - "maya-dirmap": { - "use_env_var_as_root": false, - "enabled": false, - "paths": { - "source-path": [], - "destination-path": [] - } - }, - "scriptsmenu": { - "name": "OpenPype Tools", - "definition": [ - { - "type": "action", - "command": "import openpype.hosts.maya.api.commands as op_cmds; op_cmds.edit_shader_definitions()", - "sourcetype": "python", - "title": "Edit shader name definitions", - "tooltip": "Edit shader name definitions used in validation and renaming.", - "tags": [ - "pipeline", - "shader" - ] - } - ] - }, - "RenderSettings": { - "apply_render_settings": true, - "default_render_image_folder": "renders/maya", - "enable_all_lights": true, - "aov_separator": "underscore", - "remove_aovs": false, - "reset_current_frame": false, - "arnold_renderer": { - "image_prefix": "//_", - "image_format": "exr", - "multilayer_exr": true, - "tiled": true, - "aov_list": [], - "additional_options": [] - }, - "vray_renderer": { - "image_prefix": "//", - "engine": "1", - "image_format": "exr", - "aov_list": [], - "additional_options": [] - }, - "redshift_renderer": { - "image_prefix": "//", - "primary_gi_engine": "0", - "secondary_gi_engine": "0", - "image_format": "exr", - "multilayer_exr": true, - "force_combine": true, - "aov_list": [], - "additional_options": [] - } - }, - "create": { - "CreateLook": { - "enabled": true, - "make_tx": true, - "defaults": [ - "Main" - ] - }, - "CreateRender": { - "enabled": true, - "defaults": [ - "Main" - ] - }, - "CreateUnrealStaticMesh": { - "enabled": true, - "defaults": [ - "", - "_Main" - ], - "static_mesh_prefix": "S", - "collision_prefixes": [ - "UBX", - "UCP", - "USP", - "UCX" - ] - }, - "CreateUnrealSkeletalMesh": { - "enabled": true, - "defaults": [], - "joint_hints": "jnt_org" - }, - "CreateMultiverseLook": { - "enabled": true, - "publish_mip_map": true - }, - "CreateAnimation": { - "enabled": true, - "write_color_sets": false, - "write_face_sets": false, - "defaults": [ - "Main" - ] - }, - "CreateModel": { - "enabled": true, - "write_color_sets": false, - "write_face_sets": false, - "defaults": [ - "Main", - "Proxy", - "Sculpt" - ] - }, - "CreatePointCache": { - "enabled": true, - "write_color_sets": false, - "write_face_sets": false, - "defaults": [ - "Main" - ] - }, - "CreateProxyAlembic": { - "enabled": true, - "write_color_sets": false, - "write_face_sets": false, - "defaults": [ - "Main" - ] - }, - "CreateMultiverseUsd": { - "enabled": true, - "defaults": [ - "Main" - ] - }, - "CreateMultiverseUsdComp": { - "enabled": true, - "defaults": [ - "Main" - ] - }, - "CreateMultiverseUsdOver": { - "enabled": true, - "defaults": [ - "Main" - ] - }, - "CreateAss": { - "enabled": true, - "defaults": [ - "Main" - ], - "expandProcedurals": false, - "motionBlur": true, - "motionBlurKeys": 2, - "motionBlurLength": 0.5, - "maskOptions": false, - "maskCamera": false, - "maskLight": false, - "maskShape": false, - "maskShader": false, - "maskOverride": false, - "maskDriver": false, - "maskFilter": false, - "maskColor_manager": false, - "maskOperator": false - }, - "CreateAssembly": { - "enabled": true, - "defaults": [ - "Main" - ] - }, - "CreateCamera": { - "enabled": true, - "defaults": [ - "Main" - ] - }, - "CreateLayout": { - "enabled": true, - "defaults": [ - "Main" - ] - }, - "CreateMayaScene": { - "enabled": true, - "defaults": [ - "Main" - ] - }, - "CreateRenderSetup": { - "enabled": true, - "defaults": [ - "Main" - ] - }, - "CreateReview": { - "enabled": true, - "defaults": [ - "Main" - ] - }, - "CreateRig": { - "enabled": true, - "defaults": [ - "Main", - "Sim", - "Cloth" - ] - }, - "CreateSetDress": { - "enabled": true, - "defaults": [ - "Main", - "Anim" - ] - }, - "CreateVrayProxy": { - "enabled": true, - "defaults": [ - "Main" - ] - }, - "CreateVRayScene": { - "enabled": true, - "defaults": [ - "Main" - ] - }, - "CreateYetiRig": { - "enabled": true, - "defaults": [ - "Main" - ] - } - }, - "publish": { - "CollectMayaRender": { - "sync_workfile_version": false - }, - "CollectFbxCamera": { - "enabled": false - }, - "CollectGLTF": { - "enabled": false - }, - "ValidateInstanceInContext": { - "enabled": true, - "optional": true, - "active": true - }, - "ValidateContainers": { - "enabled": true, - "optional": true, - "active": true - }, - "ValidateFrameRange": { - "enabled": true, - "optional": true, - "active": true, - "exclude_families": [ - "model", - "rig", - "staticMesh" - ] - }, - "ValidateShaderName": { - "enabled": false, - "optional": true, - "regex": "(?P.*)_(.*)_SHD" - }, - "ValidateShadingEngine": { - "enabled": true, - "optional": true, - "active": true - }, - "ValidateAttributes": { - "enabled": false, - "attributes": {} - }, - "ValidateLoadedPlugin": { - "enabled": false, - "optional": true, - "whitelist_native_plugins": false, - "authorized_plugins": [] - }, - "ValidateMayaUnits": { - "enabled": true, - "optional": false, - "validate_linear_units": true, - "linear_units": "cm", - "validate_angular_units": true, - "angular_units": "deg", - "validate_fps": true - }, - "ValidateUnrealStaticMeshName": { - "enabled": true, - "optional": true, - "validate_mesh": false, - "validate_collision": true - }, - "ValidateCycleError": { - "enabled": true, - "optional": false, - "families": [ - "rig" - ] - }, - "ValidateRenderSettings": { - "arnold_render_attributes": [], - "vray_render_attributes": [], - "redshift_render_attributes": [], - "renderman_render_attributes": [] - }, - "ValidateCurrentRenderLayerIsRenderable": { - "enabled": true, - "optional": false, - "active": true - }, - "ValidateGLTFTexturesNames": { - "enabled": false, - "optional": false, - "active": true - }, - "ValidateRenderImageRule": { - "enabled": true, - "optional": false, - "active": true - }, - "ValidateRenderNoDefaultCameras": { - "enabled": true, - "optional": false, - "active": true - }, - "ValidateRenderSingleCamera": { - "enabled": true, - "optional": false, - "active": true - }, - "ValidateRenderLayerAOVs": { - "enabled": true, - "optional": false, - "active": true - }, - "ValidateStepSize": { - "enabled": true, - "optional": false, - "active": true - }, - "ValidateVRayDistributedRendering": { - "enabled": true, - "optional": false, - "active": true - }, - "ValidateVrayReferencedAOVs": { - "enabled": true, - "optional": false, - "active": true - }, - "ValidateVRayTranslatorEnabled": { - "enabled": true, - "optional": false, - "active": true - }, - "ValidateVrayProxy": { - "enabled": true, - "optional": false, - "active": true - }, - "ValidateVrayProxyMembers": { - "enabled": true, - "optional": false, - "active": true - }, - "ValidateYetiRenderScriptCallbacks": { - "enabled": true, - "optional": false, - "active": true - }, - "ValidateYetiRigCacheState": { - "enabled": true, - "optional": false, - "active": true - }, - "ValidateYetiRigInputShapesInInstance": { - "enabled": true, - "optional": false, - "active": true - }, - "ValidateYetiRigSettings": { - "enabled": true, - "optional": false, - "active": true - }, - "ValidateModelName": { - "enabled": false, - "database": true, - "material_file": { - "windows": "", - "darwin": "", - "linux": "" - }, - "regex": "(.*)_(\\d)*_(?P.*)_(GEO)", - "top_level_regex": ".*_GRP" - }, - "ValidateModelContent": { - "enabled": true, - "optional": false, - "validate_top_group": true - }, - "ValidateTransformNamingSuffix": { - "enabled": true, - "optional": true, - "SUFFIX_NAMING_TABLE": { - "mesh": [ - "_GEO", - "_GES", - "_GEP", - "_OSD" - ], - "nurbsCurve": [ - "_CRV" - ], - "nurbsSurface": [ - "_NRB" - ], - "locator": [ - "_LOC" - ], - "group": [ - "_GRP" - ] - }, - "ALLOW_IF_NOT_IN_SUFFIX_TABLE": true - }, - "ValidateColorSets": { - "enabled": true, - "optional": true, - "active": true - }, - "ValidateMeshHasOverlappingUVs": { - "enabled": false, - "optional": true, - "active": true - }, - "ValidateMeshArnoldAttributes": { - "enabled": false, - "optional": true, - "active": true - }, - "ValidateMeshShaderConnections": { - "enabled": true, - "optional": true, - "active": true - }, - "ValidateMeshSingleUVSet": { - "enabled": false, - "optional": true, - "active": true - }, - "ValidateMeshHasUVs": { - "enabled": true, - "optional": true, - "active": true - }, - "ValidateMeshLaminaFaces": { - "enabled": false, - "optional": true, - "active": true - }, - "ValidateMeshNgons": { - "enabled": false, - "optional": true, - "active": true - }, - "ValidateMeshNonManifold": { - "enabled": false, - "optional": true, - "active": true - }, - "ValidateMeshNoNegativeScale": { - "enabled": true, - "optional": false, - "active": true - }, - "ValidateMeshNonZeroEdgeLength": { - "enabled": true, - "optional": true, - "active": true - }, - "ValidateMeshNormalsUnlocked": { - "enabled": false, - "optional": true, - "active": true - }, - "ValidateMeshUVSetMap1": { - "enabled": false, - "optional": true, - "active": true - }, - "ValidateMeshVerticesHaveEdges": { - "enabled": true, - "optional": true, - "active": true - }, - "ValidateNoAnimation": { - "enabled": false, - "optional": true, - "active": true - }, - "ValidateNoNamespace": { - "enabled": true, - "optional": false, - "active": true - }, - "ValidateNoNullTransforms": { - "enabled": true, - "optional": false, - "active": true - }, - "ValidateNoUnknownNodes": { - "enabled": true, - "optional": false, - "active": true - }, - "ValidateNodeNoGhosting": { - "enabled": false, - "optional": false, - "active": true - }, - "ValidateShapeDefaultNames": { - "enabled": false, - "optional": true, - "active": true - }, - "ValidateShapeRenderStats": { - "enabled": false, - "optional": true, - "active": true - }, - "ValidateShapeZero": { - "enabled": false, - "optional": true, - "active": true - }, - "ValidateTransformZero": { - "enabled": false, - "optional": true, - "active": true - }, - "ValidateUniqueNames": { - "enabled": false, - "optional": true, - "active": true - }, - "ValidateNoVRayMesh": { - "enabled": true, - "optional": false, - "active": true - }, - "ValidateUnrealMeshTriangulated": { - "enabled": false, - "optional": true, - "active": true - }, - "ValidateAlembicVisibleOnly": { - "enabled": true, - "optional": false, - "active": true - }, - "ExtractProxyAlembic": { - "enabled": true, - "families": [ - "proxyAbc" - ] - }, - "ExtractAlembic": { - "enabled": true, - "families": [ - "pointcache", - "model", - "vrayproxy" - ] - }, - "ExtractObj": { - "enabled": false, - "optional": true - }, - "ValidateRigContents": { - "enabled": false, - "optional": true, - "active": true - }, - "ValidateRigJointsHidden": { - "enabled": false, - "optional": true, - "active": true - }, - "ValidateRigControllers": { - "enabled": false, - "optional": true, - "active": true - }, - "ValidateAnimationContent": { - "enabled": true, - "optional": false, - "active": true - }, - "ValidateOutRelatedNodeIds": { - "enabled": true, - "optional": false, - "active": true - }, - "ValidateRigControllersArnoldAttributes": { - "enabled": true, - "optional": false, - "active": true - }, - "ValidateSkeletalMeshHierarchy": { - "enabled": true, - "optional": false, - "active": true - }, - "ValidateSkinclusterDeformerSet": { - "enabled": true, - "optional": false, - "active": true - }, - "ValidateRigOutSetNodeIds": { - "enabled": true, - "optional": false, - "allow_history_only": false - }, - "ValidateCameraAttributes": { - "enabled": false, - "optional": true, - "active": true - }, - "ValidateAssemblyName": { - "enabled": true, - "optional": true, - "active": true - }, - "ValidateAssemblyNamespaces": { - "enabled": true, - "optional": false, - "active": true - }, - "ValidateAssemblyModelTransforms": { - "enabled": true, - "optional": false, - "active": true - }, - "ValidateAssRelativePaths": { - "enabled": true, - "optional": false, - "active": true - }, - "ValidateInstancerContent": { - "enabled": true, - "optional": false, - "active": true - }, - "ValidateInstancerFrameRanges": { - "enabled": true, - "optional": false, - "active": true - }, - "ValidateNoDefaultCameras": { - "enabled": true, - "optional": false, - "active": true - }, - "ValidateUnrealUpAxis": { - "enabled": false, - "optional": true, - "active": true - }, - "ValidateCameraContents": { - "enabled": true, - "optional": false, - "validate_shapes": true - }, - "ExtractPlayblast": { - "capture_preset": { - "Codec": { - "compression": "jpg", - "format": "image", - "quality": 95 - }, - "Display Options": { - "background": [ - 125, - 125, - 125, - 255 - ], - "backgroundBottom": [ - 125, - 125, - 125, - 255 - ], - "backgroundTop": [ - 125, - 125, - 125, - 255 - ], - "override_display": true - }, - "Generic": { - "isolate_view": true, - "off_screen": true - }, - "Renderer": { - "rendererName": "vp2Renderer" - }, - "Resolution": { - "width": 1920, - "height": 1080 - }, - "Viewport Options": { - "override_viewport_options": true, - "displayLights": "default", - "displayTextures": true, - "textureMaxResolution": 1024, - "renderDepthOfField": true, - "shadows": true, - "twoSidedLighting": true, - "lineAAEnable": true, - "multiSample": 8, - "ssaoEnable": false, - "ssaoAmount": 1, - "ssaoRadius": 16, - "ssaoFilterRadius": 16, - "ssaoSamples": 16, - "fogging": false, - "hwFogFalloff": "0", - "hwFogDensity": 0.0, - "hwFogStart": 0, - "hwFogEnd": 100, - "hwFogAlpha": 0, - "hwFogColorR": 1.0, - "hwFogColorG": 1.0, - "hwFogColorB": 1.0, - "motionBlurEnable": false, - "motionBlurSampleCount": 8, - "motionBlurShutterOpenFraction": 0.2, - "cameras": false, - "clipGhosts": false, - "deformers": false, - "dimensions": false, - "dynamicConstraints": false, - "dynamics": false, - "fluids": false, - "follicles": false, - "gpuCacheDisplayFilter": false, - "greasePencils": false, - "grid": false, - "hairSystems": true, - "handles": false, - "headsUpDisplay": false, - "ikHandles": false, - "imagePlane": true, - "joints": false, - "lights": false, - "locators": false, - "manipulators": false, - "motionTrails": false, - "nCloths": false, - "nParticles": false, - "nRigids": false, - "controlVertices": false, - "nurbsCurves": false, - "hulls": false, - "nurbsSurfaces": false, - "particleInstancers": false, - "pivots": false, - "planes": false, - "pluginShapes": false, - "polymeshes": true, - "strokes": false, - "subdivSurfaces": false, - "textures": false - }, - "Camera Options": { - "displayGateMask": false, - "displayResolution": false, - "displayFilmGate": false, - "displayFieldChart": false, - "displaySafeAction": false, - "displaySafeTitle": false, - "displayFilmPivot": false, - "displayFilmOrigin": false, - "overscan": 1.0 - } - } - }, - "ConvertGLSLShader": { - "enabled": false, - "optional": true, - "active": true, - "ogsfx_path": "" - }, - "ExtractMayaSceneRaw": { - "enabled": true, - "add_for_families": [ - "layout" - ] - }, - "ExtractCameraAlembic": { - "enabled": true, - "optional": true, - "active": true, - "bake_attributes": [] - } - }, - "load": { - "colors": { - "model": [ - 209, - 132, - 30, - 255 - ], - "rig": [ - 59, - 226, - 235, - 255 - ], - "pointcache": [ - 94, - 209, - 30, - 255 - ], - "animation": [ - 94, - 209, - 30, - 255 - ], - "ass": [ - 249, - 135, - 53, - 255 - ], - "camera": [ - 136, - 114, - 244, - 255 - ], - "fbx": [ - 215, - 166, - 255, - 255 - ], - "mayaAscii": [ - 67, - 174, - 255, - 255 - ], - "mayaScene": [ - 67, - 174, - 255, - 255 - ], - "setdress": [ - 255, - 250, - 90, - 255 - ], - "layout": [ - 255, - 250, - 90, - 255 - ], - "vdbcache": [ - 249, - 54, - 0, - 255 - ], - "vrayproxy": [ - 255, - 150, - 12, - 255 - ], - "vrayscene_layer": [ - 255, - 150, - 12, - 255 - ], - "yeticache": [ - 99, - 206, - 220, - 255 - ], - "yetiRig": [ - 0, - 205, - 125, - 255 - ] - } - }, - "workfile_build": { - "profiles": [ - { - "task_types": [], - "tasks": [ - "Lighting" - ], - "current_context": [ - { - "subset_name_filters": [ - ".+[Mm]ain" - ], - "families": [ - "model" - ], - "repre_names": [ - "abc", - "ma" - ], - "loaders": [ - "ReferenceLoader" - ] - }, - { - "subset_name_filters": [], - "families": [ - "animation", - "pointcache", - "proxyAbc" - ], - "repre_names": [ - "abc" - ], - "loaders": [ - "ReferenceLoader" - ] - }, - { - "subset_name_filters": [], - "families": [ - "rendersetup" - ], - "repre_names": [ - "json" - ], - "loaders": [ - "RenderSetupLoader" - ] - }, - { - "subset_name_filters": [], - "families": [ - "camera" - ], - "repre_names": [ - "abc" - ], - "loaders": [ - "ReferenceLoader" - ] - } - ], - "linked_assets": [ - { - "subset_name_filters": [], - "families": [ - "sedress" - ], - "repre_names": [ - "ma" - ], - "loaders": [ - "ReferenceLoader" - ] - }, - { - "subset_name_filters": [], - "families": [ - "ArnoldStandin" - ], - "repre_names": [ - "ass" - ], - "loaders": [ - "assLoader" - ] - } - ] - } - ] - }, - "templated_workfile_build": { - "profiles": [] - }, - "filters": { - "preset 1": { - "ValidateNoAnimation": false, - "ValidateShapeDefaultNames": false - }, - "preset 2": { - "ValidateNoAnimation": false - } - } -} From f0fb628caf5c0baa1fc8fca0aea4ebef71837e73 Mon Sep 17 00:00:00 2001 From: Kayla Man <64118225+moonyuet@users.noreply.github.com> Date: Thu, 26 Jan 2023 15:10:31 +0800 Subject: [PATCH 22/70] Delete schema_maya_publish.json --- .../schemas/schema_maya_publish.json | 955 ------------------ 1 file changed, 955 deletions(-) delete mode 100644 openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json deleted file mode 100644 index a124aec1b3..0000000000 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json +++ /dev/null @@ -1,955 +0,0 @@ -{ - "type": "dict", - "collapsible": true, - "key": "publish", - "label": "Publish plugins", - "children": [ - { - "type": "label", - "label": "Collectors" - }, - { - "type": "dict", - "collapsible": true, - "key": "CollectMayaRender", - "label": "Collect Render Layers", - "children": [ - { - "type": "boolean", - "key": "sync_workfile_version", - "label": "Sync render version with workfile" - } - ] - }, - { - "type": "dict", - "collapsible": true, - "key": "CollectFbxCamera", - "label": "Collect Camera for FBX export", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - } - ] - }, - { - "type": "dict", - "collapsible": true, - "key": "CollectGLTF", - "label": "Collect Assets for GLTF/GLB export", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - } - ] - }, - { - "type": "splitter" - }, - { - "type": "label", - "label": "Validators" - }, - { - "type": "schema_template", - "name": "template_publish_plugin", - "template_data": [ - { - "key": "ValidateInstanceInContext", - "label": "Validate Instance In Context" - } - ] - }, - { - "type": "schema_template", - "name": "template_publish_plugin", - "template_data": [ - { - "key": "ValidateContainers", - "label": "ValidateContainers" - } - ] - }, - { - "type": "dict", - "collapsible": true, - "key": "ValidateFrameRange", - "label": "Validate Frame Range", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "boolean", - "key": "optional", - "label": "Optional" - }, - { - "type": "boolean", - "key": "active", - "label": "Active" - }, - { - "type": "splitter" - }, - { - "key": "exclude_families", - "label": "Families", - "type": "list", - "object_type": "text" - } - ] - }, - { - "type": "dict", - "collapsible": true, - "key": "ValidateShaderName", - "label": "ValidateShaderName", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "boolean", - "key": "optional", - "label": "Optional" - }, - { - "type": "label", - "label": "Shader name regex can use named capture group asset to validate against current asset name.

Example:
^.*(?P=<asset>.+)_SHD

" - }, - { - "type": "text", - "key": "regex", - "label": "Validation regex" - } - ] - }, - { - "type": "schema_template", - "name": "template_publish_plugin", - "template_data": [ - { - "key": "ValidateShadingEngine", - "label": "Validate Look Shading Engine Naming" - } - ] - }, - { - "type": "dict", - "collapsible": true, - "key": "ValidateAttributes", - "label": "ValidateAttributes", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "raw-json", - "key": "attributes", - "label": "Attributes" - } - ] - }, - { - "type": "dict", - "collapsible": true, - "key": "ValidateLoadedPlugin", - "label": "Validate Loaded Plugin", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "boolean", - "key": "optional", - "label": "Optional" - }, - { - "type": "boolean", - "key": "whitelist_native_plugins", - "label": "Whitelist Maya Native Plugins" - }, - { - "type": "list", - "key": "authorized_plugins", - "label": "Authorized plugins", - "object_type": "text" - } - ] - }, - { - "type": "dict", - "collapsible": true, - "key": "ValidateMayaUnits", - "label": "Validate Maya Units", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "boolean", - "key": "optional", - "label": "Optional" - }, - { - "type": "boolean", - "key": "validate_linear_units", - "label": "Validate linear units" - }, - { - "key": "linear_units", - "label": "Linear units", - "type": "enum", - "multiselection": false, - "defaults": "cm", - "enum_items": [ - {"mm": "millimeter"}, - {"cm": "centimeter"}, - {"m": "meter"}, - {"km": "kilometer"}, - {"in": "inch"}, - {"ft": "foot"}, - {"yd": "yard"}, - {"mi": "mile"} - ] - }, - { - "type": "boolean", - "key": "validate_angular_units", - "label": "Validate angular units" - }, - { - "key": "angular_units", - "label": "Angular units", - "type": "enum", - "multiselection": false, - "defaults": "cm", - "enum_items": [ - {"deg": "degree"}, - {"rad": "radian"} - ] - }, - { - "type": "boolean", - "key": "validate_fps", - "label": "Validate fps" - } - ] - }, - { - "type": "dict", - "collapsible": true, - "key": "ValidateUnrealStaticMeshName", - "label": "Validate Unreal Static Mesh Name", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "boolean", - "key": "optional", - "label": "Optional" - }, - { - "type": "boolean", - "key": "validate_mesh", - "label": "Validate mesh Names " - }, - { - "type": "boolean", - "key": "validate_collision", - "label": "Validate collision names" - } - ] - }, - { - "type": "dict", - "collapsible": true, - "checkbox_key": "enabled", - "key": "ValidateCycleError", - "label": "Validate Cycle Error", - "is_group": true, - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "boolean", - "key": "optional", - "label": "Optional" - }, - { - "key": "families", - "label": "Families", - "type": "list", - "object_type": "text" - } - ] - }, - { - "type": "dict", - "collapsible": true, - "key": "ValidateRenderSettings", - "label": "ValidateRenderSettings", - "children": [ - { - "type": "dict-modifiable", - "store_as_list": true, - "key": "arnold_render_attributes", - "label": "Arnold Render Attributes", - "use_label_wrap": true, - "object_type": { - "type": "text" - } - }, - { - "type": "dict-modifiable", - "store_as_list": true, - "key": "vray_render_attributes", - "label": "Vray Render Attributes", - "use_label_wrap": true, - "object_type": { - "type": "text" - } - }, - { - "type": "dict-modifiable", - "store_as_list": true, - "key": "redshift_render_attributes", - "label": "Redshift Render Attributes", - "use_label_wrap": true, - "object_type": { - "type": "text" - } - }, - { - "type": "dict-modifiable", - "store_as_list": true, - "key": "renderman_render_attributes", - "label": "Renderman Render Attributes", - "use_label_wrap": true, - "object_type": { - "type": "text" - } - } - ] - }, - { - "type": "schema_template", - "name": "template_publish_plugin", - "template_data": [ - { - "key": "ValidateCurrentRenderLayerIsRenderable", - "label": "Validate Current Render Layer Has Renderable Camera" - }, - { - "key": "ValidateGLTFTexturesNames", - "label": "Validate GLTF Textures Names" - }, - { - "key": "ValidateRenderImageRule", - "label": "Validate Images File Rule (Workspace)" - }, - { - "key": "ValidateRenderNoDefaultCameras", - "label": "Validate No Default Cameras Renderable" - }, - { - "key": "ValidateRenderSingleCamera", - "label": "Validate Render Single Camera" - }, - { - "key": "ValidateRenderLayerAOVs", - "label": "Validate Render Passes / AOVs Are Registered" - }, - { - "key": "ValidateStepSize", - "label": "Validate Step Size" - }, - { - "key": "ValidateVRayDistributedRendering", - "label": "VRay Distributed Rendering" - }, - { - "key": "ValidateVrayReferencedAOVs", - "label": "VRay Referenced AOVs" - }, - { - "key": "ValidateVRayTranslatorEnabled", - "label": "VRay Translator Settings" - }, - { - "key": "ValidateVrayProxy", - "label": "VRay Proxy Settings" - }, - { - "key": "ValidateVrayProxyMembers", - "label": "VRay Proxy Members" - }, - { - "key": "ValidateYetiRenderScriptCallbacks", - "label": "Yeti Render Script Callbacks" - }, - { - "key": "ValidateYetiRigCacheState", - "label": "Yeti Rig Cache State" - }, - { - "key": "ValidateYetiRigInputShapesInInstance", - "label": "Yeti Rig Input Shapes In Instance" - }, - { - "key": "ValidateYetiRigSettings", - "label": "Yeti Rig Settings" - } - ] - }, - { - "type": "collapsible-wrap", - "label": "Model", - "children": [ - { - "type": "dict", - "collapsible": true, - "key": "ValidateModelName", - "label": "Validate Model Name", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "boolean", - "key": "database", - "label": "Use database shader name definitions" - }, - { - "type": "label", - "label": "Path to material file defining list of material names to check. This is material name per line simple text file.
It will be checked against named group shader in your Validation regex.

For example:
^.*(?P=<shader>.+)_GEO

This is used instead of database definitions if they are disabled." - }, - { - "type": "path", - "key": "material_file", - "label": "Material File", - "multiplatform": true, - "multipath": false - }, - { - "type": "text", - "key": "regex", - "label": "Validation regex" - }, - { - "type": "label", - "label": "Regex for validating name of top level group name.
You can use named capturing groups:
(?P<asset>.*) for Asset name
(?P<subset>.*) for Subset
(?P<project>.*) for project

For example to check for asset in name so *_some_asset_name_GRP is valid, use:
.*?_(?P<asset>.*)_GEO" - }, - { - "type": "text", - "key": "top_level_regex", - "label": "Top level group name regex" - } - ] - }, - { - "type": "dict", - "collapsible": true, - "key": "ValidateModelContent", - "label": "Validate Model Content", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "boolean", - "key": "optional", - "label": "Optional" - }, - { - "type": "boolean", - "key": "validate_top_group", - "label": "Validate one top group" - } - ] - }, - { - "type": "dict", - "collapsible": true, - "key": "ValidateTransformNamingSuffix", - "label": "ValidateTransformNamingSuffix", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "boolean", - "key": "optional", - "label": "Optional" - }, - { - "type": "label", - "label": "Validates transform suffix based on the type of its children shapes." - }, - { - "type": "raw-json", - "key": "SUFFIX_NAMING_TABLE", - "label": "Suffix Naming Table" - }, - { - "type": "boolean", - "key": "ALLOW_IF_NOT_IN_SUFFIX_TABLE", - "label": "Allow if suffix not in table" - } - ] - }, - { - "type": "schema_template", - "name": "template_publish_plugin", - "template_data": [ - { - "key": "ValidateColorSets", - "label": "ValidateColorSets" - }, - { - "key": "ValidateMeshHasOverlappingUVs", - "label": "ValidateMeshHasOverlappingUVs" - }, - { - "key": "ValidateMeshArnoldAttributes", - "label": "ValidateMeshArnoldAttributes" - }, - { - "key": "ValidateMeshShaderConnections", - "label": "ValidateMeshShaderConnections" - }, - { - "key": "ValidateMeshSingleUVSet", - "label": "ValidateMeshSingleUVSet" - }, - { - "key": "ValidateMeshHasUVs", - "label": "ValidateMeshHasUVs" - }, - { - "key": "ValidateMeshLaminaFaces", - "label": "ValidateMeshLaminaFaces" - }, - { - "key": "ValidateMeshNgons", - "label": "ValidateMeshNgons" - }, - { - "key": "ValidateMeshNonManifold", - "label": "ValidateMeshNonManifold" - }, - { - "key": "ValidateMeshNoNegativeScale", - "label": "Validate Mesh No Negative Scale" - }, - { - "key": "ValidateMeshNonZeroEdgeLength", - "label": "Validate Mesh Edge Length Non Zero" - }, - { - "key": "ValidateMeshNormalsUnlocked", - "label": "ValidateMeshNormalsUnlocked" - }, - { - "key": "ValidateMeshUVSetMap1", - "label": "ValidateMeshUVSetMap1", - "docstring": "Validate model's default uv set exists and is named 'map1'.

In Maya meshes by default have a uv set named 'map1' that cannot be deleted. It can be renamed, however,
introducing some issues with some renderers. As such we ensure the first (default) UV set index is named 'map1'." - }, - { - "key": "ValidateMeshVerticesHaveEdges", - "label": "ValidateMeshVerticesHaveEdges" - }, - { - "key": "ValidateNoAnimation", - "label": "ValidateNoAnimation", - "docstring": "Ensure no keyframes on nodes in the Instance.
Even though a Model would extract without animCurves correctly this avoids getting different
output from a model when extracted from a different frame than the first frame. (Might be overly restrictive though)." - }, - { - "key": "ValidateNoNamespace", - "label": "ValidateNoNamespace" - }, - { - "key": "ValidateNoNullTransforms", - "label": "ValidateNoNullTransforms" - }, - { - "key": "ValidateNoUnknownNodes", - "label": "ValidateNoUnknownNodes" - }, - { - "key": "ValidateNodeNoGhosting", - "label": "ValidateNodeNoGhosting" - }, - { - "key": "ValidateShapeDefaultNames", - "label": "ValidateShapeDefaultNames" - }, - { - "key": "ValidateShapeRenderStats", - "label": "ValidateShapeRenderStats" - }, - { - "key": "ValidateShapeZero", - "label": "ValidateShapeZero" - }, - { - "key": "ValidateTransformZero", - "label": "ValidateTransformZero" - }, - { - "key": "ValidateUniqueNames", - "label": "ValidateUniqueNames" - }, - { - "key": "ValidateNoVRayMesh", - "label": "Validate No V-Ray Proxies (VRayMesh)" - }, - { - "key": "ValidateUnrealMeshTriangulated", - "label": "Validate if Mesh is Triangulated" - }, - { - "key": "ValidateAlembicVisibleOnly", - "label": "Validate Alembic visible node" - } - ] - }, - { - "type": "label", - "label": "Extractors" - }, - { - "type": "dict", - "collapsible": true, - "key": "ExtractProxyAlembic", - "label": "Extract Proxy Alembic", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "key": "families", - "label": "Families", - "type": "list", - "object_type": "text" - } - ] - }, - { - "type": "dict", - "collapsible": true, - "key": "ExtractAlembic", - "label": "Extract Alembic", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "key": "families", - "label": "Families", - "type": "list", - "object_type": "text" - } - ] - }, - { - "type": "dict", - "collapsible": true, - "key": "ExtractObj", - "label": "Extract OBJ", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "boolean", - "key": "optional", - "label": "Optional" - } - ] - } - ] - }, - { - "type": "collapsible-wrap", - "label": "Rig", - "children": [ - { - "type": "schema_template", - "name": "template_publish_plugin", - "template_data": [ - { - "key": "ValidateRigContents", - "label": "Validate Rig Contents" - }, - { - "key": "ValidateRigJointsHidden", - "label": "Validate Rig Joints Hidden" - }, - { - "key": "ValidateRigControllers", - "label": "Validate Rig Controllers" - }, - { - "key": "ValidateAnimationContent", - "label": "Validate Animation Content" - }, - { - "key": "ValidateOutRelatedNodeIds", - "label": "Validate Animation Out Set Related Node Ids" - }, - { - "key": "ValidateRigControllersArnoldAttributes", - "label": "Validate Rig Controllers (Arnold Attributes)" - }, - { - "key": "ValidateSkeletalMeshHierarchy", - "label": "Validate Skeletal Mesh Top Node" - }, - { - "key": "ValidateSkinclusterDeformerSet", - "label": "Validate Skincluster Deformer Relationships" - } - ] - }, - { - "type": "dict", - "collapsible": true, - "checkbox_key": "enabled", - "key": "ValidateRigOutSetNodeIds", - "label": "Validate Rig Out Set Node Ids", - "is_group": true, - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "boolean", - "key": "optional", - "label": "Optional" - }, - { - "type": "boolean", - "key": "allow_history_only", - "label": "Allow history only" - } - ] - } - ] - }, - { - "type": "schema_template", - "name": "template_publish_plugin", - "template_data": [ - { - "key": "ValidateCameraAttributes", - "label": "Validate Camera Attributes", - "docstring": "" - }, - { - "key": "ValidateAssemblyName", - "label": "Validate Assembly Name" - }, - { - "key": "ValidateAssemblyNamespaces", - "label": "Validate Assembly Namespaces" - }, - { - "key": "ValidateAssemblyModelTransforms", - "label": "Validate Assembly Model Transforms" - }, - { - "key": "ValidateAssRelativePaths", - "label": "ValidateAssRelativePaths" - }, - { - "key": "ValidateInstancerContent", - "label": "Validate Instancer Content" - }, - { - "key": "ValidateInstancerFrameRanges", - "label": "Validate Instancer Cache Frame Ranges" - }, - { - "key": "ValidateNoDefaultCameras", - "label": "Validate No Default Cameras" - }, - { - "key": "ValidateUnrealUpAxis", - "label": "Validate Unreal Up-Axis check" - } - ] - }, - { - "type": "dict", - "collapsible": true, - "key": "ValidateCameraContents", - "label": "Validate Camera Content", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "boolean", - "key": "optional", - "label": "Optional" - }, - { - "type": "boolean", - "key": "validate_shapes", - "label": "Validate presence of shapes" - } - ] - }, - { - "type": "splitter" - }, - { - "type": "label", - "label": "Extractors" - }, - { - "type": "schema", - "name": "schema_maya_capture" - }, - { - "type": "dict", - "collapsible": true, - "key": "ConvertGLSLShader", - "label": "Convert PBS Shader to GLSL Shader", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "boolean", - "key": "optional", - "label": "Optional" - }, - { - "type": "boolean", - "key": "active", - "label": "Active" - }, - { - "type": "text", - "key": "ogsfx_path", - "label": "GLSL Shader Directory" - } - ] - }, - { - "type": "dict", - "collapsible": true, - "key": "ExtractMayaSceneRaw", - "label": "Maya Scene (Raw)", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "label", - "label": "Add loaded instances to those published families:" - }, - { - "key": "add_for_families", - "label": "Families", - "type": "list", - "object_type": "text" - } - ] - }, - { - "type": "dict", - "collapsible": true, - "key": "ExtractCameraAlembic", - "label": "Extract camera to Alembic", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "label", - "label": "List of attributes that will be added to the baked alembic camera. Needs to be written in python list syntax.

For example:
[\"attributeName\", \"anotherAttribute\"]

" - }, - { - "type": "boolean", - "key": "optional", - "label": "Optional" - }, - { - "type": "boolean", - "key": "active", - "label": "Active" - }, - { - "type": "raw-json", - "key": "bake_attributes", - "label": "Bake Attributes", - "is_list": true - } - ] - } - ] -} From 4ecb95506abe6a316bc924208f1360801de0e273 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 26 Jan 2023 15:27:21 +0800 Subject: [PATCH 23/70] hound fix --- .../max/plugins/publish/extract_camera_fbx.py | 2 +- .../max/plugins/publish/extract_max_scene_raw.py | 15 +++++++-------- .../plugins/publish/validate_camera_contents.py | 3 +-- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/openpype/hosts/max/plugins/publish/extract_camera_fbx.py b/openpype/hosts/max/plugins/publish/extract_camera_fbx.py index 5a68edfbe8..e450de1275 100644 --- a/openpype/hosts/max/plugins/publish/extract_camera_fbx.py +++ b/openpype/hosts/max/plugins/publish/extract_camera_fbx.py @@ -65,4 +65,4 @@ exportFile @"{filepath}" #noPrompt selectedOnly:true using:FBXEXP } instance.data["representations"].append(representation) self.log.info("Extracted instance '%s' to: %s" % (instance.name, - filepath)) \ No newline at end of file + 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 4524609a02..97de602216 100644 --- a/openpype/hosts/max/plugins/publish/extract_max_scene_raw.py +++ b/openpype/hosts/max/plugins/publish/extract_max_scene_raw.py @@ -34,7 +34,7 @@ class ExtractMaxSceneRaw(publish.Extractor): if "representations" not in instance.data: instance.data["representations"] = [] - #add extra blacklash for saveNodes in MaxScript + # add extra blacklash for saveNodes in MaxScript re_max_path = stagingdir + "\\\\" + filename # saving max scene raw_export_cmd = ( @@ -42,13 +42,12 @@ class ExtractMaxSceneRaw(publish.Extractor): sel = getCurrentSelection() for s in sel do ( - select s - f="{re_max_path}" - print f - saveNodes selection f quiet:true + select s + f="{re_max_path}" + print f + saveNodes selection f quiet:true ) - """) - + """) # noqa self.log.debug(f"Executing Maxscript command: {raw_export_cmd}") with maintained_selection(): @@ -65,4 +64,4 @@ for s in sel do } instance.data["representations"].append(representation) self.log.info("Extracted instance '%s' to: %s" % (instance.name, - max_path)) \ No newline at end of file + max_path)) diff --git a/openpype/hosts/max/plugins/publish/validate_camera_contents.py b/openpype/hosts/max/plugins/publish/validate_camera_contents.py index 3990103e61..9c411c7a3e 100644 --- a/openpype/hosts/max/plugins/publish/validate_camera_contents.py +++ b/openpype/hosts/max/plugins/publish/validate_camera_contents.py @@ -24,7 +24,6 @@ class ValidateCameraContent(pyblish.api.InstancePlugin): raise PublishValidationError("Camera instance must only include" "camera (and camera target)") - def get_invalid(self, instance): """ Get invalid nodes if the instance is not camera @@ -32,7 +31,7 @@ class ValidateCameraContent(pyblish.api.InstancePlugin): invalid = list() container = instance.data["instance_node"] self.log.info("Validating look content for " - "'{}'".format(container)) + "{}".format(container)) con = rt.getNodeByName(container) selection_list = self.list_children(con) From ab7737dcb3e4cf1e6544b004653304bb816133d4 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 26 Jan 2023 15:28:08 +0800 Subject: [PATCH 24/70] hound fix --- openpype/hosts/max/plugins/publish/validate_camera_contents.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/hosts/max/plugins/publish/validate_camera_contents.py b/openpype/hosts/max/plugins/publish/validate_camera_contents.py index 9c411c7a3e..c7d13ac5a3 100644 --- a/openpype/hosts/max/plugins/publish/validate_camera_contents.py +++ b/openpype/hosts/max/plugins/publish/validate_camera_contents.py @@ -2,7 +2,6 @@ import pyblish.api from openpype.pipeline import PublishValidationError from pymxs import runtime as rt -from openpype.hosts.max.api import get_all_children class ValidateCameraContent(pyblish.api.InstancePlugin): From b29f382f8747a4e08caf8f6079f181105330275e Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 26 Jan 2023 15:31:39 +0800 Subject: [PATCH 25/70] resolve conflict --- .../defaults/project_settings/maya.json | 1090 +++++++++++++++++ .../schemas/scheme_maya_publish.json | 961 +++++++++++++++ 2 files changed, 2051 insertions(+) create mode 100644 openpype/settings/defaults/project_settings/maya.json create mode 100644 openpype/settings/entities/schemas/projects_schema/schemas/scheme_maya_publish.json diff --git a/openpype/settings/defaults/project_settings/maya.json b/openpype/settings/defaults/project_settings/maya.json new file mode 100644 index 0000000000..31591bf734 --- /dev/null +++ b/openpype/settings/defaults/project_settings/maya.json @@ -0,0 +1,1090 @@ +{ + "imageio": { + "ocio_config": { + "enabled": false, + "filepath": [] + }, + "file_rules": { + "enabled": false, + "rules": {} + }, + "colorManagementPreference_v2": { + "enabled": true, + "configFilePath": { + "windows": [], + "darwin": [], + "linux": [] + }, + "renderSpace": "ACEScg", + "displayName": "sRGB", + "viewName": "ACES 1.0 SDR-video" + }, + "colorManagementPreference": { + "configFilePath": { + "windows": [], + "darwin": [], + "linux": [] + }, + "renderSpace": "scene-linear Rec 709/sRGB", + "viewTransform": "sRGB gamma" + } + }, + "mel_workspace": "workspace -fr \"shaders\" \"renderData/shaders\";\nworkspace -fr \"images\" \"renders/maya\";\nworkspace -fr \"particles\" \"particles\";\nworkspace -fr \"mayaAscii\" \"\";\nworkspace -fr \"mayaBinary\" \"\";\nworkspace -fr \"scene\" \"\";\nworkspace -fr \"alembicCache\" \"cache/alembic\";\nworkspace -fr \"renderData\" \"renderData\";\nworkspace -fr \"sourceImages\" \"sourceimages\";\nworkspace -fr \"fileCache\" \"cache/nCache\";\n", + "ext_mapping": { + "model": "ma", + "mayaAscii": "ma", + "camera": "ma", + "rig": "ma", + "workfile": "ma", + "yetiRig": "ma" + }, + "maya-dirmap": { + "use_env_var_as_root": false, + "enabled": false, + "paths": { + "source-path": [], + "destination-path": [] + } + }, + "scriptsmenu": { + "name": "OpenPype Tools", + "definition": [ + { + "type": "action", + "command": "import openpype.hosts.maya.api.commands as op_cmds; op_cmds.edit_shader_definitions()", + "sourcetype": "python", + "title": "Edit shader name definitions", + "tooltip": "Edit shader name definitions used in validation and renaming.", + "tags": [ + "pipeline", + "shader" + ] + } + ] + }, + "RenderSettings": { + "apply_render_settings": true, + "default_render_image_folder": "renders/maya", + "enable_all_lights": true, + "aov_separator": "underscore", + "remove_aovs": false, + "reset_current_frame": false, + "arnold_renderer": { + "image_prefix": "//_", + "image_format": "exr", + "multilayer_exr": true, + "tiled": true, + "aov_list": [], + "additional_options": [] + }, + "vray_renderer": { + "image_prefix": "//", + "engine": "1", + "image_format": "exr", + "aov_list": [], + "additional_options": [] + }, + "redshift_renderer": { + "image_prefix": "//", + "primary_gi_engine": "0", + "secondary_gi_engine": "0", + "image_format": "exr", + "multilayer_exr": true, + "force_combine": true, + "aov_list": [], + "additional_options": [] + } + }, + "create": { + "CreateLook": { + "enabled": true, + "make_tx": true, + "defaults": [ + "Main" + ] + }, + "CreateRender": { + "enabled": true, + "defaults": [ + "Main" + ] + }, + "CreateUnrealStaticMesh": { + "enabled": true, + "defaults": [ + "", + "_Main" + ], + "static_mesh_prefix": "S", + "collision_prefixes": [ + "UBX", + "UCP", + "USP", + "UCX" + ] + }, + "CreateUnrealSkeletalMesh": { + "enabled": true, + "defaults": [], + "joint_hints": "jnt_org" + }, + "CreateMultiverseLook": { + "enabled": true, + "publish_mip_map": true + }, + "CreateAnimation": { + "enabled": true, + "write_color_sets": false, + "write_face_sets": false, + "defaults": [ + "Main" + ] + }, + "CreateModel": { + "enabled": true, + "write_color_sets": false, + "write_face_sets": false, + "defaults": [ + "Main", + "Proxy", + "Sculpt" + ] + }, + "CreatePointCache": { + "enabled": true, + "write_color_sets": false, + "write_face_sets": false, + "defaults": [ + "Main" + ] + }, + "CreateProxyAlembic": { + "enabled": true, + "write_color_sets": false, + "write_face_sets": false, + "defaults": [ + "Main" + ] + }, + "CreateAss": { + "enabled": true, + "defaults": [ + "Main" + ], + "expandProcedurals": false, + "motionBlur": true, + "motionBlurKeys": 2, + "motionBlurLength": 0.5, + "maskOptions": false, + "maskCamera": false, + "maskLight": false, + "maskShape": false, + "maskShader": false, + "maskOverride": false, + "maskDriver": false, + "maskFilter": false, + "maskColor_manager": false, + "maskOperator": false + }, + "CreateMultiverseUsd": { + "enabled": true, + "defaults": [ + "Main" + ] + }, + "CreateMultiverseUsdComp": { + "enabled": true, + "defaults": [ + "Main" + ] + }, + "CreateMultiverseUsdOver": { + "enabled": true, + "defaults": [ + "Main" + ] + }, + "CreateAssembly": { + "enabled": true, + "defaults": [ + "Main" + ] + }, + "CreateCamera": { + "enabled": true, + "defaults": [ + "Main" + ] + }, + "CreateLayout": { + "enabled": true, + "defaults": [ + "Main" + ] + }, + "CreateMayaScene": { + "enabled": true, + "defaults": [ + "Main" + ] + }, + "CreateRenderSetup": { + "enabled": true, + "defaults": [ + "Main" + ] + }, + "CreateReview": { + "enabled": true, + "defaults": [ + "Main" + ] + }, + "CreateRig": { + "enabled": true, + "defaults": [ + "Main", + "Sim", + "Cloth" + ] + }, + "CreateSetDress": { + "enabled": true, + "defaults": [ + "Main", + "Anim" + ] + }, + "CreateVrayProxy": { + "enabled": true, + "defaults": [ + "Main" + ] + }, + "CreateVRayScene": { + "enabled": true, + "defaults": [ + "Main" + ] + }, + "CreateYetiRig": { + "enabled": true, + "defaults": [ + "Main" + ] + } + }, + "publish": { + "CollectMayaRender": { + "sync_workfile_version": false + }, + "CollectFbxCamera": { + "enabled": false + }, + "CollectGLTF": { + "enabled": false + }, + "ValidateInstanceInContext": { + "enabled": true, + "optional": true, + "active": true + }, + "ValidateContainers": { + "enabled": true, + "optional": true, + "active": true + }, + "ValidateFrameRange": { + "enabled": true, + "optional": true, + "active": true, + "exclude_families": [ + "model", + "rig", + "staticMesh" + ] + }, + "ValidateShaderName": { + "enabled": false, + "optional": true, + "regex": "(?P.*)_(.*)_SHD" + }, + "ValidateShadingEngine": { + "enabled": true, + "optional": true, + "active": true + }, + "ValidateAttributes": { + "enabled": false, + "attributes": {} + }, + "ValidateLoadedPlugin": { + "enabled": false, + "optional": true, + "whitelist_native_plugins": false, + "authorized_plugins": [] + }, + "ValidateMayaUnits": { + "enabled": true, + "optional": false, + "validate_linear_units": true, + "linear_units": "cm", + "validate_angular_units": true, + "angular_units": "deg", + "validate_fps": true + }, + "ValidateUnrealStaticMeshName": { + "enabled": true, + "optional": true, + "validate_mesh": false, + "validate_collision": true + }, + "ValidateCycleError": { + "enabled": true, + "optional": false, + "families": [ + "rig" + ] + }, + "ValidatePluginPathAttributes": { + "enabled": true, + "optional": false, + "active": true, + "attribute": { + "AlembicNode": "abc_File", + "VRayProxy": "fileName", + "RenderManArchive": "filename", + "pgYetiMaya": "cacheFileName", + "aiStandIn": "dso", + "RedshiftSprite": "tex0", + "RedshiftBokeh": "dofBokehImage", + "RedshiftCameraMap": "tex0", + "RedshiftEnvironment": "tex2", + "RedshiftDomeLight": "tex1", + "RedshiftIESLight": "profile", + "RedshiftLightGobo": "tex0", + "RedshiftNormalMap": "tex0", + "RedshiftProxyMesh": "fileName", + "RedshiftVolumeShape": "fileName", + "VRayTexGLSL": "fileName", + "VRayMtlGLSL": "fileName", + "VRayVRmatMtl": "fileName", + "VRayPtex": "ptexFile", + "VRayLightIESShape": "iesFile", + "VRayMesh": "materialAssignmentsFile", + "VRayMtlOSL": "fileName", + "VRayTexOSL": "fileName", + "VRayTexOCIO": "ocioConfigFile", + "VRaySettingsNode": "pmap_autoSaveFile2", + "VRayScannedMtl": "file", + "VRayScene": "parameterOverrideFilePath", + "VRayMtlMDL": "filename", + "VRaySimbiont": "file", + "dlOpenVDBShape": "filename", + "pgYetiMayaShape": "liveABCFilename", + "gpuCache": "cacheFileName" + } + }, + "ValidateRenderSettings": { + "arnold_render_attributes": [], + "vray_render_attributes": [], + "redshift_render_attributes": [], + "renderman_render_attributes": [] + }, + "ValidateCurrentRenderLayerIsRenderable": { + "enabled": true, + "optional": false, + "active": true + }, + "ValidateRenderImageRule": { + "enabled": true, + "optional": false, + "active": true + }, + "ValidateRenderNoDefaultCameras": { + "enabled": true, + "optional": false, + "active": true + }, + "ValidateRenderSingleCamera": { + "enabled": true, + "optional": false, + "active": true + }, + "ValidateRenderLayerAOVs": { + "enabled": true, + "optional": false, + "active": true + }, + "ValidateStepSize": { + "enabled": true, + "optional": false, + "active": true + }, + "ValidateVRayDistributedRendering": { + "enabled": true, + "optional": false, + "active": true + }, + "ValidateVrayReferencedAOVs": { + "enabled": true, + "optional": false, + "active": true + }, + "ValidateVRayTranslatorEnabled": { + "enabled": true, + "optional": false, + "active": true + }, + "ValidateVrayProxy": { + "enabled": true, + "optional": false, + "active": true + }, + "ValidateVrayProxyMembers": { + "enabled": true, + "optional": false, + "active": true + }, + "ValidateYetiRenderScriptCallbacks": { + "enabled": true, + "optional": false, + "active": true + }, + "ValidateYetiRigCacheState": { + "enabled": true, + "optional": false, + "active": true + }, + "ValidateYetiRigInputShapesInInstance": { + "enabled": true, + "optional": false, + "active": true + }, + "ValidateYetiRigSettings": { + "enabled": true, + "optional": false, + "active": true + }, + "ValidateModelName": { + "enabled": false, + "database": true, + "material_file": { + "windows": "", + "darwin": "", + "linux": "" + }, + "regex": "(.*)_(\\d)*_(?P.*)_(GEO)", + "top_level_regex": ".*_GRP" + }, + "ValidateModelContent": { + "enabled": true, + "optional": false, + "validate_top_group": true + }, + "ValidateTransformNamingSuffix": { + "enabled": true, + "optional": true, + "SUFFIX_NAMING_TABLE": { + "mesh": [ + "_GEO", + "_GES", + "_GEP", + "_OSD" + ], + "nurbsCurve": [ + "_CRV" + ], + "nurbsSurface": [ + "_NRB" + ], + "locator": [ + "_LOC" + ], + "group": [ + "_GRP" + ] + }, + "ALLOW_IF_NOT_IN_SUFFIX_TABLE": true + }, + "ValidateColorSets": { + "enabled": true, + "optional": true, + "active": true + }, + "ValidateMeshHasOverlappingUVs": { + "enabled": false, + "optional": true, + "active": true + }, + "ValidateMeshArnoldAttributes": { + "enabled": false, + "optional": true, + "active": true + }, + "ValidateMeshShaderConnections": { + "enabled": true, + "optional": true, + "active": true + }, + "ValidateMeshSingleUVSet": { + "enabled": false, + "optional": true, + "active": true + }, + "ValidateMeshHasUVs": { + "enabled": true, + "optional": true, + "active": true + }, + "ValidateMeshLaminaFaces": { + "enabled": false, + "optional": true, + "active": true + }, + "ValidateMeshNgons": { + "enabled": false, + "optional": true, + "active": true + }, + "ValidateMeshNonManifold": { + "enabled": false, + "optional": true, + "active": true + }, + "ValidateMeshNoNegativeScale": { + "enabled": true, + "optional": false, + "active": true + }, + "ValidateMeshNonZeroEdgeLength": { + "enabled": true, + "optional": true, + "active": true + }, + "ValidateMeshNormalsUnlocked": { + "enabled": false, + "optional": true, + "active": true + }, + "ValidateMeshUVSetMap1": { + "enabled": false, + "optional": true, + "active": true + }, + "ValidateMeshVerticesHaveEdges": { + "enabled": true, + "optional": true, + "active": true + }, + "ValidateNoAnimation": { + "enabled": false, + "optional": true, + "active": true + }, + "ValidateNoNamespace": { + "enabled": true, + "optional": false, + "active": true + }, + "ValidateNoNullTransforms": { + "enabled": true, + "optional": false, + "active": true + }, + "ValidateNoUnknownNodes": { + "enabled": true, + "optional": false, + "active": true + }, + "ValidateNodeNoGhosting": { + "enabled": false, + "optional": false, + "active": true + }, + "ValidateShapeDefaultNames": { + "enabled": false, + "optional": true, + "active": true + }, + "ValidateShapeRenderStats": { + "enabled": false, + "optional": true, + "active": true + }, + "ValidateShapeZero": { + "enabled": false, + "optional": true, + "active": true + }, + "ValidateTransformZero": { + "enabled": false, + "optional": true, + "active": true + }, + "ValidateUniqueNames": { + "enabled": false, + "optional": true, + "active": true + }, + "ValidateNoVRayMesh": { + "enabled": true, + "optional": false, + "active": true + }, + "ValidateUnrealMeshTriangulated": { + "enabled": false, + "optional": true, + "active": true + }, + "ValidateAlembicVisibleOnly": { + "enabled": true, + "optional": false, + "active": true + }, + "ExtractProxyAlembic": { + "enabled": true, + "families": [ + "proxyAbc" + ] + }, + "ExtractAlembic": { + "enabled": true, + "families": [ + "pointcache", + "model", + "vrayproxy" + ] + }, + "ExtractObj": { + "enabled": false, + "optional": true + }, + "ValidateRigContents": { + "enabled": false, + "optional": true, + "active": true + }, + "ValidateRigJointsHidden": { + "enabled": false, + "optional": true, + "active": true + }, + "ValidateRigControllers": { + "enabled": false, + "optional": true, + "active": true + }, + "ValidateAnimationContent": { + "enabled": true, + "optional": false, + "active": true + }, + "ValidateOutRelatedNodeIds": { + "enabled": true, + "optional": false, + "active": true + }, + "ValidateRigControllersArnoldAttributes": { + "enabled": true, + "optional": false, + "active": true + }, + "ValidateSkeletalMeshHierarchy": { + "enabled": true, + "optional": false, + "active": true + }, + "ValidateSkinclusterDeformerSet": { + "enabled": true, + "optional": false, + "active": true + }, + "ValidateRigOutSetNodeIds": { + "enabled": true, + "optional": false, + "allow_history_only": false + }, + "ValidateCameraAttributes": { + "enabled": false, + "optional": true, + "active": true + }, + "ValidateAssemblyName": { + "enabled": true, + "optional": true, + "active": true + }, + "ValidateAssemblyNamespaces": { + "enabled": true, + "optional": false, + "active": true + }, + "ValidateAssemblyModelTransforms": { + "enabled": true, + "optional": false, + "active": true + }, + "ValidateAssRelativePaths": { + "enabled": true, + "optional": false, + "active": true + }, + "ValidateInstancerContent": { + "enabled": true, + "optional": false, + "active": true + }, + "ValidateInstancerFrameRanges": { + "enabled": true, + "optional": false, + "active": true + }, + "ValidateNoDefaultCameras": { + "enabled": true, + "optional": false, + "active": true + }, + "ValidateUnrealUpAxis": { + "enabled": false, + "optional": true, + "active": true + }, + "ValidateCameraContents": { + "enabled": true, + "optional": false, + "validate_shapes": true + }, + "ExtractPlayblast": { + "capture_preset": { + "Codec": { + "compression": "jpg", + "format": "image", + "quality": 95 + }, + "Display Options": { + "background": [ + 125, + 125, + 125, + 255 + ], + "backgroundBottom": [ + 125, + 125, + 125, + 255 + ], + "backgroundTop": [ + 125, + 125, + 125, + 255 + ], + "override_display": true + }, + "Generic": { + "isolate_view": true, + "off_screen": true + }, + "Renderer": { + "rendererName": "vp2Renderer" + }, + "Resolution": { + "width": 1920, + "height": 1080 + }, + "Viewport Options": { + "override_viewport_options": true, + "displayLights": "default", + "displayTextures": true, + "textureMaxResolution": 1024, + "renderDepthOfField": true, + "shadows": true, + "twoSidedLighting": true, + "lineAAEnable": true, + "multiSample": 8, + "ssaoEnable": false, + "ssaoAmount": 1, + "ssaoRadius": 16, + "ssaoFilterRadius": 16, + "ssaoSamples": 16, + "fogging": false, + "hwFogFalloff": "0", + "hwFogDensity": 0.0, + "hwFogStart": 0, + "hwFogEnd": 100, + "hwFogAlpha": 0, + "hwFogColorR": 1.0, + "hwFogColorG": 1.0, + "hwFogColorB": 1.0, + "motionBlurEnable": false, + "motionBlurSampleCount": 8, + "motionBlurShutterOpenFraction": 0.2, + "cameras": false, + "clipGhosts": false, + "deformers": false, + "dimensions": false, + "dynamicConstraints": false, + "dynamics": false, + "fluids": false, + "follicles": false, + "gpuCacheDisplayFilter": false, + "greasePencils": false, + "grid": false, + "hairSystems": true, + "handles": false, + "headsUpDisplay": false, + "ikHandles": false, + "imagePlane": true, + "joints": false, + "lights": false, + "locators": false, + "manipulators": false, + "motionTrails": false, + "nCloths": false, + "nParticles": false, + "nRigids": false, + "controlVertices": false, + "nurbsCurves": false, + "hulls": false, + "nurbsSurfaces": false, + "particleInstancers": false, + "pivots": false, + "planes": false, + "pluginShapes": false, + "polymeshes": true, + "strokes": false, + "subdivSurfaces": false, + "textures": false + }, + "Camera Options": { + "displayGateMask": false, + "displayResolution": false, + "displayFilmGate": false, + "displayFieldChart": false, + "displaySafeAction": false, + "displaySafeTitle": false, + "displayFilmPivot": false, + "displayFilmOrigin": false, + "overscan": 1.0 + } + } + }, + "ExtractMayaSceneRaw": { + "enabled": true, + "add_for_families": [ + "layout" + ] + }, + "ExtractCameraAlembic": { + "enabled": true, + "optional": true, + "active": true, + "bake_attributes": [] + } + }, + "load": { + "colors": { + "model": [ + 209, + 132, + 30, + 255 + ], + "rig": [ + 59, + 226, + 235, + 255 + ], + "pointcache": [ + 94, + 209, + 30, + 255 + ], + "animation": [ + 94, + 209, + 30, + 255 + ], + "ass": [ + 249, + 135, + 53, + 255 + ], + "camera": [ + 136, + 114, + 244, + 255 + ], + "fbx": [ + 215, + 166, + 255, + 255 + ], + "mayaAscii": [ + 67, + 174, + 255, + 255 + ], + "mayaScene": [ + 67, + 174, + 255, + 255 + ], + "setdress": [ + 255, + 250, + 90, + 255 + ], + "layout": [ + 255, + 250, + 90, + 255 + ], + "vdbcache": [ + 249, + 54, + 0, + 255 + ], + "vrayproxy": [ + 255, + 150, + 12, + 255 + ], + "vrayscene_layer": [ + 255, + 150, + 12, + 255 + ], + "yeticache": [ + 99, + 206, + 220, + 255 + ], + "yetiRig": [ + 0, + 205, + 125, + 255 + ] + } + }, + "workfile_build": { + "profiles": [ + { + "task_types": [], + "tasks": [ + "Lighting" + ], + "current_context": [ + { + "subset_name_filters": [ + ".+[Mm]ain" + ], + "families": [ + "model" + ], + "repre_names": [ + "abc", + "ma" + ], + "loaders": [ + "ReferenceLoader" + ] + }, + { + "subset_name_filters": [], + "families": [ + "animation", + "pointcache", + "proxyAbc" + ], + "repre_names": [ + "abc" + ], + "loaders": [ + "ReferenceLoader" + ] + }, + { + "subset_name_filters": [], + "families": [ + "rendersetup" + ], + "repre_names": [ + "json" + ], + "loaders": [ + "RenderSetupLoader" + ] + }, + { + "subset_name_filters": [], + "families": [ + "camera" + ], + "repre_names": [ + "abc" + ], + "loaders": [ + "ReferenceLoader" + ] + } + ], + "linked_assets": [ + { + "subset_name_filters": [], + "families": [ + "sedress" + ], + "repre_names": [ + "ma" + ], + "loaders": [ + "ReferenceLoader" + ] + }, + { + "subset_name_filters": [], + "families": [ + "ArnoldStandin" + ], + "repre_names": [ + "ass" + ], + "loaders": [ + "assLoader" + ] + } + ] + } + ] + }, + "templated_workfile_build": { + "profiles": [] + }, + "filters": { + "preset 1": { + "ValidateNoAnimation": false, + "ValidateShapeDefaultNames": false + }, + "preset 2": { + "ValidateNoAnimation": false + } + } +} \ No newline at end of file diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/scheme_maya_publish.json b/openpype/settings/entities/schemas/projects_schema/schemas/scheme_maya_publish.json new file mode 100644 index 0000000000..873bb79c95 --- /dev/null +++ b/openpype/settings/entities/schemas/projects_schema/schemas/scheme_maya_publish.json @@ -0,0 +1,961 @@ +{ + "type": "dict", + "collapsible": true, + "key": "publish", + "label": "Publish plugins", + "children": [ + { + "type": "label", + "label": "Collectors" + }, + { + "type": "dict", + "collapsible": true, + "key": "CollectMayaRender", + "label": "Collect Render Layers", + "children": [ + { + "type": "boolean", + "key": "sync_workfile_version", + "label": "Sync render version with workfile" + } + ] + }, + { + "type": "dict", + "collapsible": true, + "key": "CollectFbxCamera", + "label": "Collect Camera for FBX export", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + } + ] + }, + { + "type": "dict", + "collapsible": true, + "key": "CollectGLTF", + "label": "Collect Assets for GLTF/GLB export", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + } + ] + }, + { + "type": "splitter" + }, + { + "type": "label", + "label": "Validators" + }, + { + "type": "schema_template", + "name": "template_publish_plugin", + "template_data": [ + { + "key": "ValidateInstanceInContext", + "label": "Validate Instance In Context" + } + ] + }, + { + "type": "schema_template", + "name": "template_publish_plugin", + "template_data": [ + { + "key": "ValidateContainers", + "label": "ValidateContainers" + } + ] + }, + { + "type": "dict", + "collapsible": true, + "key": "ValidateFrameRange", + "label": "Validate Frame Range", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "type": "boolean", + "key": "active", + "label": "Active" + }, + { + "type": "splitter" + }, + { + "key": "exclude_families", + "label": "Families", + "type": "list", + "object_type": "text" + } + ] + }, + { + "type": "dict", + "collapsible": true, + "key": "ValidateShaderName", + "label": "ValidateShaderName", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "type": "label", + "label": "Shader name regex can use named capture group asset to validate against current asset name.

Example:
^.*(?P=<asset>.+)_SHD

" + }, + { + "type": "text", + "key": "regex", + "label": "Validation regex" + } + ] + }, + { + "type": "schema_template", + "name": "template_publish_plugin", + "template_data": [ + { + "key": "ValidateShadingEngine", + "label": "Validate Look Shading Engine Naming" + } + ] + }, + { + "type": "dict", + "collapsible": true, + "key": "ValidateAttributes", + "label": "ValidateAttributes", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "raw-json", + "key": "attributes", + "label": "Attributes" + } + ] + }, + { + "type": "dict", + "collapsible": true, + "key": "ValidateLoadedPlugin", + "label": "Validate Loaded Plugin", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "type": "boolean", + "key": "whitelist_native_plugins", + "label": "Whitelist Maya Native Plugins" + }, + { + "type": "list", + "key": "authorized_plugins", + "label": "Authorized plugins", + "object_type": "text" + } + ] + }, + { + "type": "dict", + "collapsible": true, + "key": "ValidateMayaUnits", + "label": "Validate Maya Units", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "type": "boolean", + "key": "validate_linear_units", + "label": "Validate linear units" + }, + { + "key": "linear_units", + "label": "Linear units", + "type": "enum", + "multiselection": false, + "defaults": "cm", + "enum_items": [ + {"mm": "millimeter"}, + {"cm": "centimeter"}, + {"m": "meter"}, + {"km": "kilometer"}, + {"in": "inch"}, + {"ft": "foot"}, + {"yd": "yard"}, + {"mi": "mile"} + ] + }, + { + "type": "boolean", + "key": "validate_angular_units", + "label": "Validate angular units" + }, + { + "key": "angular_units", + "label": "Angular units", + "type": "enum", + "multiselection": false, + "defaults": "cm", + "enum_items": [ + {"deg": "degree"}, + {"rad": "radian"} + ] + }, + { + "type": "boolean", + "key": "validate_fps", + "label": "Validate fps" + } + ] + }, + { + "type": "dict", + "collapsible": true, + "key": "ValidateUnrealStaticMeshName", + "label": "Validate Unreal Static Mesh Name", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "type": "boolean", + "key": "validate_mesh", + "label": "Validate mesh Names " + }, + { + "type": "boolean", + "key": "validate_collision", + "label": "Validate collision names" + } + ] + }, + { + "type": "dict", + "collapsible": true, + "checkbox_key": "enabled", + "key": "ValidateCycleError", + "label": "Validate Cycle Error", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "key": "families", + "label": "Families", + "type": "list", + "object_type": "text" + } + ] + }, + { + "type": "dict", + "collapsible": true, + "checkbox_key": "enabled", + "key": "ValidatePluginPathAttributes", + "label": "Plug-in Path Attributes", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "type": "boolean", + "key": "active", + "label": "Active" + }, + { + "type": "label", + "label": "Fill in the node types and attributes you want to validate.

e.g. AlembicNode.abc_file, the node type is AlembicNode and the node attribute is abc_file" + }, + { + "type": "dict-modifiable", + "collapsible": true, + "key": "attribute", + "label": "File Attribute", + "use_label_wrap": true, + "object_type": { + "type": "text" + } + } + ] + }, + { + "type": "dict", + "collapsible": true, + "key": "ValidateRenderSettings", + "label": "ValidateRenderSettings", + "children": [ + { + "type": "dict-modifiable", + "store_as_list": true, + "key": "arnold_render_attributes", + "label": "Arnold Render Attributes", + "use_label_wrap": true, + "object_type": { + "type": "text" + } + }, + { + "type": "dict-modifiable", + "store_as_list": true, + "key": "vray_render_attributes", + "label": "Vray Render Attributes", + "use_label_wrap": true, + "object_type": { + "type": "text" + } + }, + { + "type": "dict-modifiable", + "store_as_list": true, + "key": "redshift_render_attributes", + "label": "Redshift Render Attributes", + "use_label_wrap": true, + "object_type": { + "type": "text" + } + }, + { + "type": "dict-modifiable", + "store_as_list": true, + "key": "renderman_render_attributes", + "label": "Renderman Render Attributes", + "use_label_wrap": true, + "object_type": { + "type": "text" + } + } + ] + }, + { + "type": "schema_template", + "name": "template_publish_plugin", + "template_data": [ + { + "key": "ValidateCurrentRenderLayerIsRenderable", + "label": "Validate Current Render Layer Has Renderable Camera" + }, + { + "key": "ValidateRenderImageRule", + "label": "Validate Images File Rule (Workspace)" + }, + { + "key": "ValidateRenderNoDefaultCameras", + "label": "Validate No Default Cameras Renderable" + }, + { + "key": "ValidateRenderSingleCamera", + "label": "Validate Render Single Camera" + }, + { + "key": "ValidateRenderLayerAOVs", + "label": "Validate Render Passes / AOVs Are Registered" + }, + { + "key": "ValidateStepSize", + "label": "Validate Step Size" + }, + { + "key": "ValidateVRayDistributedRendering", + "label": "VRay Distributed Rendering" + }, + { + "key": "ValidateVrayReferencedAOVs", + "label": "VRay Referenced AOVs" + }, + { + "key": "ValidateVRayTranslatorEnabled", + "label": "VRay Translator Settings" + }, + { + "key": "ValidateVrayProxy", + "label": "VRay Proxy Settings" + }, + { + "key": "ValidateVrayProxyMembers", + "label": "VRay Proxy Members" + }, + { + "key": "ValidateYetiRenderScriptCallbacks", + "label": "Yeti Render Script Callbacks" + }, + { + "key": "ValidateYetiRigCacheState", + "label": "Yeti Rig Cache State" + }, + { + "key": "ValidateYetiRigInputShapesInInstance", + "label": "Yeti Rig Input Shapes In Instance" + }, + { + "key": "ValidateYetiRigSettings", + "label": "Yeti Rig Settings" + } + ] + }, + { + "type": "collapsible-wrap", + "label": "Model", + "children": [ + { + "type": "dict", + "collapsible": true, + "key": "ValidateModelName", + "label": "Validate Model Name", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "database", + "label": "Use database shader name definitions" + }, + { + "type": "label", + "label": "Path to material file defining list of material names to check. This is material name per line simple text file.
It will be checked against named group shader in your Validation regex.

For example:
^.*(?P=<shader>.+)_GEO

This is used instead of database definitions if they are disabled." + }, + { + "type": "path", + "key": "material_file", + "label": "Material File", + "multiplatform": true, + "multipath": false + }, + { + "type": "text", + "key": "regex", + "label": "Validation regex" + }, + { + "type": "label", + "label": "Regex for validating name of top level group name.
You can use named capturing groups:
(?P<asset>.*) for Asset name
(?P<subset>.*) for Subset
(?P<project>.*) for project

For example to check for asset in name so *_some_asset_name_GRP is valid, use:
.*?_(?P<asset>.*)_GEO" + }, + { + "type": "text", + "key": "top_level_regex", + "label": "Top level group name regex" + } + ] + }, + { + "type": "dict", + "collapsible": true, + "key": "ValidateModelContent", + "label": "Validate Model Content", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "type": "boolean", + "key": "validate_top_group", + "label": "Validate one top group" + } + ] + }, + { + "type": "dict", + "collapsible": true, + "key": "ValidateTransformNamingSuffix", + "label": "ValidateTransformNamingSuffix", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "type": "label", + "label": "Validates transform suffix based on the type of its children shapes." + }, + { + "type": "raw-json", + "key": "SUFFIX_NAMING_TABLE", + "label": "Suffix Naming Table" + }, + { + "type": "boolean", + "key": "ALLOW_IF_NOT_IN_SUFFIX_TABLE", + "label": "Allow if suffix not in table" + } + ] + }, + { + "type": "schema_template", + "name": "template_publish_plugin", + "template_data": [ + { + "key": "ValidateColorSets", + "label": "ValidateColorSets" + }, + { + "key": "ValidateMeshHasOverlappingUVs", + "label": "ValidateMeshHasOverlappingUVs" + }, + { + "key": "ValidateMeshArnoldAttributes", + "label": "ValidateMeshArnoldAttributes" + }, + { + "key": "ValidateMeshShaderConnections", + "label": "ValidateMeshShaderConnections" + }, + { + "key": "ValidateMeshSingleUVSet", + "label": "ValidateMeshSingleUVSet" + }, + { + "key": "ValidateMeshHasUVs", + "label": "ValidateMeshHasUVs" + }, + { + "key": "ValidateMeshLaminaFaces", + "label": "ValidateMeshLaminaFaces" + }, + { + "key": "ValidateMeshNgons", + "label": "ValidateMeshNgons" + }, + { + "key": "ValidateMeshNonManifold", + "label": "ValidateMeshNonManifold" + }, + { + "key": "ValidateMeshNoNegativeScale", + "label": "Validate Mesh No Negative Scale" + }, + { + "key": "ValidateMeshNonZeroEdgeLength", + "label": "Validate Mesh Edge Length Non Zero" + }, + { + "key": "ValidateMeshNormalsUnlocked", + "label": "ValidateMeshNormalsUnlocked" + }, + { + "key": "ValidateMeshUVSetMap1", + "label": "ValidateMeshUVSetMap1", + "docstring": "Validate model's default uv set exists and is named 'map1'.

In Maya meshes by default have a uv set named 'map1' that cannot be deleted. It can be renamed, however,
introducing some issues with some renderers. As such we ensure the first (default) UV set index is named 'map1'." + }, + { + "key": "ValidateMeshVerticesHaveEdges", + "label": "ValidateMeshVerticesHaveEdges" + }, + { + "key": "ValidateNoAnimation", + "label": "ValidateNoAnimation", + "docstring": "Ensure no keyframes on nodes in the Instance.
Even though a Model would extract without animCurves correctly this avoids getting different
output from a model when extracted from a different frame than the first frame. (Might be overly restrictive though)." + }, + { + "key": "ValidateNoNamespace", + "label": "ValidateNoNamespace" + }, + { + "key": "ValidateNoNullTransforms", + "label": "ValidateNoNullTransforms" + }, + { + "key": "ValidateNoUnknownNodes", + "label": "ValidateNoUnknownNodes" + }, + { + "key": "ValidateNodeNoGhosting", + "label": "ValidateNodeNoGhosting" + }, + { + "key": "ValidateShapeDefaultNames", + "label": "ValidateShapeDefaultNames" + }, + { + "key": "ValidateShapeRenderStats", + "label": "ValidateShapeRenderStats" + }, + { + "key": "ValidateShapeZero", + "label": "ValidateShapeZero" + }, + { + "key": "ValidateTransformZero", + "label": "ValidateTransformZero" + }, + { + "key": "ValidateUniqueNames", + "label": "ValidateUniqueNames" + }, + { + "key": "ValidateNoVRayMesh", + "label": "Validate No V-Ray Proxies (VRayMesh)" + }, + { + "key": "ValidateUnrealMeshTriangulated", + "label": "Validate if Mesh is Triangulated" + }, + { + "key": "ValidateAlembicVisibleOnly", + "label": "Validate Alembic visible node" + } + ] + }, + { + "type": "label", + "label": "Extractors" + }, + { + "type": "dict", + "collapsible": true, + "key": "ExtractProxyAlembic", + "label": "Extract Proxy Alembic", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "key": "families", + "label": "Families", + "type": "list", + "object_type": "text" + } + ] + }, + { + "type": "dict", + "collapsible": true, + "key": "ExtractAlembic", + "label": "Extract Alembic", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "key": "families", + "label": "Families", + "type": "list", + "object_type": "text" + } + ] + }, + { + "type": "dict", + "collapsible": true, + "key": "ExtractObj", + "label": "Extract OBJ", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + } + ] + } + ] + }, + { + "type": "collapsible-wrap", + "label": "Rig", + "children": [ + { + "type": "schema_template", + "name": "template_publish_plugin", + "template_data": [ + { + "key": "ValidateRigContents", + "label": "Validate Rig Contents" + }, + { + "key": "ValidateRigJointsHidden", + "label": "Validate Rig Joints Hidden" + }, + { + "key": "ValidateRigControllers", + "label": "Validate Rig Controllers" + }, + { + "key": "ValidateAnimationContent", + "label": "Validate Animation Content" + }, + { + "key": "ValidateOutRelatedNodeIds", + "label": "Validate Animation Out Set Related Node Ids" + }, + { + "key": "ValidateRigControllersArnoldAttributes", + "label": "Validate Rig Controllers (Arnold Attributes)" + }, + { + "key": "ValidateSkeletalMeshHierarchy", + "label": "Validate Skeletal Mesh Top Node" + }, + { + "key": "ValidateSkinclusterDeformerSet", + "label": "Validate Skincluster Deformer Relationships" + } + ] + }, + { + "type": "dict", + "collapsible": true, + "checkbox_key": "enabled", + "key": "ValidateRigOutSetNodeIds", + "label": "Validate Rig Out Set Node Ids", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "type": "boolean", + "key": "allow_history_only", + "label": "Allow history only" + } + ] + } + ] + }, + { + "type": "schema_template", + "name": "template_publish_plugin", + "template_data": [ + { + "key": "ValidateCameraAttributes", + "label": "Validate Camera Attributes", + "docstring": "" + }, + { + "key": "ValidateAssemblyName", + "label": "Validate Assembly Name" + }, + { + "key": "ValidateAssemblyNamespaces", + "label": "Validate Assembly Namespaces" + }, + { + "key": "ValidateAssemblyModelTransforms", + "label": "Validate Assembly Model Transforms" + }, + { + "key": "ValidateAssRelativePaths", + "label": "ValidateAssRelativePaths" + }, + { + "key": "ValidateInstancerContent", + "label": "Validate Instancer Content" + }, + { + "key": "ValidateInstancerFrameRanges", + "label": "Validate Instancer Cache Frame Ranges" + }, + { + "key": "ValidateNoDefaultCameras", + "label": "Validate No Default Cameras" + }, + { + "key": "ValidateUnrealUpAxis", + "label": "Validate Unreal Up-Axis check" + } + ] + }, + { + "type": "dict", + "collapsible": true, + "key": "ValidateCameraContents", + "label": "Validate Camera Content", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "type": "boolean", + "key": "validate_shapes", + "label": "Validate presence of shapes" + } + ] + }, + { + "type": "splitter" + }, + { + "type": "label", + "label": "Extractors" + }, + { + "type": "schema", + "name": "schema_maya_capture" + }, + { + "type": "dict", + "collapsible": true, + "key": "ExtractMayaSceneRaw", + "label": "Maya Scene (Raw)", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "label", + "label": "Add loaded instances to those published families:" + }, + { + "key": "add_for_families", + "label": "Families", + "type": "list", + "object_type": "text" + } + ] + }, + { + "type": "dict", + "collapsible": true, + "key": "ExtractCameraAlembic", + "label": "Extract camera to Alembic", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "label", + "label": "List of attributes that will be added to the baked alembic camera. Needs to be written in python list syntax.

For example:
[\"attributeName\", \"anotherAttribute\"]

" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "type": "boolean", + "key": "active", + "label": "Active" + }, + { + "type": "raw-json", + "key": "bake_attributes", + "label": "Bake Attributes", + "is_list": true + } + ] + } + ] +} From 53186ffa77ef481847ad332e8e664afac62a681b Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 26 Jan 2023 15:33:06 +0800 Subject: [PATCH 26/70] resolve conflict --- .../{scheme_maya_publish.json => schema_maya_publish.json} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename openpype/settings/entities/schemas/projects_schema/schemas/{scheme_maya_publish.json => schema_maya_publish.json} (100%) diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/scheme_maya_publish.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json similarity index 100% rename from openpype/settings/entities/schemas/projects_schema/schemas/scheme_maya_publish.json rename to openpype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json From 20e32d0d259992efcf37970bb42b9b5a59c2209d Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 26 Jan 2023 23:23:18 +0800 Subject: [PATCH 27/70] clean up the extractors and validator --- .../hosts/max/plugins/create/create_camera.py | 4 +-- .../max/plugins/publish/extract_camera_abc.py | 10 ++++-- .../max/plugins/publish/extract_camera_fbx.py | 11 +++++-- .../plugins/publish/extract_max_scene_raw.py | 31 +++++++------------ .../publish/validate_camera_contents.py | 19 ++++-------- 5 files changed, 37 insertions(+), 38 deletions(-) diff --git a/openpype/hosts/max/plugins/create/create_camera.py b/openpype/hosts/max/plugins/create/create_camera.py index 45f437b7ee..91d0d4d3dc 100644 --- a/openpype/hosts/max/plugins/create/create_camera.py +++ b/openpype/hosts/max/plugins/create/create_camera.py @@ -13,11 +13,11 @@ class CreateCamera(plugin.MaxCreator): def create(self, subset_name, instance_data, pre_create_data): from pymxs import runtime as rt sel_obj = list(rt.selection) - _ = super(CreateCamera, self).create( + instance = super(CreateCamera, self).create( subset_name, instance_data, pre_create_data) # type: CreatedInstance - container = rt.getNodeByName(subset_name) + 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: diff --git a/openpype/hosts/max/plugins/publish/extract_camera_abc.py b/openpype/hosts/max/plugins/publish/extract_camera_abc.py index 83cf2c3a6e..2a62c12927 100644 --- a/openpype/hosts/max/plugins/publish/extract_camera_abc.py +++ b/openpype/hosts/max/plugins/publish/extract_camera_abc.py @@ -1,6 +1,9 @@ import os import pyblish.api -from openpype.pipeline import publish +from openpype.pipeline import ( + publish, + OptionalPyblishPluginMixin +) from pymxs import runtime as rt from openpype.hosts.max.api import ( maintained_selection, @@ -8,7 +11,8 @@ from openpype.hosts.max.api import ( ) -class ExtractAlembicCamera(publish.Extractor): +class ExtractAlembicCamera(publish.Extractor, + OptionalPyblishPluginMixin): """ Extract Camera with AlembicExport """ @@ -20,6 +24,8 @@ class ExtractAlembicCamera(publish.Extractor): optional = True def process(self, instance): + if not self.is_active(instance.data): + return start = float(instance.data.get("frameStartHandle", 1)) end = float(instance.data.get("frameEndHandle", 1)) diff --git a/openpype/hosts/max/plugins/publish/extract_camera_fbx.py b/openpype/hosts/max/plugins/publish/extract_camera_fbx.py index e450de1275..7e92f355ed 100644 --- a/openpype/hosts/max/plugins/publish/extract_camera_fbx.py +++ b/openpype/hosts/max/plugins/publish/extract_camera_fbx.py @@ -1,6 +1,9 @@ import os import pyblish.api -from openpype.pipeline import publish +from openpype.pipeline import ( + publish, + OptionalPyblishPluginMixin +) from pymxs import runtime as rt from openpype.hosts.max.api import ( maintained_selection, @@ -8,7 +11,8 @@ from openpype.hosts.max.api import ( ) -class ExtractCameraFbx(publish.Extractor): +class ExtractCameraFbx(publish.Extractor, + OptionalPyblishPluginMixin): """ Extract Camera with FbxExporter """ @@ -17,8 +21,11 @@ class ExtractCameraFbx(publish.Extractor): label = "Extract Fbx Camera" hosts = ["max"] families = ["camera"] + optional = True def process(self, instance): + if not self.is_active(instance.data): + return container = instance.data["instance_node"] self.log.info("Extracting Camera ...") 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 97de602216..7ac072b829 100644 --- a/openpype/hosts/max/plugins/publish/extract_max_scene_raw.py +++ b/openpype/hosts/max/plugins/publish/extract_max_scene_raw.py @@ -1,6 +1,9 @@ import os import pyblish.api -from openpype.pipeline import publish +from openpype.pipeline import ( + publish, + OptionalPyblishPluginMixin +) from pymxs import runtime as rt from openpype.hosts.max.api import ( maintained_selection, @@ -8,7 +11,8 @@ from openpype.hosts.max.api import ( ) -class ExtractMaxSceneRaw(publish.Extractor): +class ExtractMaxSceneRaw(publish.Extractor, + OptionalPyblishPluginMixin): """ Extract Raw Max Scene with SaveSelected """ @@ -17,12 +21,15 @@ class ExtractMaxSceneRaw(publish.Extractor): label = "Max Scene(Raw)" hosts = ["max"] families = ["camera"] + optional = True 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 Camera ...") + self.log.info("Extracting Raw Max Scene ...") stagingdir = self.staging_dir(instance) filename = "{name}.max".format(**instance.data) @@ -34,28 +41,14 @@ class ExtractMaxSceneRaw(publish.Extractor): if "representations" not in instance.data: instance.data["representations"] = [] - # add extra blacklash for saveNodes in MaxScript - re_max_path = stagingdir + "\\\\" + filename # saving max scene - raw_export_cmd = ( - f""" -sel = getCurrentSelection() -for s in sel do -( - select s - f="{re_max_path}" - print f - saveNodes selection f quiet:true -) - """) # noqa - self.log.debug(f"Executing Maxscript command: {raw_export_cmd}") - with maintained_selection(): # need to figure out how to select the camera rt.select(get_all_children(rt.getNodeByName(container))) - rt.execute(raw_export_cmd) + rt.execute(f'saveNodes selection "{max_path}" quiet:true') self.log.info("Performing Extraction ...") + representation = { 'name': 'max', 'ext': 'max', diff --git a/openpype/hosts/max/plugins/publish/validate_camera_contents.py b/openpype/hosts/max/plugins/publish/validate_camera_contents.py index c7d13ac5a3..c81e28a61f 100644 --- a/openpype/hosts/max/plugins/publish/validate_camera_contents.py +++ b/openpype/hosts/max/plugins/publish/validate_camera_contents.py @@ -33,23 +33,16 @@ class ValidateCameraContent(pyblish.api.InstancePlugin): "{}".format(container)) con = rt.getNodeByName(container) - selection_list = self.list_children(con) - validation_msg = list() + selection_list = list(con.Children) 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): - validation_msg.append("Camera Found") - else: - validation_msg.append("Camera Not Found") - if "Camera Found" not in validation_msg: + found = True + break + if not found: + self.log.error("Camera not found") invalid.append(sel) - # go through the camera type to see if there are same name return invalid - - def list_children(self, node): - children = [] - for c in node.Children: - children.append(c) - return children From 5cf9ce768404241d99bed02d248a4a9cf583296b Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 26 Jan 2023 23:38:21 +0800 Subject: [PATCH 28/70] fix typo --- openpype/hosts/max/plugins/publish/extract_camera_abc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/max/plugins/publish/extract_camera_abc.py b/openpype/hosts/max/plugins/publish/extract_camera_abc.py index 83cf2c3a6e..38afbd8441 100644 --- a/openpype/hosts/max/plugins/publish/extract_camera_abc.py +++ b/openpype/hosts/max/plugins/publish/extract_camera_abc.py @@ -8,13 +8,13 @@ from openpype.hosts.max.api import ( ) -class ExtractAlembicCamera(publish.Extractor): +class ExtractCameraAlembic(publish.Extractor): """ Extract Camera with AlembicExport """ order = pyblish.api.ExtractorOrder - 0.1 - label = "Extract Almebic Camera" + label = "Extract Alembic Camera" hosts = ["max"] families = ["camera"] optional = True From 8334323a4f62a1b99571a668101f21617fe867f4 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 26 Jan 2023 23:52:30 +0800 Subject: [PATCH 29/70] fix typo --- openpype/hosts/max/plugins/publish/extract_camera_abc.py | 2 +- openpype/hosts/max/plugins/publish/extract_max_scene_raw.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/max/plugins/publish/extract_camera_abc.py b/openpype/hosts/max/plugins/publish/extract_camera_abc.py index 5f88df041b..8c23ff9878 100644 --- a/openpype/hosts/max/plugins/publish/extract_camera_abc.py +++ b/openpype/hosts/max/plugins/publish/extract_camera_abc.py @@ -11,7 +11,7 @@ from openpype.hosts.max.api import ( ) -class ExtractAlembicCamera(publish.Extractor, +class ExtractCameraAlembic(publish.Extractor, OptionalPyblishPluginMixin): """ Extract Camera with AlembicExport 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 7ac072b829..cacc84c591 100644 --- a/openpype/hosts/max/plugins/publish/extract_max_scene_raw.py +++ b/openpype/hosts/max/plugins/publish/extract_max_scene_raw.py @@ -18,7 +18,7 @@ class ExtractMaxSceneRaw(publish.Extractor, """ order = pyblish.api.ExtractorOrder - 0.2 - label = "Max Scene(Raw)" + label = "Extract Max Scene (Raw)" hosts = ["max"] families = ["camera"] optional = True From 06222e727b4fe3483bf0a0ccc1adaf3b3d641041 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 27 Jan 2023 15:46:57 +0100 Subject: [PATCH 30/70] implemented "not equal" method for attribute definitions (Py2 comp) --- openpype/lib/attribute_definitions.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openpype/lib/attribute_definitions.py b/openpype/lib/attribute_definitions.py index 04db0edc64..ca82644894 100644 --- a/openpype/lib/attribute_definitions.py +++ b/openpype/lib/attribute_definitions.py @@ -156,6 +156,9 @@ class AbtractAttrDef(object): return False return self.key == other.key + def __ne__(self, other): + return not self.__eq__(other) + @abstractproperty def type(self): """Attribute definition type also used as identifier of class. From 36df58aba11a2334bc6e0d664f1dc08097f22e82 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 27 Jan 2023 15:47:30 +0100 Subject: [PATCH 31/70] added more conditions for comparison --- openpype/lib/attribute_definitions.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/openpype/lib/attribute_definitions.py b/openpype/lib/attribute_definitions.py index ca82644894..1debd0aa79 100644 --- a/openpype/lib/attribute_definitions.py +++ b/openpype/lib/attribute_definitions.py @@ -154,7 +154,12 @@ class AbtractAttrDef(object): def __eq__(self, other): if not isinstance(other, self.__class__): return False - return self.key == other.key + return ( + self.key == other.key + and self.hidden == other.hidden + and self.default == other.default + and self.disabled == other.disabled + ) def __ne__(self, other): return not self.__eq__(other) From d48b73ed61c9ff385a8fd2bf376ecfaaa51ad91d Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 27 Jan 2023 16:28:00 +0100 Subject: [PATCH 32/70] fix typo 'AbtractAttrDef' to 'AbstractAttrDef' --- openpype/lib/__init__.py | 4 +-- openpype/lib/attribute_definitions.py | 36 +++++++++---------- openpype/pipeline/create/context.py | 2 +- openpype/pipeline/create/creator_plugins.py | 4 +-- openpype/pipeline/publish/publish_plugins.py | 2 +- .../workfile/workfile_template_builder.py | 6 ++-- openpype/tools/attribute_defs/widgets.py | 6 ++-- openpype/tools/loader/lib.py | 4 +-- openpype/tools/utils/widgets.py | 4 +-- 9 files changed, 34 insertions(+), 34 deletions(-) diff --git a/openpype/lib/__init__.py b/openpype/lib/__init__.py index a64b7c2911..b5fb955a84 100644 --- a/openpype/lib/__init__.py +++ b/openpype/lib/__init__.py @@ -30,7 +30,7 @@ from .vendor_bin_utils import ( ) from .attribute_definitions import ( - AbtractAttrDef, + AbstractAttrDef, UIDef, UISeparatorDef, @@ -246,7 +246,7 @@ __all__ = [ "get_ffmpeg_tool_path", "is_oiio_supported", - "AbtractAttrDef", + "AbstractAttrDef", "UIDef", "UISeparatorDef", diff --git a/openpype/lib/attribute_definitions.py b/openpype/lib/attribute_definitions.py index 1debd0aa79..efd38761c8 100644 --- a/openpype/lib/attribute_definitions.py +++ b/openpype/lib/attribute_definitions.py @@ -20,7 +20,7 @@ def register_attr_def_class(cls): Currently are registered definitions used to deserialize data to objects. Attrs: - cls (AbtractAttrDef): Non-abstract class to be registered with unique + cls (AbstractAttrDef): Non-abstract class to be registered with unique 'type' attribute. Raises: @@ -36,7 +36,7 @@ def get_attributes_keys(attribute_definitions): """Collect keys from list of attribute definitions. Args: - attribute_definitions (List[AbtractAttrDef]): Objects of attribute + attribute_definitions (List[AbstractAttrDef]): Objects of attribute definitions. Returns: @@ -57,7 +57,7 @@ def get_default_values(attribute_definitions): """Receive default values for attribute definitions. Args: - attribute_definitions (List[AbtractAttrDef]): Attribute definitions for + attribute_definitions (List[AbstractAttrDef]): Attribute definitions for which default values should be collected. Returns: @@ -76,15 +76,15 @@ def get_default_values(attribute_definitions): class AbstractAttrDefMeta(ABCMeta): - """Meta class to validate existence of 'key' attribute. + """Metaclass to validate existence of 'key' attribute. - Each object of `AbtractAttrDef` mus have defined 'key' attribute. + Each object of `AbstractAttrDef` mus have defined 'key' attribute. """ def __call__(self, *args, **kwargs): obj = super(AbstractAttrDefMeta, self).__call__(*args, **kwargs) init_class = getattr(obj, "__init__class__", None) - if init_class is not AbtractAttrDef: + if init_class is not AbstractAttrDef: raise TypeError("{} super was not called in __init__.".format( type(obj) )) @@ -92,7 +92,7 @@ class AbstractAttrDefMeta(ABCMeta): @six.add_metaclass(AbstractAttrDefMeta) -class AbtractAttrDef(object): +class AbstractAttrDef(object): """Abstraction of attribute definiton. Each attribute definition must have implemented validation and @@ -145,7 +145,7 @@ class AbtractAttrDef(object): self.disabled = disabled self._id = uuid.uuid4().hex - self.__init__class__ = AbtractAttrDef + self.__init__class__ = AbstractAttrDef @property def id(self): @@ -220,7 +220,7 @@ class AbtractAttrDef(object): # UI attribute definitoins won't hold value # ----------------------------------------- -class UIDef(AbtractAttrDef): +class UIDef(AbstractAttrDef): is_value_def = False def __init__(self, key=None, default=None, *args, **kwargs): @@ -245,7 +245,7 @@ class UILabelDef(UIDef): # Attribute defintioins should hold value # --------------------------------------- -class UnknownDef(AbtractAttrDef): +class UnknownDef(AbstractAttrDef): """Definition is not known because definition is not available. This attribute can be used to keep existing data unchanged but does not @@ -262,7 +262,7 @@ class UnknownDef(AbtractAttrDef): return value -class HiddenDef(AbtractAttrDef): +class HiddenDef(AbstractAttrDef): """Hidden value of Any type. This attribute can be used for UI purposes to pass values related @@ -282,7 +282,7 @@ class HiddenDef(AbtractAttrDef): return value -class NumberDef(AbtractAttrDef): +class NumberDef(AbstractAttrDef): """Number definition. Number can have defined minimum/maximum value and decimal points. Value @@ -358,7 +358,7 @@ class NumberDef(AbtractAttrDef): return round(float(value), self.decimals) -class TextDef(AbtractAttrDef): +class TextDef(AbstractAttrDef): """Text definition. Text can have multiline option so endline characters are allowed regex @@ -423,7 +423,7 @@ class TextDef(AbtractAttrDef): return data -class EnumDef(AbtractAttrDef): +class EnumDef(AbstractAttrDef): """Enumeration of single item from items. Args: @@ -531,7 +531,7 @@ class EnumDef(AbtractAttrDef): return output -class BoolDef(AbtractAttrDef): +class BoolDef(AbstractAttrDef): """Boolean representation. Args: @@ -776,7 +776,7 @@ class FileDefItem(object): return output -class FileDef(AbtractAttrDef): +class FileDef(AbstractAttrDef): """File definition. It is possible to define filters of allowed file extensions and if supports folders. @@ -894,7 +894,7 @@ def serialize_attr_def(attr_def): """Serialize attribute definition to data. Args: - attr_def (AbtractAttrDef): Attribute definition to serialize. + attr_def (AbstractAttrDef): Attribute definition to serialize. Returns: Dict[str, Any]: Serialized data. @@ -907,7 +907,7 @@ def serialize_attr_defs(attr_defs): """Serialize attribute definitions to data. Args: - attr_defs (List[AbtractAttrDef]): Attribute definitions to serialize. + attr_defs (List[AbstractAttrDef]): Attribute definitions to serialize. Returns: List[Dict[str, Any]]: Serialized data. diff --git a/openpype/pipeline/create/context.py b/openpype/pipeline/create/context.py index 9c468ae8fc..c3cf3e9b4b 100644 --- a/openpype/pipeline/create/context.py +++ b/openpype/pipeline/create/context.py @@ -208,7 +208,7 @@ class AttributeValues(object): Has dictionary like methods. Not all of them are allowed all the time. Args: - attr_defs(AbtractAttrDef): Defintions of value type and properties. + attr_defs(AbstractAttrDef): Defintions of value type and properties. values(dict): Values after possible conversion. origin_data(dict): Values loaded from host before conversion. """ diff --git a/openpype/pipeline/create/creator_plugins.py b/openpype/pipeline/create/creator_plugins.py index 8500dd1e22..8ac8959c76 100644 --- a/openpype/pipeline/create/creator_plugins.py +++ b/openpype/pipeline/create/creator_plugins.py @@ -425,7 +425,7 @@ class BaseCreator: keys/values when plugin attributes change. Returns: - List[AbtractAttrDef]: Attribute definitions that can be tweaked for + List[AbstractAttrDef]: Attribute definitions that can be tweaked for created instance. """ @@ -563,7 +563,7 @@ class Creator(BaseCreator): updating keys/values when plugin attributes change. Returns: - List[AbtractAttrDef]: Attribute definitions that can be tweaked for + List[AbstractAttrDef]: Attribute definitions that can be tweaked for created instance. """ return self.pre_create_attr_defs diff --git a/openpype/pipeline/publish/publish_plugins.py b/openpype/pipeline/publish/publish_plugins.py index d9145275f7..96e4aae237 100644 --- a/openpype/pipeline/publish/publish_plugins.py +++ b/openpype/pipeline/publish/publish_plugins.py @@ -118,7 +118,7 @@ class OpenPypePyblishPluginMixin: Attributes available for all families in plugin's `families` attribute. Returns: - list: Attribute definitions for plugin. + list: Attribute definitions for plugin. """ return [] diff --git a/openpype/pipeline/workfile/workfile_template_builder.py b/openpype/pipeline/workfile/workfile_template_builder.py index 1266c27fd7..051eb444c6 100644 --- a/openpype/pipeline/workfile/workfile_template_builder.py +++ b/openpype/pipeline/workfile/workfile_template_builder.py @@ -842,7 +842,7 @@ class PlaceholderPlugin(object): """Placeholder options for data showed. Returns: - List[AbtractAttrDef]: Attribute definitions of placeholder options. + List[AbstractAttrDef]: Attribute definitions of placeholder options. """ return [] @@ -1143,7 +1143,7 @@ class PlaceholderLoadMixin(object): as defaults for attributes. Returns: - List[AbtractAttrDef]: Attribute definitions common for load + List[AbstractAttrDef]: Attribute definitions common for load plugins. """ @@ -1513,7 +1513,7 @@ class PlaceholderCreateMixin(object): as defaults for attributes. Returns: - List[AbtractAttrDef]: Attribute definitions common for create + List[AbstractAttrDef]: Attribute definitions common for create plugins. """ diff --git a/openpype/tools/attribute_defs/widgets.py b/openpype/tools/attribute_defs/widgets.py index bf61dc3776..3cec1d2683 100644 --- a/openpype/tools/attribute_defs/widgets.py +++ b/openpype/tools/attribute_defs/widgets.py @@ -4,7 +4,7 @@ import copy from qtpy import QtWidgets, QtCore from openpype.lib.attribute_definitions import ( - AbtractAttrDef, + AbstractAttrDef, UnknownDef, HiddenDef, NumberDef, @@ -33,9 +33,9 @@ def create_widget_for_attr_def(attr_def, parent=None): def _create_widget_for_attr_def(attr_def, parent=None): - if not isinstance(attr_def, AbtractAttrDef): + if not isinstance(attr_def, AbstractAttrDef): raise TypeError("Unexpected type \"{}\" expected \"{}\"".format( - str(type(attr_def)), AbtractAttrDef + str(type(attr_def)), AbstractAttrDef )) if isinstance(attr_def, NumberDef): diff --git a/openpype/tools/loader/lib.py b/openpype/tools/loader/lib.py index 552dc91a10..d47bc7e07a 100644 --- a/openpype/tools/loader/lib.py +++ b/openpype/tools/loader/lib.py @@ -2,7 +2,7 @@ import inspect from qtpy import QtGui import qtawesome -from openpype.lib.attribute_definitions import AbtractAttrDef +from openpype.lib.attribute_definitions import AbstractAttrDef from openpype.tools.attribute_defs import AttributeDefinitionsDialog from openpype.tools.utils.widgets import ( OptionalAction, @@ -43,7 +43,7 @@ def get_options(action, loader, parent, repre_contexts): if not getattr(action, "optioned", False) or not loader_options: return options - if isinstance(loader_options[0], AbtractAttrDef): + if isinstance(loader_options[0], AbstractAttrDef): qargparse_options = False dialog = AttributeDefinitionsDialog(loader_options, parent) else: diff --git a/openpype/tools/utils/widgets.py b/openpype/tools/utils/widgets.py index a9d6fa35b2..41573687e1 100644 --- a/openpype/tools/utils/widgets.py +++ b/openpype/tools/utils/widgets.py @@ -8,7 +8,7 @@ from openpype.style import ( get_objected_colors, get_style_image_path ) -from openpype.lib.attribute_definitions import AbtractAttrDef +from openpype.lib.attribute_definitions import AbstractAttrDef log = logging.getLogger(__name__) @@ -406,7 +406,7 @@ class OptionalAction(QtWidgets.QWidgetAction): def set_option_tip(self, options): sep = "\n\n" - if not options or not isinstance(options[0], AbtractAttrDef): + if not options or not isinstance(options[0], AbstractAttrDef): mak = (lambda opt: opt["name"] + " :\n " + opt["help"]) self.option_tip = sep.join(mak(opt) for opt in options) return From 36065080c7796cf61e9e1d8e2f55436bd58f46fd Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 27 Jan 2023 16:30:02 +0100 Subject: [PATCH 33/70] import 'UnknownDef' at the top of file --- openpype/pipeline/create/context.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openpype/pipeline/create/context.py b/openpype/pipeline/create/context.py index c3cf3e9b4b..9d3aa37de2 100644 --- a/openpype/pipeline/create/context.py +++ b/openpype/pipeline/create/context.py @@ -13,6 +13,9 @@ from openpype.settings import ( get_system_settings, get_project_settings ) +from openpype.lib.attribute_definitions import ( + UnknownDef, +) from openpype.host import IPublishHost from openpype.pipeline import legacy_io from openpype.pipeline.mongodb import ( @@ -214,8 +217,6 @@ class AttributeValues(object): """ def __init__(self, attr_defs, values, origin_data=None): - from openpype.lib.attribute_definitions import UnknownDef - if origin_data is None: origin_data = copy.deepcopy(values) self._origin_data = origin_data From 1d91ee53388c806e8c04be79e8e2249a052cd4d7 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 27 Jan 2023 16:31:01 +0100 Subject: [PATCH 34/70] attr_defs property returns list copy of attributes --- openpype/pipeline/create/context.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/openpype/pipeline/create/context.py b/openpype/pipeline/create/context.py index 9d3aa37de2..9360db63ed 100644 --- a/openpype/pipeline/create/context.py +++ b/openpype/pipeline/create/context.py @@ -289,8 +289,13 @@ class AttributeValues(object): @property def attr_defs(self): - """Pointer to attribute definitions.""" - return self._attr_defs + """Pointer to attribute definitions. + + Returns: + List[AbstractAttrDef]: Attribute definitions. + """ + + return list(self._attr_defs) def data_to_store(self): """Create new dictionary with data to store.""" From 8f6d36dfa0291590cf245cd10592b40e4606f5c5 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 27 Jan 2023 16:33:50 +0100 Subject: [PATCH 35/70] implemented de/serialization methods for attribute values --- openpype/pipeline/create/context.py | 47 +++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/openpype/pipeline/create/context.py b/openpype/pipeline/create/context.py index 9360db63ed..fe88fbc5c3 100644 --- a/openpype/pipeline/create/context.py +++ b/openpype/pipeline/create/context.py @@ -15,6 +15,8 @@ from openpype.settings import ( ) from openpype.lib.attribute_definitions import ( UnknownDef, + serialize_attr_defs, + deserialize_attr_defs, ) from openpype.host import IPublishHost from openpype.pipeline import legacy_io @@ -331,6 +333,15 @@ class AttributeValues(object): elif self.get(key) != new_value: self[key] = new_value + def get_serialized_attr_defs(self): + """Serialize attribute definitions to json serializable types. + + Returns: + List[Dict[str, Any]]: Serialized attribute definitions. + """ + + return serialize_attr_defs(self._attr_defs) + class CreatorAttributeValues(AttributeValues): """Creator specific attribute values of an instance. @@ -515,6 +526,42 @@ class PublishAttributes: self, [], value, value ) + def serialize_attributes(self): + return { + "attr_defs": { + plugin_name: attrs_value.get_serialized_attr_defs() + for plugin_name, attrs_value in self._data.items() + }, + "plugin_names_order": self._plugin_names_order, + "missing_plugins": self._missing_plugins + } + + def deserialize_attributes(self, data): + self._plugin_names_order = data["plugin_names_order"] + self._missing_plugins = data["missing_plugins"] + + attr_defs = deserialize_attr_defs(data["attr_defs"]) + + origin_data = self._origin_data + data = self._data + self._data = {} + + added_keys = set() + for plugin_name, attr_defs_data in attr_defs.items(): + attr_defs = deserialize_attr_defs(attr_defs_data) + value = data.get(plugin_name) or {} + orig_value = copy.deepcopy(origin_data.get(plugin_name) or {}) + self._data[plugin_name] = PublishAttributeValues( + self, attr_defs, value, orig_value + ) + + for key, value in data.items(): + if key not in added_keys: + self._missing_plugins.append(key) + self._data[key] = PublishAttributeValues( + self, [], value, value + ) + class CreatedInstance: """Instance entity with data that will be stored to workfile. From eac4167a22703cc2b77adcf45d73978c28c3b5f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= <33513211+antirotor@users.noreply.github.com> Date: Fri, 27 Jan 2023 16:33:51 +0100 Subject: [PATCH 36/70] :bug: hotfix condition --- openpype/hosts/houdini/api/plugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/houdini/api/plugin.py b/openpype/hosts/houdini/api/plugin.py index 4ca6b50702..61127bda57 100644 --- a/openpype/hosts/houdini/api/plugin.py +++ b/openpype/hosts/houdini/api/plugin.py @@ -113,7 +113,7 @@ class HoudiniCreatorBase(object): Dict[str, Any]: Shared data dictionary. """ - if shared_data.get("houdini_cached_subsets") is not None: + if shared_data.get("houdini_cached_subsets") is None: cache = dict() cache_legacy = dict() From 6a1acc166425ca716b10403f02d38c73ba2f2ab8 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 27 Jan 2023 16:34:36 +0100 Subject: [PATCH 37/70] 'CreatedInstance' can be initialized without creator --- openpype/pipeline/create/context.py | 50 +++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/openpype/pipeline/create/context.py b/openpype/pipeline/create/context.py index fe88fbc5c3..2c1a13100b 100644 --- a/openpype/pipeline/create/context.py +++ b/openpype/pipeline/create/context.py @@ -570,15 +570,22 @@ class CreatedInstance: about instance like "asset" and "task" and all data used for filling subset name as creators may have custom data for subset name filling. + Notes: + Object have 2 possible initialization. One using 'creator' object which + is recommended for api usage. Second by passing information about + creator. + Args: - family(str): Name of family that will be created. - subset_name(str): Name of subset that will be created. - data(dict): Data used for filling subset name or override data from - already existing instance. - creator(BaseCreator): Creator responsible for instance. - host(ModuleType): Host implementation loaded with - `openpype.pipeline.registered_host`. - new(bool): Is instance new. + family (str): Name of family that will be created. + subset_name (str): Name of subset that will be created. + data (Dict[str, Any]): Data used for filling subset name or override + data from already existing instance. + creator (Union[BaseCreator, None]): Creator responsible for instance. + creator_identifier (str): Identifier of creator plugin. + creator_label (str): Creator plugin label. + group_label (str): Default group label from creator plugin. + creator_attr_defs (List[AbstractAttrDef]): Attribute definitions from + creator. """ # Keys that can't be changed or removed from data after loading using @@ -595,9 +602,24 @@ class CreatedInstance: ) def __init__( - self, family, subset_name, data, creator, new=True + self, + family, + subset_name, + data, + creator=None, + creator_identifier=None, + creator_label=None, + group_label=None, + creator_attr_defs=None, ): - self.creator = creator + if creator is not None: + creator_identifier = creator.identifier + group_label = creator.get_group_label() + creator_label = creator.label + creator_attr_defs = creator.get_instance_attr_defs() + + self._creator_label = creator_label + self._group_label = group_label or creator_identifier # Instance members may have actions on them # TODO implement members logic @@ -627,7 +649,7 @@ class CreatedInstance: self._data["family"] = family self._data["subset"] = subset_name self._data["active"] = data.get("active", True) - self._data["creator_identifier"] = creator.identifier + self._data["creator_identifier"] = creator_identifier # Pop from source data all keys that are defined in `_data` before # this moment and through their values away @@ -641,10 +663,12 @@ class CreatedInstance: # Stored creator specific attribute values # {key: value} creator_values = copy.deepcopy(orig_creator_attributes) - creator_attr_defs = creator.get_instance_attr_defs() self._data["creator_attributes"] = CreatorAttributeValues( - self, creator_attr_defs, creator_values, orig_creator_attributes + self, + list(creator_attr_defs), + creator_values, + orig_creator_attributes ) # Stored publish specific attribute values From 373d2452423f7a7eca5161361022d7cba15fb705 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 27 Jan 2023 16:35:20 +0100 Subject: [PATCH 38/70] moved context validation methods to bottom --- openpype/pipeline/create/context.py | 88 ++++++++++++++--------------- 1 file changed, 43 insertions(+), 45 deletions(-) diff --git a/openpype/pipeline/create/context.py b/openpype/pipeline/create/context.py index 2c1a13100b..081fdd86ff 100644 --- a/openpype/pipeline/create/context.py +++ b/openpype/pipeline/create/context.py @@ -763,51 +763,6 @@ class CreatedInstance: def creator_label(self): return self.creator.label or self.creator_identifier - @property - def create_context(self): - return self.creator.create_context - - @property - def host(self): - return self.create_context.host - - @property - def has_set_asset(self): - """Asset name is set in data.""" - return "asset" in self._data - - @property - def has_set_task(self): - """Task name is set in data.""" - return "task" in self._data - - @property - def has_valid_context(self): - """Context data are valid for publishing.""" - return self.has_valid_asset and self.has_valid_task - - @property - def has_valid_asset(self): - """Asset set in context exists in project.""" - if not self.has_set_asset: - return False - return self._asset_is_valid - - @property - def has_valid_task(self): - """Task set in context exists in project.""" - if not self.has_set_task: - return False - return self._task_is_valid - - def set_asset_invalid(self, invalid): - # TODO replace with `set_asset_name` - self._asset_is_valid = not invalid - - def set_task_invalid(self, invalid): - # TODO replace with `set_task_name` - self._task_is_valid = not invalid - @property def id(self): """Instance identifier.""" @@ -1039,6 +994,49 @@ class CreatedInstance: if current_value != new_value: self[key] = new_value + # Context validation related methods/properties + @property + def has_set_asset(self): + """Asset name is set in data.""" + + return "asset" in self._data + + @property + def has_set_task(self): + """Task name is set in data.""" + + return "task" in self._data + + @property + def has_valid_context(self): + """Context data are valid for publishing.""" + + return self.has_valid_asset and self.has_valid_task + + @property + def has_valid_asset(self): + """Asset set in context exists in project.""" + + if not self.has_set_asset: + return False + return self._asset_is_valid + + @property + def has_valid_task(self): + """Task set in context exists in project.""" + + if not self.has_set_task: + return False + return self._task_is_valid + + def set_asset_invalid(self, invalid): + # TODO replace with `set_asset_name` + self._asset_is_valid = not invalid + + def set_task_invalid(self, invalid): + # TODO replace with `set_task_name` + self._task_is_valid = not invalid + class ConvertorItem(object): """Item representing convertor plugin. From e7fdb1d151a117f975eb6094be4b4d761029136f Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 27 Jan 2023 16:36:42 +0100 Subject: [PATCH 39/70] don't use creator in methods --- openpype/pipeline/create/context.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openpype/pipeline/create/context.py b/openpype/pipeline/create/context.py index 081fdd86ff..0f288f0bd5 100644 --- a/openpype/pipeline/create/context.py +++ b/openpype/pipeline/create/context.py @@ -753,15 +753,15 @@ class CreatedInstance: label = self._data.get("group") if label: return label - return self.creator.get_group_label() + return self._group_label @property def creator_identifier(self): - return self.creator.identifier + return self._data["creator_identifier"] @property def creator_label(self): - return self.creator.label or self.creator_identifier + return self._creator_label or self.creator_identifier @property def id(self): @@ -1477,7 +1477,7 @@ class CreateContext: self._instances_by_id[instance.id] = instance # Prepare publish plugin attributes and set it on instance attr_plugins = self._get_publish_plugins_with_attr_for_family( - instance.creator.family + instance.family ) instance.set_publish_plugins(attr_plugins) From 86ece89a3a2756516ec1e3903e1ba4d4f6b52f69 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 27 Jan 2023 16:37:14 +0100 Subject: [PATCH 40/70] de/serialization of CreatedInstance does not require creator --- openpype/pipeline/create/context.py | 35 ++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/openpype/pipeline/create/context.py b/openpype/pipeline/create/context.py index 0f288f0bd5..0a5d186273 100644 --- a/openpype/pipeline/create/context.py +++ b/openpype/pipeline/create/context.py @@ -904,9 +904,21 @@ class CreatedInstance: self._members.append(member) def serialize_for_remote(self): + """Serialize object into data to be possible recreated object. + + Returns: + Dict[str, Any]: Serialized data. + """ + + creator_attr_defs = self.creator_attributes.get_serialized_attr_defs() + publish_attributes = self.publish_attributes.serialize_attributes() return { "data": self.data_to_store(), - "orig_data": copy.deepcopy(self._orig_data) + "orig_data": copy.deepcopy(self._orig_data), + "creator_attr_defs": creator_attr_defs, + "publish_attributes": publish_attributes, + "creator_label": self._creator_label, + "group_label": self._group_label, } @classmethod @@ -927,17 +939,28 @@ class CreatedInstance: instance_data = copy.deepcopy(serialized_data["data"]) creator_identifier = instance_data["creator_identifier"] - creator_item = creator_items[creator_identifier] - family = instance_data.get("family", None) - if family is None: - family = creator_item.family + family = instance_data["family"] subset_name = instance_data.get("subset", None) + creator_label = serialized_data["creator_label"] + group_label = serialized_data["group_label"] + creator_attr_defs = deserialize_attr_defs( + serialized_data["creator_attr_defs"] + ) + publish_attributes = serialized_data["publish_attributes"] + obj = cls( - family, subset_name, instance_data, creator_item, new=False + family, + subset_name, + instance_data, + creator_identifier=creator_identifier, + creator_label=creator_label, + group_label=group_label, + creator_attributes=creator_attr_defs ) obj._orig_data = serialized_data["orig_data"] + obj.publish_attributes.deserialize_attributes(publish_attributes) return obj From 4ec904e2bfd592f956917888014bdc5acc1195e5 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 27 Jan 2023 16:37:40 +0100 Subject: [PATCH 41/70] don't pass removed 'new' attribute --- openpype/pipeline/create/context.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/pipeline/create/context.py b/openpype/pipeline/create/context.py index 0a5d186273..2ccd50006e 100644 --- a/openpype/pipeline/create/context.py +++ b/openpype/pipeline/create/context.py @@ -891,7 +891,7 @@ class CreatedInstance: subset_name = instance_data.get("subset", None) return cls( - family, subset_name, instance_data, creator, new=False + family, subset_name, instance_data, creator ) def set_publish_plugins(self, attr_plugins): From 951e8a50557c1e3545da8cb63b557813b163d179 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 27 Jan 2023 16:42:22 +0100 Subject: [PATCH 42/70] don't pass creator_items to 'deserialize_on_remote' --- openpype/pipeline/create/context.py | 2 +- openpype/tools/publisher/control_qt.py | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/openpype/pipeline/create/context.py b/openpype/pipeline/create/context.py index 2ccd50006e..b52c870329 100644 --- a/openpype/pipeline/create/context.py +++ b/openpype/pipeline/create/context.py @@ -922,7 +922,7 @@ class CreatedInstance: } @classmethod - def deserialize_on_remote(cls, serialized_data, creator_items): + def deserialize_on_remote(cls, serialized_data): """Convert instance data to CreatedInstance. This is fake instance in remote process e.g. in UI process. The creator diff --git a/openpype/tools/publisher/control_qt.py b/openpype/tools/publisher/control_qt.py index 3639c4bb30..132b42f9ec 100644 --- a/openpype/tools/publisher/control_qt.py +++ b/openpype/tools/publisher/control_qt.py @@ -136,10 +136,7 @@ class QtRemotePublishController(BasePublisherController): created_instances = {} for serialized_data in serialized_instances: - item = CreatedInstance.deserialize_on_remote( - serialized_data, - self._creator_items - ) + item = CreatedInstance.deserialize_on_remote(serialized_data) created_instances[item.id] = item self._created_instances = created_instances From 75d72f4d2dd7fa8c8e65085ee1351ca54ab21121 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 27 Jan 2023 16:42:38 +0100 Subject: [PATCH 43/70] fix 'pre_create_attributes_defs' --- openpype/tools/publisher/control.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/tools/publisher/control.py b/openpype/tools/publisher/control.py index 50a814de5c..ca2b083e80 100644 --- a/openpype/tools/publisher/control.py +++ b/openpype/tools/publisher/control.py @@ -910,7 +910,7 @@ class CreatorItem: pre_create_attributes_defs = None if self.pre_create_attributes_defs is not None: - instance_attributes_defs = serialize_attr_defs( + pre_create_attributes_defs = serialize_attr_defs( self.pre_create_attributes_defs ) From b5e35eaa63bd03463abd4f6b4a5d410745321afa Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 27 Jan 2023 16:43:06 +0100 Subject: [PATCH 44/70] CreatorItem in controller does not have 'instance_attributes_defs' --- openpype/tools/publisher/control.py | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/openpype/tools/publisher/control.py b/openpype/tools/publisher/control.py index ca2b083e80..61969691c6 100644 --- a/openpype/tools/publisher/control.py +++ b/openpype/tools/publisher/control.py @@ -826,7 +826,6 @@ class CreatorItem: label, group_label, icon, - instance_attributes_defs, description, detailed_description, default_variant, @@ -847,12 +846,8 @@ class CreatorItem: self.default_variants = default_variants self.create_allow_context_change = create_allow_context_change self.create_allow_thumbnail = create_allow_thumbnail - self.instance_attributes_defs = instance_attributes_defs self.pre_create_attributes_defs = pre_create_attributes_defs - def get_instance_attr_defs(self): - return self.instance_attributes_defs - def get_group_label(self): return self.group_label @@ -891,7 +886,6 @@ class CreatorItem: creator.label or identifier, creator.get_group_label(), creator.get_icon(), - creator.get_instance_attr_defs(), description, detail_description, default_variant, @@ -902,12 +896,6 @@ class CreatorItem: ) def to_data(self): - instance_attributes_defs = None - if self.instance_attributes_defs is not None: - instance_attributes_defs = serialize_attr_defs( - self.instance_attributes_defs - ) - pre_create_attributes_defs = None if self.pre_create_attributes_defs is not None: pre_create_attributes_defs = serialize_attr_defs( @@ -927,18 +915,11 @@ class CreatorItem: "default_variants": self.default_variants, "create_allow_context_change": self.create_allow_context_change, "create_allow_thumbnail": self.create_allow_thumbnail, - "instance_attributes_defs": instance_attributes_defs, "pre_create_attributes_defs": pre_create_attributes_defs, } @classmethod def from_data(cls, data): - instance_attributes_defs = data["instance_attributes_defs"] - if instance_attributes_defs is not None: - data["instance_attributes_defs"] = deserialize_attr_defs( - instance_attributes_defs - ) - pre_create_attributes_defs = data["pre_create_attributes_defs"] if pre_create_attributes_defs is not None: data["pre_create_attributes_defs"] = deserialize_attr_defs( From d448004f541114c50a987a96bc5454a828c4de72 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 27 Jan 2023 16:43:24 +0100 Subject: [PATCH 45/70] get attributes from instances directly --- openpype/tools/publisher/control.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openpype/tools/publisher/control.py b/openpype/tools/publisher/control.py index 61969691c6..7c8da66744 100644 --- a/openpype/tools/publisher/control.py +++ b/openpype/tools/publisher/control.py @@ -1860,12 +1860,12 @@ class PublisherController(BasePublisherController): which should be attribute definitions returned. """ + # NOTE it would be great if attrdefs would have hash method implemented + # so they could be used as keys in dictionary output = [] _attr_defs = {} for instance in instances: - creator_identifier = instance.creator_identifier - creator_item = self.creator_items[creator_identifier] - for attr_def in creator_item.instance_attributes_defs: + for attr_def in instance.creator_attribute_defs: found_idx = None for idx, _attr_def in _attr_defs.items(): if attr_def == _attr_def: From 96094324fabfe015730415b265188ce84e000924 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 27 Jan 2023 16:43:50 +0100 Subject: [PATCH 46/70] check for 'creator_identifier' instead of 'creator' --- openpype/tools/publisher/widgets/widgets.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openpype/tools/publisher/widgets/widgets.py b/openpype/tools/publisher/widgets/widgets.py index 2e8d0ce37c..587bcb059d 100644 --- a/openpype/tools/publisher/widgets/widgets.py +++ b/openpype/tools/publisher/widgets/widgets.py @@ -1220,7 +1220,8 @@ class GlobalAttrsWidget(QtWidgets.QWidget): asset_task_combinations = [] for instance in instances: - if instance.creator is None: + # NOTE I'm not sure how this can even happen? + if instance.creator_identifier is None: editable = False variants.add(instance.get("variant") or self.unknown_value) From 3aaf349b694dcb6306eda7ebcda10a37636dd2f7 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 27 Jan 2023 16:44:05 +0100 Subject: [PATCH 47/70] modified few docstrings --- openpype/pipeline/create/context.py | 60 ++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 9 deletions(-) diff --git a/openpype/pipeline/create/context.py b/openpype/pipeline/create/context.py index b52c870329..9d42764aef 100644 --- a/openpype/pipeline/create/context.py +++ b/openpype/pipeline/create/context.py @@ -33,6 +33,7 @@ from .creator_plugins import ( CreatorError, ) +# Changes of instances and context are send as tuple of 2 information UpdateData = collections.namedtuple("UpdateData", ["instance", "changes"]) @@ -300,7 +301,12 @@ class AttributeValues(object): return list(self._attr_defs) def data_to_store(self): - """Create new dictionary with data to store.""" + """Create new dictionary with data to store. + + Returns: + Dict[str, Any]: Attribute values that should be stored. + """ + output = {} for key in self._data: output[key] = self[key] @@ -313,6 +319,7 @@ class AttributeValues(object): @staticmethod def calculate_changes(new_data, old_data): """Calculate changes of 2 dictionary objects.""" + changes = {} for key, new_value in new_data.items(): old_value = old_data.get(key) @@ -379,13 +386,14 @@ class PublishAttributes: """Wrapper for publish plugin attribute definitions. Cares about handling attribute definitions of multiple publish plugins. + Keep information about attribute definitions and their values. Args: parent(CreatedInstance, CreateContext): Parent for which will be data stored and from which are data loaded. origin_data(dict): Loaded data by plugin class name. - attr_plugins(list): List of publish plugins that may have defined - attribute definitions. + attr_plugins(Union[List[pyblish.api.Plugin], None]): List of publish + plugins that may have defined attribute definitions. """ def __init__(self, parent, origin_data, attr_plugins=None): @@ -765,7 +773,11 @@ class CreatedInstance: @property def id(self): - """Instance identifier.""" + """Instance identifier. + + Returns: + str: UUID of instance. + """ return self._data["instance_id"] @@ -774,6 +786,10 @@ class CreatedInstance: """Legacy access to data. Access to data is needed to modify values. + + Returns: + CreatedInstance: Object can be used as dictionary but with + validations of immutable keys. """ return self @@ -850,6 +866,12 @@ class CreatedInstance: @property def creator_attribute_defs(self): + """Attribute defintions defined by creator plugin. + + Returns: + List[AbstractAttrDef]: Attribute defitions. + """ + return self.creator_attributes.attr_defs @property @@ -861,7 +883,7 @@ class CreatedInstance: It is possible to recreate the instance using these data. - Todo: + Todos: We probably don't need OrderedDict. When data are loaded they are not ordered anymore. @@ -882,7 +904,15 @@ class CreatedInstance: @classmethod def from_existing(cls, instance_data, creator): - """Convert instance data from workfile to CreatedInstance.""" + """Convert instance data from workfile to CreatedInstance. + + Args: + instance_data (Dict[str, Any]): Data in a structure ready for + 'CreatedInstance' object. + creator (Creator): Creator plugin which is creating the instance + of for which the instance belong. + """ + instance_data = copy.deepcopy(instance_data) family = instance_data.get("family", None) @@ -895,10 +925,21 @@ class CreatedInstance: ) def set_publish_plugins(self, attr_plugins): + """Set publish plugins with attribute definitions. + + This method should be called only from 'CreateContext'. + + Args: + attr_plugins (List[pyblish.api.Plugin]): Pyblish plugins which + inherit from 'OpenPypePyblishPluginMixin' and may contain + attribute definitions. + """ + self.publish_attributes.set_publish_plugins(attr_plugins) def add_members(self, members): """Currently unused method.""" + for member in members: if member not in self._members: self._members.append(member) @@ -932,9 +973,6 @@ class CreatedInstance: Args: serialized_data (Dict[str, Any]): Serialized data for remote recreating. Should contain 'data' and 'orig_data'. - creator_items (Dict[str, Any]): Mapping of creator identifier and - objects that behave like a creator for most of attribute - access. """ instance_data = copy.deepcopy(serialized_data["data"]) @@ -1098,6 +1136,10 @@ class CreateContext: Context itself also can store data related to whole creation (workfile). - those are mainly for Context publish plugins + Todos: + Don't use 'AvalonMongoDB'. It's used only to keep track about current + context which should be handled by host. + Args: host(ModuleType): Host implementation which handles implementation and global metadata. From 5d9e7cf52d02ab2346d8a5e06a9ce06d1c2b675b Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Fri, 27 Jan 2023 17:21:28 +0100 Subject: [PATCH 48/70] fix formatting --- openpype/lib/attribute_definitions.py | 5 +++-- openpype/pipeline/create/context.py | 4 ++-- openpype/pipeline/create/creator_plugins.py | 8 ++++---- openpype/pipeline/workfile/workfile_template_builder.py | 3 ++- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/openpype/lib/attribute_definitions.py b/openpype/lib/attribute_definitions.py index efd38761c8..a2fe8314b2 100644 --- a/openpype/lib/attribute_definitions.py +++ b/openpype/lib/attribute_definitions.py @@ -57,8 +57,8 @@ def get_default_values(attribute_definitions): """Receive default values for attribute definitions. Args: - attribute_definitions (List[AbstractAttrDef]): Attribute definitions for - which default values should be collected. + attribute_definitions (List[AbstractAttrDef]): Attribute definitions + for which default values should be collected. Returns: Dict[str, Any]: Default values for passet attribute definitions. @@ -531,6 +531,7 @@ class EnumDef(AbstractAttrDef): return output + class BoolDef(AbstractAttrDef): """Boolean representation. diff --git a/openpype/pipeline/create/context.py b/openpype/pipeline/create/context.py index 9d42764aef..2b4c8a05ca 100644 --- a/openpype/pipeline/create/context.py +++ b/openpype/pipeline/create/context.py @@ -867,11 +867,11 @@ class CreatedInstance: @property def creator_attribute_defs(self): """Attribute defintions defined by creator plugin. - + Returns: List[AbstractAttrDef]: Attribute defitions. """ - + return self.creator_attributes.attr_defs @property diff --git a/openpype/pipeline/create/creator_plugins.py b/openpype/pipeline/create/creator_plugins.py index 8ac8959c76..1f92056b23 100644 --- a/openpype/pipeline/create/creator_plugins.py +++ b/openpype/pipeline/create/creator_plugins.py @@ -425,8 +425,8 @@ class BaseCreator: keys/values when plugin attributes change. Returns: - List[AbstractAttrDef]: Attribute definitions that can be tweaked for - created instance. + List[AbstractAttrDef]: Attribute definitions that can be tweaked + for created instance. """ return self.instance_attr_defs @@ -563,8 +563,8 @@ class Creator(BaseCreator): updating keys/values when plugin attributes change. Returns: - List[AbstractAttrDef]: Attribute definitions that can be tweaked for - created instance. + List[AbstractAttrDef]: Attribute definitions that can be tweaked + for created instance. """ return self.pre_create_attr_defs diff --git a/openpype/pipeline/workfile/workfile_template_builder.py b/openpype/pipeline/workfile/workfile_template_builder.py index 051eb444c6..119e4aaeb7 100644 --- a/openpype/pipeline/workfile/workfile_template_builder.py +++ b/openpype/pipeline/workfile/workfile_template_builder.py @@ -842,7 +842,8 @@ class PlaceholderPlugin(object): """Placeholder options for data showed. Returns: - List[AbstractAttrDef]: Attribute definitions of placeholder options. + List[AbstractAttrDef]: Attribute definitions of + placeholder options. """ return [] From 1af1909e0e936b62fa1a029c4921a43744ff1633 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Sat, 28 Jan 2023 16:09:23 +0000 Subject: [PATCH 49/70] Revert clean up --- openpype/hosts/maya/api/lib.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openpype/hosts/maya/api/lib.py b/openpype/hosts/maya/api/lib.py index 71d890f46b..358996fc7f 100644 --- a/openpype/hosts/maya/api/lib.py +++ b/openpype/hosts/maya/api/lib.py @@ -690,6 +690,11 @@ def get_current_renderlayer(): return cmds.editRenderLayerGlobals(query=True, currentRenderLayer=True) +def get_renderer(layer): + with renderlayer(layer): + return cmds.getAttr("defaultRenderGlobals.currentRenderer") + + @contextlib.contextmanager def no_undo(flush=False): """Disable the undo queue during the context From 0f4ca3643eeca0568705570d6c2bf06a89ede319 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Sat, 28 Jan 2023 16:09:32 +0000 Subject: [PATCH 50/70] Remove redundant variable --- openpype/hosts/maya/api/menu.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/hosts/maya/api/menu.py b/openpype/hosts/maya/api/menu.py index 67109e9958..791475173f 100644 --- a/openpype/hosts/maya/api/menu.py +++ b/openpype/hosts/maya/api/menu.py @@ -50,7 +50,6 @@ def install(): parent="MayaWindow" ) - renderer = cmds.getAttr('defaultRenderGlobals.currentRenderer').lower() # Create context menu context_label = "{}, {}".format( legacy_io.Session["AVALON_ASSET"], From 14c23246fbda7a6a4d571c9bbff93252f52466e9 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Sat, 28 Jan 2023 16:14:10 +0000 Subject: [PATCH 51/70] Resolve plugin --- openpype/hosts/maya/plugins/publish/submit_maya_muster.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/submit_maya_muster.py b/openpype/hosts/maya/plugins/publish/submit_maya_muster.py index 8ae3e5124b..1a6463fb9d 100644 --- a/openpype/hosts/maya/plugins/publish/submit_maya_muster.py +++ b/openpype/hosts/maya/plugins/publish/submit_maya_muster.py @@ -52,11 +52,6 @@ def _get_script(): return module_path -def get_renderer(layer): - with lib.renderlayer(layer): - return cmds.getAttr("defaultRenderGlobals.currentRenderer") - - def get_renderer_variables(renderlayer=None): """Retrieve the extension which has been set in the VRay settings @@ -71,7 +66,7 @@ def get_renderer_variables(renderlayer=None): dict """ - renderer = get_renderer(renderlayer or lib.get_current_renderlayer()) + renderer = lib.get_renderer(renderlayer or lib.get_current_renderlayer()) render_attrs = lib.RENDER_ATTRS.get(renderer, lib.RENDER_ATTRS["default"]) padding = cmds.getAttr("{}.{}".format(render_attrs["node"], From 01a70c06a45ddfd7f20522a592451e753bb27739 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 30 Jan 2023 15:06:55 +0800 Subject: [PATCH 52/70] add loaders for fbx import and max scene import --- .../hosts/max/plugins/load/load_camera_fbx.py | 48 +++++++++++++++++ .../hosts/max/plugins/load/load_max_scene.py | 51 +++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 openpype/hosts/max/plugins/load/load_camera_fbx.py create mode 100644 openpype/hosts/max/plugins/load/load_max_scene.py diff --git a/openpype/hosts/max/plugins/load/load_camera_fbx.py b/openpype/hosts/max/plugins/load/load_camera_fbx.py new file mode 100644 index 0000000000..e7b12ea4c8 --- /dev/null +++ b/openpype/hosts/max/plugins/load/load_camera_fbx.py @@ -0,0 +1,48 @@ +import os +from openpype.pipeline import( + load +) + +class FbxLoader(load.LoaderPlugin): + """Fbx Loader""" + + families = ["camera"] + representations = ["fbx"] + 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) + + fbx_import_cmd = ( + f""" + +FBXImporterSetParam "Animation" true +FBXImporterSetParam "Cameras" true +FBXImporterSetParam "AxisConversionMethod" true +FbxExporterSetParam "UpAxis" "Y" +FbxExporterSetParam "Preserveinstances" true + +importFile @"{filepath}" #noPrompt using:FBXIMP + """) + + self.log.debug(f"Executing command: {fbx_import_cmd}") + rt.execute(fbx_import_cmd) + + container_name = f"{name}_CON" + + asset = rt.getNodeByName(f"{name}") + # rename the container with "_CON" + container = rt.container(name=container_name) + asset.Parent = container + + return container + + def remove(self, container): + from pymxs import runtime as rt + + node = container["node"] + rt.delete(node) diff --git a/openpype/hosts/max/plugins/load/load_max_scene.py b/openpype/hosts/max/plugins/load/load_max_scene.py new file mode 100644 index 0000000000..54983c1e6e --- /dev/null +++ b/openpype/hosts/max/plugins/load/load_max_scene.py @@ -0,0 +1,51 @@ +import os +from openpype.pipeline import( + load +) + +class MaxSceneLoader(load.LoaderPlugin): + """Max Scene Loader""" + + families = ["camera"] + representations = ["max"] + order = -8 + icon = "code-fork" + color = "green" + + def load(self, context, name=None, namespace=None, data=None): + from pymxs import runtime as rt + import re + path = os.path.normpath(self.fname) + # import the max scene by using "merge file" + path = path.replace('\\', '/') + + merge_before = { + c for c in rt.rootNode.Children + if rt.classOf(c) == rt.Container + } + rt.mergeMaxFile(path) + + merge_after = { + c for c in rt.rootNode.Children + if rt.classOf(c) == rt.Container + } + max_containers = merge_after.difference(merge_before) + + if len(max_containers) != 1: + self.log.error("Something failed when loading.") + + max_container = max_containers.pop() + container_name = f"{name}_CON" + # rename the container with "_CON" + # get the original container + container = rt.container(name=container_name) + max_container.Parent = container + + return container + + def remove(self, container): + from pymxs import runtime as rt + + node = container["node"] + rt.delete(node) + From 92986bcff5f5428793581727355989904ab23fe1 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 30 Jan 2023 15:09:23 +0800 Subject: [PATCH 53/70] hound fix --- openpype/hosts/max/plugins/load/load_camera_fbx.py | 3 ++- openpype/hosts/max/plugins/load/load_max_scene.py | 5 ++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/max/plugins/load/load_camera_fbx.py b/openpype/hosts/max/plugins/load/load_camera_fbx.py index e7b12ea4c8..1b1df364c1 100644 --- a/openpype/hosts/max/plugins/load/load_camera_fbx.py +++ b/openpype/hosts/max/plugins/load/load_camera_fbx.py @@ -1,8 +1,9 @@ import os -from openpype.pipeline import( +from openpype.pipeline import ( load ) + class FbxLoader(load.LoaderPlugin): """Fbx Loader""" diff --git a/openpype/hosts/max/plugins/load/load_max_scene.py b/openpype/hosts/max/plugins/load/load_max_scene.py index 54983c1e6e..57f172cf6a 100644 --- a/openpype/hosts/max/plugins/load/load_max_scene.py +++ b/openpype/hosts/max/plugins/load/load_max_scene.py @@ -1,8 +1,9 @@ import os -from openpype.pipeline import( +from openpype.pipeline import ( load ) + class MaxSceneLoader(load.LoaderPlugin): """Max Scene Loader""" @@ -14,7 +15,6 @@ class MaxSceneLoader(load.LoaderPlugin): def load(self, context, name=None, namespace=None, data=None): from pymxs import runtime as rt - import re path = os.path.normpath(self.fname) # import the max scene by using "merge file" path = path.replace('\\', '/') @@ -48,4 +48,3 @@ class MaxSceneLoader(load.LoaderPlugin): node = container["node"] rt.delete(node) - From 46996bb592bcfe054f19b979f94267cb026d9826 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 30 Jan 2023 18:51:03 +0800 Subject: [PATCH 54/70] add camera family in abc loader --- openpype/hosts/max/plugins/load/load_pointcache.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/max/plugins/load/load_pointcache.py b/openpype/hosts/max/plugins/load/load_pointcache.py index a2e567ed5d..65d0662faa 100644 --- a/openpype/hosts/max/plugins/load/load_pointcache.py +++ b/openpype/hosts/max/plugins/load/load_pointcache.py @@ -15,7 +15,10 @@ from openpype.hosts.max.api import lib class AbcLoader(load.LoaderPlugin): """Alembic loader.""" - families = ["model", "animation", "pointcache"] + families = ["model", + "camera", + "animation", + "pointcache"] label = "Load Alembic" representations = ["abc"] order = -10 From 0d527a477bfa3f6d66a4745b5424534bc575ecbd Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Mon, 30 Jan 2023 12:07:24 +0100 Subject: [PATCH 55/70] fix super call --- openpype/lib/attribute_definitions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/lib/attribute_definitions.py b/openpype/lib/attribute_definitions.py index a2fe8314b2..b5cd15f41a 100644 --- a/openpype/lib/attribute_definitions.py +++ b/openpype/lib/attribute_definitions.py @@ -465,7 +465,7 @@ class EnumDef(AbstractAttrDef): return self.default def serialize(self): - data = super(TextDef, self).serialize() + data = super(EnumDef, self).serialize() data["items"] = copy.deepcopy(self.items) return data From b8c7f067c31d7dd1c7a18de65072e4fbdb1375a1 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 31 Jan 2023 07:56:20 +0100 Subject: [PATCH 56/70] global: host settings should be optional --- openpype/pipeline/colorspace.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/openpype/pipeline/colorspace.py b/openpype/pipeline/colorspace.py index e1ffe9d333..a13e6df811 100644 --- a/openpype/pipeline/colorspace.py +++ b/openpype/pipeline/colorspace.py @@ -438,7 +438,8 @@ def get_imageio_file_rules(project_name, host_name, project_settings=None): # get file rules from global and host_name frules_global = imageio_global["file_rules"] - frules_host = imageio_host["file_rules"] + # host is optional, some might not have any settings + frules_host = imageio_host.get("file_rules", {}) # compile file rules dictionary file_rules = {} @@ -455,7 +456,7 @@ def _get_imageio_settings(project_settings, host_name): Args: project_settings (dict): project settings. - Defaults to None. + Defaults to None. host_name (str): host name Returns: @@ -463,6 +464,7 @@ def _get_imageio_settings(project_settings, host_name): """ # get image io from global and host_name imageio_global = project_settings["global"]["imageio"] - imageio_host = project_settings[host_name]["imageio"] + # host is optional, some might not have any settings + imageio_host = project_settings[host_name].get("imageio", {}) return imageio_global, imageio_host From 25b7d69aabbb90dbbc328f98efafc64668dbe8e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Je=C5=BEek?= Date: Tue, 31 Jan 2023 11:58:38 +0100 Subject: [PATCH 57/70] Update openpype/pipeline/colorspace.py Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- openpype/pipeline/colorspace.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/pipeline/colorspace.py b/openpype/pipeline/colorspace.py index a13e6df811..15d545c49f 100644 --- a/openpype/pipeline/colorspace.py +++ b/openpype/pipeline/colorspace.py @@ -465,6 +465,6 @@ def _get_imageio_settings(project_settings, host_name): # get image io from global and host_name imageio_global = project_settings["global"]["imageio"] # host is optional, some might not have any settings - imageio_host = project_settings[host_name].get("imageio", {}) + imageio_host = project_settings.get(host_name, {}).get("imageio", {}) return imageio_global, imageio_host From 06863de23e512bdd0aac5787376c4b4724308dcf Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 31 Jan 2023 12:01:43 +0100 Subject: [PATCH 58/70] PR comments --- openpype/pipeline/colorspace.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/pipeline/colorspace.py b/openpype/pipeline/colorspace.py index 15d545c49f..14daa44db8 100644 --- a/openpype/pipeline/colorspace.py +++ b/openpype/pipeline/colorspace.py @@ -445,7 +445,7 @@ def get_imageio_file_rules(project_name, host_name, project_settings=None): file_rules = {} if frules_global["enabled"]: file_rules.update(frules_global["rules"]) - if frules_host["enabled"]: + if frules_host.get("enabled"): file_rules.update(frules_host["rules"]) return file_rules From 153783c2fd290006e3ba5abda2cbf430137bee28 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 31 Jan 2023 12:17:52 +0100 Subject: [PATCH 59/70] Refactor `self.` to `cls.` --- .../hosts/maya/plugins/publish/validate_attributes.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_attributes.py b/openpype/hosts/maya/plugins/publish/validate_attributes.py index 136c38bc1d..7a1f0cf086 100644 --- a/openpype/hosts/maya/plugins/publish/validate_attributes.py +++ b/openpype/hosts/maya/plugins/publish/validate_attributes.py @@ -58,23 +58,23 @@ class ValidateAttributes(pyblish.api.ContextPlugin): # Filter families. families = [instance.data["family"]] families += instance.data.get("families", []) - families = list(set(families) & set(self.attributes.keys())) + families = list(set(families) & set(cls.attributes.keys())) if not families: continue # Get all attributes to validate. attributes = {} for family in families: - for preset in self.attributes[family]: + for preset in cls.attributes[family]: [node_name, attribute_name] = preset.split(".") try: attributes[node_name].update( - {attribute_name: self.attributes[family][preset]} + {attribute_name: cls.attributes[family][preset]} ) except KeyError: attributes.update({ node_name: { - attribute_name: self.attributes[family][preset] + attribute_name: cls.attributes[family][preset] } }) From fe688bd2437304f95e729c5672e83b6e31b37c48 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 31 Jan 2023 12:34:33 +0100 Subject: [PATCH 60/70] Remove unused `version` attribute --- openpype/hosts/maya/plugins/publish/collect_maya_workspace.py | 1 - .../hosts/maya/plugins/publish/validate_mesh_lamina_faces.py | 1 - .../hosts/maya/plugins/publish/validate_mesh_non_zero_edge.py | 1 - .../hosts/maya/plugins/publish/validate_mesh_normals_unlocked.py | 1 - .../hosts/maya/plugins/publish/validate_mesh_single_uv_set.py | 1 - .../hosts/maya/plugins/publish/validate_no_default_camera.py | 1 - openpype/hosts/maya/plugins/publish/validate_no_namespace.py | 1 - .../hosts/maya/plugins/publish/validate_no_null_transforms.py | 1 - .../hosts/maya/plugins/publish/validate_rig_joints_hidden.py | 1 - .../hosts/maya/plugins/publish/validate_scene_set_workspace.py | 1 - .../hosts/maya/plugins/publish/validate_shape_default_names.py | 1 - .../maya/plugins/publish/validate_transform_naming_suffix.py | 1 - openpype/hosts/maya/plugins/publish/validate_transform_zero.py | 1 - 13 files changed, 13 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/collect_maya_workspace.py b/openpype/hosts/maya/plugins/publish/collect_maya_workspace.py index 1250ea438f..122fabe8a1 100644 --- a/openpype/hosts/maya/plugins/publish/collect_maya_workspace.py +++ b/openpype/hosts/maya/plugins/publish/collect_maya_workspace.py @@ -12,7 +12,6 @@ class CollectMayaWorkspace(pyblish.api.ContextPlugin): label = "Maya Workspace" hosts = ['maya'] - version = (0, 1, 0) def process(self, context): workspace = cmds.workspace(rootDirectory=True, query=True) diff --git a/openpype/hosts/maya/plugins/publish/validate_mesh_lamina_faces.py b/openpype/hosts/maya/plugins/publish/validate_mesh_lamina_faces.py index 4427c6eece..8cd33aa1be 100644 --- a/openpype/hosts/maya/plugins/publish/validate_mesh_lamina_faces.py +++ b/openpype/hosts/maya/plugins/publish/validate_mesh_lamina_faces.py @@ -16,7 +16,6 @@ class ValidateMeshLaminaFaces(pyblish.api.InstancePlugin): hosts = ['maya'] families = ['model'] category = 'geometry' - version = (0, 1, 0) label = 'Mesh Lamina Faces' actions = [openpype.hosts.maya.api.action.SelectInvalidAction] diff --git a/openpype/hosts/maya/plugins/publish/validate_mesh_non_zero_edge.py b/openpype/hosts/maya/plugins/publish/validate_mesh_non_zero_edge.py index 0ef2716559..fc6da82338 100644 --- a/openpype/hosts/maya/plugins/publish/validate_mesh_non_zero_edge.py +++ b/openpype/hosts/maya/plugins/publish/validate_mesh_non_zero_edge.py @@ -20,7 +20,6 @@ class ValidateMeshNonZeroEdgeLength(pyblish.api.InstancePlugin): families = ['model'] hosts = ['maya'] category = 'geometry' - version = (0, 1, 0) label = 'Mesh Edge Length Non Zero' actions = [openpype.hosts.maya.api.action.SelectInvalidAction] optional = True diff --git a/openpype/hosts/maya/plugins/publish/validate_mesh_normals_unlocked.py b/openpype/hosts/maya/plugins/publish/validate_mesh_normals_unlocked.py index c8892a8e59..2079c159c2 100644 --- a/openpype/hosts/maya/plugins/publish/validate_mesh_normals_unlocked.py +++ b/openpype/hosts/maya/plugins/publish/validate_mesh_normals_unlocked.py @@ -21,7 +21,6 @@ class ValidateMeshNormalsUnlocked(pyblish.api.Validator): hosts = ['maya'] families = ['model'] category = 'geometry' - version = (0, 1, 0) label = 'Mesh Normals Unlocked' actions = [openpype.hosts.maya.api.action.SelectInvalidAction, RepairAction] diff --git a/openpype/hosts/maya/plugins/publish/validate_mesh_single_uv_set.py b/openpype/hosts/maya/plugins/publish/validate_mesh_single_uv_set.py index 6ca8c06ba5..155ab23294 100644 --- a/openpype/hosts/maya/plugins/publish/validate_mesh_single_uv_set.py +++ b/openpype/hosts/maya/plugins/publish/validate_mesh_single_uv_set.py @@ -23,7 +23,6 @@ class ValidateMeshSingleUVSet(pyblish.api.InstancePlugin): families = ['model', 'pointcache'] category = 'uv' optional = True - version = (0, 1, 0) label = "Mesh Single UV Set" actions = [openpype.hosts.maya.api.action.SelectInvalidAction, RepairAction] diff --git a/openpype/hosts/maya/plugins/publish/validate_no_default_camera.py b/openpype/hosts/maya/plugins/publish/validate_no_default_camera.py index 1a5773e6a7..a4fb938d43 100644 --- a/openpype/hosts/maya/plugins/publish/validate_no_default_camera.py +++ b/openpype/hosts/maya/plugins/publish/validate_no_default_camera.py @@ -16,7 +16,6 @@ class ValidateNoDefaultCameras(pyblish.api.InstancePlugin): order = ValidateContentsOrder hosts = ['maya'] families = ['camera'] - version = (0, 1, 0) label = "No Default Cameras" actions = [openpype.hosts.maya.api.action.SelectInvalidAction] diff --git a/openpype/hosts/maya/plugins/publish/validate_no_namespace.py b/openpype/hosts/maya/plugins/publish/validate_no_namespace.py index 01c77e5b2e..61b531aa0f 100644 --- a/openpype/hosts/maya/plugins/publish/validate_no_namespace.py +++ b/openpype/hosts/maya/plugins/publish/validate_no_namespace.py @@ -24,7 +24,6 @@ class ValidateNoNamespace(pyblish.api.InstancePlugin): hosts = ['maya'] families = ['model'] category = 'cleanup' - version = (0, 1, 0) label = 'No Namespaces' actions = [openpype.hosts.maya.api.action.SelectInvalidAction, RepairAction] diff --git a/openpype/hosts/maya/plugins/publish/validate_no_null_transforms.py b/openpype/hosts/maya/plugins/publish/validate_no_null_transforms.py index b430c2b63c..291fe6890a 100644 --- a/openpype/hosts/maya/plugins/publish/validate_no_null_transforms.py +++ b/openpype/hosts/maya/plugins/publish/validate_no_null_transforms.py @@ -44,7 +44,6 @@ class ValidateNoNullTransforms(pyblish.api.InstancePlugin): hosts = ['maya'] families = ['model'] category = 'cleanup' - version = (0, 1, 0) label = 'No Empty/Null Transforms' actions = [RepairAction, openpype.hosts.maya.api.action.SelectInvalidAction] diff --git a/openpype/hosts/maya/plugins/publish/validate_rig_joints_hidden.py b/openpype/hosts/maya/plugins/publish/validate_rig_joints_hidden.py index d5bf7fd1cf..30d95128a2 100644 --- a/openpype/hosts/maya/plugins/publish/validate_rig_joints_hidden.py +++ b/openpype/hosts/maya/plugins/publish/validate_rig_joints_hidden.py @@ -24,7 +24,6 @@ class ValidateRigJointsHidden(pyblish.api.InstancePlugin): order = ValidateContentsOrder hosts = ['maya'] families = ['rig'] - version = (0, 1, 0) label = "Joints Hidden" actions = [openpype.hosts.maya.api.action.SelectInvalidAction, RepairAction] diff --git a/openpype/hosts/maya/plugins/publish/validate_scene_set_workspace.py b/openpype/hosts/maya/plugins/publish/validate_scene_set_workspace.py index ec2bea220d..91f30f2f4f 100644 --- a/openpype/hosts/maya/plugins/publish/validate_scene_set_workspace.py +++ b/openpype/hosts/maya/plugins/publish/validate_scene_set_workspace.py @@ -32,7 +32,6 @@ class ValidateSceneSetWorkspace(pyblish.api.ContextPlugin): order = ValidatePipelineOrder hosts = ['maya'] category = 'scene' - version = (0, 1, 0) label = 'Maya Workspace Set' def process(self, context): diff --git a/openpype/hosts/maya/plugins/publish/validate_shape_default_names.py b/openpype/hosts/maya/plugins/publish/validate_shape_default_names.py index 651c6bcec9..6b3375ae7e 100644 --- a/openpype/hosts/maya/plugins/publish/validate_shape_default_names.py +++ b/openpype/hosts/maya/plugins/publish/validate_shape_default_names.py @@ -40,7 +40,6 @@ class ValidateShapeDefaultNames(pyblish.api.InstancePlugin): families = ['model'] category = 'cleanup' optional = True - version = (0, 1, 0) label = "Shape Default Naming" actions = [openpype.hosts.maya.api.action.SelectInvalidAction, RepairAction] diff --git a/openpype/hosts/maya/plugins/publish/validate_transform_naming_suffix.py b/openpype/hosts/maya/plugins/publish/validate_transform_naming_suffix.py index 65551c8d5e..2bb8bca3e1 100644 --- a/openpype/hosts/maya/plugins/publish/validate_transform_naming_suffix.py +++ b/openpype/hosts/maya/plugins/publish/validate_transform_naming_suffix.py @@ -34,7 +34,6 @@ class ValidateTransformNamingSuffix(pyblish.api.InstancePlugin): families = ['model'] category = 'cleanup' optional = True - version = (0, 1, 0) label = 'Suffix Naming Conventions' actions = [openpype.hosts.maya.api.action.SelectInvalidAction] SUFFIX_NAMING_TABLE = {"mesh": ["_GEO", "_GES", "_GEP", "_OSD"], diff --git a/openpype/hosts/maya/plugins/publish/validate_transform_zero.py b/openpype/hosts/maya/plugins/publish/validate_transform_zero.py index da569195e8..034d325091 100644 --- a/openpype/hosts/maya/plugins/publish/validate_transform_zero.py +++ b/openpype/hosts/maya/plugins/publish/validate_transform_zero.py @@ -19,7 +19,6 @@ class ValidateTransformZero(pyblish.api.Validator): hosts = ["maya"] families = ["model"] category = "geometry" - version = (0, 1, 0) label = "Transform Zero (Freeze)" actions = [openpype.hosts.maya.api.action.SelectInvalidAction] From 7d81f1906c371e35c153c1fd78ab9cc491f0fee4 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 31 Jan 2023 12:35:33 +0100 Subject: [PATCH 61/70] Remove unused `category` attribute --- openpype/hosts/maya/plugins/publish/validate_color_sets.py | 1 - .../maya/plugins/publish/validate_mesh_arnold_attributes.py | 1 - openpype/hosts/maya/plugins/publish/validate_mesh_has_uv.py | 1 - .../hosts/maya/plugins/publish/validate_mesh_lamina_faces.py | 1 - .../hosts/maya/plugins/publish/validate_mesh_non_zero_edge.py | 1 - .../hosts/maya/plugins/publish/validate_mesh_normals_unlocked.py | 1 - .../hosts/maya/plugins/publish/validate_mesh_overlapping_uvs.py | 1 - .../hosts/maya/plugins/publish/validate_mesh_single_uv_set.py | 1 - .../maya/plugins/publish/validate_mesh_vertices_have_edges.py | 1 - openpype/hosts/maya/plugins/publish/validate_no_namespace.py | 1 - .../hosts/maya/plugins/publish/validate_no_null_transforms.py | 1 - .../hosts/maya/plugins/publish/validate_scene_set_workspace.py | 1 - .../hosts/maya/plugins/publish/validate_shape_default_names.py | 1 - .../maya/plugins/publish/validate_transform_naming_suffix.py | 1 - openpype/hosts/maya/plugins/publish/validate_transform_zero.py | 1 - .../maya/plugins/publish/validate_unreal_mesh_triangulated.py | 1 - 16 files changed, 16 deletions(-) diff --git a/openpype/hosts/maya/plugins/publish/validate_color_sets.py b/openpype/hosts/maya/plugins/publish/validate_color_sets.py index 905417bafa..7ce3cca61a 100644 --- a/openpype/hosts/maya/plugins/publish/validate_color_sets.py +++ b/openpype/hosts/maya/plugins/publish/validate_color_sets.py @@ -19,7 +19,6 @@ class ValidateColorSets(pyblish.api.Validator): order = ValidateMeshOrder hosts = ['maya'] families = ['model'] - category = 'geometry' label = 'Mesh ColorSets' actions = [openpype.hosts.maya.api.action.SelectInvalidAction, RepairAction] diff --git a/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py b/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py index c1c0636b9e..fa4c66952c 100644 --- a/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py +++ b/openpype/hosts/maya/plugins/publish/validate_mesh_arnold_attributes.py @@ -19,7 +19,6 @@ class ValidateMeshArnoldAttributes(pyblish.api.InstancePlugin): order = ValidateMeshOrder hosts = ["maya"] families = ["model"] - category = "geometry" label = "Mesh Arnold Attributes" actions = [ openpype.hosts.maya.api.action.SelectInvalidAction, diff --git a/openpype/hosts/maya/plugins/publish/validate_mesh_has_uv.py b/openpype/hosts/maya/plugins/publish/validate_mesh_has_uv.py index 36a0da7a59..0eece1014e 100644 --- a/openpype/hosts/maya/plugins/publish/validate_mesh_has_uv.py +++ b/openpype/hosts/maya/plugins/publish/validate_mesh_has_uv.py @@ -48,7 +48,6 @@ class ValidateMeshHasUVs(pyblish.api.InstancePlugin): order = ValidateMeshOrder hosts = ['maya'] families = ['model'] - category = 'geometry' label = 'Mesh Has UVs' actions = [openpype.hosts.maya.api.action.SelectInvalidAction] optional = True diff --git a/openpype/hosts/maya/plugins/publish/validate_mesh_lamina_faces.py b/openpype/hosts/maya/plugins/publish/validate_mesh_lamina_faces.py index 8cd33aa1be..f120361583 100644 --- a/openpype/hosts/maya/plugins/publish/validate_mesh_lamina_faces.py +++ b/openpype/hosts/maya/plugins/publish/validate_mesh_lamina_faces.py @@ -15,7 +15,6 @@ class ValidateMeshLaminaFaces(pyblish.api.InstancePlugin): order = ValidateMeshOrder hosts = ['maya'] families = ['model'] - category = 'geometry' label = 'Mesh Lamina Faces' actions = [openpype.hosts.maya.api.action.SelectInvalidAction] diff --git a/openpype/hosts/maya/plugins/publish/validate_mesh_non_zero_edge.py b/openpype/hosts/maya/plugins/publish/validate_mesh_non_zero_edge.py index fc6da82338..78e844d201 100644 --- a/openpype/hosts/maya/plugins/publish/validate_mesh_non_zero_edge.py +++ b/openpype/hosts/maya/plugins/publish/validate_mesh_non_zero_edge.py @@ -19,7 +19,6 @@ class ValidateMeshNonZeroEdgeLength(pyblish.api.InstancePlugin): order = ValidateMeshOrder families = ['model'] hosts = ['maya'] - category = 'geometry' label = 'Mesh Edge Length Non Zero' actions = [openpype.hosts.maya.api.action.SelectInvalidAction] optional = True diff --git a/openpype/hosts/maya/plugins/publish/validate_mesh_normals_unlocked.py b/openpype/hosts/maya/plugins/publish/validate_mesh_normals_unlocked.py index 2079c159c2..1b754a9829 100644 --- a/openpype/hosts/maya/plugins/publish/validate_mesh_normals_unlocked.py +++ b/openpype/hosts/maya/plugins/publish/validate_mesh_normals_unlocked.py @@ -20,7 +20,6 @@ class ValidateMeshNormalsUnlocked(pyblish.api.Validator): order = ValidateMeshOrder hosts = ['maya'] families = ['model'] - category = 'geometry' label = 'Mesh Normals Unlocked' actions = [openpype.hosts.maya.api.action.SelectInvalidAction, RepairAction] diff --git a/openpype/hosts/maya/plugins/publish/validate_mesh_overlapping_uvs.py b/openpype/hosts/maya/plugins/publish/validate_mesh_overlapping_uvs.py index be7324a68f..be23f61ec5 100644 --- a/openpype/hosts/maya/plugins/publish/validate_mesh_overlapping_uvs.py +++ b/openpype/hosts/maya/plugins/publish/validate_mesh_overlapping_uvs.py @@ -235,7 +235,6 @@ class ValidateMeshHasOverlappingUVs(pyblish.api.InstancePlugin): order = ValidateMeshOrder hosts = ['maya'] families = ['model'] - category = 'geometry' label = 'Mesh Has Overlapping UVs' actions = [openpype.hosts.maya.api.action.SelectInvalidAction] optional = True diff --git a/openpype/hosts/maya/plugins/publish/validate_mesh_single_uv_set.py b/openpype/hosts/maya/plugins/publish/validate_mesh_single_uv_set.py index 155ab23294..faa360380e 100644 --- a/openpype/hosts/maya/plugins/publish/validate_mesh_single_uv_set.py +++ b/openpype/hosts/maya/plugins/publish/validate_mesh_single_uv_set.py @@ -21,7 +21,6 @@ class ValidateMeshSingleUVSet(pyblish.api.InstancePlugin): order = ValidateMeshOrder hosts = ['maya'] families = ['model', 'pointcache'] - category = 'uv' optional = True label = "Mesh Single UV Set" actions = [openpype.hosts.maya.api.action.SelectInvalidAction, diff --git a/openpype/hosts/maya/plugins/publish/validate_mesh_vertices_have_edges.py b/openpype/hosts/maya/plugins/publish/validate_mesh_vertices_have_edges.py index 1e6d290ae7..9ac7735501 100644 --- a/openpype/hosts/maya/plugins/publish/validate_mesh_vertices_have_edges.py +++ b/openpype/hosts/maya/plugins/publish/validate_mesh_vertices_have_edges.py @@ -63,7 +63,6 @@ class ValidateMeshVerticesHaveEdges(pyblish.api.InstancePlugin): order = ValidateMeshOrder hosts = ['maya'] families = ['model'] - category = 'geometry' label = 'Mesh Vertices Have Edges' actions = [openpype.hosts.maya.api.action.SelectInvalidAction, RepairAction] diff --git a/openpype/hosts/maya/plugins/publish/validate_no_namespace.py b/openpype/hosts/maya/plugins/publish/validate_no_namespace.py index 61b531aa0f..e91b99359d 100644 --- a/openpype/hosts/maya/plugins/publish/validate_no_namespace.py +++ b/openpype/hosts/maya/plugins/publish/validate_no_namespace.py @@ -23,7 +23,6 @@ class ValidateNoNamespace(pyblish.api.InstancePlugin): order = ValidateContentsOrder hosts = ['maya'] families = ['model'] - category = 'cleanup' label = 'No Namespaces' actions = [openpype.hosts.maya.api.action.SelectInvalidAction, RepairAction] diff --git a/openpype/hosts/maya/plugins/publish/validate_no_null_transforms.py b/openpype/hosts/maya/plugins/publish/validate_no_null_transforms.py index 291fe6890a..f77fc81dc1 100644 --- a/openpype/hosts/maya/plugins/publish/validate_no_null_transforms.py +++ b/openpype/hosts/maya/plugins/publish/validate_no_null_transforms.py @@ -43,7 +43,6 @@ class ValidateNoNullTransforms(pyblish.api.InstancePlugin): order = ValidateContentsOrder hosts = ['maya'] families = ['model'] - category = 'cleanup' label = 'No Empty/Null Transforms' actions = [RepairAction, openpype.hosts.maya.api.action.SelectInvalidAction] diff --git a/openpype/hosts/maya/plugins/publish/validate_scene_set_workspace.py b/openpype/hosts/maya/plugins/publish/validate_scene_set_workspace.py index 91f30f2f4f..f1fa4d3c4c 100644 --- a/openpype/hosts/maya/plugins/publish/validate_scene_set_workspace.py +++ b/openpype/hosts/maya/plugins/publish/validate_scene_set_workspace.py @@ -31,7 +31,6 @@ class ValidateSceneSetWorkspace(pyblish.api.ContextPlugin): order = ValidatePipelineOrder hosts = ['maya'] - category = 'scene' label = 'Maya Workspace Set' def process(self, context): diff --git a/openpype/hosts/maya/plugins/publish/validate_shape_default_names.py b/openpype/hosts/maya/plugins/publish/validate_shape_default_names.py index 6b3375ae7e..4ab669f46b 100644 --- a/openpype/hosts/maya/plugins/publish/validate_shape_default_names.py +++ b/openpype/hosts/maya/plugins/publish/validate_shape_default_names.py @@ -38,7 +38,6 @@ class ValidateShapeDefaultNames(pyblish.api.InstancePlugin): order = ValidateContentsOrder hosts = ['maya'] families = ['model'] - category = 'cleanup' optional = True label = "Shape Default Naming" actions = [openpype.hosts.maya.api.action.SelectInvalidAction, diff --git a/openpype/hosts/maya/plugins/publish/validate_transform_naming_suffix.py b/openpype/hosts/maya/plugins/publish/validate_transform_naming_suffix.py index 2bb8bca3e1..0147aa8a52 100644 --- a/openpype/hosts/maya/plugins/publish/validate_transform_naming_suffix.py +++ b/openpype/hosts/maya/plugins/publish/validate_transform_naming_suffix.py @@ -32,7 +32,6 @@ class ValidateTransformNamingSuffix(pyblish.api.InstancePlugin): order = ValidateContentsOrder hosts = ['maya'] families = ['model'] - category = 'cleanup' optional = True label = 'Suffix Naming Conventions' actions = [openpype.hosts.maya.api.action.SelectInvalidAction] diff --git a/openpype/hosts/maya/plugins/publish/validate_transform_zero.py b/openpype/hosts/maya/plugins/publish/validate_transform_zero.py index 034d325091..abd9e00af1 100644 --- a/openpype/hosts/maya/plugins/publish/validate_transform_zero.py +++ b/openpype/hosts/maya/plugins/publish/validate_transform_zero.py @@ -18,7 +18,6 @@ class ValidateTransformZero(pyblish.api.Validator): order = ValidateContentsOrder hosts = ["maya"] families = ["model"] - category = "geometry" label = "Transform Zero (Freeze)" actions = [openpype.hosts.maya.api.action.SelectInvalidAction] diff --git a/openpype/hosts/maya/plugins/publish/validate_unreal_mesh_triangulated.py b/openpype/hosts/maya/plugins/publish/validate_unreal_mesh_triangulated.py index 4211e76a73..e78962bf97 100644 --- a/openpype/hosts/maya/plugins/publish/validate_unreal_mesh_triangulated.py +++ b/openpype/hosts/maya/plugins/publish/validate_unreal_mesh_triangulated.py @@ -13,7 +13,6 @@ class ValidateUnrealMeshTriangulated(pyblish.api.InstancePlugin): order = ValidateMeshOrder hosts = ["maya"] families = ["staticMesh"] - category = "geometry" label = "Mesh is Triangulated" actions = [openpype.hosts.maya.api.action.SelectInvalidAction] active = False From ca6d6f7ccafa7b85d72f573c4a4519a326d60b54 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 31 Jan 2023 12:36:22 +0100 Subject: [PATCH 62/70] Remove unused `category` attribute from blender plug-ins too --- openpype/hosts/blender/plugins/publish/validate_mesh_has_uv.py | 1 - .../blender/plugins/publish/validate_mesh_no_negative_scale.py | 1 - 2 files changed, 2 deletions(-) diff --git a/openpype/hosts/blender/plugins/publish/validate_mesh_has_uv.py b/openpype/hosts/blender/plugins/publish/validate_mesh_has_uv.py index cee855671d..edf47193be 100644 --- a/openpype/hosts/blender/plugins/publish/validate_mesh_has_uv.py +++ b/openpype/hosts/blender/plugins/publish/validate_mesh_has_uv.py @@ -14,7 +14,6 @@ class ValidateMeshHasUvs(pyblish.api.InstancePlugin): order = ValidateContentsOrder hosts = ["blender"] families = ["model"] - category = "geometry" label = "Mesh Has UV's" actions = [openpype.hosts.blender.api.action.SelectInvalidAction] optional = True diff --git a/openpype/hosts/blender/plugins/publish/validate_mesh_no_negative_scale.py b/openpype/hosts/blender/plugins/publish/validate_mesh_no_negative_scale.py index 45ac08811d..618feb95c1 100644 --- a/openpype/hosts/blender/plugins/publish/validate_mesh_no_negative_scale.py +++ b/openpype/hosts/blender/plugins/publish/validate_mesh_no_negative_scale.py @@ -14,7 +14,6 @@ class ValidateMeshNoNegativeScale(pyblish.api.Validator): order = ValidateContentsOrder hosts = ["blender"] families = ["model"] - category = "geometry" label = "Mesh No Negative Scale" actions = [openpype.hosts.blender.api.action.SelectInvalidAction] From 529ab6ca9bf0de6656fa11ba5f4e38af4b048049 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Tue, 31 Jan 2023 12:37:28 +0100 Subject: [PATCH 63/70] Remove unused `version` attribute from blender plug-ins too --- .../blender/plugins/publish/validate_camera_zero_keyframe.py | 1 - .../hosts/blender/plugins/publish/validate_no_colons_in_name.py | 1 - .../hosts/blender/plugins/publish/validate_transform_zero.py | 1 - 3 files changed, 3 deletions(-) diff --git a/openpype/hosts/blender/plugins/publish/validate_camera_zero_keyframe.py b/openpype/hosts/blender/plugins/publish/validate_camera_zero_keyframe.py index 84b9dd1a6e..48c267fd18 100644 --- a/openpype/hosts/blender/plugins/publish/validate_camera_zero_keyframe.py +++ b/openpype/hosts/blender/plugins/publish/validate_camera_zero_keyframe.py @@ -19,7 +19,6 @@ class ValidateCameraZeroKeyframe(pyblish.api.InstancePlugin): order = ValidateContentsOrder hosts = ["blender"] families = ["camera"] - version = (0, 1, 0) label = "Zero Keyframe" actions = [openpype.hosts.blender.api.action.SelectInvalidAction] diff --git a/openpype/hosts/blender/plugins/publish/validate_no_colons_in_name.py b/openpype/hosts/blender/plugins/publish/validate_no_colons_in_name.py index f5dc9fdd5c..1a98ec4c1d 100644 --- a/openpype/hosts/blender/plugins/publish/validate_no_colons_in_name.py +++ b/openpype/hosts/blender/plugins/publish/validate_no_colons_in_name.py @@ -19,7 +19,6 @@ class ValidateNoColonsInName(pyblish.api.InstancePlugin): order = ValidateContentsOrder hosts = ["blender"] families = ["model", "rig"] - version = (0, 1, 0) label = "No Colons in names" actions = [openpype.hosts.blender.api.action.SelectInvalidAction] diff --git a/openpype/hosts/blender/plugins/publish/validate_transform_zero.py b/openpype/hosts/blender/plugins/publish/validate_transform_zero.py index 742826d3d9..66ef731e6e 100644 --- a/openpype/hosts/blender/plugins/publish/validate_transform_zero.py +++ b/openpype/hosts/blender/plugins/publish/validate_transform_zero.py @@ -21,7 +21,6 @@ class ValidateTransformZero(pyblish.api.InstancePlugin): order = ValidateContentsOrder hosts = ["blender"] families = ["model"] - version = (0, 1, 0) label = "Transform Zero" actions = [openpype.hosts.blender.api.action.SelectInvalidAction] From 148c55361f13508fce1c2e9c82b7719be7b8a4a6 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 31 Jan 2023 18:06:44 +0100 Subject: [PATCH 64/70] OP-4850 - fix AE tests 'png' extension have 2 representations instead 1. (One is regular, one is from review, with name 'png_png' --- .../aftereffects/test_deadline_publish_in_aftereffects.py | 4 ++-- .../test_deadline_publish_in_aftereffects_multicomposition.py | 2 +- .../hosts/aftereffects/test_publish_in_aftereffects.py | 4 ++-- .../aftereffects/test_publish_in_aftereffects_multiframe.py | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/integration/hosts/aftereffects/test_deadline_publish_in_aftereffects.py b/tests/integration/hosts/aftereffects/test_deadline_publish_in_aftereffects.py index 04fe6cb9aa..30761693a8 100644 --- a/tests/integration/hosts/aftereffects/test_deadline_publish_in_aftereffects.py +++ b/tests/integration/hosts/aftereffects/test_deadline_publish_in_aftereffects.py @@ -62,7 +62,7 @@ class TestDeadlinePublishInAfterEffects(AEDeadlinePublishTestClass): failures.append( DBAssert.count_of_types(dbcon, "representation", 4)) - additional_args = {"context.subset": "renderTest_taskMain", + additional_args = {"context.subset": "workfileTest_task", "context.ext": "aep"} failures.append( DBAssert.count_of_types(dbcon, "representation", 1, @@ -71,7 +71,7 @@ class TestDeadlinePublishInAfterEffects(AEDeadlinePublishTestClass): additional_args = {"context.subset": "renderTest_taskMain", "context.ext": "png"} failures.append( - DBAssert.count_of_types(dbcon, "representation", 1, + DBAssert.count_of_types(dbcon, "representation", 2, additional_args=additional_args)) additional_args = {"context.subset": "renderTest_taskMain", diff --git a/tests/integration/hosts/aftereffects/test_deadline_publish_in_aftereffects_multicomposition.py b/tests/integration/hosts/aftereffects/test_deadline_publish_in_aftereffects_multicomposition.py index f009b45f4d..4adff6a815 100644 --- a/tests/integration/hosts/aftereffects/test_deadline_publish_in_aftereffects_multicomposition.py +++ b/tests/integration/hosts/aftereffects/test_deadline_publish_in_aftereffects_multicomposition.py @@ -80,7 +80,7 @@ class TestDeadlinePublishInAfterEffectsMultiComposition(AEDeadlinePublishTestCla additional_args = {"context.subset": "renderTest_taskMain", "context.ext": "png"} failures.append( - DBAssert.count_of_types(dbcon, "representation", 1, + DBAssert.count_of_types(dbcon, "representation", 2, additional_args=additional_args)) additional_args = {"context.subset": "renderTest_taskMain", diff --git a/tests/integration/hosts/aftereffects/test_publish_in_aftereffects.py b/tests/integration/hosts/aftereffects/test_publish_in_aftereffects.py index 57d5a3e3f1..2e4f343a5a 100644 --- a/tests/integration/hosts/aftereffects/test_publish_in_aftereffects.py +++ b/tests/integration/hosts/aftereffects/test_publish_in_aftereffects.py @@ -60,7 +60,7 @@ class TestPublishInAfterEffects(AELocalPublishTestClass): failures.append( DBAssert.count_of_types(dbcon, "representation", 4)) - additional_args = {"context.subset": "renderTest_taskMain", + additional_args = {"context.subset": "workfileTest_task", "context.ext": "aep"} failures.append( DBAssert.count_of_types(dbcon, "representation", 1, @@ -69,7 +69,7 @@ class TestPublishInAfterEffects(AELocalPublishTestClass): additional_args = {"context.subset": "renderTest_taskMain", "context.ext": "png"} failures.append( - DBAssert.count_of_types(dbcon, "representation", 1, + DBAssert.count_of_types(dbcon, "representation", 2, additional_args=additional_args)) additional_args = {"context.subset": "renderTest_taskMain", diff --git a/tests/integration/hosts/aftereffects/test_publish_in_aftereffects_multiframe.py b/tests/integration/hosts/aftereffects/test_publish_in_aftereffects_multiframe.py index 2d95eada99..dcf34844d1 100644 --- a/tests/integration/hosts/aftereffects/test_publish_in_aftereffects_multiframe.py +++ b/tests/integration/hosts/aftereffects/test_publish_in_aftereffects_multiframe.py @@ -47,7 +47,7 @@ class TestPublishInAfterEffects(AELocalPublishTestClass): failures.append( DBAssert.count_of_types(dbcon, "representation", 4)) - additional_args = {"context.subset": "renderTest_taskMain", + additional_args = {"context.subset": "workfileTest_task", "context.ext": "aep"} failures.append( DBAssert.count_of_types(dbcon, "representation", 1, From 6704ba153126facf6ff3e34e2a6bfdfea96915c5 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Tue, 31 Jan 2023 18:35:36 +0100 Subject: [PATCH 65/70] OP-4850 - fix AE multicomposition 3 subsets >> 3 versions --- .../test_deadline_publish_in_aftereffects_multicomposition.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/hosts/aftereffects/test_deadline_publish_in_aftereffects_multicomposition.py b/tests/integration/hosts/aftereffects/test_deadline_publish_in_aftereffects_multicomposition.py index 4adff6a815..d372efcb9a 100644 --- a/tests/integration/hosts/aftereffects/test_deadline_publish_in_aftereffects_multicomposition.py +++ b/tests/integration/hosts/aftereffects/test_deadline_publish_in_aftereffects_multicomposition.py @@ -47,7 +47,7 @@ class TestDeadlinePublishInAfterEffectsMultiComposition(AEDeadlinePublishTestCla print("test_db_asserts") failures = [] - failures.append(DBAssert.count_of_types(dbcon, "version", 2)) + failures.append(DBAssert.count_of_types(dbcon, "version", 3)) failures.append( DBAssert.count_of_types(dbcon, "version", 0, name={"$ne": 1})) From 06086b36bc0b84e70afc8b09232961811041d212 Mon Sep 17 00:00:00 2001 From: OpenPype Date: Wed, 1 Feb 2023 03:32:20 +0000 Subject: [PATCH 66/70] [Automated] Bump version --- openpype/version.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openpype/version.py b/openpype/version.py index ab61b16a14..3941912c6e 100644 --- a/openpype/version.py +++ b/openpype/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring Pype version.""" -__version__ = "3.15.1-nightly.1" +__version__ = "3.15.1-nightly.2" diff --git a/pyproject.toml b/pyproject.toml index a872ed3609..634aeda5ac 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "OpenPype" -version = "3.15.0" # OpenPype +version = "3.15.1-nightly.2" # OpenPype description = "Open VFX and Animation pipeline with support." authors = ["OpenPype Team "] license = "MIT License" From 0fb0f74250761c4e6f1582b8ca64613caf0087a7 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Wed, 1 Feb 2023 11:23:52 +0100 Subject: [PATCH 67/70] Fix pyproject.toml version because of Poetry Automatization injects wrong format --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 634aeda5ac..2fc4f6fe39 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "OpenPype" -version = "3.15.1-nightly.2" # OpenPype +version = "3.15.1" # OpenPype description = "Open VFX and Animation pipeline with support." authors = ["OpenPype Team "] license = "MIT License" From fb56e169dc745d6b934dcd509367dee27b91b0f3 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 1 Feb 2023 12:34:21 +0100 Subject: [PATCH 68/70] check for source class instead of for function by name availability --- openpype/pipeline/context_tools.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/openpype/pipeline/context_tools.py b/openpype/pipeline/context_tools.py index 06538dd91f..6610fd7da7 100644 --- a/openpype/pipeline/context_tools.py +++ b/openpype/pipeline/context_tools.py @@ -11,6 +11,7 @@ import pyblish.api from pyblish.lib import MessageHandler import openpype +from openpype.host import HostBase from openpype.client import ( get_project, get_asset_by_id, @@ -317,7 +318,7 @@ def get_current_host_name(): """ host = registered_host() - if host is not None and hasattr(host, "name"): + if isinstance(host, HostBase): return host.name return os.environ.get("AVALON_APP") @@ -332,28 +333,28 @@ def get_global_context(): def get_current_context(): host = registered_host() - if host is not None and hasattr(host, "get_current_context"): + if isinstance(host, HostBase): return host.get_current_context() return get_global_context() def get_current_project_name(): host = registered_host() - if host is not None and hasattr(host, "get_current_project_name"): + if isinstance(host, HostBase): return host.get_current_project_name() return get_global_context()["project_name"] def get_current_asset_name(): host = registered_host() - if host is not None and hasattr(host, "get_current_asset_name"): + if isinstance(host, HostBase): return host.get_current_asset_name() return get_global_context()["asset_name"] def get_current_task_name(): host = registered_host() - if host is not None and hasattr(host, "get_current_task_name"): + if isinstance(host, HostBase): return host.get_current_task_name() return get_global_context()["task_name"] From 2313cd0507c73b5175cc5f353d74db64e016c367 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 1 Feb 2023 12:38:54 +0100 Subject: [PATCH 69/70] added context getter functions to pipeline init --- openpype/pipeline/__init__.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/openpype/pipeline/__init__.py b/openpype/pipeline/__init__.py index f5319c5a48..7a2ef59a5a 100644 --- a/openpype/pipeline/__init__.py +++ b/openpype/pipeline/__init__.py @@ -86,6 +86,12 @@ from .context_tools import ( registered_host, deregister_host, get_process_id, + + get_current_context, + get_current_host_name, + get_current_project_name, + get_current_asset_name, + get_current_task_name, ) install = install_host uninstall = uninstall_host @@ -176,6 +182,13 @@ __all__ = ( "register_host", "registered_host", "deregister_host", + "get_process_id", + + "get_current_context", + "get_current_host_name", + "get_current_project_name", + "get_current_asset_name", + "get_current_task_name", # Backwards compatible function names "install", From 1690a64216b16e6305485d80b5710c8f2f1dab70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Je=C5=BEek?= Date: Wed, 1 Feb 2023 15:21:18 +0100 Subject: [PATCH 70/70] Update openpype/pipeline/colorspace.py Co-authored-by: Roy Nieterau --- openpype/pipeline/colorspace.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/pipeline/colorspace.py b/openpype/pipeline/colorspace.py index 14daa44db8..cb37b2c4ae 100644 --- a/openpype/pipeline/colorspace.py +++ b/openpype/pipeline/colorspace.py @@ -445,7 +445,7 @@ def get_imageio_file_rules(project_name, host_name, project_settings=None): file_rules = {} if frules_global["enabled"]: file_rules.update(frules_global["rules"]) - if frules_host.get("enabled"): + if frules_host and frules_host["enabled"]: file_rules.update(frules_host["rules"]) return file_rules