mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
Merge branch 'develop' into enhancement/add-ruff-and-code-spell
This commit is contained in:
commit
7d0c014367
89 changed files with 813 additions and 482 deletions
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
"""
|
||||
)
|
||||
|
|
@ -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.
|
||||
"""
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 = []
|
||||
|
|
|
|||
|
|
@ -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 "
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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: "
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
||||
|
|
|
|||
|
|
@ -1,75 +0,0 @@
|
|||
import maya.cmds as cmds
|
||||
import pyblish.api
|
||||
|
||||
from ayon_core.hosts.maya.api import lib
|
||||
from ayon_core.pipeline.publish import PublishValidationError
|
||||
|
||||
|
||||
class ValidateInstancerContent(pyblish.api.InstancePlugin):
|
||||
"""Validates that all meshes in the instance have object IDs.
|
||||
|
||||
This skips a check on intermediate objects because we consider them
|
||||
not important.
|
||||
"""
|
||||
order = pyblish.api.ValidatorOrder
|
||||
label = 'Instancer Content'
|
||||
families = ['instancer']
|
||||
|
||||
def process(self, instance):
|
||||
|
||||
error = False
|
||||
members = instance.data['setMembers']
|
||||
export_members = instance.data['exactExportMembers']
|
||||
|
||||
self.log.debug("Contents {0}".format(members))
|
||||
|
||||
if not len(members) == len(cmds.ls(members, type="instancer")):
|
||||
self.log.error("Instancer can only contain instancers")
|
||||
error = True
|
||||
|
||||
# TODO: Implement better check for particles are cached
|
||||
if not cmds.ls(export_members, type="nucleus"):
|
||||
self.log.error("Instancer must have a connected nucleus")
|
||||
error = True
|
||||
|
||||
if not cmds.ls(export_members, type="cacheFile"):
|
||||
self.log.error("Instancer must be cached")
|
||||
error = True
|
||||
|
||||
hidden = self.check_geometry_hidden(export_members)
|
||||
if not hidden:
|
||||
error = True
|
||||
self.log.error("Instancer input geometry must be hidden "
|
||||
"the scene. Invalid: {0}".format(hidden))
|
||||
|
||||
# Ensure all in one group
|
||||
parents = cmds.listRelatives(members,
|
||||
allParents=True,
|
||||
fullPath=True) or []
|
||||
roots = list(set(cmds.ls(parents, assemblies=True, long=True)))
|
||||
if len(roots) > 1:
|
||||
self.log.error("Instancer should all be contained in a single "
|
||||
"group. Current roots: {0}".format(roots))
|
||||
error = True
|
||||
|
||||
if error:
|
||||
raise PublishValidationError(
|
||||
"Instancer Content is invalid. See log.")
|
||||
|
||||
def check_geometry_hidden(self, export_members):
|
||||
|
||||
# Ensure all instanced geometry is hidden
|
||||
shapes = cmds.ls(export_members,
|
||||
dag=True,
|
||||
shapes=True,
|
||||
noIntermediate=True)
|
||||
meshes = cmds.ls(shapes, type="mesh")
|
||||
|
||||
visible = [node for node in meshes
|
||||
if lib.is_visible(node,
|
||||
displayLayer=False,
|
||||
intermediateObject=False)]
|
||||
if visible:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
|
@ -1,167 +0,0 @@
|
|||
import os
|
||||
import re
|
||||
|
||||
import pyblish.api
|
||||
|
||||
from ayon_core.pipeline.publish import PublishValidationError
|
||||
|
||||
|
||||
def is_cache_resource(resource):
|
||||
"""Return whether resource is a cacheFile resource"""
|
||||
required = set(["maya", "node", "cacheFile"])
|
||||
tags = resource.get("tags", [])
|
||||
return required.issubset(tags)
|
||||
|
||||
|
||||
def valdidate_files(files):
|
||||
for f in files:
|
||||
assert os.path.exists(f)
|
||||
assert f.endswith(".mcx") or f.endswith(".mcc")
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def filter_ticks(files):
|
||||
tick_files = set()
|
||||
ticks = set()
|
||||
for path in files:
|
||||
match = re.match(".+Tick([0-9]+).mcx$", os.path.basename(path))
|
||||
if match:
|
||||
tick_files.add(path)
|
||||
num = match.group(1)
|
||||
ticks.add(int(num))
|
||||
|
||||
return tick_files, ticks
|
||||
|
||||
|
||||
class ValidateInstancerFrameRanges(pyblish.api.InstancePlugin):
|
||||
"""Validates all instancer particle systems are cached correctly.
|
||||
|
||||
This means they should have the files/frames as required by the start-end
|
||||
frame (including handles).
|
||||
|
||||
This also checks the files exist and checks the "ticks" (substeps) files.
|
||||
|
||||
"""
|
||||
order = pyblish.api.ValidatorOrder
|
||||
label = 'Instancer Cache Frame Ranges'
|
||||
families = ['instancer']
|
||||
|
||||
@classmethod
|
||||
def get_invalid(cls, instance):
|
||||
|
||||
import pyseq
|
||||
|
||||
start_frame = instance.data.get("frameStart", 0)
|
||||
end_frame = instance.data.get("frameEnd", 0)
|
||||
required = range(int(start_frame), int(end_frame) + 1)
|
||||
|
||||
invalid = list()
|
||||
resources = instance.data.get("resources", [])
|
||||
|
||||
for resource in resources:
|
||||
if not is_cache_resource(resource):
|
||||
continue
|
||||
|
||||
node = resource['node']
|
||||
all_files = resource['files'][:]
|
||||
all_lookup = set(all_files)
|
||||
|
||||
# The first file is usually the .xml description file.
|
||||
xml = all_files.pop(0)
|
||||
assert xml.endswith(".xml")
|
||||
|
||||
# Ensure all files exist (including ticks)
|
||||
# The remainder file paths should be the .mcx or .mcc files
|
||||
valdidate_files(all_files)
|
||||
|
||||
# Maya particle caches support substeps by saving out additional
|
||||
# files that end with a Tick60.mcx, Tick120.mcx, etc. suffix.
|
||||
# To avoid `pyseq` getting confused we filter those out and then
|
||||
# for each file (except the last frame) check that at least all
|
||||
# ticks exist.
|
||||
|
||||
tick_files, ticks = filter_ticks(all_files)
|
||||
if tick_files:
|
||||
files = [f for f in all_files if f not in tick_files]
|
||||
else:
|
||||
files = all_files
|
||||
|
||||
sequences = pyseq.get_sequences(files)
|
||||
if len(sequences) != 1:
|
||||
invalid.append(node)
|
||||
cls.log.warning("More than one sequence found? "
|
||||
"{0} {1}".format(node, files))
|
||||
cls.log.warning("Found caches: {0}".format(sequences))
|
||||
continue
|
||||
|
||||
sequence = sequences[0]
|
||||
cls.log.debug("Found sequence: {0}".format(sequence))
|
||||
|
||||
start = sequence.start()
|
||||
end = sequence.end()
|
||||
|
||||
if start > start_frame or end < end_frame:
|
||||
invalid.append(node)
|
||||
cls.log.warning("Sequence does not have enough "
|
||||
"frames: {0}-{1} (requires: {2}-{3})"
|
||||
"".format(start, end,
|
||||
start_frame,
|
||||
end_frame))
|
||||
continue
|
||||
|
||||
# Ensure all frames are present
|
||||
missing = set(sequence.missing())
|
||||
if missing:
|
||||
required_missing = [x for x in required if x in missing]
|
||||
if required_missing:
|
||||
invalid.append(node)
|
||||
cls.log.warning("Sequence is missing required frames: "
|
||||
"{0}".format(required_missing))
|
||||
continue
|
||||
|
||||
# Ensure all tick files (substep) exist for the files in the folder
|
||||
# for the frames required by the time range.
|
||||
if ticks:
|
||||
ticks = list(sorted(ticks))
|
||||
cls.log.debug("Found ticks: {0} "
|
||||
"(substeps: {1})".format(ticks, len(ticks)))
|
||||
|
||||
# Check all frames except the last since we don't
|
||||
# require subframes after our time range.
|
||||
tick_check_frames = set(required[:-1])
|
||||
|
||||
# Check all frames
|
||||
for item in sequence:
|
||||
frame = item.frame
|
||||
if not frame:
|
||||
invalid.append(node)
|
||||
cls.log.error("Path is not a frame in sequence: "
|
||||
"{0}".format(item))
|
||||
continue
|
||||
|
||||
# Not required for our time range
|
||||
if frame not in tick_check_frames:
|
||||
continue
|
||||
|
||||
path = item.path
|
||||
for num in ticks:
|
||||
base, ext = os.path.splitext(path)
|
||||
tick_file = base + "Tick{0}".format(num) + ext
|
||||
if tick_file not in all_lookup:
|
||||
invalid.append(node)
|
||||
cls.log.warning("Tick file found that is not "
|
||||
"in cache query filenames: "
|
||||
"{0}".format(tick_file))
|
||||
|
||||
return invalid
|
||||
|
||||
def process(self, instance):
|
||||
|
||||
invalid = self.get_invalid(instance)
|
||||
|
||||
if invalid:
|
||||
self.log.error("Invalid nodes: {0}".format(invalid))
|
||||
raise PublishValidationError(
|
||||
("Invalid particle caches in instance. "
|
||||
"See logs for details."))
|
||||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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.")
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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 '
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
||||
|
|
|
|||
|
|
@ -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. "
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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'!"
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
"""
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
__version__ = "0.1.7"
|
||||
__version__ = "0.1.8"
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
__version__ = "0.1.9"
|
||||
__version__ = "0.1.10"
|
||||
|
|
|
|||
|
|
@ -753,14 +753,6 @@ class PublishersModel(BaseSettingsModel):
|
|||
default_factory=BasicValidateModel,
|
||||
title="Validate Ass Relative Paths"
|
||||
)
|
||||
ValidateInstancerContent: BasicValidateModel = SettingsField(
|
||||
default_factory=BasicValidateModel,
|
||||
title="Validate Instancer Content"
|
||||
)
|
||||
ValidateInstancerFrameRanges: BasicValidateModel = SettingsField(
|
||||
default_factory=BasicValidateModel,
|
||||
title="Validate Instancer Cache Frame Ranges"
|
||||
)
|
||||
ValidateNoDefaultCameras: BasicValidateModel = SettingsField(
|
||||
default_factory=BasicValidateModel,
|
||||
title="Validate No Default Cameras"
|
||||
|
|
@ -1300,16 +1292,6 @@ DEFAULT_PUBLISH_SETTINGS = {
|
|||
"optional": False,
|
||||
"active": True
|
||||
},
|
||||
"ValidateInstancerContent": {
|
||||
"enabled": True,
|
||||
"optional": False,
|
||||
"active": True
|
||||
},
|
||||
"ValidateInstancerFrameRanges": {
|
||||
"enabled": True,
|
||||
"optional": False,
|
||||
"active": True
|
||||
},
|
||||
"ValidateNoDefaultCameras": {
|
||||
"enabled": True,
|
||||
"optional": False,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Package declaring addon version."""
|
||||
__version__ = "0.1.9"
|
||||
__version__ = "0.1.10"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue