Merge remote-tracking branch 'upstream/develop' into bugfix/inventory_latest_version

This commit is contained in:
Roy Nieterau 2024-03-20 09:58:19 +01:00
commit 81eed5a9eb
64 changed files with 461 additions and 167 deletions

View file

@ -39,6 +39,8 @@ class ValidateMeshHasUVs(pyblish.api.InstancePlugin,
return invalid
def process(self, instance):
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:
bullet_point_invalid_statement = "\n".join(

View file

@ -7,9 +7,9 @@ loader will use them instead of native vray vrmesh format.
"""
import os
from ayon_api import get_representation_by_name
import maya.cmds as cmds
import ayon_api
from ayon_core.settings import get_project_settings
from ayon_core.pipeline import (
load,

View file

@ -2,12 +2,14 @@ import pyblish.api
import ayon_core.hosts.maya.api.action
from ayon_core.pipeline.publish import (
PublishValidationError,
ValidateContentsOrder
ValidateContentsOrder,
OptionalPyblishPluginMixin
)
from maya import cmds
class ValidateAnimatedReferenceRig(pyblish.api.InstancePlugin):
class ValidateAnimatedReferenceRig(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Validate all nodes in skeletonAnim_SET are referenced"""
order = ValidateContentsOrder
@ -16,8 +18,11 @@ class ValidateAnimatedReferenceRig(pyblish.api.InstancePlugin):
label = "Animated Reference Rig"
accepted_controllers = ["transform", "locator"]
actions = [ayon_core.hosts.maya.api.action.SelectInvalidAction]
optional = False
def process(self, instance):
if not self.is_active(instance.data):
return
animated_sets = instance.data.get("animated_skeleton", [])
if not animated_sets:
self.log.debug(

View file

@ -2,11 +2,13 @@ import pyblish.api
import ayon_core.hosts.maya.api.action
from ayon_core.pipeline.publish import (
PublishValidationError,
ValidateContentsOrder
ValidateContentsOrder,
OptionalPyblishPluginMixin
)
class ValidateAnimationContent(pyblish.api.InstancePlugin):
class ValidateAnimationContent(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Adheres to the content of 'animation' product type
- Must have collected `out_hierarchy` data.
@ -19,6 +21,7 @@ class ValidateAnimationContent(pyblish.api.InstancePlugin):
families = ["animation"]
label = "Animation Content"
actions = [ayon_core.hosts.maya.api.action.SelectInvalidAction]
optional = False
@classmethod
def get_invalid(cls, instance):
@ -48,6 +51,8 @@ class ValidateAnimationContent(pyblish.api.InstancePlugin):
return invalid
def process(self, instance):
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:
raise PublishValidationError(

View file

@ -6,11 +6,13 @@ from ayon_core.hosts.maya.api import lib
from ayon_core.pipeline.publish import (
RepairAction,
ValidateContentsOrder,
PublishValidationError
PublishValidationError,
OptionalPyblishPluginMixin
)
class ValidateOutRelatedNodeIds(pyblish.api.InstancePlugin):
class ValidateOutRelatedNodeIds(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Validate if deformed shapes have related IDs to the original shapes
When a deformer is applied in the scene on a referenced mesh that already
@ -28,10 +30,12 @@ class ValidateOutRelatedNodeIds(pyblish.api.InstancePlugin):
ayon_core.hosts.maya.api.action.SelectInvalidAction,
RepairAction
]
optional = False
def process(self, instance):
"""Process all meshes"""
if not self.is_active(instance.data):
return
# Ensure all nodes have a cbId and a related ID to the original shapes
# if a deformer has been created on the shape
invalid = self.get_invalid(instance)

View file

@ -1,11 +1,15 @@
import pyblish.api
from ayon_core.hosts.maya.api import lib
from ayon_core.pipeline.publish import (
ValidateContentsOrder, PublishValidationError, RepairAction
ValidateContentsOrder,
PublishValidationError,
RepairAction,
OptionalPyblishPluginMixin
)
class ValidateArnoldSceneSourceCbid(pyblish.api.InstancePlugin):
class ValidateArnoldSceneSourceCbid(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Validate Arnold Scene Source Cbid.
It is required for the proxy and content nodes to share the same cbid.
@ -16,6 +20,7 @@ class ValidateArnoldSceneSourceCbid(pyblish.api.InstancePlugin):
families = ["ass"]
label = "Validate Arnold Scene Source CBID"
actions = [RepairAction]
optional = False
@staticmethod
def _get_nodes_by_name(nodes):
@ -55,6 +60,8 @@ class ValidateArnoldSceneSourceCbid(pyblish.api.InstancePlugin):
return invalid_couples
def process(self, instance):
if not self.is_active(instance.data):
return
# Proxy validation.
if not instance.data.get("proxy", []):
return

View file

@ -8,11 +8,13 @@ import pyblish.api
from ayon_core.pipeline.publish import (
RepairAction,
ValidateContentsOrder,
PublishValidationError
PublishValidationError,
OptionalPyblishPluginMixin
)
class ValidateAssRelativePaths(pyblish.api.InstancePlugin):
class ValidateAssRelativePaths(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Ensure exporting ass file has set relative texture paths"""
order = ValidateContentsOrder
@ -20,8 +22,11 @@ class ValidateAssRelativePaths(pyblish.api.InstancePlugin):
families = ['ass']
label = "ASS has relative texture paths"
actions = [RepairAction]
optional = False
def process(self, instance):
if not self.is_active(instance.data):
return
# we cannot ask this until user open render settings as
# `defaultArnoldRenderOptions` doesn't exist
errors = []

View file

@ -2,11 +2,13 @@ import pyblish.api
import maya.cmds as cmds
import ayon_core.hosts.maya.api.action
from ayon_core.pipeline.publish import (
PublishValidationError
PublishValidationError,
OptionalPyblishPluginMixin
)
class ValidateAssemblyName(pyblish.api.InstancePlugin):
class ValidateAssemblyName(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
""" Ensure Assembly name ends with `GRP`
Check if assembly name ends with `_GRP` string.
@ -17,6 +19,7 @@ class ValidateAssemblyName(pyblish.api.InstancePlugin):
families = ["assembly"]
actions = [ayon_core.hosts.maya.api.action.SelectInvalidAction]
active = False
optional = True
@classmethod
def get_invalid(cls, instance):
@ -47,7 +50,8 @@ class ValidateAssemblyName(pyblish.api.InstancePlugin):
return invalid
def process(self, instance):
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:
raise PublishValidationError("Found {} invalid named assembly "

View file

@ -1,10 +1,12 @@
import pyblish.api
import ayon_core.hosts.maya.api.action
from ayon_core.pipeline.publish import (
PublishValidationError
PublishValidationError,
OptionalPyblishPluginMixin
)
class ValidateAssemblyNamespaces(pyblish.api.InstancePlugin):
class ValidateAssemblyNamespaces(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Ensure namespaces are not nested
In the outliner an item in a normal namespace looks as following:
@ -20,9 +22,11 @@ class ValidateAssemblyNamespaces(pyblish.api.InstancePlugin):
order = pyblish.api.ValidatorOrder
families = ["assembly"]
actions = [ayon_core.hosts.maya.api.action.SelectInvalidAction]
optional = False
def process(self, instance):
if not self.is_active(instance.data):
return
self.log.debug("Checking namespace for %s" % instance.name)
if self.get_invalid(instance):
raise PublishValidationError("Nested namespaces found")

View file

@ -2,10 +2,15 @@ import pyblish.api
from maya import cmds
import ayon_core.hosts.maya.api.action
from ayon_core.pipeline.publish import PublishValidationError, RepairAction
from ayon_core.pipeline.publish import (
PublishValidationError,
RepairAction,
OptionalPyblishPluginMixin
)
class ValidateAssemblyModelTransforms(pyblish.api.InstancePlugin):
class ValidateAssemblyModelTransforms(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Verify only root nodes of the loaded asset have transformations.
Note: This check is temporary and is subject to change.
@ -34,7 +39,11 @@ class ValidateAssemblyModelTransforms(pyblish.api.InstancePlugin):
" This can alter the look of your scene. "
"Are you sure you want to continue?")
optional = False
def process(self, instance):
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:
raise PublishValidationError(

View file

@ -3,10 +3,14 @@ from maya import cmds
import ayon_core.hosts.maya.api.action
from ayon_core.pipeline.publish import (
PublishValidationError, ValidateContentsOrder)
PublishValidationError,
ValidateContentsOrder,
OptionalPyblishPluginMixin
)
class ValidateCameraAttributes(pyblish.api.InstancePlugin):
class ValidateCameraAttributes(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Validates Camera has no invalid attribute keys or values.
The Alembic file format does not a specific subset of attributes as such
@ -20,6 +24,7 @@ class ValidateCameraAttributes(pyblish.api.InstancePlugin):
hosts = ['maya']
label = 'Camera Attributes'
actions = [ayon_core.hosts.maya.api.action.SelectInvalidAction]
optional = True
DEFAULTS = [
("filmFitOffset", 0.0),
@ -62,7 +67,8 @@ class ValidateCameraAttributes(pyblish.api.InstancePlugin):
def process(self, instance):
"""Process all the nodes in the instance"""
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:

View file

@ -3,10 +3,13 @@ from maya import cmds
import ayon_core.hosts.maya.api.action
from ayon_core.pipeline.publish import (
PublishValidationError, ValidateContentsOrder)
PublishValidationError,
ValidateContentsOrder,
OptionalPyblishPluginMixin)
class ValidateCameraContents(pyblish.api.InstancePlugin):
class ValidateCameraContents(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Validates Camera instance contents.
A Camera instance may only hold a SINGLE camera's transform, nothing else.
@ -22,6 +25,7 @@ class ValidateCameraContents(pyblish.api.InstancePlugin):
label = 'Camera Contents'
actions = [ayon_core.hosts.maya.api.action.SelectInvalidAction]
validate_shapes = True
optional = False
@classmethod
def get_invalid(cls, instance):
@ -71,7 +75,8 @@ class ValidateCameraContents(pyblish.api.InstancePlugin):
def process(self, instance):
"""Process all the nodes in the instance"""
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:
raise PublishValidationError("Invalid camera contents: "

View file

@ -1,10 +1,13 @@
import pyblish.api
from maya import cmds
from ayon_core.pipeline.publish import context_plugin_should_run
from ayon_core.pipeline.publish import (
context_plugin_should_run,
OptionalPyblishPluginMixin
)
class ValidateCurrentRenderLayerIsRenderable(pyblish.api.ContextPlugin):
class ValidateCurrentRenderLayerIsRenderable(pyblish.api.ContextPlugin,
OptionalPyblishPluginMixin):
"""Validate if current render layer has a renderable camera
There is a bug in Redshift which occurs when the current render layer
@ -20,9 +23,11 @@ class ValidateCurrentRenderLayerIsRenderable(pyblish.api.ContextPlugin):
order = pyblish.api.ValidatorOrder
hosts = ["maya"]
families = ["renderlayer"]
optional = False
def process(self, context):
if not self.is_active(context.data):
return
# Workaround bug pyblish-base#250
if not context_plugin_should_run(self, context):
return

View file

@ -6,10 +6,11 @@ from ayon_core.pipeline.publish import (
RepairAction,
ValidateContentsOrder
)
from ayon_core.pipeline import PublishValidationError
from ayon_core.pipeline import PublishValidationError, OptionalPyblishPluginMixin
class ValidateGLSLMaterial(pyblish.api.InstancePlugin):
class ValidateGLSLMaterial(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""
Validate if the asset uses GLSL Shader
"""
@ -23,6 +24,8 @@ class ValidateGLSLMaterial(pyblish.api.InstancePlugin):
active = True
def process(self, instance):
if not self.is_active(instance.data):
return
shading_grp = self.get_material_from_shapes(instance)
if not shading_grp:
raise PublishValidationError("No shading group found")

View file

@ -5,11 +5,13 @@ import pyblish.api
from ayon_core.pipeline.publish import (
RepairAction,
ValidateContentsOrder,
PublishValidationError
PublishValidationError,
OptionalPyblishPluginMixin
)
class ValidateGLSLPlugin(pyblish.api.InstancePlugin):
class ValidateGLSLPlugin(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""
Validate if the asset uses GLSL Shader
"""
@ -19,8 +21,11 @@ class ValidateGLSLPlugin(pyblish.api.InstancePlugin):
hosts = ['maya']
label = 'maya2glTF plugin'
actions = [RepairAction]
optional = False
def process(self, instance):
if not self.is_active(instance.data):
return
if not cmds.pluginInfo("maya2glTF", query=True, loaded=True):
raise PublishValidationError("maya2glTF is not loaded")

View file

@ -2,10 +2,14 @@ import maya.cmds as cmds
import pyblish.api
from ayon_core.hosts.maya.api import lib
from ayon_core.pipeline.publish import PublishValidationError
from ayon_core.pipeline.publish import (
PublishValidationError,
OptionalPyblishPluginMixin
)
class ValidateInstancerContent(pyblish.api.InstancePlugin):
class ValidateInstancerContent(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Validates that all meshes in the instance have object IDs.
This skips a check on intermediate objects because we consider them
@ -14,9 +18,11 @@ class ValidateInstancerContent(pyblish.api.InstancePlugin):
order = pyblish.api.ValidatorOrder
label = 'Instancer Content'
families = ['instancer']
optional = False
def process(self, instance):
if not self.is_active(instance.data):
return
error = False
members = instance.data['setMembers']
export_members = instance.data['exactExportMembers']

View file

@ -3,8 +3,10 @@ import re
import pyblish.api
from ayon_core.pipeline.publish import PublishValidationError
from ayon_core.pipeline.publish import (
PublishValidationError,
OptionalPyblishPluginMixin
)
def is_cache_resource(resource):
"""Return whether resource is a cacheFile resource"""
@ -34,7 +36,8 @@ def filter_ticks(files):
return tick_files, ticks
class ValidateInstancerFrameRanges(pyblish.api.InstancePlugin):
class ValidateInstancerFrameRanges(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Validates all instancer particle systems are cached correctly.
This means they should have the files/frames as required by the start-end
@ -46,10 +49,12 @@ class ValidateInstancerFrameRanges(pyblish.api.InstancePlugin):
order = pyblish.api.ValidatorOrder
label = 'Instancer Cache Frame Ranges'
families = ['instancer']
optional = False
@classmethod
def get_invalid(cls, instance):
if not self.is_active(instance.data):
return
import pyseq
start_frame = instance.data.get("frameStart", 0)

View file

@ -4,17 +4,20 @@ import maya.cmds as cmds
from ayon_core.pipeline.publish import (
RepairContextAction,
PublishValidationError
PublishValidationError,
OptionalPyblishPluginMixin
)
class ValidateLoadedPlugin(pyblish.api.ContextPlugin):
class ValidateLoadedPlugin(pyblish.api.ContextPlugin,
OptionalPyblishPluginMixin):
"""Ensure there are no unauthorized loaded plugins"""
label = "Loaded Plugin"
order = pyblish.api.ValidatorOrder
host = ["maya"]
actions = [RepairContextAction]
optional = True
@classmethod
def get_invalid(cls, context):
@ -35,7 +38,8 @@ class ValidateLoadedPlugin(pyblish.api.ContextPlugin):
return invalid
def process(self, context):
if not self.is_active(context.data):
return
invalid = self.get_invalid(context)
if invalid:
raise PublishValidationError(

View file

@ -5,16 +5,18 @@ import ayon_core.hosts.maya.api.action
from ayon_core.pipeline.publish import (
RepairAction,
ValidateContentsOrder,
PublishValidationError
PublishValidationError,
OptionalPyblishPluginMixin
)
class ValidateShadingEngine(pyblish.api.InstancePlugin):
class ValidateShadingEngine(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Validate all shading engines are named after the surface material.
Shading engines should be named "{surface_shader}SG"
"""
``
order = ValidateContentsOrder
families = ["look"]
hosts = ["maya"]
@ -22,9 +24,12 @@ class ValidateShadingEngine(pyblish.api.InstancePlugin):
actions = [
ayon_core.hosts.maya.api.action.SelectInvalidAction, RepairAction
]
optional = True
# The default connections to check
def process(self, instance):
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:

View file

@ -7,11 +7,13 @@ from ayon_core.pipeline.context_tools import get_current_project_folder
from ayon_core.pipeline.publish import (
RepairContextAction,
ValidateSceneOrder,
PublishXmlValidationError
PublishXmlValidationError,
OptionalPyblishPluginMixin
)
class ValidateMayaUnits(pyblish.api.ContextPlugin):
class ValidateMayaUnits(pyblish.api.ContextPlugin,
OptionalPyblishPluginMixin):
"""Check if the Maya units are set correct"""
order = ValidateSceneOrder
@ -35,6 +37,7 @@ class ValidateMayaUnits(pyblish.api.ContextPlugin):
"Maya scene {setting} must be '{required_value}'. "
"Current value is '{current_value}'."
)
optional = False
@classmethod
def apply_settings(cls, project_settings):
@ -52,7 +55,8 @@ class ValidateMayaUnits(pyblish.api.ContextPlugin):
cls.validate_fps = settings.get("validate_fps", cls.validate_fps)
def process(self, context):
if not self.is_active(context.data):
return
# Collected units
linearunits = context.data.get('linearUnits')
angularunits = context.data.get('angularUnits')

View file

@ -2,10 +2,11 @@ from maya import cmds
import pyblish.api
import ayon_core.hosts.maya.api.action
from ayon_core.pipeline.publish import ValidateMeshOrder
from ayon_core.pipeline.publish import ValidateMeshOrder, OptionalPyblishPluginMixin
class ValidateMeshLaminaFaces(pyblish.api.InstancePlugin):
class ValidateMeshLaminaFaces(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Validate meshes don't have lamina faces.
Lamina faces share all of their edges.
@ -17,6 +18,7 @@ class ValidateMeshLaminaFaces(pyblish.api.InstancePlugin):
families = ['model']
label = 'Mesh Lamina Faces'
actions = [ayon_core.hosts.maya.api.action.SelectInvalidAction]
optional = True
@staticmethod
def get_invalid(instance):
@ -28,6 +30,8 @@ class ValidateMeshLaminaFaces(pyblish.api.InstancePlugin):
def process(self, instance):
"""Process all the nodes in the instance 'objectSet'"""
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)

View file

@ -3,10 +3,14 @@ from maya import cmds
import pyblish.api
import ayon_core.hosts.maya.api.action
from ayon_core.hosts.maya.api import lib
from ayon_core.pipeline.publish import ValidateContentsOrder
from ayon_core.pipeline.publish import (
ValidateContentsOrder,
OptionalPyblishPluginMixin
)
class ValidateMeshNgons(pyblish.api.Validator):
class ValidateMeshNgons(pyblish.api.Validator,
OptionalPyblishPluginMixin):
"""Ensure that meshes don't have ngons
Ngon are faces with more than 4 sides.
@ -21,6 +25,7 @@ class ValidateMeshNgons(pyblish.api.Validator):
families = ["model"]
label = "Mesh ngons"
actions = [ayon_core.hosts.maya.api.action.SelectInvalidAction]
optional = True
@staticmethod
def get_invalid(instance):
@ -39,6 +44,8 @@ class ValidateMeshNgons(pyblish.api.Validator):
def process(self, instance):
"""Process all the nodes in the instance "objectSet"""
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:

View file

@ -4,7 +4,8 @@ import pyblish.api
import ayon_core.hosts.maya.api.action
from ayon_core.pipeline.publish import (
ValidateMeshOrder,
PublishValidationError
PublishValidationError,
OptionalPyblishPluginMixin
)
@ -15,7 +16,8 @@ def _as_report_list(values, prefix="- ", suffix="\n"):
return prefix + (suffix + prefix).join(values)
class ValidateMeshNoNegativeScale(pyblish.api.Validator):
class ValidateMeshNoNegativeScale(pyblish.api.Validator,
OptionalPyblishPluginMixin):
"""Ensure that meshes don't have a negative scale.
Using negatively scaled proxies in a VRayMesh results in inverted
@ -32,6 +34,7 @@ class ValidateMeshNoNegativeScale(pyblish.api.Validator):
families = ['model']
label = 'Mesh No Negative Scale'
actions = [ayon_core.hosts.maya.api.action.SelectInvalidAction]
optional = False
@staticmethod
def get_invalid(instance):
@ -52,7 +55,8 @@ class ValidateMeshNoNegativeScale(pyblish.api.Validator):
def process(self, instance):
"""Process all the nodes in the instance 'objectSet'"""
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:

View file

@ -4,7 +4,8 @@ import pyblish.api
import ayon_core.hosts.maya.api.action
from ayon_core.pipeline.publish import (
ValidateMeshOrder,
PublishValidationError
PublishValidationError,
OptionalPyblishPluginMixin
)
@ -15,7 +16,8 @@ def _as_report_list(values, prefix="- ", suffix="\n"):
return prefix + (suffix + prefix).join(values)
class ValidateMeshNonManifold(pyblish.api.Validator):
class ValidateMeshNonManifold(pyblish.api.Validator,
OptionalPyblishPluginMixin):
"""Ensure that meshes don't have non-manifold edges or vertices
To debug the problem on the meshes you can use Maya's modeling
@ -28,6 +30,7 @@ class ValidateMeshNonManifold(pyblish.api.Validator):
families = ['model']
label = 'Mesh Non-Manifold Edges/Vertices'
actions = [ayon_core.hosts.maya.api.action.SelectInvalidAction]
optional = True
@staticmethod
def get_invalid(instance):
@ -44,7 +47,8 @@ class ValidateMeshNonManifold(pyblish.api.Validator):
def process(self, instance):
"""Process all the nodes in the instance 'objectSet'"""
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:

View file

@ -5,7 +5,8 @@ import ayon_core.hosts.maya.api.action
from ayon_core.pipeline.publish import (
RepairAction,
ValidateMeshOrder,
PublishValidationError
PublishValidationError,
OptionalPyblishPluginMixin
)
@ -79,7 +80,8 @@ def disconnect(node_a, node_b):
cmds.disconnectAttr(source, input)
class ValidateMeshShaderConnections(pyblish.api.InstancePlugin):
class ValidateMeshShaderConnections(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Ensure mesh shading engine connections are valid.
In some scenarios Maya keeps connections to multiple shaders even if just
@ -96,10 +98,12 @@ class ValidateMeshShaderConnections(pyblish.api.InstancePlugin):
label = "Mesh Shader Connections"
actions = [ayon_core.hosts.maya.api.action.SelectInvalidAction,
RepairAction]
optional = True
def process(self, instance):
"""Process all the nodes in the instance 'objectSet'"""
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:

View file

@ -4,10 +4,15 @@ from maya import cmds
import ayon_core.hosts.maya.api.action
from ayon_core.hosts.maya.api.lib import len_flattened
from ayon_core.pipeline.publish import (
PublishValidationError, RepairAction, ValidateMeshOrder)
PublishValidationError,
RepairAction,
ValidateMeshOrder,
OptionalPyblishPluginMixin
)
class ValidateMeshVerticesHaveEdges(pyblish.api.InstancePlugin):
class ValidateMeshVerticesHaveEdges(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Validate meshes have only vertices that are connected to edges.
Maya can have invalid geometry with vertices that have no edges or
@ -32,6 +37,7 @@ class ValidateMeshVerticesHaveEdges(pyblish.api.InstancePlugin):
label = 'Mesh Vertices Have Edges'
actions = [ayon_core.hosts.maya.api.action.SelectInvalidAction,
RepairAction]
optional = True
@classmethod
def repair(cls, instance):
@ -72,7 +78,8 @@ class ValidateMeshVerticesHaveEdges(pyblish.api.InstancePlugin):
return invalid
def process(self, instance):
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:
raise PublishValidationError(

View file

@ -5,11 +5,13 @@ import ayon_core.hosts.maya.api.action
from ayon_core.hosts.maya.api import lib
from ayon_core.pipeline.publish import (
ValidateContentsOrder,
PublishValidationError
PublishValidationError,
OptionalPyblishPluginMixin
)
class ValidateModelContent(pyblish.api.InstancePlugin):
class ValidateModelContent(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Adheres to the content of 'model' product type
- Must have one top group. (configurable)
@ -24,6 +26,7 @@ class ValidateModelContent(pyblish.api.InstancePlugin):
actions = [ayon_core.hosts.maya.api.action.SelectInvalidAction]
validate_top_group = True
optional = False
@classmethod
def get_invalid(cls, instance):
@ -91,7 +94,8 @@ class ValidateModelContent(pyblish.api.InstancePlugin):
return list(invalid)
def process(self, instance):
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:

View file

@ -4,7 +4,8 @@ import pyblish.api
import ayon_core.hosts.maya.api.action
from ayon_core.pipeline.publish import (
ValidateContentsOrder,
PublishValidationError
PublishValidationError,
OptionalPyblishPluginMixin
)
@ -15,7 +16,8 @@ def _as_report_list(values, prefix="- ", suffix="\n"):
return prefix + (suffix + prefix).join(values)
class ValidateNoDefaultCameras(pyblish.api.InstancePlugin):
class ValidateNoDefaultCameras(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Ensure no default (startup) cameras are in the instance.
This might be unnecessary. In the past there were some issues with
@ -28,6 +30,7 @@ class ValidateNoDefaultCameras(pyblish.api.InstancePlugin):
families = ['camera']
label = "No Default Cameras"
actions = [ayon_core.hosts.maya.api.action.SelectInvalidAction]
optional = False
@staticmethod
def get_invalid(instance):
@ -37,6 +40,8 @@ class ValidateNoDefaultCameras(pyblish.api.InstancePlugin):
def process(self, instance):
"""Process all the cameras in the instance"""
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:
raise PublishValidationError(

View file

@ -4,7 +4,8 @@ import pyblish.api
from ayon_core.pipeline.publish import (
RepairAction,
ValidateContentsOrder,
PublishValidationError
PublishValidationError,
OptionalPyblishPluginMixin
)
import ayon_core.hosts.maya.api.action
@ -24,7 +25,8 @@ def get_namespace(node_name):
return node_name.rpartition(":")[0]
class ValidateNoNamespace(pyblish.api.InstancePlugin):
class ValidateNoNamespace(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Ensure the nodes don't have a namespace"""
order = ValidateContentsOrder
@ -33,6 +35,7 @@ class ValidateNoNamespace(pyblish.api.InstancePlugin):
label = 'No Namespaces'
actions = [ayon_core.hosts.maya.api.action.SelectInvalidAction,
RepairAction]
optional = False
@staticmethod
def get_invalid(instance):
@ -41,6 +44,8 @@ class ValidateNoNamespace(pyblish.api.InstancePlugin):
def process(self, instance):
"""Process all the nodes in the instance"""
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:

View file

@ -5,7 +5,8 @@ import ayon_core.hosts.maya.api.action
from ayon_core.pipeline.publish import (
RepairAction,
ValidateContentsOrder,
PublishValidationError
PublishValidationError,
OptionalPyblishPluginMixin
)
@ -37,7 +38,8 @@ def has_shape_children(node):
return True
class ValidateNoNullTransforms(pyblish.api.InstancePlugin):
class ValidateNoNullTransforms(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Ensure no null transforms are in the scene.
Warning:
@ -54,6 +56,7 @@ class ValidateNoNullTransforms(pyblish.api.InstancePlugin):
label = 'No Empty/Null Transforms'
actions = [RepairAction,
ayon_core.hosts.maya.api.action.SelectInvalidAction]
optional = False
@staticmethod
def get_invalid(instance):
@ -70,6 +73,8 @@ class ValidateNoNullTransforms(pyblish.api.InstancePlugin):
def process(self, instance):
"""Process all the transform nodes in the instance """
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:
raise PublishValidationError(

View file

@ -1,7 +1,9 @@
import pyblish.api
from maya import cmds
from ayon_core.pipeline.publish import PublishValidationError
from ayon_core.pipeline.publish import (
PublishValidationError,
OptionalPyblishPluginMixin
)
def _as_report_list(values, prefix="- ", suffix="\n"):
"""Return list as bullet point list for a report"""
@ -10,15 +12,18 @@ def _as_report_list(values, prefix="- ", suffix="\n"):
return prefix + (suffix + prefix).join(values)
class ValidateNoVRayMesh(pyblish.api.InstancePlugin):
class ValidateNoVRayMesh(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Validate there are no VRayMesh objects in the instance"""
order = pyblish.api.ValidatorOrder
label = 'No V-Ray Proxies (VRayMesh)'
families = ["pointcache"]
optional = False
def process(self, instance):
if not self.is_active(instance.data):
return
if not cmds.pluginInfo("vrayformaya", query=True, loaded=True):
return

View file

@ -3,10 +3,13 @@ from maya import cmds
import pyblish.api
import ayon_core.hosts.maya.api.action
from ayon_core.pipeline.publish import ValidateContentsOrder
from ayon_core.pipeline.publish import (
ValidateContentsOrder,
OptionalPyblishPluginMixin
class ValidateNodeNoGhosting(pyblish.api.InstancePlugin):
)
class ValidateNodeNoGhosting(pyblish.api.InstancePlugin.
OptionalPyblishPluginMixin):
"""Ensure nodes do not have ghosting enabled.
If one would publish towards a non-Maya format it's likely that stats
@ -23,6 +26,7 @@ class ValidateNodeNoGhosting(pyblish.api.InstancePlugin):
families = ['model', 'rig']
label = "No Ghosting"
actions = [ayon_core.hosts.maya.api.action.SelectInvalidAction]
optional = False
_attributes = {'ghosting': 0}
@ -46,7 +50,8 @@ class ValidateNodeNoGhosting(pyblish.api.InstancePlugin):
return invalid
def process(self, instance):
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:

View file

@ -8,11 +8,13 @@ from ayon_core.hosts.maya.api.lib import pairwise
from ayon_core.hosts.maya.api.action import SelectInvalidAction
from ayon_core.pipeline.publish import (
ValidateContentsOrder,
PublishValidationError
PublishValidationError,
OptionalPyblishPluginMixin
)
class ValidatePluginPathAttributes(pyblish.api.InstancePlugin):
class ValidatePluginPathAttributes(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""
Validate plug-in path attributes point to existing file paths.
"""
@ -22,6 +24,7 @@ class ValidatePluginPathAttributes(pyblish.api.InstancePlugin):
families = ["workfile"]
label = "Plug-in Path Attributes"
actions = [SelectInvalidAction]
optional = False
# Attributes are defined in project settings
attribute = []
@ -60,6 +63,8 @@ class ValidatePluginPathAttributes(pyblish.api.InstancePlugin):
def process(self, instance):
"""Process all directories Set as Filenames in Non-Maya Nodes"""
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:
raise PublishValidationError(

View file

@ -5,10 +5,15 @@ import pyblish.api
from maya import cmds
from ayon_core.pipeline.publish import (
PublishValidationError, RepairAction, ValidateContentsOrder)
PublishValidationError,
RepairAction,
ValidateContentsOrder,
OptionalPyblishPluginMixin
)
class ValidateRenderImageRule(pyblish.api.InstancePlugin):
class ValidateRenderImageRule(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Validates Maya Workpace "images" file rule matches project settings.
This validates against the configured default render image folder:
@ -22,9 +27,11 @@ class ValidateRenderImageRule(pyblish.api.InstancePlugin):
hosts = ["maya"]
families = ["renderlayer"]
actions = [RepairAction]
optional = False
def process(self, instance):
if not self.is_active(instance.data):
return
required_images_rule = os.path.normpath(
self.get_default_render_image_folder(instance)
)

View file

@ -6,10 +6,12 @@ import ayon_core.hosts.maya.api.action
from ayon_core.pipeline.publish import (
ValidateContentsOrder,
PublishValidationError,
OptionalPyblishPluginMixin
)
class ValidateRenderNoDefaultCameras(pyblish.api.InstancePlugin):
class ValidateRenderNoDefaultCameras(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Ensure no default (startup) cameras are to be rendered."""
order = ValidateContentsOrder
@ -17,6 +19,7 @@ class ValidateRenderNoDefaultCameras(pyblish.api.InstancePlugin):
families = ['renderlayer']
label = "No Default Cameras Renderable"
actions = [ayon_core.hosts.maya.api.action.SelectInvalidAction]
optional = False
@staticmethod
def get_invalid(instance):
@ -32,6 +35,8 @@ class ValidateRenderNoDefaultCameras(pyblish.api.InstancePlugin):
def process(self, instance):
"""Process all the cameras in the instance"""
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:
raise PublishValidationError(

View file

@ -7,11 +7,13 @@ import ayon_core.hosts.maya.api.action
from ayon_core.hosts.maya.api.lib_rendersettings import RenderSettings
from ayon_core.pipeline.publish import (
ValidateContentsOrder,
PublishValidationError
PublishValidationError,
OptionalPyblishPluginMixin
)
class ValidateRenderSingleCamera(pyblish.api.InstancePlugin):
class ValidateRenderSingleCamera(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Validate renderable camera count for layer and <Camera> token.
Pipeline is supporting multiple renderable cameras per layer, but image
@ -24,11 +26,14 @@ class ValidateRenderSingleCamera(pyblish.api.InstancePlugin):
families = ["renderlayer",
"vrayscene"]
actions = [ayon_core.hosts.maya.api.action.SelectInvalidAction]
optional = False
R_CAMERA_TOKEN = re.compile(r'%c|<camera>', re.IGNORECASE)
def process(self, instance):
"""Process all the cameras in the instance"""
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:
raise PublishValidationError("Invalid cameras for render.")

View file

@ -2,10 +2,13 @@ import ayon_api
import pyblish.api
import ayon_core.hosts.maya.api.action
from ayon_core.pipeline.publish import PublishValidationError
from ayon_core.pipeline.publish import (
PublishValidationError,
OptionalPyblishPluginMixin
)
class ValidateRenderLayerAOVs(pyblish.api.InstancePlugin):
class ValidateRenderLayerAOVs(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Validate created AOVs / RenderElement is registered in the database
Each render element is registered as a product which is formatted based on
@ -26,8 +29,12 @@ class ValidateRenderLayerAOVs(pyblish.api.InstancePlugin):
hosts = ["maya"]
families = ["renderlayer"]
actions = [ayon_core.hosts.maya.api.action.SelectInvalidAction]
optional = False
def process(self, instance):
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:
raise PublishValidationError(

View file

@ -3,11 +3,13 @@ from maya import cmds
import ayon_core.hosts.maya.api.action
from ayon_core.pipeline.publish import (
PublishValidationError,
ValidateContentsOrder
ValidateContentsOrder,
OptionalPyblishPluginMixin
)
class ValidateRigContents(pyblish.api.InstancePlugin):
class ValidateRigContents(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Ensure rig contains pipeline-critical content
Every rig must contain at least two object sets:
@ -21,11 +23,14 @@ class ValidateRigContents(pyblish.api.InstancePlugin):
hosts = ["maya"]
families = ["rig"]
action = [ayon_core.hosts.maya.api.action.SelectInvalidAction]
optional = True
accepted_output = ["mesh", "transform"]
accepted_controllers = ["transform"]
def process(self, instance):
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:
raise PublishValidationError(
@ -213,6 +218,7 @@ class ValidateSkeletonRigContents(ValidateRigContents):
label = "Skeleton Rig Contents"
hosts = ["maya"]
families = ["rig.fbx"]
optional = True
@classmethod
def get_invalid(cls, instance):

View file

@ -5,13 +5,15 @@ import pyblish.api
from ayon_core.pipeline.publish import (
ValidateContentsOrder,
RepairAction,
PublishValidationError
PublishValidationError,
OptionalPyblishPluginMixin
)
import ayon_core.hosts.maya.api.action
from ayon_core.hosts.maya.api.lib import undo_chunk
class ValidateRigControllers(pyblish.api.InstancePlugin):
class ValidateRigControllers(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Validate rig controllers.
Controls must have the transformation attributes on their default
@ -33,6 +35,7 @@ class ValidateRigControllers(pyblish.api.InstancePlugin):
label = "Rig Controllers"
hosts = ["maya"]
families = ["rig"]
optional = True
actions = [RepairAction,
ayon_core.hosts.maya.api.action.SelectInvalidAction]
@ -50,6 +53,9 @@ class ValidateRigControllers(pyblish.api.InstancePlugin):
}
def process(self, instance):
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:
raise PublishValidationError(

View file

@ -5,14 +5,16 @@ import pyblish.api
from ayon_core.pipeline.publish import (
ValidateContentsOrder,
RepairAction,
PublishValidationError
PublishValidationError,
OptionalPyblishPluginMixin
)
from ayon_core.hosts.maya.api import lib
import ayon_core.hosts.maya.api.action
class ValidateRigControllersArnoldAttributes(pyblish.api.InstancePlugin):
class ValidateRigControllersArnoldAttributes(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Validate rig control curves have no keyable arnold attributes.
The Arnold plug-in will create curve attributes like:
@ -35,6 +37,7 @@ class ValidateRigControllersArnoldAttributes(pyblish.api.InstancePlugin):
label = "Rig Controllers (Arnold Attributes)"
hosts = ["maya"]
families = ["rig"]
optional = False
actions = [RepairAction,
ayon_core.hosts.maya.api.action.SelectInvalidAction]
@ -48,6 +51,9 @@ class ValidateRigControllersArnoldAttributes(pyblish.api.InstancePlugin):
]
def process(self, instance):
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:
raise PublishValidationError('{} failed, see log '

View file

@ -7,11 +7,13 @@ from ayon_core.hosts.maya.api import lib
from ayon_core.pipeline.publish import (
RepairAction,
ValidateContentsOrder,
PublishValidationError
PublishValidationError,
OptionalPyblishPluginMixin
)
class ValidateRigJointsHidden(pyblish.api.InstancePlugin):
class ValidateRigJointsHidden(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Validate all joints are hidden visually.
This includes being hidden:
@ -28,6 +30,7 @@ class ValidateRigJointsHidden(pyblish.api.InstancePlugin):
label = "Joints Hidden"
actions = [ayon_core.hosts.maya.api.action.SelectInvalidAction,
RepairAction]
optional = True
@staticmethod
def get_invalid(instance):
@ -36,6 +39,8 @@ class ValidateRigJointsHidden(pyblish.api.InstancePlugin):
def process(self, instance):
"""Process all the nodes in the instance 'objectSet'"""
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:

View file

@ -7,11 +7,13 @@ from ayon_core.hosts.maya.api import lib
from ayon_core.pipeline.publish import (
RepairAction,
ValidateContentsOrder,
PublishValidationError
PublishValidationError,
OptionalPyblishPluginMixin
)
class ValidateRigOutSetNodeIds(pyblish.api.InstancePlugin):
class ValidateRigOutSetNodeIds(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Validate if deformed shapes have related IDs to the original shapes.
When a deformer is applied in the scene on a referenced mesh that already
@ -30,10 +32,12 @@ class ValidateRigOutSetNodeIds(pyblish.api.InstancePlugin):
RepairAction
]
allow_history_only = False
optional = False
def process(self, instance):
"""Process all meshes"""
if not self.is_active(instance.data):
return
# Ensure all nodes have a cbId and a related ID to the original shapes
# if a deformer has been created on the shape
invalid = self.get_invalid(instance)
@ -114,6 +118,7 @@ class ValidateSkeletonRigOutSetNodeIds(ValidateRigOutSetNodeIds):
families = ["rig.fbx"]
hosts = ['maya']
label = 'Skeleton Rig Out Set Node Ids'
optional = False
@classmethod
def get_node(cls, instance):

View file

@ -6,10 +6,12 @@ import ayon_core.hosts.maya.api.action
from ayon_core.pipeline.publish import (
RepairAction,
ValidateMeshOrder,
OptionalPyblishPluginMixin
)
class ValidateShapeRenderStats(pyblish.api.Validator):
class ValidateShapeRenderStats(pyblish.api.Validator,
OptionalPyblishPluginMixin):
"""Ensure all render stats are set to the default values."""
order = ValidateMeshOrder
@ -18,6 +20,7 @@ class ValidateShapeRenderStats(pyblish.api.Validator):
label = 'Shape Default Render Stats'
actions = [ayon_core.hosts.maya.api.action.SelectInvalidAction,
RepairAction]
optional = True
defaults = {'castsShadows': 1,
'receiveShadows': 1,
@ -46,7 +49,8 @@ class ValidateShapeRenderStats(pyblish.api.Validator):
return invalid
def process(self, instance):
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:

View file

@ -7,11 +7,13 @@ from ayon_core.hosts.maya.api import lib
from ayon_core.pipeline.publish import (
ValidateContentsOrder,
RepairAction,
PublishValidationError
PublishValidationError,
OptionalPyblishPluginMixin
)
class ValidateShapeZero(pyblish.api.Validator):
class ValidateShapeZero(pyblish.api.Validator,
OptionalPyblishPluginMixin):
"""Shape components may not have any "tweak" values
To solve this issue, try freezing the shapes.
@ -26,6 +28,7 @@ class ValidateShapeZero(pyblish.api.Validator):
ayon_core.hosts.maya.api.action.SelectInvalidAction,
RepairAction
]
optional = True
@staticmethod
def get_invalid(instance):
@ -65,6 +68,8 @@ class ValidateShapeZero(pyblish.api.Validator):
def process(self, instance):
"""Process all the nodes in the instance "objectSet"""
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:

View file

@ -4,20 +4,25 @@ import pyblish.api
from ayon_core.pipeline.publish import (
ValidateContentsOrder,
PublishXmlValidationError,
OptionalPyblishPluginMixin
)
from maya import cmds
class ValidateSkeletalMeshHierarchy(pyblish.api.InstancePlugin):
class ValidateSkeletalMeshHierarchy(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Validates that nodes has common root."""
order = ValidateContentsOrder
hosts = ["maya"]
families = ["skeletalMesh"]
label = "Skeletal Mesh Top Node"
optional = False
def process(self, instance):
if not self.is_active(instance.data):
return
geo = instance.data.get("geometry")
joints = instance.data.get("joints")

View file

@ -21,8 +21,12 @@ class ValidateSkeletonTopGroupHierarchy(pyblish.api.InstancePlugin,
order = ValidateContentsOrder + 0.05
label = "Skeleton Rig Top Group Hierarchy"
families = ["rig.fbx"]
optional = True
def process(self, instance):
if not self.is_active(instance.data):
return
invalid = []
skeleton_mesh_data = instance.data("skeleton_mesh", [])
if skeleton_mesh_data:

View file

@ -3,10 +3,11 @@ from maya import cmds
import pyblish.api
import ayon_core.hosts.maya.api.action
from ayon_core.pipeline.publish import ValidateContentsOrder
from ayon_core.pipeline.publish import ValidateContentsOrder,OptionalPyblishPluginMixin
class ValidateSkinclusterDeformerSet(pyblish.api.InstancePlugin):
class ValidateSkinclusterDeformerSet(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Validate skinClusters on meshes have valid member relationships.
In rare cases it can happen that a mesh has a skinCluster in its history
@ -20,9 +21,12 @@ class ValidateSkinclusterDeformerSet(pyblish.api.InstancePlugin):
families = ['fbx']
label = "Skincluster Deformer Relationships"
actions = [ayon_core.hosts.maya.api.action.SelectInvalidAction]
optional = False
def process(self, instance):
"""Process all the transform nodes in the instance"""
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:

View file

@ -3,11 +3,13 @@ import pyblish.api
import ayon_core.hosts.maya.api.action
from ayon_core.pipeline.publish import (
PublishValidationError,
ValidateContentsOrder
ValidateContentsOrder,
OptionalPyblishPluginMixin
)
class ValidateStepSize(pyblish.api.InstancePlugin):
class ValidateStepSize(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Validates the step size for the instance is in a valid range.
For example the `step` size should never be lower or equal to zero.
@ -20,7 +22,7 @@ class ValidateStepSize(pyblish.api.InstancePlugin):
'pointcache',
'animation']
actions = [ayon_core.hosts.maya.api.action.SelectInvalidAction]
optional = False
MIN = 0.01
MAX = 1.0
@ -40,7 +42,8 @@ class ValidateStepSize(pyblish.api.InstancePlugin):
return []
def process(self, instance):
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:
raise PublishValidationError(

View file

@ -5,11 +5,13 @@ import pyblish.api
import ayon_core.hosts.maya.api.action
from ayon_core.pipeline.publish import (
ValidateContentsOrder,
PublishValidationError
PublishValidationError,
OptionalPyblishPluginMixin
)
class ValidateTransformZero(pyblish.api.Validator):
class ValidateTransformZero(pyblish.api.Validator,
OptionalPyblishPluginMixin):
"""Transforms can't have any values
To solve this issue, try freezing the transforms. So long
@ -29,6 +31,7 @@ class ValidateTransformZero(pyblish.api.Validator):
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0]
_tolerance = 1e-30
optional = True
@classmethod
def get_invalid(cls, instance):
@ -62,7 +65,8 @@ class ValidateTransformZero(pyblish.api.Validator):
def process(self, instance):
"""Process all the nodes in the instance "objectSet"""
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:

View file

@ -2,10 +2,13 @@ from maya import cmds
import pyblish.api
import ayon_core.hosts.maya.api.action
from ayon_core.pipeline.publish import ValidateContentsOrder
from ayon_core.pipeline.publish import (
ValidateContentsOrder,
OptionalPyblishPluginMixin
)
class ValidateUniqueNames(pyblish.api.Validator):
class ValidateUniqueNames(pyblish.api.Validator,
OptionalPyblishPluginMixin):
"""transform names should be unique
ie: using cmds.ls(someNodeName) should always return shortname
@ -17,6 +20,7 @@ class ValidateUniqueNames(pyblish.api.Validator):
families = ["model"]
label = "Unique transform name"
actions = [ayon_core.hosts.maya.api.action.SelectInvalidAction]
optional = True
@staticmethod
def get_invalid(instance):
@ -32,7 +36,8 @@ class ValidateUniqueNames(pyblish.api.Validator):
def process(self, instance):
"""Process all the nodes in the instance "objectSet"""
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:
raise ValueError("Nodes found with none unique names. "

View file

@ -3,11 +3,15 @@
from maya import cmds
import pyblish.api
from ayon_core.pipeline.publish import ValidateMeshOrder
from ayon_core.pipeline.publish import (
ValidateMeshOrder,
OptionalPyblishPluginMixin
)
import ayon_core.hosts.maya.api.action
class ValidateUnrealMeshTriangulated(pyblish.api.InstancePlugin):
class ValidateUnrealMeshTriangulated(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Validate if mesh is made of triangles for Unreal Engine"""
order = ValidateMeshOrder
@ -30,6 +34,8 @@ class ValidateUnrealMeshTriangulated(pyblish.api.InstancePlugin):
return invalid
def process(self, instance):
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
assert len(invalid) == 0, (
"Found meshes without triangles")

View file

@ -4,11 +4,13 @@ from ayon_core.hosts.maya.api.lib import iter_visible_nodes_in_range
import ayon_core.hosts.maya.api.action
from ayon_core.pipeline.publish import (
ValidateContentsOrder,
PublishValidationError
PublishValidationError,
OptionalPyblishPluginMixin
)
class ValidateAlembicVisibleOnly(pyblish.api.InstancePlugin):
class ValidateAlembicVisibleOnly(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Validates at least a single node is visible in frame range.
This validation only validates if the `visibleOnly` flag is enabled
@ -20,9 +22,11 @@ class ValidateAlembicVisibleOnly(pyblish.api.InstancePlugin):
hosts = ["maya"]
families = ["pointcache", "animation"]
actions = [ayon_core.hosts.maya.api.action.SelectInvalidAction]
optional = False
def process(self, instance):
if not self.is_active(instance.data):
return
if not instance.data.get("visibleOnly", False):
self.log.debug("Visible only is disabled. Validation skipped..")
return

View file

@ -3,10 +3,15 @@ from maya import cmds
from ayon_core.hosts.maya.api import lib
from ayon_core.pipeline.publish import (
PublishValidationError, RepairAction, ValidateContentsOrder)
PublishValidationError,
RepairAction,
ValidateContentsOrder,
OptionalPyblishPluginMixin
)
class ValidateVRayDistributedRendering(pyblish.api.InstancePlugin):
class ValidateVRayDistributedRendering(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Validate V-Ray Distributed Rendering is ignored in batch mode.
Whenever Distributed Rendering is enabled for V-Ray in the render settings
@ -20,13 +25,15 @@ class ValidateVRayDistributedRendering(pyblish.api.InstancePlugin):
label = "VRay Distributed Rendering"
families = ["renderlayer"]
actions = [RepairAction]
optional = False
# V-Ray attribute names
enabled_attr = "vraySettings.sys_distributed_rendering_on"
ignored_attr = "vraySettings.sys_distributed_rendering_ignore_batch"
def process(self, instance):
if not self.is_active(instance.data):
return
if instance.data.get("renderer") != "vray":
# If not V-Ray ignore..
return

View file

@ -4,10 +4,13 @@ import pyblish.api
import types
from maya import cmds
from ayon_core.pipeline.publish import RepairContextAction
from ayon_core.pipeline.publish import (
RepairContextAction,
OptionalPyblishPluginMixin
)
class ValidateVrayReferencedAOVs(pyblish.api.InstancePlugin):
class ValidateVrayReferencedAOVs(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Validate whether the V-Ray Render Elements (AOVs) include references.
This will check if there are AOVs pulled from references. If
@ -21,9 +24,12 @@ class ValidateVrayReferencedAOVs(pyblish.api.InstancePlugin):
hosts = ['maya']
families = ['renderlayer']
actions = [RepairContextAction]
optional = False
def process(self, instance):
"""Plugin main entry point."""
if not self.is_active(instance.data):
return
if instance.data.get("renderer") != "vray":
# If not V-Ray ignore..
return

View file

@ -5,22 +5,27 @@ from ayon_core.pipeline.publish import (
context_plugin_should_run,
RepairContextAction,
ValidateContentsOrder,
PublishValidationError
PublishValidationError,
OptionalPyblishPluginMixin
)
from maya import cmds
class ValidateVRayTranslatorEnabled(pyblish.api.ContextPlugin):
class ValidateVRayTranslatorEnabled(pyblish.api.ContextPlugin,
OptionalPyblishPluginMixin):
"""Validate VRay Translator settings for extracting vrscenes."""
order = ValidateContentsOrder
label = "VRay Translator Settings"
families = ["vrayscene_layer"]
actions = [RepairContextAction]
optional = False
def process(self, context):
"""Plugin entry point."""
if not self.is_active(context.data):
return
# Workaround bug pyblish-base#250
if not context_plugin_should_run(self, context):
return

View file

@ -1,18 +1,21 @@
import pyblish.api
from ayon_core.pipeline import KnownPublishError
from ayon_core.pipeline.publish import OptionalPyblishPluginMixin
class ValidateVrayProxy(pyblish.api.InstancePlugin):
class ValidateVrayProxy(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
order = pyblish.api.ValidatorOrder
label = "VRay Proxy Settings"
hosts = ["maya"]
families = ["vrayproxy"]
optional = False
def process(self, instance):
data = instance.data
if not self.is_active(data):
return
if not data["setMembers"]:
raise KnownPublishError(
"'%s' is empty! This is a bug" % instance.name

View file

@ -4,12 +4,14 @@ from maya import cmds
import ayon_core.hosts.maya.api.action
from ayon_core.pipeline.publish import (
PublishValidationError
PublishValidationError,
OptionalPyblishPluginMixin
)
class ValidateVrayProxyMembers(pyblish.api.InstancePlugin):
class ValidateVrayProxyMembers(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Validate whether the V-Ray Proxy instance has shape members"""
order = pyblish.api.ValidatorOrder
@ -17,9 +19,11 @@ class ValidateVrayProxyMembers(pyblish.api.InstancePlugin):
hosts = ['maya']
families = ['vrayproxy']
actions = [ayon_core.hosts.maya.api.action.SelectInvalidAction]
optional = False
def process(self, instance):
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:

View file

@ -1,10 +1,13 @@
from maya import cmds
import pyblish.api
from ayon_core.pipeline.publish import ValidateContentsOrder
from ayon_core.pipeline.publish import (
ValidateContentsOrder,
OptionalPyblishPluginMixin
)
class ValidateYetiRenderScriptCallbacks(pyblish.api.InstancePlugin):
class ValidateYetiRenderScriptCallbacks(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Check if the render script callbacks will be used during the rendering
In order to ensure the render tasks are executed properly we need to check
@ -24,6 +27,7 @@ class ValidateYetiRenderScriptCallbacks(pyblish.api.InstancePlugin):
label = "Yeti Render Script Callbacks"
hosts = ["maya"]
families = ["renderlayer"]
optional = False
# Settings per renderer
callbacks = {
@ -37,7 +41,8 @@ class ValidateYetiRenderScriptCallbacks(pyblish.api.InstancePlugin):
}
def process(self, instance):
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:
raise ValueError("Invalid render callbacks found for '%s'!"

View file

@ -3,12 +3,14 @@ import maya.cmds as cmds
import ayon_core.hosts.maya.api.action
from ayon_core.pipeline.publish import (
RepairAction,
PublishValidationError
PublishValidationError,
OptionalPyblishPluginMixin
)
class ValidateYetiRigCacheState(pyblish.api.InstancePlugin):
class ValidateYetiRigCacheState(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Validate the I/O attributes of the node
Every pgYetiMaya cache node per instance should have:
@ -23,8 +25,11 @@ class ValidateYetiRigCacheState(pyblish.api.InstancePlugin):
families = ["yetiRig"]
actions = [RepairAction,
ayon_core.hosts.maya.api.action.SelectInvalidAction]
optional = False
def process(self, instance):
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:
raise PublishValidationError("Nodes have incorrect I/O settings")

View file

@ -5,11 +5,13 @@ import pyblish.api
import ayon_core.hosts.maya.api.action
from ayon_core.pipeline.publish import (
ValidateContentsOrder,
PublishValidationError
PublishValidationError,
OptionalPyblishPluginMixin
)
class ValidateYetiRigInputShapesInInstance(pyblish.api.Validator):
class ValidateYetiRigInputShapesInInstance(pyblish.api.Validator,
OptionalPyblishPluginMixin):
"""Validate if all input nodes are part of the instance's hierarchy"""
order = ValidateContentsOrder
@ -17,9 +19,11 @@ class ValidateYetiRigInputShapesInInstance(pyblish.api.Validator):
families = ["yetiRig"]
label = "Yeti Rig Input Shapes In Instance"
actions = [ayon_core.hosts.maya.api.action.SelectInvalidAction]
optional = False
def process(self, instance):
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:
raise PublishValidationError("Yeti Rig has invalid input meshes")

View file

@ -1,9 +1,13 @@
import pyblish.api
from ayon_core.pipeline.publish import PublishValidationError
from ayon_core.pipeline.publish import (
PublishValidationError,
OptionalPyblishPluginMixin
)
class ValidateYetiRigSettings(pyblish.api.InstancePlugin):
class ValidateYetiRigSettings(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Validate Yeti Rig Settings have collected input connections.
The input connections are collected for the nodes in the `input_SET`.
@ -15,9 +19,11 @@ class ValidateYetiRigSettings(pyblish.api.InstancePlugin):
order = pyblish.api.ValidatorOrder
label = "Yeti Rig Settings"
families = ["yetiRig"]
optional = False
def process(self, instance):
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:
raise PublishValidationError(

View file

@ -1,10 +1,7 @@
import collections
from ayon_core.lib.attribute_definitions import BoolDef
from ayon_core.pipeline import (
get_representation_context,
registered_host,
)
from ayon_core.pipeline import registered_host
from ayon_core.hosts.tvpaint.api import plugin
from ayon_core.hosts.tvpaint.api.lib import (
get_layers_data,
@ -218,10 +215,7 @@ class LoadImage(plugin.Loader):
removed.
"""
repre_entity = context["representation"]
# Create new containers first
context = get_representation_context(repre_entity["id"])
# Get layer ids from previous container
old_layer_names = self.get_members_from_container(container)

View file

@ -1953,11 +1953,11 @@ class CreateContext:
"""Trigger create of plugins with standartized arguments.
Arguments 'folder_entity' and 'task_name' use current context as
default values. If only 'task_name' is provided it will be overriden
by task name from current context. If 'task_name' is not provided
when 'folder_entity' is, it is considered that task name is not
specified, which can lead to error if product name template requires
task name.
default values. If only 'task_entity' is provided it will be
overridden by task name from current context. If 'task_name' is not
provided when 'folder_entity' is, it is considered that task name is
not specified, which can lead to error if product name template
requires task name.
Args:
creator_identifier (str): Identifier of creator plugin.
@ -1986,6 +1986,8 @@ class CreateContext:
raise CreatorError(
"Folder '{}' was not found".format(folder_path)
)
task_name = None
if task_entity is None:
task_name = self.get_current_task_name()
task_entity = ayon_api.get_task_by_name(

View file

@ -240,7 +240,7 @@ class SwitchAssetDialog(QtWidgets.QDialog):
return ayon_api.get_last_versions(
project_name,
product_ids,
fields={"id", "folderId", "version"}
fields={"id", "productId", "version"}
)
def _on_show_timer(self):