From 09e0ba54f24c73a721f6f4d31ce23c3d786178c6 Mon Sep 17 00:00:00 2001
From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com>
Date: Mon, 27 Mar 2023 09:57:37 +0200
Subject: [PATCH] TVPaint: Optional Validation plugins can be de/activated by
user (#4674)
* fix TVPaint validation plugins so they can be enabled/disabled
* add missing 'is_active' method usage
* added option to enable auto detet render creator
* added fps to instance data
* safe access to layers
* fix handling of missing render layer
* render passes are safer
* fix convertor plugin
---
.../tvpaint/plugins/create/convert_legacy.py | 4 ++--
.../hosts/tvpaint/plugins/create/create_render.py | 15 ++++++++-------
.../plugins/publish/collect_instance_frames.py | 2 ++
.../plugins/publish/validate_asset_name.py | 12 ++++++++++--
.../plugins/publish/validate_layers_visibility.py | 2 +-
.../tvpaint/plugins/publish/validate_marks.py | 13 +++++++++++--
.../plugins/publish/validate_scene_settings.py | 13 +++++++++++--
.../plugins/publish/validate_start_frame.py | 13 +++++++++++--
.../defaults/project_settings/tvpaint.json | 1 +
.../projects_schema/schema_project_tvpaint.json | 6 ++++++
10 files changed, 63 insertions(+), 18 deletions(-)
diff --git a/openpype/hosts/tvpaint/plugins/create/convert_legacy.py b/openpype/hosts/tvpaint/plugins/create/convert_legacy.py
index 538c6e4c5e..5cfa1faa50 100644
--- a/openpype/hosts/tvpaint/plugins/create/convert_legacy.py
+++ b/openpype/hosts/tvpaint/plugins/create/convert_legacy.py
@@ -55,7 +55,7 @@ class TVPaintLegacyConverted(SubsetConvertorPlugin):
self._convert_render_layers(
to_convert["renderLayer"], current_instances)
self._convert_render_passes(
- to_convert["renderpass"], current_instances)
+ to_convert["renderPass"], current_instances)
self._convert_render_scenes(
to_convert["renderScene"], current_instances)
self._convert_workfiles(
@@ -116,7 +116,7 @@ class TVPaintLegacyConverted(SubsetConvertorPlugin):
render_layers_by_group_id = {}
for instance in current_instances:
if instance.get("creator_identifier") == "render.layer":
- group_id = instance["creator_identifier"]["group_id"]
+ group_id = instance["creator_attributes"]["group_id"]
render_layers_by_group_id[group_id] = instance
for render_pass in render_passes:
diff --git a/openpype/hosts/tvpaint/plugins/create/create_render.py b/openpype/hosts/tvpaint/plugins/create/create_render.py
index 9711024c79..2369c7329f 100644
--- a/openpype/hosts/tvpaint/plugins/create/create_render.py
+++ b/openpype/hosts/tvpaint/plugins/create/create_render.py
@@ -415,11 +415,11 @@ class CreateRenderPass(TVPaintCreator):
.get("creator_attributes", {})
.get("render_layer_instance_id")
)
- render_layer_info = render_layers.get(render_layer_instance_id)
+ render_layer_info = render_layers.get(render_layer_instance_id, {})
self.update_instance_labels(
instance_data,
- render_layer_info["variant"],
- render_layer_info["template_data"]
+ render_layer_info.get("variant"),
+ render_layer_info.get("template_data")
)
instance = CreatedInstance.from_existing(instance_data, self)
self._add_instance_to_context(instance)
@@ -607,11 +607,11 @@ class CreateRenderPass(TVPaintCreator):
current_instances = self.host.list_instances()
render_layers = [
{
- "value": instance["instance_id"],
- "label": instance["subset"]
+ "value": inst["instance_id"],
+ "label": inst["subset"]
}
- for instance in current_instances
- if instance["creator_identifier"] == CreateRenderlayer.identifier
+ for inst in current_instances
+ if inst.get("creator_identifier") == CreateRenderlayer.identifier
]
if not render_layers:
render_layers.append({"value": None, "label": "N/A"})
@@ -697,6 +697,7 @@ class TVPaintAutoDetectRenderCreator(TVPaintCreator):
["create"]
["auto_detect_render"]
)
+ self.enabled = plugin_settings.get("enabled", False)
self.allow_group_rename = plugin_settings["allow_group_rename"]
self.group_name_template = plugin_settings["group_name_template"]
self.group_idx_offset = plugin_settings["group_idx_offset"]
diff --git a/openpype/hosts/tvpaint/plugins/publish/collect_instance_frames.py b/openpype/hosts/tvpaint/plugins/publish/collect_instance_frames.py
index 5eb702a1da..63f04cf3ce 100644
--- a/openpype/hosts/tvpaint/plugins/publish/collect_instance_frames.py
+++ b/openpype/hosts/tvpaint/plugins/publish/collect_instance_frames.py
@@ -22,9 +22,11 @@ class CollectOutputFrameRange(pyblish.api.InstancePlugin):
context = instance.context
frame_start = asset_doc["data"]["frameStart"]
+ fps = asset_doc["data"]["fps"]
frame_end = frame_start + (
context.data["sceneMarkOut"] - context.data["sceneMarkIn"]
)
+ instance.data["fps"] = fps
instance.data["frameStart"] = frame_start
instance.data["frameEnd"] = frame_end
self.log.info(
diff --git a/openpype/hosts/tvpaint/plugins/publish/validate_asset_name.py b/openpype/hosts/tvpaint/plugins/publish/validate_asset_name.py
index 7e35726030..d7984ce971 100644
--- a/openpype/hosts/tvpaint/plugins/publish/validate_asset_name.py
+++ b/openpype/hosts/tvpaint/plugins/publish/validate_asset_name.py
@@ -1,5 +1,8 @@
import pyblish.api
-from openpype.pipeline import PublishXmlValidationError
+from openpype.pipeline import (
+ PublishXmlValidationError,
+ OptionalPyblishPluginMixin,
+)
from openpype.hosts.tvpaint.api.pipeline import (
list_instances,
write_instances,
@@ -31,7 +34,10 @@ class FixAssetNames(pyblish.api.Action):
write_instances(new_instance_items)
-class ValidateAssetNames(pyblish.api.ContextPlugin):
+class ValidateAssetName(
+ OptionalPyblishPluginMixin,
+ pyblish.api.ContextPlugin
+):
"""Validate assset name present on instance.
Asset name on instance should be the same as context's.
@@ -43,6 +49,8 @@ class ValidateAssetNames(pyblish.api.ContextPlugin):
actions = [FixAssetNames]
def process(self, context):
+ if not self.is_active(context.data):
+ return
context_asset_name = context.data["asset"]
for instance in context:
asset_name = instance.data.get("asset")
diff --git a/openpype/hosts/tvpaint/plugins/publish/validate_layers_visibility.py b/openpype/hosts/tvpaint/plugins/publish/validate_layers_visibility.py
index 6a496a2e49..8e52a636f4 100644
--- a/openpype/hosts/tvpaint/plugins/publish/validate_layers_visibility.py
+++ b/openpype/hosts/tvpaint/plugins/publish/validate_layers_visibility.py
@@ -11,7 +11,7 @@ class ValidateLayersVisiblity(pyblish.api.InstancePlugin):
families = ["review", "render"]
def process(self, instance):
- layers = instance.data["layers"]
+ layers = instance.data.get("layers")
# Instance have empty layers
# - it is not job of this validator to check that
if not layers:
diff --git a/openpype/hosts/tvpaint/plugins/publish/validate_marks.py b/openpype/hosts/tvpaint/plugins/publish/validate_marks.py
index 0030b0fd1c..7b2cc62bb5 100644
--- a/openpype/hosts/tvpaint/plugins/publish/validate_marks.py
+++ b/openpype/hosts/tvpaint/plugins/publish/validate_marks.py
@@ -1,7 +1,10 @@
import json
import pyblish.api
-from openpype.pipeline import PublishXmlValidationError
+from openpype.pipeline import (
+ PublishXmlValidationError,
+ OptionalPyblishPluginMixin,
+)
from openpype.hosts.tvpaint.api.lib import execute_george
@@ -23,7 +26,10 @@ class ValidateMarksRepair(pyblish.api.Action):
)
-class ValidateMarks(pyblish.api.ContextPlugin):
+class ValidateMarks(
+ OptionalPyblishPluginMixin,
+ pyblish.api.ContextPlugin
+):
"""Validate mark in and out are enabled and it's duration.
Mark In/Out does not have to match frameStart and frameEnd but duration is
@@ -59,6 +65,9 @@ class ValidateMarks(pyblish.api.ContextPlugin):
}
def process(self, context):
+ if not self.is_active(context.data):
+ return
+
current_data = {
"markIn": context.data["sceneMarkIn"],
"markInState": context.data["sceneMarkInState"],
diff --git a/openpype/hosts/tvpaint/plugins/publish/validate_scene_settings.py b/openpype/hosts/tvpaint/plugins/publish/validate_scene_settings.py
index 4473e4b1b7..0ab8e811f5 100644
--- a/openpype/hosts/tvpaint/plugins/publish/validate_scene_settings.py
+++ b/openpype/hosts/tvpaint/plugins/publish/validate_scene_settings.py
@@ -1,11 +1,17 @@
import json
import pyblish.api
-from openpype.pipeline import PublishXmlValidationError
+from openpype.pipeline import (
+ PublishXmlValidationError,
+ OptionalPyblishPluginMixin,
+)
# TODO @iLliCiTiT add fix action for fps
-class ValidateProjectSettings(pyblish.api.ContextPlugin):
+class ValidateProjectSettings(
+ OptionalPyblishPluginMixin,
+ pyblish.api.ContextPlugin
+):
"""Validate scene settings against database."""
label = "Validate Scene Settings"
@@ -13,6 +19,9 @@ class ValidateProjectSettings(pyblish.api.ContextPlugin):
optional = True
def process(self, context):
+ if not self.is_active(context.data):
+ return
+
expected_data = context.data["assetEntity"]["data"]
scene_data = {
"fps": context.data.get("sceneFps"),
diff --git a/openpype/hosts/tvpaint/plugins/publish/validate_start_frame.py b/openpype/hosts/tvpaint/plugins/publish/validate_start_frame.py
index 066e54c670..229ccfcd18 100644
--- a/openpype/hosts/tvpaint/plugins/publish/validate_start_frame.py
+++ b/openpype/hosts/tvpaint/plugins/publish/validate_start_frame.py
@@ -1,5 +1,8 @@
import pyblish.api
-from openpype.pipeline import PublishXmlValidationError
+from openpype.pipeline import (
+ PublishXmlValidationError,
+ OptionalPyblishPluginMixin,
+)
from openpype.hosts.tvpaint.api.lib import execute_george
@@ -14,7 +17,10 @@ class RepairStartFrame(pyblish.api.Action):
execute_george("tv_startframe 0")
-class ValidateStartFrame(pyblish.api.ContextPlugin):
+class ValidateStartFrame(
+ OptionalPyblishPluginMixin,
+ pyblish.api.ContextPlugin
+):
"""Validate start frame being at frame 0."""
label = "Validate Start Frame"
@@ -24,6 +30,9 @@ class ValidateStartFrame(pyblish.api.ContextPlugin):
optional = True
def process(self, context):
+ if not self.is_active(context.data):
+ return
+
start_frame = execute_george("tv_startframe")
if start_frame == 0:
return
diff --git a/openpype/settings/defaults/project_settings/tvpaint.json b/openpype/settings/defaults/project_settings/tvpaint.json
index 9173a8c3d5..1671748e97 100644
--- a/openpype/settings/defaults/project_settings/tvpaint.json
+++ b/openpype/settings/defaults/project_settings/tvpaint.json
@@ -42,6 +42,7 @@
"default_variants": []
},
"auto_detect_render": {
+ "enabled": false,
"allow_group_rename": true,
"group_name_template": "L{group_index}",
"group_idx_offset": 10,
diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_tvpaint.json b/openpype/settings/entities/schemas/projects_schema/schema_project_tvpaint.json
index 708b688ba5..1094595851 100644
--- a/openpype/settings/entities/schemas/projects_schema/schema_project_tvpaint.json
+++ b/openpype/settings/entities/schemas/projects_schema/schema_project_tvpaint.json
@@ -202,7 +202,13 @@
"key": "auto_detect_render",
"label": "Auto-Detect Create Render",
"is_group": true,
+ "checkbox_key": "enabled",
"children": [
+ {
+ "type": "boolean",
+ "key": "enabled",
+ "label": "Enabled"
+ },
{
"type": "label",
"label": "The creator tries to auto-detect Render Layers and Render Passes in scene. For Render Layers is used group name as a variant and for Render Passes is used TVPaint layer name.
Group names can be renamed by their used order in scene. The renaming template where can be used {group_index} formatting key which is filled by \"used position index of group\".
- Template: L{group_index}
- Group offset: 10
- Group padding: 3
Would create group names \"L010\", \"L020\", ..."