diff --git a/openpype/hosts/tvpaint/plugins/publish/collect_instances.py b/openpype/hosts/tvpaint/plugins/publish/collect_instances.py
index 9cbfb61550..5e8d13592c 100644
--- a/openpype/hosts/tvpaint/plugins/publish/collect_instances.py
+++ b/openpype/hosts/tvpaint/plugins/publish/collect_instances.py
@@ -20,21 +20,30 @@ class CollectInstances(pyblish.api.ContextPlugin):
json.dumps(workfile_instances, indent=4)
))
+ filtered_instance_data = []
# Backwards compatibility for workfiles that already have review
# instance in metadata.
review_instance_exist = False
for instance_data in workfile_instances:
- if instance_data["family"] == "review":
+ family = instance_data["family"]
+ if family == "review":
review_instance_exist = True
- break
+
+ elif family not in ("renderPass", "renderLayer"):
+ self.log.info("Unknown family \"{}\". Skipping {}".format(
+ family, json.dumps(instance_data, indent=4)
+ ))
+ continue
+
+ filtered_instance_data.append(instance_data)
# Fake review instance if review was not found in metadata families
if not review_instance_exist:
- workfile_instances.append(
+ filtered_instance_data.append(
self._create_review_instance_data(context)
)
- for instance_data in workfile_instances:
+ for instance_data in filtered_instance_data:
instance_data["fps"] = context.data["sceneFps"]
# Store workfile instance data to instance data
@@ -42,8 +51,11 @@ class CollectInstances(pyblish.api.ContextPlugin):
# Global instance data modifications
# Fill families
family = instance_data["family"]
+ families = [family]
+ if family != "review":
+ families.append("review")
# Add `review` family for thumbnail integration
- instance_data["families"] = [family, "review"]
+ instance_data["families"] = families
# Instance name
subset_name = instance_data["subset"]
@@ -78,7 +90,7 @@ class CollectInstances(pyblish.api.ContextPlugin):
# Project name from workfile context
project_name = context.data["workfile_context"]["project"]
# Host name from environment variable
- host_name = os.environ["AVALON_APP"]
+ host_name = context.data["hostName"]
# Use empty variant value
variant = ""
task_name = io.Session["AVALON_TASK"]
@@ -106,12 +118,6 @@ class CollectInstances(pyblish.api.ContextPlugin):
instance = self.create_render_pass_instance(
context, instance_data
)
- else:
- raise AssertionError(
- "Instance with unknown family \"{}\": {}".format(
- family, instance_data
- )
- )
if instance is None:
continue
diff --git a/openpype/hosts/tvpaint/plugins/publish/collect_scene_render.py b/openpype/hosts/tvpaint/plugins/publish/collect_scene_render.py
new file mode 100644
index 0000000000..0af9a9a400
--- /dev/null
+++ b/openpype/hosts/tvpaint/plugins/publish/collect_scene_render.py
@@ -0,0 +1,110 @@
+import json
+import copy
+import pyblish.api
+from avalon import io
+
+from openpype.lib import get_subset_name_with_asset_doc
+
+
+class CollectRenderScene(pyblish.api.ContextPlugin):
+ """Collect instance which renders whole scene in PNG.
+
+ Creates instance with family 'renderScene' which will have all layers
+ to render which will be composite into one result. The instance is not
+ collected from scene.
+
+ Scene will be rendered with all visible layers similar way like review is.
+
+ Instance is disabled if there are any created instances of 'renderLayer'
+ or 'renderPass'. That is because it is expected that this instance is
+ used as lazy publish of TVPaint file.
+
+ Subset name is created similar way like 'renderLayer' family. It can use
+ `renderPass` and `renderLayer` keys which can be set using settings and
+ `variant` is filled using `renderPass` value.
+ """
+ label = "Collect Render Scene"
+ order = pyblish.api.CollectorOrder - 0.39
+ hosts = ["tvpaint"]
+
+ # Value of 'render_pass' in subset name template
+ render_pass = "beauty"
+
+ # Settings attributes
+ enabled = False
+ # Value of 'render_layer' and 'variant' in subset name template
+ render_layer = "Main"
+
+ def process(self, context):
+ # Check if there are created instances of renderPass and renderLayer
+ # - that will define if renderScene instance is enabled after
+ # collection
+ any_created_instance = False
+ for instance in context:
+ family = instance.data["family"]
+ if family in ("renderPass", "renderLayer"):
+ any_created_instance = True
+ break
+
+ # Global instance data modifications
+ # Fill families
+ family = "renderScene"
+ # Add `review` family for thumbnail integration
+ families = [family, "review"]
+
+ # Collect asset doc to get asset id
+ # - not sure if it's good idea to require asset id in
+ # get_subset_name?
+ workfile_context = context.data["workfile_context"]
+ asset_name = workfile_context["asset"]
+ asset_doc = io.find_one({
+ "type": "asset",
+ "name": asset_name
+ })
+
+ # Project name from workfile context
+ project_name = context.data["workfile_context"]["project"]
+ # Host name from environment variable
+ host_name = context.data["hostName"]
+ # Variant is using render pass name
+ variant = self.render_layer
+ dynamic_data = {
+ "render_layer": self.render_layer,
+ "render_pass": self.render_pass
+ }
+
+ task_name = workfile_context["task"]
+ subset_name = get_subset_name_with_asset_doc(
+ "render",
+ variant,
+ task_name,
+ asset_doc,
+ project_name,
+ host_name,
+ dynamic_data=dynamic_data
+ )
+
+ instance_data = {
+ "family": family,
+ "families": families,
+ "fps": context.data["sceneFps"],
+ "subset": subset_name,
+ "name": subset_name,
+ "label": "{} [{}-{}]".format(
+ subset_name,
+ context.data["sceneMarkIn"] + 1,
+ context.data["sceneMarkOut"] + 1
+ ),
+ "active": not any_created_instance,
+ "publish": not any_created_instance,
+ "representations": [],
+ "layers": copy.deepcopy(context.data["layersData"]),
+ "asset": asset_name,
+ "task": task_name
+ }
+
+ instance = context.create_instance(**instance_data)
+
+ self.log.debug("Created instance: {}\n{}".format(
+ instance, json.dumps(instance.data, indent=4)
+ ))
diff --git a/openpype/hosts/tvpaint/plugins/publish/extract_sequence.py b/openpype/hosts/tvpaint/plugins/publish/extract_sequence.py
index 139dabadee..d4fd1dff4b 100644
--- a/openpype/hosts/tvpaint/plugins/publish/extract_sequence.py
+++ b/openpype/hosts/tvpaint/plugins/publish/extract_sequence.py
@@ -18,7 +18,7 @@ from openpype.hosts.tvpaint.lib import (
class ExtractSequence(pyblish.api.Extractor):
label = "Extract Sequence"
hosts = ["tvpaint"]
- families = ["review", "renderPass", "renderLayer"]
+ families = ["review", "renderPass", "renderLayer", "renderScene"]
# Modifiable with settings
review_bg = [255, 255, 255, 255]
@@ -159,7 +159,7 @@ class ExtractSequence(pyblish.api.Extractor):
# Fill tags and new families
tags = []
- if family_lowered in ("review", "renderlayer"):
+ if family_lowered in ("review", "renderlayer", "renderscene"):
tags.append("review")
# Sequence of one frame
@@ -185,7 +185,7 @@ class ExtractSequence(pyblish.api.Extractor):
instance.data["representations"].append(new_repre)
- if family_lowered in ("renderpass", "renderlayer"):
+ if family_lowered in ("renderpass", "renderlayer", "renderscene"):
# Change family to render
instance.data["family"] = "render"
diff --git a/openpype/hosts/tvpaint/plugins/publish/validate_layers_visibility.py b/openpype/hosts/tvpaint/plugins/publish/validate_layers_visibility.py
index 7ea0587b8f..d3a04cc69f 100644
--- a/openpype/hosts/tvpaint/plugins/publish/validate_layers_visibility.py
+++ b/openpype/hosts/tvpaint/plugins/publish/validate_layers_visibility.py
@@ -8,7 +8,7 @@ class ValidateLayersVisiblity(pyblish.api.InstancePlugin):
label = "Validate Layers Visibility"
order = pyblish.api.ValidatorOrder
- families = ["review", "renderPass", "renderLayer"]
+ families = ["review", "renderPass", "renderLayer", "renderScene"]
def process(self, instance):
layer_names = set()
diff --git a/openpype/settings/defaults/project_settings/tvpaint.json b/openpype/settings/defaults/project_settings/tvpaint.json
index 46beeb85b9..88b5a598cd 100644
--- a/openpype/settings/defaults/project_settings/tvpaint.json
+++ b/openpype/settings/defaults/project_settings/tvpaint.json
@@ -1,6 +1,10 @@
{
"stop_timer_on_application_exit": false,
"publish": {
+ "CollectRenderScene": {
+ "enabled": false,
+ "render_layer": "Main"
+ },
"ExtractSequence": {
"review_bg": [
255,
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 97462a8b62..20fe5b0855 100644
--- a/openpype/settings/entities/schemas/projects_schema/schema_project_tvpaint.json
+++ b/openpype/settings/entities/schemas/projects_schema/schema_project_tvpaint.json
@@ -16,6 +16,30 @@
"key": "publish",
"label": "Publish plugins",
"children": [
+ {
+ "type": "dict",
+ "collapsible": true,
+ "key": "CollectRenderScene",
+ "label": "Collect Render Scene",
+ "is_group": true,
+ "checkbox_key": "enabled",
+ "children": [
+ {
+ "type": "boolean",
+ "key": "enabled",
+ "label": "Enabled"
+ },
+ {
+ "type": "label",
+ "label": "It is possible to fill 'render_layer' or 'variant' in subset name template with custom value.
- value of 'render_pass' is always \"beauty\"."
+ },
+ {
+ "type": "text",
+ "key": "render_layer",
+ "label": "Render Layer"
+ }
+ ]
+ },
{
"type": "dict",
"collapsible": true,