From 516d9208301c7cd5de498cd03eac1b1e43927e89 Mon Sep 17 00:00:00 2001 From: CAILLOT Cyprien Date: Tue, 10 Oct 2023 10:40:58 +0200 Subject: [PATCH 01/17] Save my stuff --- quad_pyblish_module/plugins/hiero/__init__.py | 0 .../plugins/hiero/publish/__init__.py | 0 .../publish/integrate_version_to_task.py | 23 +++++++++++++++++++ 3 files changed, 23 insertions(+) create mode 100644 quad_pyblish_module/plugins/hiero/__init__.py create mode 100644 quad_pyblish_module/plugins/hiero/publish/__init__.py create mode 100644 quad_pyblish_module/plugins/hiero/publish/integrate_version_to_task.py diff --git a/quad_pyblish_module/plugins/hiero/__init__.py b/quad_pyblish_module/plugins/hiero/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/quad_pyblish_module/plugins/hiero/publish/__init__.py b/quad_pyblish_module/plugins/hiero/publish/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/quad_pyblish_module/plugins/hiero/publish/integrate_version_to_task.py b/quad_pyblish_module/plugins/hiero/publish/integrate_version_to_task.py new file mode 100644 index 0000000..270270e --- /dev/null +++ b/quad_pyblish_module/plugins/hiero/publish/integrate_version_to_task.py @@ -0,0 +1,23 @@ +import pyblish import api + + +class IntegrateVersionToTask(api.ContextPlugin): + """Integrate Version To Task""" + + order = api.IntegratorOrder + 10.1 + hosts = ["hiero"] + label = "Integrate Version To Task" + optional = False + + def process(self, context): + print('----------------------------------------') + print('----------------------------------------') + print('----------------------------------------') + print('----------------------------------------') + from pprint import pprint + print(type(context)) + pprint(context.data) + print('----------------------------------------') + print('----------------------------------------') + print('----------------------------------------') + print('----------------------------------------') From c7e92e31d7d706982d6b8653475b23920428a117 Mon Sep 17 00:00:00 2001 From: Cyprien Caillot Date: Wed, 11 Oct 2023 22:08:51 +0200 Subject: [PATCH 02/17] add integrate_version_to_task.py --- .../publish/integrate_version_to_task.py | 65 +++++++++++++++---- 1 file changed, 53 insertions(+), 12 deletions(-) diff --git a/quad_pyblish_module/plugins/hiero/publish/integrate_version_to_task.py b/quad_pyblish_module/plugins/hiero/publish/integrate_version_to_task.py index 270270e..278e8ff 100644 --- a/quad_pyblish_module/plugins/hiero/publish/integrate_version_to_task.py +++ b/quad_pyblish_module/plugins/hiero/publish/integrate_version_to_task.py @@ -1,4 +1,4 @@ -import pyblish import api +from pyblish import api class IntegrateVersionToTask(api.ContextPlugin): @@ -6,18 +6,59 @@ class IntegrateVersionToTask(api.ContextPlugin): order = api.IntegratorOrder + 10.1 hosts = ["hiero"] + families = ["clip"] label = "Integrate Version To Task" optional = False + def get_all_task_types(self, project): + tasks = {} + proj_template = project['project_schema'] + temp_task_types = proj_template['_task_type_schema']['types'] + + for type in temp_task_types: + if type['name'] not in tasks: + tasks[type['name']] = type + + return tasks + def process(self, context): - print('----------------------------------------') - print('----------------------------------------') - print('----------------------------------------') - print('----------------------------------------') - from pprint import pprint - print(type(context)) - pprint(context.data) - print('----------------------------------------') - print('----------------------------------------') - print('----------------------------------------') - print('----------------------------------------') + # Get Usefull Data + task_type = context.data.get('task').lower() + ftrack_session = context.data.get('ftrackSession') + ftrack_project = context.data.get('ftrackProject') + ftrack_task_types = self.get_all_task_types(ftrack_project) + + if ftrack_session is None: + self.log.info('Ftrack session is not created.') + return + + to_analyze_lst = [] + for result_dict in context.data.get('results'): + if 'Collect OTIO Review' in result_dict['plugin'].label: + to_analyze_lst.append(result_dict) + + for to_analyze in to_analyze_lst: + ftrack_shot_version = to_analyze['instance'].data['ftrackEntity'] + ftrack_asset_versions = to_analyze['instance'].data['ftrackIntegratedAssetVersions'] + + # Check if confo task already exists in ftrack + is_task_exist = ftrack_session.query('Task where name is "{0}" and parent.id is {1}'.format(task_type, ftrack_shot_version['id'])).first() + if not is_task_exist: + new_task = ftrack_session.create( + 'Task', + { + 'name': task_type, + 'parent': ftrack_shot_version, + 'type': ftrack_task_types[task_type] + } + ) + else: + new_task = is_task_exist + + ftrack_session.commit() + + # Link Publish version to Task + for asset_version in ftrack_asset_versions: + asset_version['task'] = new_task + + ftrack_session.commit() \ No newline at end of file From b932548f58b664abd00e543ac94f7b3e525fef17 Mon Sep 17 00:00:00 2001 From: Cyprien Caillot Date: Thu, 12 Oct 2023 11:54:30 +0200 Subject: [PATCH 03/17] Add documenation --- .../publish/integrate_version_to_task.py | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/quad_pyblish_module/plugins/hiero/publish/integrate_version_to_task.py b/quad_pyblish_module/plugins/hiero/publish/integrate_version_to_task.py index 278e8ff..3486359 100644 --- a/quad_pyblish_module/plugins/hiero/publish/integrate_version_to_task.py +++ b/quad_pyblish_module/plugins/hiero/publish/integrate_version_to_task.py @@ -11,6 +11,14 @@ class IntegrateVersionToTask(api.ContextPlugin): optional = False def get_all_task_types(self, project): + """Get all task types from the project schema. + + :param project: The Ftrack project Entity. + :type project: ftrack Project Object + :return: A dictionary containing all task types. + :rtype: dict + + """ tasks = {} proj_template = project['project_schema'] temp_task_types = proj_template['_task_type_schema']['types'] @@ -22,7 +30,12 @@ def get_all_task_types(self, project): return tasks def process(self, context): - # Get Usefull Data + """Process the Pyblish context. + + :param context: The Pyblish context. + :type context: pyblish.api.Context + """ + # Get Data we need task_type = context.data.get('task').lower() ftrack_session = context.data.get('ftrackSession') ftrack_project = context.data.get('ftrackProject') @@ -32,6 +45,7 @@ def process(self, context): self.log.info('Ftrack session is not created.') return + # Build Plugin dict list to analyze to_analyze_lst = [] for result_dict in context.data.get('results'): if 'Collect OTIO Review' in result_dict['plugin'].label: @@ -42,7 +56,8 @@ def process(self, context): ftrack_asset_versions = to_analyze['instance'].data['ftrackIntegratedAssetVersions'] # Check if confo task already exists in ftrack - is_task_exist = ftrack_session.query('Task where name is "{0}" and parent.id is {1}'.format(task_type, ftrack_shot_version['id'])).first() + is_task_exist = ftrack_session.query( + 'Task where name is "{0}" and parent.id is {1}'.format(task_type, ftrack_shot_version['id'])).first() if not is_task_exist: new_task = ftrack_session.create( 'Task', @@ -61,4 +76,4 @@ def process(self, context): for asset_version in ftrack_asset_versions: asset_version['task'] = new_task - ftrack_session.commit() \ No newline at end of file + ftrack_session.commit() From 3d1a67a30816d5975d33ce82223405a42f51bc6a Mon Sep 17 00:00:00 2001 From: Guilhemz Date: Tue, 17 Oct 2023 12:30:45 +0200 Subject: [PATCH 04/17] #152: feat: add new create_playblast tvPaint plugin with corresponding config --- .../tvpaint/create/create_playblast.py | 233 ++++++++++++++++++ .../settings/defaults/project_settings.json | 6 + .../schemas/project_schemas/tvpaint.json | 37 +++ 3 files changed, 276 insertions(+) create mode 100644 quad_pyblish_module/plugins/tvpaint/create/create_playblast.py diff --git a/quad_pyblish_module/plugins/tvpaint/create/create_playblast.py b/quad_pyblish_module/plugins/tvpaint/create/create_playblast.py new file mode 100644 index 0000000..006d9ce --- /dev/null +++ b/quad_pyblish_module/plugins/tvpaint/create/create_playblast.py @@ -0,0 +1,233 @@ +"""Render Layer and Passes creators. + +Render layer is main part which is represented by group in TVPaint. All TVPaint +layers marked with that group color are part of the render layer. To be more +specific about some parts of layer it is possible to create sub-sets of layer +which are named passes. Render pass consist of layers in same color group as +render layer but define more specific part. + +For example render layer could be 'Bob' which consist of 5 TVPaint layers. +- Bob has 'head' which consist of 2 TVPaint layers -> Render pass 'head' +- Bob has 'body' which consist of 1 TVPaint layer -> Render pass 'body' +- Bob has 'arm' which consist of 1 TVPaint layer -> Render pass 'arm' +- Last layer does not belong to render pass at all + +Bob will be rendered as 'beauty' of bob (all visible layers in group). +His head will be rendered too but without any other parts. The same for body +and arm. + +What is this good for? Compositing has more power how the renders are used. +Can do transforms on each render pass without need to modify a re-render them +using TVPaint. + +The workflow may hit issues when there are used other blending modes than +default 'color' blend more. In that case it is not recommended to use this +workflow at all as other blend modes may affect all layers in clip which can't +be done. + +There is special case for simple publishing of scene which is called +'render.scene'. That will use all visible layers and render them as one big +sequence. + +Todos: + Add option to extract marked layers and passes as json output format for + AfterEffects. +""" + +import collections +from typing import Any, Optional, Union + +from openpype.client import get_asset_by_name +from openpype.lib import ( + prepare_template_data, + AbstractAttrDef, + UILabelDef, + UISeparatorDef, + EnumDef, + TextDef, + BoolDef, +) +from openpype.pipeline.create import ( + CreatedInstance, + CreatorError, +) +from openpype.hosts.tvpaint.api.plugin import ( + TVPaintCreator, + TVPaintAutoCreator, +) +from openpype.hosts.tvpaint.api.lib import ( + get_layers_data, + get_groups_data, + execute_george_through_file, +) + +RENDER_LAYER_DETAILED_DESCRIPTIONS = ( + """Render Layer is "a group of TVPaint layers" + +Be aware Render Layer is not TVPaint layer. + +All TVPaint layers in the scene with the color group id are rendered in the +beauty pass. To create sub passes use Render Pass creator which is +dependent on existence of render layer instance. + +The group can represent an asset (tree) or different part of scene that consist +of one or more TVPaint layers that can be used as single item during +compositing (for example). + +In some cases may be needed to have sub parts of the layer. For example 'Bob' +could be Render Layer which has 'Arm', 'Head' and 'Body' as Render Passes. +""" +) + + +RENDER_PASS_DETAILED_DESCRIPTIONS = ( + """Render Pass is sub part of Render Layer. + +Render Pass can consist of one or more TVPaint layers. Render Pass must +belong to a Render Layer. Marked TVPaint layers will change it's group color +to match group color of Render Layer. +""" +) + + +AUTODETECT_RENDER_DETAILED_DESCRIPTION = ( + """Semi-automated Render Layer and Render Pass creation. + +Based on information in TVPaint scene will be created Render Layers and Render +Passes. All color groups used in scene will be used for Render Layer creation. +Name of the group is used as a variant. + +All TVPaint layers under the color group will be created as Render Pass where +layer name is used as variant. + +The plugin will use all used color groups and layers, or can skip those that +are not visible. + +There is option to auto-rename color groups before Render Layer creation. That +is based on settings template where is filled index of used group from bottom +to top. +""" +) + + +class TVPaintSceneRenderCreator(TVPaintAutoCreator): + family = "render" + subset_template_family_filter = "playblast" + identifier = "render.playblast" + label = "Playblast" + icon = "fa.file-image-o" + + # Settings + default_pass_name = "beauty" + mark_for_review = True + active_on_create = False + + def apply_settings(self, project_settings, system_settings): + plugin_settings = ( + project_settings["tvpaint"]["create"]["create_playblast"] + ) + self.default_variant = plugin_settings["default_variant"] + self.default_variants = plugin_settings["default_variants"] + self.mark_for_review = plugin_settings["mark_for_review"] + self.default_pass_name = plugin_settings["default_pass_name"] + self.exports_types = ['camera', 'scene'] + self.export_type = exports_types[0] + + + def _create_new_instance(self): + create_context = self.create_context + host_name = create_context.host_name + project_name = create_context.get_current_project_name() + asset_name = create_context.get_current_asset_name() + task_name = create_context.get_current_task_name() + + asset_doc = get_asset_by_name(project_name, asset_name) + subset_name = self.get_subset_name( + self.default_variant, + task_name, + asset_doc, + project_name, + host_name + ) + data = { + "asset": asset_name, + "task": task_name, + "variant": self.default_variant, + "creator_attributes": { + "mark_for_review": True, + "export_type": self.export_type + }, + "label": self._get_label(subset_name) + } + data["active"] = False + + new_instance = CreatedInstance( + self.family, subset_name, data, self + ) + instances_data = self.host.list_instances() + instances_data.append(new_instance.data_to_store()) + self.host.write_instances(instances_data) + self._add_instance_to_context(new_instance) + return new_instance + + def create(self): + existing_instance = None + for instance in self.create_context.instances: + if instance.creator_identifier == self.identifier: + existing_instance = instance + break + + if existing_instance is None: + return self._create_new_instance() + + create_context = self.create_context + host_name = create_context.host_name + project_name = create_context.get_current_project_name() + asset_name = create_context.get_current_asset_name() + task_name = create_context.get_current_task_name() + + if ( + existing_instance["asset"] != asset_name + or existing_instance["task"] != task_name + ): + asset_doc = get_asset_by_name(project_name, asset_name) + subset_name = self.get_subset_name( + existing_instance["variant"], + task_name, + asset_doc, + project_name, + host_name, + existing_instance + ) + existing_instance["asset"] = asset_name + existing_instance["task"] = task_name + existing_instance["subset"] = subset_name + + existing_instance["label"] = self._get_label(existing_instance["subset"]) + + def _get_label(self, subset_name): + try: + subset_name = subset_name.format(**prepare_template_data({})) + except (KeyError, ValueError): + pass + + return subset_name + + def get_dynamic_data(self, variant, *args, **kwargs): + dynamic_data = super().get_dynamic_data(variant, *args, **kwargs) + return dynamic_data + + def get_instance_attr_defs(self): + return [ + BoolDef( + "mark_for_review", + label="Review", + default=self.mark_for_review + ), + EnumDef( + "export_type", + self.exports_types, + label="Export type", + default=self.export_type + ) + ] diff --git a/quad_pyblish_module/settings/defaults/project_settings.json b/quad_pyblish_module/settings/defaults/project_settings.json index cf459fc..c002186 100644 --- a/quad_pyblish_module/settings/defaults/project_settings.json +++ b/quad_pyblish_module/settings/defaults/project_settings.json @@ -14,6 +14,12 @@ "enabled": true, "default_variant": "Main", "default_variants": [] + }, + "create_playblast": { + "enabled": true, + "default_variant": "Main", + "default_variants": [], + "export_type": "camera" } } } diff --git a/quad_pyblish_module/settings/schemas/project_schemas/tvpaint.json b/quad_pyblish_module/settings/schemas/project_schemas/tvpaint.json index 5785638..7a63917 100644 --- a/quad_pyblish_module/settings/schemas/project_schemas/tvpaint.json +++ b/quad_pyblish_module/settings/schemas/project_schemas/tvpaint.json @@ -73,6 +73,43 @@ } } ] + }, + { + "type": "dict", + "collapsible": true, + "key": "create_playblast", + "label": "Create Playblast", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "text", + "key": "default_variant", + "label": "Default variant" + }, + { + "type": "list", + "key": "default_variants", + "label": "Default variants", + "object_type": { + "type": "text" + } + }, + { + "type": "enum", + "key": "export_type", + "label": "Export type", + "multiselection": false, + "enum_items": [ + {"PROJECT": "project"}, + {"CAMERA": "camera"} + ] + } + ] } ] } From 26bfc4950aecef4609e5f09b15e3f6936d647dfa Mon Sep 17 00:00:00 2001 From: Guilhemz Date: Tue, 17 Oct 2023 17:10:13 +0200 Subject: [PATCH 05/17] #152: bugfix: for tvpaint/create_playblast, update settings key index because of errors. Also remove unused settings --- .../plugins/tvpaint/create/create_playblast.py | 12 +++--------- .../settings/defaults/project_settings.json | 3 +-- .../settings/schemas/project_schemas/tvpaint.json | 10 ---------- 3 files changed, 4 insertions(+), 21 deletions(-) diff --git a/quad_pyblish_module/plugins/tvpaint/create/create_playblast.py b/quad_pyblish_module/plugins/tvpaint/create/create_playblast.py index 006d9ce..eea64d8 100644 --- a/quad_pyblish_module/plugins/tvpaint/create/create_playblast.py +++ b/quad_pyblish_module/plugins/tvpaint/create/create_playblast.py @@ -124,14 +124,13 @@ class TVPaintSceneRenderCreator(TVPaintAutoCreator): def apply_settings(self, project_settings, system_settings): plugin_settings = ( - project_settings["tvpaint"]["create"]["create_playblast"] + project_settings["fix_custom_settings"]["tvpaint"]["create"]["create_playblast"] ) self.default_variant = plugin_settings["default_variant"] self.default_variants = plugin_settings["default_variants"] - self.mark_for_review = plugin_settings["mark_for_review"] - self.default_pass_name = plugin_settings["default_pass_name"] + self.mark_for_review = True self.exports_types = ['camera', 'scene'] - self.export_type = exports_types[0] + self.export_type = self.exports_types[0] def _create_new_instance(self): @@ -219,11 +218,6 @@ def get_dynamic_data(self, variant, *args, **kwargs): def get_instance_attr_defs(self): return [ - BoolDef( - "mark_for_review", - label="Review", - default=self.mark_for_review - ), EnumDef( "export_type", self.exports_types, diff --git a/quad_pyblish_module/settings/defaults/project_settings.json b/quad_pyblish_module/settings/defaults/project_settings.json index c002186..d08a689 100644 --- a/quad_pyblish_module/settings/defaults/project_settings.json +++ b/quad_pyblish_module/settings/defaults/project_settings.json @@ -18,8 +18,7 @@ "create_playblast": { "enabled": true, "default_variant": "Main", - "default_variants": [], - "export_type": "camera" + "default_variants": [] } } } diff --git a/quad_pyblish_module/settings/schemas/project_schemas/tvpaint.json b/quad_pyblish_module/settings/schemas/project_schemas/tvpaint.json index 7a63917..96c8e26 100644 --- a/quad_pyblish_module/settings/schemas/project_schemas/tvpaint.json +++ b/quad_pyblish_module/settings/schemas/project_schemas/tvpaint.json @@ -98,16 +98,6 @@ "object_type": { "type": "text" } - }, - { - "type": "enum", - "key": "export_type", - "label": "Export type", - "multiselection": false, - "enum_items": [ - {"PROJECT": "project"}, - {"CAMERA": "camera"} - ] } ] } From eda06257b669b7d295ebf39cf9e44ae3e1bd23ac Mon Sep 17 00:00:00 2001 From: Guilhemz Date: Tue, 17 Oct 2023 17:14:43 +0200 Subject: [PATCH 06/17] #152: clean: remove unused private variable --- quad_pyblish_module/plugins/tvpaint/create/create_playblast.py | 1 - 1 file changed, 1 deletion(-) diff --git a/quad_pyblish_module/plugins/tvpaint/create/create_playblast.py b/quad_pyblish_module/plugins/tvpaint/create/create_playblast.py index eea64d8..652181e 100644 --- a/quad_pyblish_module/plugins/tvpaint/create/create_playblast.py +++ b/quad_pyblish_module/plugins/tvpaint/create/create_playblast.py @@ -128,7 +128,6 @@ def apply_settings(self, project_settings, system_settings): ) self.default_variant = plugin_settings["default_variant"] self.default_variants = plugin_settings["default_variants"] - self.mark_for_review = True self.exports_types = ['camera', 'scene'] self.export_type = self.exports_types[0] From ccc9663388f2378b91389c5619eeaf81bf76b15f Mon Sep 17 00:00:00 2001 From: Guilhemz Date: Tue, 17 Oct 2023 17:23:15 +0200 Subject: [PATCH 07/17] #152: clean: remove whitespaces --- quad_pyblish_module/plugins/tvpaint/create/create_playblast.py | 1 - 1 file changed, 1 deletion(-) diff --git a/quad_pyblish_module/plugins/tvpaint/create/create_playblast.py b/quad_pyblish_module/plugins/tvpaint/create/create_playblast.py index 652181e..27a8868 100644 --- a/quad_pyblish_module/plugins/tvpaint/create/create_playblast.py +++ b/quad_pyblish_module/plugins/tvpaint/create/create_playblast.py @@ -131,7 +131,6 @@ def apply_settings(self, project_settings, system_settings): self.exports_types = ['camera', 'scene'] self.export_type = self.exports_types[0] - def _create_new_instance(self): create_context = self.create_context host_name = create_context.host_name From b362245e98075381498a853c1000c10f3f44a9bf Mon Sep 17 00:00:00 2001 From: Guilhemz Date: Wed, 18 Oct 2023 10:27:02 +0200 Subject: [PATCH 08/17] #152: feature: add missing settings option for review enabling and activation at launch --- .../plugins/tvpaint/create/create_playblast.py | 10 ++++++++-- .../settings/defaults/project_settings.json | 2 ++ .../settings/schemas/project_schemas/tvpaint.json | 10 ++++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/quad_pyblish_module/plugins/tvpaint/create/create_playblast.py b/quad_pyblish_module/plugins/tvpaint/create/create_playblast.py index 27a8868..5d4a46c 100644 --- a/quad_pyblish_module/plugins/tvpaint/create/create_playblast.py +++ b/quad_pyblish_module/plugins/tvpaint/create/create_playblast.py @@ -118,14 +118,15 @@ class TVPaintSceneRenderCreator(TVPaintAutoCreator): icon = "fa.file-image-o" # Settings - default_pass_name = "beauty" mark_for_review = True - active_on_create = False + active_on_create = True def apply_settings(self, project_settings, system_settings): plugin_settings = ( project_settings["fix_custom_settings"]["tvpaint"]["create"]["create_playblast"] ) + self.mark_for_review = plugin_settings["mark_for_review"] + self.active_on_create = plugin_settings["active_on_create"] self.default_variant = plugin_settings["default_variant"] self.default_variants = plugin_settings["default_variants"] self.exports_types = ['camera', 'scene'] @@ -216,6 +217,11 @@ def get_dynamic_data(self, variant, *args, **kwargs): def get_instance_attr_defs(self): return [ + BoolDef( + "mark_for_review", + label="Review by default", + default=self.mark_for_review + ), EnumDef( "export_type", self.exports_types, diff --git a/quad_pyblish_module/settings/defaults/project_settings.json b/quad_pyblish_module/settings/defaults/project_settings.json index d08a689..17b53e1 100644 --- a/quad_pyblish_module/settings/defaults/project_settings.json +++ b/quad_pyblish_module/settings/defaults/project_settings.json @@ -17,6 +17,8 @@ }, "create_playblast": { "enabled": true, + "active_on_create": true, + "mark_for_review": true, "default_variant": "Main", "default_variants": [] } diff --git a/quad_pyblish_module/settings/schemas/project_schemas/tvpaint.json b/quad_pyblish_module/settings/schemas/project_schemas/tvpaint.json index 96c8e26..3b91b9d 100644 --- a/quad_pyblish_module/settings/schemas/project_schemas/tvpaint.json +++ b/quad_pyblish_module/settings/schemas/project_schemas/tvpaint.json @@ -86,6 +86,16 @@ "key": "enabled", "label": "Enabled" }, + { + "type": "boolean", + "key": "active_on_create", + "label": "Active by default" + }, + { + "type": "boolean", + "key": "mark_for_review", + "label": "Review by default" + }, { "type": "text", "key": "default_variant", From 0579aa5a42cee0514fd0cc5e61af776f45d72189 Mon Sep 17 00:00:00 2001 From: Guilhemz Date: Wed, 18 Oct 2023 10:38:15 +0200 Subject: [PATCH 09/17] #152: bugfix: create_playblast - remove hardcoded value for active boolean at subset initialization --- .../plugins/tvpaint/create/create_playblast.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/quad_pyblish_module/plugins/tvpaint/create/create_playblast.py b/quad_pyblish_module/plugins/tvpaint/create/create_playblast.py index 5d4a46c..ce46ead 100644 --- a/quad_pyblish_module/plugins/tvpaint/create/create_playblast.py +++ b/quad_pyblish_module/plugins/tvpaint/create/create_playblast.py @@ -152,12 +152,12 @@ def _create_new_instance(self): "task": task_name, "variant": self.default_variant, "creator_attributes": { - "mark_for_review": True, + "mark_for_review": self.mark_for_review, "export_type": self.export_type }, - "label": self._get_label(subset_name) + "label": self._get_label(subset_name), + "active": self.active_on_create } - data["active"] = False new_instance = CreatedInstance( self.family, subset_name, data, self From bfffbf580f7b9595949e25eeff3bc6dacaa2bf56 Mon Sep 17 00:00:00 2001 From: Guilhemz Date: Thu, 19 Oct 2023 10:14:31 +0200 Subject: [PATCH 10/17] #152: clean: remove unused imports and prints --- .../tvpaint/create/create_playblast.py | 106 +----------------- 1 file changed, 2 insertions(+), 104 deletions(-) diff --git a/quad_pyblish_module/plugins/tvpaint/create/create_playblast.py b/quad_pyblish_module/plugins/tvpaint/create/create_playblast.py index ce46ead..36a0834 100644 --- a/quad_pyblish_module/plugins/tvpaint/create/create_playblast.py +++ b/quad_pyblish_module/plugins/tvpaint/create/create_playblast.py @@ -1,113 +1,11 @@ -"""Render Layer and Passes creators. - -Render layer is main part which is represented by group in TVPaint. All TVPaint -layers marked with that group color are part of the render layer. To be more -specific about some parts of layer it is possible to create sub-sets of layer -which are named passes. Render pass consist of layers in same color group as -render layer but define more specific part. - -For example render layer could be 'Bob' which consist of 5 TVPaint layers. -- Bob has 'head' which consist of 2 TVPaint layers -> Render pass 'head' -- Bob has 'body' which consist of 1 TVPaint layer -> Render pass 'body' -- Bob has 'arm' which consist of 1 TVPaint layer -> Render pass 'arm' -- Last layer does not belong to render pass at all - -Bob will be rendered as 'beauty' of bob (all visible layers in group). -His head will be rendered too but without any other parts. The same for body -and arm. - -What is this good for? Compositing has more power how the renders are used. -Can do transforms on each render pass without need to modify a re-render them -using TVPaint. - -The workflow may hit issues when there are used other blending modes than -default 'color' blend more. In that case it is not recommended to use this -workflow at all as other blend modes may affect all layers in clip which can't -be done. - -There is special case for simple publishing of scene which is called -'render.scene'. That will use all visible layers and render them as one big -sequence. - -Todos: - Add option to extract marked layers and passes as json output format for - AfterEffects. -""" - -import collections -from typing import Any, Optional, Union - from openpype.client import get_asset_by_name from openpype.lib import ( prepare_template_data, - AbstractAttrDef, - UILabelDef, - UISeparatorDef, EnumDef, - TextDef, BoolDef, ) -from openpype.pipeline.create import ( - CreatedInstance, - CreatorError, -) -from openpype.hosts.tvpaint.api.plugin import ( - TVPaintCreator, - TVPaintAutoCreator, -) -from openpype.hosts.tvpaint.api.lib import ( - get_layers_data, - get_groups_data, - execute_george_through_file, -) - -RENDER_LAYER_DETAILED_DESCRIPTIONS = ( - """Render Layer is "a group of TVPaint layers" - -Be aware Render Layer is not TVPaint layer. - -All TVPaint layers in the scene with the color group id are rendered in the -beauty pass. To create sub passes use Render Pass creator which is -dependent on existence of render layer instance. - -The group can represent an asset (tree) or different part of scene that consist -of one or more TVPaint layers that can be used as single item during -compositing (for example). - -In some cases may be needed to have sub parts of the layer. For example 'Bob' -could be Render Layer which has 'Arm', 'Head' and 'Body' as Render Passes. -""" -) - - -RENDER_PASS_DETAILED_DESCRIPTIONS = ( - """Render Pass is sub part of Render Layer. - -Render Pass can consist of one or more TVPaint layers. Render Pass must -belong to a Render Layer. Marked TVPaint layers will change it's group color -to match group color of Render Layer. -""" -) - - -AUTODETECT_RENDER_DETAILED_DESCRIPTION = ( - """Semi-automated Render Layer and Render Pass creation. - -Based on information in TVPaint scene will be created Render Layers and Render -Passes. All color groups used in scene will be used for Render Layer creation. -Name of the group is used as a variant. - -All TVPaint layers under the color group will be created as Render Pass where -layer name is used as variant. - -The plugin will use all used color groups and layers, or can skip those that -are not visible. - -There is option to auto-rename color groups before Render Layer creation. That -is based on settings template where is filled index of used group from bottom -to top. -""" -) +from openpype.pipeline.create import CreatedInstance +from openpype.hosts.tvpaint.api.plugin import TVPaintAutoCreator class TVPaintSceneRenderCreator(TVPaintAutoCreator): From cea21a805e90a0d3609204540a1860701b47cd03 Mon Sep 17 00:00:00 2001 From: Guilhemz <146825030+Guilhemz@users.noreply.github.com> Date: Thu, 19 Oct 2023 10:16:01 +0200 Subject: [PATCH 11/17] #152: clean: update class name --- quad_pyblish_module/plugins/tvpaint/create/create_playblast.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quad_pyblish_module/plugins/tvpaint/create/create_playblast.py b/quad_pyblish_module/plugins/tvpaint/create/create_playblast.py index 36a0834..3ef1e08 100644 --- a/quad_pyblish_module/plugins/tvpaint/create/create_playblast.py +++ b/quad_pyblish_module/plugins/tvpaint/create/create_playblast.py @@ -8,7 +8,7 @@ from openpype.hosts.tvpaint.api.plugin import TVPaintAutoCreator -class TVPaintSceneRenderCreator(TVPaintAutoCreator): +class TVPaintPlayblastCreator(TVPaintAutoCreator): family = "render" subset_template_family_filter = "playblast" identifier = "render.playblast" From 5c88a91e05a1fefcf200215272c6a2363a9695d1 Mon Sep 17 00:00:00 2001 From: Guilhemz Date: Mon, 23 Oct 2023 16:44:47 +0200 Subject: [PATCH 12/17] #159: feat: add new create_publish_layout tvPaint subset and integrate_kitsu_sequence Kitsu module --- .../plugins/kitsu/publish/__init__.py | 0 .../kitsu/publish/integrate_kitsu_sequence.py | 61 +++++++++ .../tvpaint/create/create_publish_layout.py | 129 ++++++++++++++++++ .../settings/defaults/project_settings.json | 12 ++ .../schemas/project_schemas/tvpaint.json | 59 ++++++++ 5 files changed, 261 insertions(+) create mode 100644 quad_pyblish_module/plugins/kitsu/publish/__init__.py create mode 100644 quad_pyblish_module/plugins/kitsu/publish/integrate_kitsu_sequence.py create mode 100644 quad_pyblish_module/plugins/tvpaint/create/create_publish_layout.py diff --git a/quad_pyblish_module/plugins/kitsu/publish/__init__.py b/quad_pyblish_module/plugins/kitsu/publish/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/quad_pyblish_module/plugins/kitsu/publish/integrate_kitsu_sequence.py b/quad_pyblish_module/plugins/kitsu/publish/integrate_kitsu_sequence.py new file mode 100644 index 0000000..e7a4528 --- /dev/null +++ b/quad_pyblish_module/plugins/kitsu/publish/integrate_kitsu_sequence.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +import re +import gazu +import pyblish.api + + +class IntegrateKitsuSequence(pyblish.api.InstancePlugin): + """Integrate Kitsu Sequence""" + + order = pyblish.api.IntegratorOrder + 0.02 + label = "Kitsu Sequence" + families = ["render", "kitsu"] + optional = True + + def process(self, instance): + # Check comment has been created + comment_id = instance.data.get("kitsu_comment", {}).get("id") + if not comment_id: + self.log.debug( + "Comment not created, review not pushed to preview." + ) + return + + # Add review representations as preview of comment + task_id = instance.data["kitsu_task"]["id"] + for representation in instance.data.get("representations", []): + # Skip if Publish Sequence option hasn't been enabled from creator subset. + if not instance.data["creator_attributes"].get("publish_sequence"): + continue + + # Skip if Extract Sequence has interpreted image generation + # as review (before video concatenation) instead of a simple sequence. + if "sequence" not in representation.get("tags", []): + continue + + filesnames = representation.get("files") + if not filesnames: + self.log.warning("No files found following sequence extract.") + raise IndexError + + extension = representation.get("ext") + if not extension: + self.log.warning("No extension found in representation.") + raise IndexError + + published_path = representation.get("published_path") + if not published_path: + self.log.warning("No publish path found in representation.") + raise IndexError + + for filename in filesnames: + image_filepath = _generate_files_paths(published_path, extension, filename) + gazu.task.add_preview( + task_id, comment_id, image_filepath, normalize_movie=True + ) + + self.log.info("{} images has been uploaded to Kitsu.".format(len(filesnames))) + + +def _generate_files_paths(published_path, extension, filename): + return re.sub("\d{4}."+extension, filename, published_path) diff --git a/quad_pyblish_module/plugins/tvpaint/create/create_publish_layout.py b/quad_pyblish_module/plugins/tvpaint/create/create_publish_layout.py new file mode 100644 index 0000000..caa5366 --- /dev/null +++ b/quad_pyblish_module/plugins/tvpaint/create/create_publish_layout.py @@ -0,0 +1,129 @@ +from openpype.client import get_asset_by_name +from openpype.lib import ( + prepare_template_data, + EnumDef, + BoolDef, +) +from openpype.pipeline.create import ( + CreatedInstance, + CreatorError, +) +from openpype.hosts.tvpaint.api.plugin import TVPaintAutoCreator + + +class TVPaintPublishLayoutCreator(TVPaintAutoCreator): + family = "render" + subset_template_family_filter = "publish.sequence" + identifier = "publish.sequence" + label = "Publish Layout" + icon = "fa.file-image-o" + + # Settings + publish_sequence = True + ignore_layers_transparency = False + + def apply_settings(self, project_settings, system_settings): + plugin_settings = ( + project_settings["fix_custom_settings"]["tvpaint"]["create"]["create_publish_layout"] + ) + self.active_on_create = plugin_settings["active_on_create"] + self.ignore_layers_transparency = plugin_settings["ignore_layers_transparency"] + self.default_variant = plugin_settings["default_variant"] + self.default_variants = plugin_settings["default_variants"] + + def _create_new_instance(self): + create_context = self.create_context + host_name = create_context.host_name + project_name = create_context.get_current_project_name() + asset_name = create_context.get_current_asset_name() + task_name = create_context.get_current_task_name() + + asset_doc = get_asset_by_name(project_name, asset_name) + subset_name = self.get_subset_name( + self.default_variant, + task_name, + asset_doc, + project_name, + host_name + ) + data = { + "asset": asset_name, + "task": task_name, + "variant": self.default_variant, + "creator_attributes": { + "publish_sequence": self.publish_sequence, + "ignore_layers_transparency": self.ignore_layers_transparency + }, + "label": self._get_label(subset_name), + "active": self.active_on_create + } + + new_instance = CreatedInstance( + self.family, subset_name, data, self + ) + instances_data = self.host.list_instances() + instances_data.append(new_instance.data_to_store()) + self.host.write_instances(instances_data) + self._add_instance_to_context(new_instance) + return new_instance + + def create(self): + existing_instance = None + for instance in self.create_context.instances: + if instance.creator_identifier == self.identifier: + existing_instance = instance + break + + if existing_instance is None: + return self._create_new_instance() + + create_context = self.create_context + host_name = create_context.host_name + project_name = create_context.get_current_project_name() + asset_name = create_context.get_current_asset_name() + task_name = create_context.get_current_task_name() + + if ( + existing_instance["asset"] != asset_name + or existing_instance["task"] != task_name + ): + asset_doc = get_asset_by_name(project_name, asset_name) + subset_name = self.get_subset_name( + existing_instance["variant"], + task_name, + asset_doc, + project_name, + host_name, + existing_instance + ) + existing_instance["asset"] = asset_name + existing_instance["task"] = task_name + existing_instance["subset"] = subset_name + + existing_instance["label"] = self._get_label(existing_instance["subset"]) + + def _get_label(self, subset_name): + try: + subset_name = subset_name.format(**prepare_template_data({})) + except (KeyError, ValueError): + pass + + return subset_name + + def get_dynamic_data(self, variant, *args, **kwargs): + dynamic_data = super().get_dynamic_data(variant, *args, **kwargs) + return dynamic_data + + def get_instance_attr_defs(self): + return [ + BoolDef( + "ignore_layers_transparency", + label="Ignore Layers Transparency", + default=self.ignore_layers_transparency + ), + BoolDef( + "publish_sequence", + label="Publish Sequence", + default=self.publish_sequence + ) + ] diff --git a/quad_pyblish_module/settings/defaults/project_settings.json b/quad_pyblish_module/settings/defaults/project_settings.json index cf459fc..c901bee 100644 --- a/quad_pyblish_module/settings/defaults/project_settings.json +++ b/quad_pyblish_module/settings/defaults/project_settings.json @@ -7,13 +7,25 @@ }, "ExtractJson": { "enabled": false + }, + "IntegrateKitsuSequence": { + "enabled": false } + }, "create": { "create_json": { "enabled": true, "default_variant": "Main", "default_variants": [] + }, + "create_publish_layout": { + "enabled": true, + "active_on_create": true, + "ignore_layers_transparency": true, + "default_variant": "Main", + "default_variants": [], + "authorized_tasks": [] } } } diff --git a/quad_pyblish_module/settings/schemas/project_schemas/tvpaint.json b/quad_pyblish_module/settings/schemas/project_schemas/tvpaint.json index 5785638..d0b9b02 100644 --- a/quad_pyblish_module/settings/schemas/project_schemas/tvpaint.json +++ b/quad_pyblish_module/settings/schemas/project_schemas/tvpaint.json @@ -38,6 +38,20 @@ "label": "Enabled" } ] + }, + { + "type": "dict", + "key": "IntegrateKitsuSequence", + "label": "Integrate Kitsu Sequence", + "is_group": false, + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + } + ] } ] }, @@ -73,6 +87,51 @@ } } ] + }, + { + "type": "dict", + "collapsible": true, + "key": "create_publish_layout", + "label": "Create Publish Layout", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "active_on_create", + "label": "Active on create" + }, + { + "type": "boolean", + "key": "ignore_layers_transparency", + "label": "Ignore Layers Transparency" + }, + { + "type": "text", + "key": "default_variant", + "label": "Default variant" + }, + { + "type": "list", + "key": "default_variants", + "label": "Default variants", + "object_type": { + "type": "text" + } + }, + { + "type": "list", + "key": "authorized_tasks", + "label": "Authorized tasks", + "object_type": { + "type": "text" + } + } + ] } ] } From 84282ea89836476ecffa7de36690e567ae8a3bb4 Mon Sep 17 00:00:00 2001 From: Guilhemz Date: Mon, 23 Oct 2023 17:34:46 +0200 Subject: [PATCH 13/17] #159: clean: create_publish_layout - update label from publish sequence to review --- .../plugins/tvpaint/create/create_publish_layout.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quad_pyblish_module/plugins/tvpaint/create/create_publish_layout.py b/quad_pyblish_module/plugins/tvpaint/create/create_publish_layout.py index caa5366..280e843 100644 --- a/quad_pyblish_module/plugins/tvpaint/create/create_publish_layout.py +++ b/quad_pyblish_module/plugins/tvpaint/create/create_publish_layout.py @@ -123,7 +123,7 @@ def get_instance_attr_defs(self): ), BoolDef( "publish_sequence", - label="Publish Sequence", + label="Review", default=self.publish_sequence ) ] From 1bc11d8ef85c7ae9a4acbb14002671e57d054445 Mon Sep 17 00:00:00 2001 From: Guilhemz Date: Thu, 26 Oct 2023 17:19:40 +0200 Subject: [PATCH 14/17] #159: clean: update from 'ignore_layers_transparency' to 'keep_layers_transparency' for better user comprehension --- .../plugins/tvpaint/create/create_publish_layout.py | 12 ++++++------ .../settings/defaults/project_settings.json | 5 ++--- .../settings/schemas/project_schemas/tvpaint.json | 12 ++---------- 3 files changed, 10 insertions(+), 19 deletions(-) diff --git a/quad_pyblish_module/plugins/tvpaint/create/create_publish_layout.py b/quad_pyblish_module/plugins/tvpaint/create/create_publish_layout.py index caa5366..b8447b5 100644 --- a/quad_pyblish_module/plugins/tvpaint/create/create_publish_layout.py +++ b/quad_pyblish_module/plugins/tvpaint/create/create_publish_layout.py @@ -20,7 +20,7 @@ class TVPaintPublishLayoutCreator(TVPaintAutoCreator): # Settings publish_sequence = True - ignore_layers_transparency = False + keep_layers_transparency = False def apply_settings(self, project_settings, system_settings): plugin_settings = ( @@ -52,7 +52,7 @@ def _create_new_instance(self): "variant": self.default_variant, "creator_attributes": { "publish_sequence": self.publish_sequence, - "ignore_layers_transparency": self.ignore_layers_transparency + "ignore_layers_transparency": not self.keep_layers_transparency }, "label": self._get_label(subset_name), "active": self.active_on_create @@ -117,13 +117,13 @@ def get_dynamic_data(self, variant, *args, **kwargs): def get_instance_attr_defs(self): return [ BoolDef( - "ignore_layers_transparency", - label="Ignore Layers Transparency", - default=self.ignore_layers_transparency + "keep_layers_transparency", + label="Keep Layers Transparency", + default=self.keep_layers_transparency ), BoolDef( "publish_sequence", - label="Publish Sequence", + label="Review", default=self.publish_sequence ) ] diff --git a/quad_pyblish_module/settings/defaults/project_settings.json b/quad_pyblish_module/settings/defaults/project_settings.json index c901bee..766a9b3 100644 --- a/quad_pyblish_module/settings/defaults/project_settings.json +++ b/quad_pyblish_module/settings/defaults/project_settings.json @@ -22,10 +22,9 @@ "create_publish_layout": { "enabled": true, "active_on_create": true, - "ignore_layers_transparency": true, + "keep_layers_transparency": true, "default_variant": "Main", - "default_variants": [], - "authorized_tasks": [] + "default_variants": [] } } } diff --git a/quad_pyblish_module/settings/schemas/project_schemas/tvpaint.json b/quad_pyblish_module/settings/schemas/project_schemas/tvpaint.json index d0b9b02..145e87a 100644 --- a/quad_pyblish_module/settings/schemas/project_schemas/tvpaint.json +++ b/quad_pyblish_module/settings/schemas/project_schemas/tvpaint.json @@ -107,8 +107,8 @@ }, { "type": "boolean", - "key": "ignore_layers_transparency", - "label": "Ignore Layers Transparency" + "key": "keep_layers_transparency", + "label": "Keep Layers Transparency" }, { "type": "text", @@ -122,14 +122,6 @@ "object_type": { "type": "text" } - }, - { - "type": "list", - "key": "authorized_tasks", - "label": "Authorized tasks", - "object_type": { - "type": "text" - } } ] } From 0d7af58b545df052d5f9a5bf317c0c9b945a7ad1 Mon Sep 17 00:00:00 2001 From: Guilhemz Date: Thu, 26 Oct 2023 17:43:06 +0200 Subject: [PATCH 15/17] #159: bugfixe: update setting variable name --- .../plugins/tvpaint/create/create_publish_layout.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quad_pyblish_module/plugins/tvpaint/create/create_publish_layout.py b/quad_pyblish_module/plugins/tvpaint/create/create_publish_layout.py index b8447b5..5bc8c2d 100644 --- a/quad_pyblish_module/plugins/tvpaint/create/create_publish_layout.py +++ b/quad_pyblish_module/plugins/tvpaint/create/create_publish_layout.py @@ -27,7 +27,7 @@ def apply_settings(self, project_settings, system_settings): project_settings["fix_custom_settings"]["tvpaint"]["create"]["create_publish_layout"] ) self.active_on_create = plugin_settings["active_on_create"] - self.ignore_layers_transparency = plugin_settings["ignore_layers_transparency"] + self.keep_layers_transparency = plugin_settings["keep_layers_transparency"] self.default_variant = plugin_settings["default_variant"] self.default_variants = plugin_settings["default_variants"] From 4d40395bdb6aaa7f2ecf79a29f7411d5d5542b92 Mon Sep 17 00:00:00 2001 From: Guilhemz Date: Fri, 27 Oct 2023 10:24:09 +0200 Subject: [PATCH 16/17] #159: bugfixe: remove keep_layers_transparency attribute initialization at subset creation and replace it by keep_layers_transparency --- .../plugins/tvpaint/create/create_publish_layout.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quad_pyblish_module/plugins/tvpaint/create/create_publish_layout.py b/quad_pyblish_module/plugins/tvpaint/create/create_publish_layout.py index 5bc8c2d..d625168 100644 --- a/quad_pyblish_module/plugins/tvpaint/create/create_publish_layout.py +++ b/quad_pyblish_module/plugins/tvpaint/create/create_publish_layout.py @@ -52,7 +52,7 @@ def _create_new_instance(self): "variant": self.default_variant, "creator_attributes": { "publish_sequence": self.publish_sequence, - "ignore_layers_transparency": not self.keep_layers_transparency + "keep_layers_transparency": self.keep_layers_transparency }, "label": self._get_label(subset_name), "active": self.active_on_create From 27cb0f9e4f1ebdf6163efae88ce3ae8debc45534 Mon Sep 17 00:00:00 2001 From: BenSouchet Date: Fri, 27 Oct 2023 15:00:27 +0200 Subject: [PATCH 17/17] Add .idea to .gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 68bc17f..2dc53ca 100644 --- a/.gitignore +++ b/.gitignore @@ -157,4 +157,4 @@ cython_debug/ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore # and can be added to the global gitignore or merged into this file. For a more nuclear # option (not recommended) you can uncomment the following to ignore the entire idea folder. -#.idea/ +.idea/