Merge branch 'develop' into chore/fix_typos

This commit is contained in:
Ondřej Samohel 2024-03-25 12:07:19 +01:00 committed by GitHub
commit bdf7029720
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
87 changed files with 830 additions and 228 deletions

View file

@ -67,8 +67,6 @@ class Commands:
install_ayon_plugins,
get_global_context,
)
from ayon_core.tools.utils.host_tools import show_publish
from ayon_core.tools.utils.lib import qt_app_context
# Register target and host
import pyblish.api
@ -134,6 +132,8 @@ class Commands:
print(plugin)
if gui:
from ayon_core.tools.utils.host_tools import show_publish
from ayon_core.tools.utils.lib import qt_app_context
with qt_app_context():
show_publish()
else:

View file

@ -37,7 +37,8 @@ class ValidateFileSaved(pyblish.api.ContextPlugin,
if not context.data["currentFile"]:
# File has not been saved at all and has no filename
raise PublishValidationError(
"Current file is empty. Save the file before continuing."
"Current workfile has not been saved yet.\n"
"Save the workfile before continuing."
)
# Do not validate workfile has unsaved changes if only instances

View file

@ -0,0 +1,94 @@
import inspect
from typing import List
import bpy
import pyblish.api
from ayon_core.pipeline.publish import (
ValidateContentsOrder,
OptionalPyblishPluginMixin,
PublishValidationError,
RepairAction
)
import ayon_core.hosts.blender.api.action
class ValidateModelMeshUvMap1(
pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin,
):
"""Validate model mesh uvs are named `map1`.
This is solely to get them to work nicely for the Maya pipeline.
"""
order = ValidateContentsOrder
hosts = ["blender"]
families = ["model"]
label = "Mesh UVs named map1"
actions = [ayon_core.hosts.blender.api.action.SelectInvalidAction,
RepairAction]
optional = True
enabled = False
@classmethod
def get_invalid(cls, instance) -> List:
invalid = []
for obj in instance:
if obj.mode != "OBJECT":
cls.log.warning(
f"Mesh object {obj.name} should be in 'OBJECT' mode"
" to be properly checked."
)
obj_data = obj.data
if isinstance(obj_data, bpy.types.Mesh):
mesh = obj_data
# Ignore mesh without UVs
if not mesh.uv_layers:
continue
# If mesh has map1 all is ok
if mesh.uv_layers.get("map1"):
continue
cls.log.warning(
f"Mesh object {obj.name} should be in 'OBJECT' mode"
" to be properly checked."
)
invalid.append(obj)
return invalid
@classmethod
def repair(cls, instance):
for obj in cls.get_invalid(instance):
mesh = obj.data
# Rename the first UV set to map1
mesh.uv_layers[0].name = "map1"
def process(self, instance):
if not self.is_active(instance.data):
return
invalid = self.get_invalid(instance)
if invalid:
raise PublishValidationError(
f"Meshes found in instance without valid UV's: {invalid}",
description=self.get_description()
)
def get_description(self):
return inspect.cleandoc(
"""## Meshes must have map1 uv set
To accompany a better Maya-focused pipeline with Alembics it is
expected that a Mesh has a `map1` UV set. Blender defaults to
a UV set named `UVMap` and thus needs to be renamed.
"""
)

View file

@ -1,3 +1,4 @@
import inspect
from typing import List
import mathutils
@ -5,29 +6,26 @@ import bpy
import pyblish.api
from ayon_core.hosts.blender.api import plugin, lib
import ayon_core.hosts.blender.api.action
from ayon_core.pipeline.publish import (
ValidateContentsOrder,
OptionalPyblishPluginMixin,
PublishValidationError
PublishValidationError,
RepairAction
)
class ValidateTransformZero(pyblish.api.InstancePlugin,
OptionalPyblishPluginMixin):
"""Transforms can't have any values
To solve this issue, try freezing the transforms. So long
as the transforms, rotation and scale values are zero,
you're all good.
"""
"""Transforms can't have any values"""
order = ValidateContentsOrder
hosts = ["blender"]
families = ["model"]
label = "Transform Zero"
actions = [ayon_core.hosts.blender.api.action.SelectInvalidAction]
actions = [ayon_core.hosts.blender.api.action.SelectInvalidAction,
RepairAction]
_identity = mathutils.Matrix()
@ -51,5 +49,46 @@ class ValidateTransformZero(pyblish.api.InstancePlugin,
names = ", ".join(obj.name for obj in invalid)
raise PublishValidationError(
"Objects found in instance which do not"
f" have transform set to zero: {names}"
f" have transform set to zero: {names}",
description=self.get_description()
)
@classmethod
def repair(cls, instance):
invalid = cls.get_invalid(instance)
if not invalid:
return
context = plugin.create_blender_context(
active=invalid[0], selected=invalid
)
with lib.maintained_selection():
with bpy.context.temp_override(**context):
plugin.deselect_all()
for obj in invalid:
obj.select_set(True)
# TODO: Preferably this does allow custom pivot point locations
# and if so, this should likely apply to the delta instead
# using `bpy.ops.object.transforms_to_deltas(mode="ALL")`
bpy.ops.object.transform_apply(location=True,
rotation=True,
scale=True)
def get_description(self):
return inspect.cleandoc(
"""## Transforms can't have any values.
The location, rotation and scale on the transform must be at
the default values. This also goes for the delta transforms.
To solve this issue, try freezing the transforms:
- `Object` > `Apply` > `All Transforms`
Using the Repair action directly will do the same.
So long as the transforms, rotation and scale values are zero,
you're all good.
"""
)

View file

@ -1,7 +1,6 @@
from ayon_core.lib import NumberDef
from ayon_core.hosts.fusion.api.plugin import GenericCreateSaver
from ayon_core.hosts.fusion.api import get_current_comp
class CreateImageSaver(GenericCreateSaver):

View file

@ -50,11 +50,11 @@ class ImportTemplateLoader(load.LoaderPlugin):
self.__class__.__name__
)
def update(self, container, context):
pass
def update(self, container, context):
pass
def remove(self, container):
pass
def remove(self, container):
pass
class ImportWorkfileLoader(ImportTemplateLoader):

View file

@ -147,7 +147,6 @@ class HoudiniCreatorBase(object):
def create_instance_node(
folder_path, node_name, parent, node_type="geometry"
):
# type: (str, str, str) -> hou.Node
"""Create node representing instance.
Arguments:

View file

@ -16,7 +16,7 @@ class CreateHDA(plugin.HoudiniCreator):
maintain_selection = False
def _check_existing(self, folder_path, product_name):
# type: (str) -> bool
# type: (str, str) -> bool
"""Check if existing product name versions already exists."""
# Get all products of the current folder
project_name = self.project_name

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

@ -40,9 +40,11 @@ class _NodeTypeAttrib(object):
return "{}.{}".format(node, self.colour_space)
def __str__(self):
return "_NodeTypeAttrib(name={}, fname={}, "
"computed_fname={}, colour_space={})".format(
self.name, self.fname, self.computed_fname, self.colour_space)
return (
"_NodeTypeAttrib(name={}, fname={}, "
"computed_fname={}, colour_space={})".format(
self.name, self.fname, self.computed_fname, self.colour_space)
)
NODETYPES = {

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

@ -9,7 +9,6 @@ class CollectAutoImage(pyblish.api.ContextPlugin):
"""
label = "Collect Auto Image"
order = pyblish.api.CollectorOrder
hosts = ["photoshop"]
order = pyblish.api.CollectorOrder + 0.2

View file

@ -8,7 +8,6 @@ class CollectAutoImageRefresh(pyblish.api.ContextPlugin):
"""
label = "Collect Auto Image Refresh"
order = pyblish.api.CollectorOrder
hosts = ["photoshop"]
order = pyblish.api.CollectorOrder + 0.2

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

@ -10,6 +10,87 @@ class _Cache:
initialized = False
def _new_get_last_versions(
self,
project_name,
product_ids,
active=True,
fields=None,
own_attributes=False
):
"""Query last version entities by product ids.
Args:
project_name (str): Project where to look for representation.
product_ids (Iterable[str]): Product ids.
active (Optional[bool]): Receive active/inactive entities.
Both are returned when 'None' is passed.
fields (Optional[Iterable[str]]): fields to be queried
for representations.
own_attributes (Optional[bool]): Attribute values that are
not explicitly set on entity will have 'None' value.
Returns:
dict[str, dict[str, Any]]: Last versions by product id.
"""
if fields:
fields = set(fields)
fields.add("productId")
versions = self.get_versions(
project_name,
product_ids=product_ids,
latest=True,
hero=False,
active=active,
fields=fields,
own_attributes=own_attributes
)
return {
version["productId"]: version
for version in versions
}
def _new_get_last_version_by_product_id(
self,
project_name,
product_id,
active=True,
fields=None,
own_attributes=False
):
"""Query last version entity by product id.
Args:
project_name (str): Project where to look for representation.
product_id (str): Product id.
active (Optional[bool]): Receive active/inactive entities.
Both are returned when 'None' is passed.
fields (Optional[Iterable[str]]): fields to be queried
for representations.
own_attributes (Optional[bool]): Attribute values that are
not explicitly set on entity will have 'None' value.
Returns:
Union[dict[str, Any], None]: Queried version entity or None.
"""
versions = self.get_versions(
project_name,
product_ids=[product_id],
latest=True,
hero=False,
active=active,
fields=fields,
own_attributes=own_attributes
)
for version in versions:
return version
return None
def _new_get_last_version_by_product_name(
self,
project_name,
@ -73,9 +154,15 @@ def initialize_ayon_connection(force=False):
semver.VersionInfo.parse(ayon_api.__version__).to_tuple()
)
# TODO remove mokey patching after when AYON api is safely updated
fix_last_version_by_product_name = ayon_api_version < (1, 0, 2)
fix_before_1_0_2 = ayon_api_version < (1, 0, 2)
# Monkey patching to fix 'get_last_version_by_product_name'
if fix_last_version_by_product_name:
if fix_before_1_0_2:
ayon_api.ServerAPI.get_last_versions = (
_new_get_last_versions
)
ayon_api.ServerAPI.get_last_version_by_product_id = (
_new_get_last_version_by_product_id
)
ayon_api.ServerAPI.get_last_version_by_product_name = (
_new_get_last_version_by_product_name
)
@ -85,12 +172,22 @@ def initialize_ayon_connection(force=False):
if ayon_api.is_connection_created():
con = ayon_api.get_server_api_connection()
# Monkey patching to fix 'get_last_version_by_product_name'
if fix_last_version_by_product_name:
def _con_wrapper(*args, **kwargs):
if fix_before_1_0_2:
def _lvs_wrapper(*args, **kwargs):
return _new_get_last_versions(
con, *args, **kwargs
)
def _lv_by_pi_wrapper(*args, **kwargs):
return _new_get_last_version_by_product_id(
con, *args, **kwargs
)
def _lv_by_pn_wrapper(*args, **kwargs):
return _new_get_last_version_by_product_name(
con, *args, **kwargs
)
con.get_last_version_by_product_name = _con_wrapper
con.get_last_versions = _lvs_wrapper
con.get_last_version_by_product_id = _lv_by_pi_wrapper
con.get_last_version_by_product_name = _lv_by_pn_wrapper
con.set_site_id(site_id)
con.set_client_version(version)
else:

View file

@ -46,7 +46,6 @@ class DeadlineModule(AYONAddon, IPluginPaths):
@staticmethod
def get_deadline_pools(webservice, log=None):
# type: (str) -> list
"""Get pools from Deadline.
Args:
webservice (str): Server url.

View file

@ -9,11 +9,11 @@ class CollectDefaultDeadlineServer(pyblish.api.ContextPlugin):
DL webservice addresses must be configured first in System Settings for
project settings enum to work.
Default webservice could be overriden by
Default webservice could be overridden by
`project_settings/deadline/deadline_servers`. Currently only single url
is expected.
This url could be overriden by some hosts directly on instances with
This url could be overridden by some hosts directly on instances with
`CollectDeadlineServerFromInstance`.
"""

View file

@ -31,14 +31,22 @@ class CollectDeadlinePools(pyblish.api.InstancePlugin,
"harmony"
"nuke",
"maya",
"max"]
"max",
"houdini"]
families = ["render",
"rendering",
"render.farm",
"renderFarm",
"renderlayer",
"maxrender"]
"maxrender",
"usdrender",
"redshift_rop",
"arnold_rop",
"mantra_rop",
"karma_rop",
"vray_rop",
"publish.hou"]
primary_pool = None
secondary_pool = None

View file

@ -45,9 +45,11 @@ class HoudiniCacheSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline
targets = ["local"]
priority = 50
chunk_size = 999999
group = None
jobInfo = {}
pluginInfo = {}
group = None
def get_job_info(self):
job_info = DeadlineJobInfo(Plugin="Houdini")
@ -88,7 +90,7 @@ class HoudiniCacheSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline
attr_values = self.get_attr_values_from_data(instance.data)
job_info.ChunkSize = instance.data["chunkSize"]
job_info.ChunkSize = instance.data.get("chunk_size", self.chunk_size)
job_info.Comment = context.data.get("comment")
job_info.Priority = attr_values.get("priority", self.priority)
job_info.Group = attr_values.get("group", self.group)

View file

@ -11,6 +11,7 @@ from openpype_modules.deadline.abstract_submit_deadline import DeadlineJobInfo
from ayon_core.lib import (
is_in_tests,
BoolDef,
TextDef,
NumberDef
)
@ -79,16 +80,21 @@ class HoudiniSubmitDeadline(
use_published = True
# presets
priority = 50
chunk_size = 1
export_priority = 50
export_chunk_size = 10
group = ""
export_group = ""
priority = 50
chunk_size = 1
group = ""
@classmethod
def get_attribute_defs(cls):
return [
BoolDef(
"suspend_publish",
default=False,
label="Suspend publish"
),
NumberDef(
"priority",
label="Priority",
@ -103,10 +109,15 @@ class HoudiniSubmitDeadline(
minimum=1,
maximum=1000
),
TextDef(
"group",
default=cls.group,
label="Group Name"
),
NumberDef(
"export_priority",
label="Export Priority",
default=cls.priority,
default=cls.export_priority,
decimals=0
),
NumberDef(
@ -117,11 +128,11 @@ class HoudiniSubmitDeadline(
minimum=1,
maximum=1000
),
BoolDef(
"suspend_publish",
default=False,
label="Suspend publish"
)
TextDef(
"export_group",
default=cls.export_group,
label="Export Group Name"
),
]
def get_job_info(self, dependency_job_ids=None):
@ -163,15 +174,6 @@ class HoudiniSubmitDeadline(
job_info.UserName = context.data.get(
"deadlineUser", getpass.getuser())
if split_render_job and is_export_job:
job_info.Priority = attribute_values.get(
"export_priority", self.export_priority
)
else:
job_info.Priority = attribute_values.get(
"priority", self.priority
)
if is_in_tests():
job_info.BatchName += datetime.now().strftime("%d%m%Y%H%M%S")
@ -192,15 +194,23 @@ class HoudiniSubmitDeadline(
job_info.Pool = instance.data.get("primaryPool")
job_info.SecondaryPool = instance.data.get("secondaryPool")
job_info.Group = self.group
if split_render_job and is_export_job:
job_info.Priority = attribute_values.get(
"export_priority", self.export_priority
)
job_info.ChunkSize = attribute_values.get(
"export_chunk", self.export_chunk_size
)
job_info.Group = self.export_group
else:
job_info.Priority = attribute_values.get(
"priority", self.priority
)
job_info.ChunkSize = attribute_values.get(
"chunk", self.chunk_size
)
job_info.Group = self.group
job_info.Comment = context.data.get("comment")

View file

@ -149,7 +149,7 @@ class ValidateExpectedFiles(pyblish.api.InstancePlugin):
"""
# no frames in file name at all, eg 'renderCompositingMain.withLut.mov'
if not frame_placeholder:
return set([file_name_template])
return {file_name_template}
real_expected_rendered = set()
src_padding_exp = "%0{}d".format(len(frame_placeholder))

View file

@ -404,7 +404,7 @@ class OpenPypeTileAssembler(DeadlinePlugin):
Args:
output_width (int): Width of output image.
output_height (int): Height of output image.
tiles_info (list): List of tile items, each item must be
tile_info (list): List of tile items, each item must be
dictionary with `filepath`, `pos_x` and `pos_y` keys
representing path to file and x, y coordinates on output
image where top-left point of tile item should start.

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):

View file

@ -89,6 +89,10 @@ class PublishPuginsModel(BaseSettingsModel):
default_factory=ValidatePluginModel,
title="Validate Mesh No Negative Scale"
)
ValidateModelMeshUvMap1: ValidatePluginModel = SettingsField(
default_factory=ValidatePluginModel,
title="Validate Model Mesh Has UV map named map1"
)
ValidateTransformZero: ValidatePluginModel = SettingsField(
default_factory=ValidatePluginModel,
title="Validate Transform Zero"
@ -181,6 +185,11 @@ DEFAULT_BLENDER_PUBLISH_SETTINGS = {
"optional": False,
"active": True
},
"ValidateModelMeshUvMap1": {
"enabled": False,
"optional": True,
"active": True
},
"ValidateTransformZero": {
"enabled": False,
"optional": True,

View file

@ -1 +1 @@
__version__ = "0.1.7"
__version__ = "0.1.8"

View file

@ -211,6 +211,32 @@ class HarmonySubmitDeadlineModel(BaseSettingsModel):
department: str = SettingsField(title="Department")
class HoudiniSubmitDeadlineModel(BaseSettingsModel):
"""Houdini deadline render submitter settings."""
enabled: bool = SettingsField(title="Enabled")
optional: bool = SettingsField(title="Optional")
active: bool = SettingsField(title="Active")
priority: int = SettingsField(title="Priority")
chunk_size: int = SettingsField(title="Chunk Size")
group: str = SettingsField(title="Group")
export_priority: int = SettingsField(title="Export Priority")
export_chunk_size: int = SettingsField(title="Export Chunk Size")
export_group: str = SettingsField(title="Export Group")
class HoudiniCacheSubmitDeadlineModel(BaseSettingsModel):
"""Houdini deadline cache submitter settings."""
enabled: bool = SettingsField(title="Enabled")
optional: bool = SettingsField(title="Optional")
active: bool = SettingsField(title="Active")
priority: int = SettingsField(title="Priority")
chunk_size: int = SettingsField(title="Chunk Size")
group: str = SettingsField(title="Group")
class AfterEffectsSubmitDeadlineModel(BaseSettingsModel):
"""After Effects deadline submitter settings."""
@ -332,6 +358,12 @@ class PublishPluginsModel(BaseSettingsModel):
HarmonySubmitDeadline: HarmonySubmitDeadlineModel = SettingsField(
default_factory=HarmonySubmitDeadlineModel,
title="Harmony Submit to deadline")
HoudiniCacheSubmitDeadline: HoudiniCacheSubmitDeadlineModel = SettingsField(
default_factory=HoudiniCacheSubmitDeadlineModel,
title="Houdini Submit cache to deadline")
HoudiniSubmitDeadline: HoudiniSubmitDeadlineModel = SettingsField(
default_factory=HoudiniSubmitDeadlineModel,
title="Houdini Submit render to deadline")
MaxSubmitDeadline: MaxSubmitDeadlineModel = SettingsField(
default_factory=MaxSubmitDeadlineModel,
title="Max Submit to deadline")
@ -416,6 +448,25 @@ DEFAULT_DEADLINE_PLUGINS_SETTINGS = {
"group": "",
"department": ""
},
"HoudiniCacheSubmitDeadline": {
"enabled": True,
"optional": False,
"active": True,
"priority": 50,
"chunk_size": 999999,
"group": ""
},
"HoudiniSubmitDeadline": {
"enabled": True,
"optional": False,
"active": True,
"priority": 50,
"chunk_size": 1,
"group": "",
"export_priority": 50,
"export_chunk_size": 10,
"export_group": ""
},
"MaxSubmitDeadline": {
"enabled": True,
"optional": False,

View file

@ -1 +1 @@
__version__ = "0.1.9"
__version__ = "0.1.10"