From 37d81b09481d44b9f17a377a287e85b57872d0d4 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 2 Nov 2020 11:43:00 +0100 Subject: [PATCH 01/79] modified imports in loader --- pype/plugins/tvpaint/load/load_image.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pype/plugins/tvpaint/load/load_image.py b/pype/plugins/tvpaint/load/load_image.py index ec126adbee..ca4b7a4c86 100644 --- a/pype/plugins/tvpaint/load/load_image.py +++ b/pype/plugins/tvpaint/load/load_image.py @@ -1,5 +1,5 @@ from avalon import api -from avalon.tvpaint import CommunicatorWrapper +from avalon.tvpaint import CommunicationWrapper class ImportImage(api.Loader): @@ -35,4 +35,4 @@ class ImportImage(api.Loader): self.fname.replace("\\", "/"), layer_name ) - return CommunicatorWrapper.execute_george_through_file(george_script) + return CommunicationWrapper.execute_george_through_file(george_script) From 189c72e139bddd95fa2652eb5c5e7b43c198da09 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 2 Nov 2020 11:43:14 +0100 Subject: [PATCH 02/79] added review creator --- pype/plugins/tvpaint/create/create_review.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 pype/plugins/tvpaint/create/create_review.py diff --git a/pype/plugins/tvpaint/create/create_review.py b/pype/plugins/tvpaint/create/create_review.py new file mode 100644 index 0000000000..34c7e0c6ed --- /dev/null +++ b/pype/plugins/tvpaint/create/create_review.py @@ -0,0 +1,19 @@ +from avalon.tvpaint import pipeline, CommunicationWrapper + + +class CreateReview(pipeline.TVPaintCreator): + """Arnold Archive""" + + name = "review" + label = "Review" + family = "review" + icon = "cube" + defaults = ["Main"] + + def process(self): + instances = pipeline.list_instances() + for instance in instances: + if instance["family"] == self.family: + self.log.info("Review family is already Created.") + return + super(CreateReview, self).process() From 6bdace7a21540096d0439fb287c8c732c1f97215 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 3 Nov 2020 18:56:43 +0100 Subject: [PATCH 03/79] Initial beauty creator --- pype/plugins/tvpaint/create/create_beauty.py | 60 ++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 pype/plugins/tvpaint/create/create_beauty.py diff --git a/pype/plugins/tvpaint/create/create_beauty.py b/pype/plugins/tvpaint/create/create_beauty.py new file mode 100644 index 0000000000..08e1262943 --- /dev/null +++ b/pype/plugins/tvpaint/create/create_beauty.py @@ -0,0 +1,60 @@ +import avalon.io +from avalon.tvpaint import pipeline, CommunicationWrapper + + +class CreateBeauty(pipeline.TVPaintCreator): + """Arnold Archive""" + + name = "beauty" + label = "Beauty" + family = "renderLayer" + icon = "cube" + defaults = ["Main"] + + subset_template = "{family}{task}_{name}_{pass}" + + def process(self): + instances = pipeline.list_instances() + layers_data = CommunicationWrapper.layers_data() + group_ids = set() + for layer in layers_data: + if layer["selected"]: + group_ids.add(layer["group_id"]) + + if not group_ids: + raise AssertionError("Nothing is selected.") + + if len(group_ids) > 1: + raise AssertionError("More than one group is in selection.") + + group_id = tuple(group_ids)[0] + + existing_instance = None + existing_instance_idx = None + for idx, instance in enumerate(instances): + if ( + instance["family"] == self.family + and instance["group_id"] == group_id + ): + existing_instance = instance + existing_instance_idx = idx + break + + fill_data = { + "family": self.family, + "task": avalon.io.Session["AVALON_TASK"], + "name": "name", + "pass": "beauty" + } + subset_name = self.subset_template.format(**fill_data) + self.data["subset"] = subset_name + self.data["group_id"] = group_id + if existing_instance is not None: + if existing_instance == self.data: + self.log.info("Instance to create is same. Did nothing.") + return + instances[existing_instance_idx] = self.data + else: + instances.append(self.data) + + self.write_instances(instances) From 17044990936ac61744c494ea7275c262ff110ceb Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 3 Nov 2020 19:33:21 +0100 Subject: [PATCH 04/79] implemented basic collector --- .../tvpaint/publish/collect_instances.py | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 pype/plugins/tvpaint/publish/collect_instances.py diff --git a/pype/plugins/tvpaint/publish/collect_instances.py b/pype/plugins/tvpaint/publish/collect_instances.py new file mode 100644 index 0000000000..931d5b490b --- /dev/null +++ b/pype/plugins/tvpaint/publish/collect_instances.py @@ -0,0 +1,38 @@ +import json + +import pyblish.api +import avalon.io +from avalon.tvpaint import pipeline + + +class CollectInstances(pyblish.api.ContextPlugin): + label = "Collect Instances" + order = pyblish.api.CollectorOrder + hosts = ["tvpaint"] + + def process(self, context): + self.log.info("Collecting instance data from workfile") + instances_data = pipeline.list_instances() + self.log.debug("Collected ({}) instances: {}".format( + len(instances_data), instances_data + )) + + # TODO add validations of existing instances + # - layer id exists + for instance_data in instances_data: + asset_name = instance_data["asset"] + subset_name = instance_data["subset"] + family = instance_data["family"] + name = instance_data.get("name", subset_name) + active = instance_data.get("active", True) + + instance = context.create_instance( + name=name, + family=family, + families=[family], + subset=subset_name, + asset=asset_name, + active=active, + publish=active, + ) + self.log.debug(instance) From ceac453ed4e6223a27af1b3aff3a9dcae17ef100 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 3 Nov 2020 19:33:39 +0100 Subject: [PATCH 05/79] create beauty has more data --- pype/plugins/tvpaint/create/create_beauty.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/pype/plugins/tvpaint/create/create_beauty.py b/pype/plugins/tvpaint/create/create_beauty.py index 08e1262943..c8303c8b11 100644 --- a/pype/plugins/tvpaint/create/create_beauty.py +++ b/pype/plugins/tvpaint/create/create_beauty.py @@ -40,15 +40,19 @@ class CreateBeauty(pipeline.TVPaintCreator): existing_instance_idx = idx break - fill_data = { + self.data["group_id"] = group_id + + name = self.data["subset"] + self.data["name"] = name + + subset_name = self.subset_template.format(**{ "family": self.family, "task": avalon.io.Session["AVALON_TASK"], - "name": "name", + "name": name, "pass": "beauty" - } - subset_name = self.subset_template.format(**fill_data) + }) self.data["subset"] = subset_name - self.data["group_id"] = group_id + if existing_instance is not None: if existing_instance == self.data: self.log.info("Instance to create is same. Did nothing.") From 3277c8c2b943c402dd51d579c1cda26ac0776766 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 4 Nov 2020 10:39:21 +0100 Subject: [PATCH 06/79] using tvpaint's lib instead of CommunicationWrapper --- pype/plugins/tvpaint/create/create_beauty.py | 4 ++-- pype/plugins/tvpaint/create/create_review.py | 2 +- pype/plugins/tvpaint/load/load_image.py | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pype/plugins/tvpaint/create/create_beauty.py b/pype/plugins/tvpaint/create/create_beauty.py index c8303c8b11..dd08c1a0d2 100644 --- a/pype/plugins/tvpaint/create/create_beauty.py +++ b/pype/plugins/tvpaint/create/create_beauty.py @@ -1,5 +1,5 @@ import avalon.io -from avalon.tvpaint import pipeline, CommunicationWrapper +from avalon.tvpaint import pipeline, lib class CreateBeauty(pipeline.TVPaintCreator): @@ -15,7 +15,7 @@ class CreateBeauty(pipeline.TVPaintCreator): def process(self): instances = pipeline.list_instances() - layers_data = CommunicationWrapper.layers_data() + layers_data = lib.layers_data() group_ids = set() for layer in layers_data: if layer["selected"]: diff --git a/pype/plugins/tvpaint/create/create_review.py b/pype/plugins/tvpaint/create/create_review.py index 34c7e0c6ed..567ab10f42 100644 --- a/pype/plugins/tvpaint/create/create_review.py +++ b/pype/plugins/tvpaint/create/create_review.py @@ -1,4 +1,4 @@ -from avalon.tvpaint import pipeline, CommunicationWrapper +from avalon.tvpaint import pipeline class CreateReview(pipeline.TVPaintCreator): diff --git a/pype/plugins/tvpaint/load/load_image.py b/pype/plugins/tvpaint/load/load_image.py index ca4b7a4c86..72bd23a720 100644 --- a/pype/plugins/tvpaint/load/load_image.py +++ b/pype/plugins/tvpaint/load/load_image.py @@ -1,5 +1,5 @@ from avalon import api -from avalon.tvpaint import CommunicationWrapper +from avalon.tvpaint import lib class ImportImage(api.Loader): @@ -35,4 +35,4 @@ class ImportImage(api.Loader): self.fname.replace("\\", "/"), layer_name ) - return CommunicationWrapper.execute_george_through_file(george_script) + return lib.execute_george_through_file(george_script) From 093fa1825c6d4a162e77fd3b6880c8cf8fe84b3b Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 5 Nov 2020 10:35:15 +0100 Subject: [PATCH 07/79] remove invalid docstring --- pype/plugins/tvpaint/create/create_beauty.py | 2 -- pype/plugins/tvpaint/create/create_review.py | 2 -- 2 files changed, 4 deletions(-) diff --git a/pype/plugins/tvpaint/create/create_beauty.py b/pype/plugins/tvpaint/create/create_beauty.py index dd08c1a0d2..a838c2a5c9 100644 --- a/pype/plugins/tvpaint/create/create_beauty.py +++ b/pype/plugins/tvpaint/create/create_beauty.py @@ -3,8 +3,6 @@ from avalon.tvpaint import pipeline, lib class CreateBeauty(pipeline.TVPaintCreator): - """Arnold Archive""" - name = "beauty" label = "Beauty" family = "renderLayer" diff --git a/pype/plugins/tvpaint/create/create_review.py b/pype/plugins/tvpaint/create/create_review.py index 567ab10f42..279e03caea 100644 --- a/pype/plugins/tvpaint/create/create_review.py +++ b/pype/plugins/tvpaint/create/create_review.py @@ -2,8 +2,6 @@ from avalon.tvpaint import pipeline class CreateReview(pipeline.TVPaintCreator): - """Arnold Archive""" - name = "review" label = "Review" family = "review" From 8170ff5559e2a940ecd99da5d018e3f776593e2d Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 5 Nov 2020 11:03:30 +0100 Subject: [PATCH 08/79] create beauty also renames group --- pype/plugins/tvpaint/create/create_beauty.py | 30 +++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/pype/plugins/tvpaint/create/create_beauty.py b/pype/plugins/tvpaint/create/create_beauty.py index a838c2a5c9..49ef2164d1 100644 --- a/pype/plugins/tvpaint/create/create_beauty.py +++ b/pype/plugins/tvpaint/create/create_beauty.py @@ -10,9 +10,14 @@ class CreateBeauty(pipeline.TVPaintCreator): defaults = ["Main"] subset_template = "{family}{task}_{name}_{pass}" + rename_script_template = ( + "tv_layercolor \"setcolor\"" + " {clip_id} {group_id} {r} {g} {b} \"{name}\"" + ) def process(self): instances = pipeline.list_instances() + groups_data = lib.groups_data() layers_data = lib.layers_data() group_ids = set() for layer in layers_data: @@ -26,6 +31,10 @@ class CreateBeauty(pipeline.TVPaintCreator): raise AssertionError("More than one group is in selection.") group_id = tuple(group_ids)[0] + if group_id == 0: + raise AssertionError( + "Selection is not in group. Can't mark selection as Beauty." + ) existing_instance = None existing_instance_idx = None @@ -39,7 +48,6 @@ class CreateBeauty(pipeline.TVPaintCreator): break self.data["group_id"] = group_id - name = self.data["subset"] self.data["name"] = name @@ -60,3 +68,23 @@ class CreateBeauty(pipeline.TVPaintCreator): instances.append(self.data) self.write_instances(instances) + + group = None + for group_data in groups_data: + if group_data["id"] == group_id: + group = group_data + + if not group: + return + + new_group_name = name.replace(" ", "_") + + rename_script = self.rename_script_template.format( + clip_id=group["clip_id"], + group_id=group["id"], + r=group["red"], + g=group["green"], + b=group["blue"], + name=new_group_name + ) + lib.execute_george_through_file(rename_script) From a2089fb2d283916dbce7eb5e3116ca0bfae3d568 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 5 Nov 2020 11:43:14 +0100 Subject: [PATCH 09/79] extract name from subset name --- pype/plugins/tvpaint/create/create_beauty.py | 27 +++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/pype/plugins/tvpaint/create/create_beauty.py b/pype/plugins/tvpaint/create/create_beauty.py index 49ef2164d1..07c66f8d02 100644 --- a/pype/plugins/tvpaint/create/create_beauty.py +++ b/pype/plugins/tvpaint/create/create_beauty.py @@ -36,19 +36,11 @@ class CreateBeauty(pipeline.TVPaintCreator): "Selection is not in group. Can't mark selection as Beauty." ) - existing_instance = None - existing_instance_idx = None - for idx, instance in enumerate(instances): - if ( - instance["family"] == self.family - and instance["group_id"] == group_id - ): - existing_instance = instance - existing_instance_idx = idx - break - - self.data["group_id"] = group_id + family = self.data["family"] name = self.data["subset"] + # Is this right way how to get name? + name = name[len(family):] + self.data["group_id"] = group_id self.data["name"] = name subset_name = self.subset_template.format(**{ @@ -59,6 +51,17 @@ class CreateBeauty(pipeline.TVPaintCreator): }) self.data["subset"] = subset_name + existing_instance = None + existing_instance_idx = None + for idx, instance in enumerate(instances): + if ( + instance["family"] == family + and instance["group_id"] == group_id + ): + existing_instance = instance + existing_instance_idx = idx + break + if existing_instance is not None: if existing_instance == self.data: self.log.info("Instance to create is same. Did nothing.") From c93a34dd14750b54bc35156c6add6da0b664b528 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 5 Nov 2020 12:03:41 +0100 Subject: [PATCH 10/79] added few logs --- pype/plugins/tvpaint/create/create_beauty.py | 45 ++++++++++++++------ 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/pype/plugins/tvpaint/create/create_beauty.py b/pype/plugins/tvpaint/create/create_beauty.py index 07c66f8d02..918c18070a 100644 --- a/pype/plugins/tvpaint/create/create_beauty.py +++ b/pype/plugins/tvpaint/create/create_beauty.py @@ -9,6 +9,8 @@ class CreateBeauty(pipeline.TVPaintCreator): icon = "cube" defaults = ["Main"] + rename_group = True + subset_template = "{family}{task}_{name}_{pass}" rename_script_template = ( "tv_layercolor \"setcolor\"" @@ -16,9 +18,12 @@ class CreateBeauty(pipeline.TVPaintCreator): ) def process(self): + self.log.debug("Query data from workfile.") instances = pipeline.list_instances() groups_data = lib.groups_data() layers_data = lib.layers_data() + + self.log.debug("Checking for selection groups.") group_ids = set() for layer in layers_data: if layer["selected"]: @@ -36,11 +41,14 @@ class CreateBeauty(pipeline.TVPaintCreator): "Selection is not in group. Can't mark selection as Beauty." ) + self.log.debug(f"Selected group id is \"{group_id}\".") + self.data["group_id"] = group_id + family = self.data["family"] name = self.data["subset"] # Is this right way how to get name? name = name[len(family):] - self.data["group_id"] = group_id + self.log.info(f"Extracted name form subset name \"{name}\".") self.data["name"] = name subset_name = self.subset_template.format(**{ @@ -49,6 +57,7 @@ class CreateBeauty(pipeline.TVPaintCreator): "name": name, "pass": "beauty" }) + self.log.info(f"New subset name \"{subset_name}\".") self.data["subset"] = subset_name existing_instance = None @@ -63,31 +72,41 @@ class CreateBeauty(pipeline.TVPaintCreator): break if existing_instance is not None: + self.log.info( + f"Beauty instance for group id {group_id} already exists." + ) if existing_instance == self.data: self.log.info("Instance to create is same. Did nothing.") return + self.log.debug("Overriding beauty instance with new data.") instances[existing_instance_idx] = self.data else: instances.append(self.data) self.write_instances(instances) - group = None - for group_data in groups_data: - if group_data["id"] == group_id: - group = group_data - - if not group: + if not self.rename_group: + self.log.info("Group rename function is turned off. Skipping") return - new_group_name = name.replace(" ", "_") + self.log.debug("Changing name of the group.") + selected_group = None + for group_data in groups_data: + if group_data["id"] == group_id: + selected_group = group_data + new_group_name = name.replace(" ", "_") rename_script = self.rename_script_template.format( - clip_id=group["clip_id"], - group_id=group["id"], - r=group["red"], - g=group["green"], - b=group["blue"], + clip_id=selected_group["clip_id"], + group_id=selected_group["id"], + r=selected_group["red"], + g=selected_group["green"], + b=selected_group["blue"], name=new_group_name ) lib.execute_george_through_file(rename_script) + + self.log.info( + f"Name of group with index {group_id}" + f" was changed to {new_group_name}." + ) From 917ca76bd36cdc79ac8e9583eca16b46b83d8a7a Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 5 Nov 2020 12:07:45 +0100 Subject: [PATCH 11/79] typo fix --- pype/plugins/tvpaint/create/create_beauty.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pype/plugins/tvpaint/create/create_beauty.py b/pype/plugins/tvpaint/create/create_beauty.py index 918c18070a..43ae4232aa 100644 --- a/pype/plugins/tvpaint/create/create_beauty.py +++ b/pype/plugins/tvpaint/create/create_beauty.py @@ -48,7 +48,7 @@ class CreateBeauty(pipeline.TVPaintCreator): name = self.data["subset"] # Is this right way how to get name? name = name[len(family):] - self.log.info(f"Extracted name form subset name \"{name}\".") + self.log.info(f"Extracted name from subset name \"{name}\".") self.data["name"] = name subset_name = self.subset_template.format(**{ @@ -108,5 +108,5 @@ class CreateBeauty(pipeline.TVPaintCreator): self.log.info( f"Name of group with index {group_id}" - f" was changed to {new_group_name}." + f" was changed to \"{new_group_name}\"." ) From 353c962617c47cefe63bf6c6e02aecb64792e1f5 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 5 Nov 2020 14:01:35 +0100 Subject: [PATCH 12/79] implemented render pass creator --- .../tvpaint/create/create_render_pass.py | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 pype/plugins/tvpaint/create/create_render_pass.py diff --git a/pype/plugins/tvpaint/create/create_render_pass.py b/pype/plugins/tvpaint/create/create_render_pass.py new file mode 100644 index 0000000000..fa51dcad26 --- /dev/null +++ b/pype/plugins/tvpaint/create/create_render_pass.py @@ -0,0 +1,85 @@ +import tempfile +import avalon.io +from avalon.tvpaint import pipeline, lib + + +class CreateRenderPass(pipeline.TVPaintCreator): + name = "render_pass" + label = "Render Pass" + family = "renderPass" + icon = "cube" + defaults = ["Main"] + + def process(self): + instances = pipeline.list_instances() + layers_data = lib.layers_data() + group_ids = set() + selected_layers = [] + for layer in layers_data: + if layer["selected"]: + selected_layers.append(layer) + group_ids.add(layer["group_id"]) + + if not selected_layers: + raise AssertionError("Nothing is selected.") + + if len(group_ids) != 1: + raise AssertionError("More than one group is in selection.") + + group_id = tuple(group_ids)[0] + + beauty_instance = None + for instance in instances: + if ( + instance["family"] == "renderLayer" + and instance["group_id"] == group_id + ): + beauty_instance = instance + break + + if beauty_instance is None: + raise AssertionError("Beauty pass does not exist yet.") + + family = self.data["family"] + name = self.data["subset"] + # Is this right way how to get name? + name = name[len(family):] + + self.data["group_id"] = group_id + self.data["name"] = name + + layer_ids = [layer["id"] for layer in selected_layers] + self.data["layer_ids"] = layer_ids + + beauty_subset_name = beauty_instance["subset"] + beauty_pass_name = "beauty" + if not beauty_subset_name.endswith(beauty_pass_name): + raise AssertionError( + "BUG: Beauty subset name does not end with \"{}\"".format( + beauty_pass_name + ) + ) + subset_name = beauty_subset_name[:-len(beauty_pass_name)] + name + self.data["subset"] = subset_name + + existing_instance = None + existing_instance_idx = None + for idx, instance in enumerate(instances): + if ( + instance["family"] == family + and instance["group_id"] == group_id + and instance["name"] == name + ): + existing_instance = instance + existing_instance_idx = idx + break + + if existing_instance is not None: + if existing_instance == self.data: + self.log.info("Instance to create is same. Did nothing.") + return + instances[existing_instance_idx] = self.data + else: + instances.append(self.data) + + self.write_instances(instances) From fe3310a2226959f6892d7a83239274b2ac81b967 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 5 Nov 2020 14:11:29 +0100 Subject: [PATCH 13/79] added few logs --- pype/plugins/tvpaint/create/create_beauty.py | 4 +-- .../tvpaint/create/create_render_pass.py | 25 ++++++++++++++++--- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/pype/plugins/tvpaint/create/create_beauty.py b/pype/plugins/tvpaint/create/create_beauty.py index 43ae4232aa..5701845288 100644 --- a/pype/plugins/tvpaint/create/create_beauty.py +++ b/pype/plugins/tvpaint/create/create_beauty.py @@ -45,14 +45,14 @@ class CreateBeauty(pipeline.TVPaintCreator): self.data["group_id"] = group_id family = self.data["family"] - name = self.data["subset"] # Is this right way how to get name? - name = name[len(family):] + name = self.data["subset"][len(family):] self.log.info(f"Extracted name from subset name \"{name}\".") self.data["name"] = name subset_name = self.subset_template.format(**{ "family": self.family, + # Should be task name capitalized? "task": avalon.io.Session["AVALON_TASK"], "name": name, "pass": "beauty" diff --git a/pype/plugins/tvpaint/create/create_render_pass.py b/pype/plugins/tvpaint/create/create_render_pass.py index fa51dcad26..ff60f299a3 100644 --- a/pype/plugins/tvpaint/create/create_render_pass.py +++ b/pype/plugins/tvpaint/create/create_render_pass.py @@ -10,9 +10,14 @@ class CreateRenderPass(pipeline.TVPaintCreator): icon = "cube" defaults = ["Main"] + beauty_pass_name = "beauty" + def process(self): + self.log.debug("Query data from workfile.") instances = pipeline.list_instances() layers_data = lib.layers_data() + + self.log.debug("Checking selection.") group_ids = set() selected_layers = [] for layer in layers_data: @@ -27,6 +32,7 @@ class CreateRenderPass(pipeline.TVPaintCreator): raise AssertionError("More than one group is in selection.") group_id = tuple(group_ids)[0] + self.log.debug(f"Selected group id is \"{group_id}\".") beauty_instance = None for instance in instances: @@ -44,6 +50,7 @@ class CreateRenderPass(pipeline.TVPaintCreator): name = self.data["subset"] # Is this right way how to get name? name = name[len(family):] + self.log.info(f"Extracted name from subset name \"{name}\".") self.data["group_id"] = group_id self.data["name"] = name @@ -52,15 +59,20 @@ class CreateRenderPass(pipeline.TVPaintCreator): self.data["layer_ids"] = layer_ids beauty_subset_name = beauty_instance["subset"] - beauty_pass_name = "beauty" - if not beauty_subset_name.endswith(beauty_pass_name): + self.log.info( + "New subset name will be created from " + f"beauty instance \"{beauty_subset_name}\"." + ) + + if not beauty_subset_name.endswith(self.beauty_pass_name): raise AssertionError( "BUG: Beauty subset name does not end with \"{}\"".format( - beauty_pass_name + self.beauty_pass_name ) ) - subset_name = beauty_subset_name[:-len(beauty_pass_name)] + name + subset_name = beauty_subset_name[:-len(self.beauty_pass_name)] + name self.data["subset"] = subset_name + self.log.info(f"New subset name is \"{subset_name}\".") existing_instance = None existing_instance_idx = None @@ -75,9 +87,14 @@ class CreateRenderPass(pipeline.TVPaintCreator): break if existing_instance is not None: + self.log.info( + f"Render pass instance for group id {group_id}" + f" and name \"{name}\" already exists." + ) if existing_instance == self.data: self.log.info("Instance to create is same. Did nothing.") return + self.log.debug("Overriding beauty instance with new data.") instances[existing_instance_idx] = self.data else: instances.append(self.data) From 89ccf0724b60d8a84933c2fc24ed89647dce838f Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 5 Nov 2020 14:34:45 +0100 Subject: [PATCH 14/79] added poor docstrings --- pype/plugins/tvpaint/create/create_beauty.py | 1 + pype/plugins/tvpaint/create/create_render_pass.py | 5 +++++ pype/plugins/tvpaint/create/create_review.py | 1 + 3 files changed, 7 insertions(+) diff --git a/pype/plugins/tvpaint/create/create_beauty.py b/pype/plugins/tvpaint/create/create_beauty.py index 5701845288..aaa51f156e 100644 --- a/pype/plugins/tvpaint/create/create_beauty.py +++ b/pype/plugins/tvpaint/create/create_beauty.py @@ -3,6 +3,7 @@ from avalon.tvpaint import pipeline, lib class CreateBeauty(pipeline.TVPaintCreator): + """Mark layer group as one instance.""" name = "beauty" label = "Beauty" family = "renderLayer" diff --git a/pype/plugins/tvpaint/create/create_render_pass.py b/pype/plugins/tvpaint/create/create_render_pass.py index ff60f299a3..37d7c501f9 100644 --- a/pype/plugins/tvpaint/create/create_render_pass.py +++ b/pype/plugins/tvpaint/create/create_render_pass.py @@ -4,6 +4,11 @@ from avalon.tvpaint import pipeline, lib class CreateRenderPass(pipeline.TVPaintCreator): + """Render pass is combination of one or more layers from same group. + + Requirement to create Render Pass is to have already created beauty + instance. Beauty instance is used as base for subset name. + """ name = "render_pass" label = "Render Pass" family = "renderPass" diff --git a/pype/plugins/tvpaint/create/create_review.py b/pype/plugins/tvpaint/create/create_review.py index 279e03caea..0163d26160 100644 --- a/pype/plugins/tvpaint/create/create_review.py +++ b/pype/plugins/tvpaint/create/create_review.py @@ -2,6 +2,7 @@ from avalon.tvpaint import pipeline class CreateReview(pipeline.TVPaintCreator): + """Review for global review of all layers.""" name = "review" label = "Review" family = "review" From 0b38b162259896dc33a550d97206783a5da6544c Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 5 Nov 2020 14:51:32 +0100 Subject: [PATCH 15/79] few more comments --- pype/plugins/tvpaint/create/create_beauty.py | 14 ++++++++++++-- pype/plugins/tvpaint/create/create_render_pass.py | 10 ++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/pype/plugins/tvpaint/create/create_beauty.py b/pype/plugins/tvpaint/create/create_beauty.py index aaa51f156e..f68365a2d4 100644 --- a/pype/plugins/tvpaint/create/create_beauty.py +++ b/pype/plugins/tvpaint/create/create_beauty.py @@ -21,22 +21,25 @@ class CreateBeauty(pipeline.TVPaintCreator): def process(self): self.log.debug("Query data from workfile.") instances = pipeline.list_instances() - groups_data = lib.groups_data() layers_data = lib.layers_data() self.log.debug("Checking for selection groups.") + # Collect group ids from selection group_ids = set() for layer in layers_data: if layer["selected"]: group_ids.add(layer["group_id"]) + # Raise if there is no selection if not group_ids: raise AssertionError("Nothing is selected.") + # This creator should run only on one group if len(group_ids) > 1: raise AssertionError("More than one group is in selection.") group_id = tuple(group_ids)[0] + # If group id is `0` it is `default` group which is invalid if group_id == 0: raise AssertionError( "Selection is not in group. Can't mark selection as Beauty." @@ -46,11 +49,12 @@ class CreateBeauty(pipeline.TVPaintCreator): self.data["group_id"] = group_id family = self.data["family"] - # Is this right way how to get name? + # Extract entered name name = self.data["subset"][len(family):] self.log.info(f"Extracted name from subset name \"{name}\".") self.data["name"] = name + # Change subset name by template subset_name = self.subset_template.format(**{ "family": self.family, # Should be task name capitalized? @@ -61,6 +65,7 @@ class CreateBeauty(pipeline.TVPaintCreator): self.log.info(f"New subset name \"{subset_name}\".") self.data["subset"] = subset_name + # Check for instances for same group existing_instance = None existing_instance_idx = None for idx, instance in enumerate(instances): @@ -90,12 +95,17 @@ class CreateBeauty(pipeline.TVPaintCreator): self.log.info("Group rename function is turned off. Skipping") return + self.log.debug("Querying groups data from workfile.") + groups_data = lib.groups_data() + self.log.debug("Changing name of the group.") selected_group = None for group_data in groups_data: if group_data["id"] == group_id: selected_group = group_data + # Rename TVPaint group (keep color same) + # - groups can't contain spaces new_group_name = name.replace(" ", "_") rename_script = self.rename_script_template.format( clip_id=selected_group["clip_id"], diff --git a/pype/plugins/tvpaint/create/create_render_pass.py b/pype/plugins/tvpaint/create/create_render_pass.py index 37d7c501f9..a28348f46a 100644 --- a/pype/plugins/tvpaint/create/create_render_pass.py +++ b/pype/plugins/tvpaint/create/create_render_pass.py @@ -23,6 +23,7 @@ class CreateRenderPass(pipeline.TVPaintCreator): layers_data = lib.layers_data() self.log.debug("Checking selection.") + # Get all selected layers and their group ids group_ids = set() selected_layers = [] for layer in layers_data: @@ -30,15 +31,18 @@ class CreateRenderPass(pipeline.TVPaintCreator): selected_layers.append(layer) group_ids.add(layer["group_id"]) + # Raise if nothing is selected if not selected_layers: raise AssertionError("Nothing is selected.") + # Raise if layers from multiple groups are selected if len(group_ids) != 1: raise AssertionError("More than one group is in selection.") group_id = tuple(group_ids)[0] self.log.debug(f"Selected group id is \"{group_id}\".") + # Find beauty instance for selected layers beauty_instance = None for instance in instances: if ( @@ -48,9 +52,11 @@ class CreateRenderPass(pipeline.TVPaintCreator): beauty_instance = instance break + # Beauty is required for this creator so raise if was not found if beauty_instance is None: raise AssertionError("Beauty pass does not exist yet.") + # Extract entered name family = self.data["family"] name = self.data["subset"] # Is this right way how to get name? @@ -60,6 +66,7 @@ class CreateRenderPass(pipeline.TVPaintCreator): self.data["group_id"] = group_id self.data["name"] = name + # Collect selected layer ids to be stored into instance layer_ids = [layer["id"] for layer in selected_layers] self.data["layer_ids"] = layer_ids @@ -69,16 +76,19 @@ class CreateRenderPass(pipeline.TVPaintCreator): f"beauty instance \"{beauty_subset_name}\"." ) + # Beauty instance subset name should if not beauty_subset_name.endswith(self.beauty_pass_name): raise AssertionError( "BUG: Beauty subset name does not end with \"{}\"".format( self.beauty_pass_name ) ) + # Replace `beauty` in beauty's subset name with entered name subset_name = beauty_subset_name[:-len(self.beauty_pass_name)] + name self.data["subset"] = subset_name self.log.info(f"New subset name is \"{subset_name}\".") + # Check if same instance already exists existing_instance = None existing_instance_idx = None for idx, instance in enumerate(instances): From 5525113e219a2a224d9a6a293b0e6f79219a3ca5 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 5 Nov 2020 14:58:31 +0100 Subject: [PATCH 16/79] Instance collecting should work --- .../tvpaint/publish/collect_instances.py | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/pype/plugins/tvpaint/publish/collect_instances.py b/pype/plugins/tvpaint/publish/collect_instances.py index 931d5b490b..193302751d 100644 --- a/pype/plugins/tvpaint/publish/collect_instances.py +++ b/pype/plugins/tvpaint/publish/collect_instances.py @@ -1,5 +1,3 @@ -import json - import pyblish.api import avalon.io from avalon.tvpaint import pipeline @@ -20,19 +18,18 @@ class CollectInstances(pyblish.api.ContextPlugin): # TODO add validations of existing instances # - layer id exists for instance_data in instances_data: - asset_name = instance_data["asset"] - subset_name = instance_data["subset"] + # Fill families family = instance_data["family"] - name = instance_data.get("name", subset_name) - active = instance_data.get("active", True) + instance_data["families"] = [family] - instance = context.create_instance( - name=name, - family=family, - families=[family], - subset=subset_name, - asset=asset_name, - active=active, - publish=active, - ) - self.log.debug(instance) + # Instance name + subset_name = instance_data["subset"] + name = instance_data.get("name", subset_name) + instance_data["name"] = name + + active = instance_data.get("active", True) + instance_data["active"] = active + instance_data["publish"] = active + + instance = context.create_instance(**instance_data) + self.log.debug("Created instance: {}".format(instance)) From 727be359f2e0282b6f9875de133d535616e2aca3 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 5 Nov 2020 16:02:44 +0100 Subject: [PATCH 17/79] implemented collector where global data are collected --- .../tvpaint/publish/collect_workfile_data.py | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 pype/plugins/tvpaint/publish/collect_workfile_data.py diff --git a/pype/plugins/tvpaint/publish/collect_workfile_data.py b/pype/plugins/tvpaint/publish/collect_workfile_data.py new file mode 100644 index 0000000000..d81250c05b --- /dev/null +++ b/pype/plugins/tvpaint/publish/collect_workfile_data.py @@ -0,0 +1,57 @@ +import json + +import pyblish.api +from avalon.tvpaint import pipeline, lib + + +class CollectWorkfileData(pyblish.api.ContextPlugin): + label = "Collect Workfile Data" + order = pyblish.api.CollectorOrder - 0.01 + hosts = ["tvpaint"] + + def process(self, context): + self.log.info("Collecting instance data from workfile") + instance_data = pipeline.list_instances() + self.log.debug( + "Instance data:\"{}".format(json.dumps(instance_data, indent=4)) + ) + context.data["workfileInstances"] = instance_data + + self.log.info("Collecting layers data from workfile") + layers_data = lib.layers_data() + self.log.debug( + "Layers data:\"{}".format(json.dumps(layers_data, indent=4)) + ) + context.data["layersData"] = layers_data + + self.log.info("Collecting groups data from workfile") + group_data = lib.groups_data() + self.log.debug( + "Group data:\"{}".format(json.dumps(group_data, indent=4)) + ) + context.data["groupsData"] = group_data + + self.log.info("Collecting scene data from workfile") + workfile_info_parts = lib.execute_george("tv_projectinfo").split(" ") + + frame_start = int(workfile_info_parts.pop(-1)) + field_order = workfile_info_parts.pop(-1) + frame_rate = float(workfile_info_parts.pop(-1)) + pixel_apsect = float(workfile_info_parts.pop(-1)) + height = int(workfile_info_parts.pop(-1)) + width = int(workfile_info_parts.pop(-1)) + workfile_path = " ".join(workfile_info_parts).replace("\"", "") + + sceme_data = { + "currentFile": workfile_path, + "sceneWidth": width, + "sceneHeight": height, + "pixelAspect": pixel_apsect, + "frameStart": frame_start, + "frameRate": frame_rate, + "fieldOrder": field_order + } + self.log.debug( + "Scene data: {}".format(json.dumps(sceme_data,indent=4)) + ) + context.data.update(sceme_data) From 3b2a5a09e67cfb0f2c23e841a6ffa59d888ec482 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 5 Nov 2020 16:02:58 +0100 Subject: [PATCH 18/79] collect instances use globaly collected data --- .../tvpaint/publish/collect_instances.py | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/pype/plugins/tvpaint/publish/collect_instances.py b/pype/plugins/tvpaint/publish/collect_instances.py index 193302751d..caf6adee5f 100644 --- a/pype/plugins/tvpaint/publish/collect_instances.py +++ b/pype/plugins/tvpaint/publish/collect_instances.py @@ -1,5 +1,6 @@ +import json + import pyblish.api -import avalon.io from avalon.tvpaint import pipeline @@ -9,27 +10,28 @@ class CollectInstances(pyblish.api.ContextPlugin): hosts = ["tvpaint"] def process(self, context): - self.log.info("Collecting instance data from workfile") - instances_data = pipeline.list_instances() - self.log.debug("Collected ({}) instances: {}".format( - len(instances_data), instances_data + workfile_instances = context.data["workfileInstances"] + + self.log.debug("Collected ({}) instances:\n{}".format( + len(workfile_instances), + json.dumps(workfile_instances, indent=4) )) # TODO add validations of existing instances # - layer id exists - for instance_data in instances_data: + for workfile_instance in workfile_instances: # Fill families - family = instance_data["family"] - instance_data["families"] = [family] + family = workfile_instance["family"] + workfile_instance["families"] = [family] # Instance name - subset_name = instance_data["subset"] - name = instance_data.get("name", subset_name) - instance_data["name"] = name + subset_name = workfile_instance["subset"] + name = workfile_instance.get("name", subset_name) + workfile_instance["name"] = name - active = instance_data.get("active", True) - instance_data["active"] = active - instance_data["publish"] = active + active = workfile_instance.get("active", True) + workfile_instance["active"] = active + workfile_instance["publish"] = active - instance = context.create_instance(**instance_data) + instance = context.create_instance(**workfile_instance) self.log.debug("Created instance: {}".format(instance)) From 5b32de6d1043b5f5981f1e5f05ea2d2c89b22147 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 5 Nov 2020 16:05:29 +0100 Subject: [PATCH 19/79] using explicit id keys --- pype/plugins/tvpaint/create/create_beauty.py | 4 ++-- pype/plugins/tvpaint/create/create_render_pass.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pype/plugins/tvpaint/create/create_beauty.py b/pype/plugins/tvpaint/create/create_beauty.py index f68365a2d4..da7dd9aa82 100644 --- a/pype/plugins/tvpaint/create/create_beauty.py +++ b/pype/plugins/tvpaint/create/create_beauty.py @@ -101,7 +101,7 @@ class CreateBeauty(pipeline.TVPaintCreator): self.log.debug("Changing name of the group.") selected_group = None for group_data in groups_data: - if group_data["id"] == group_id: + if group_data["group_id"] == group_id: selected_group = group_data # Rename TVPaint group (keep color same) @@ -109,7 +109,7 @@ class CreateBeauty(pipeline.TVPaintCreator): new_group_name = name.replace(" ", "_") rename_script = self.rename_script_template.format( clip_id=selected_group["clip_id"], - group_id=selected_group["id"], + group_id=selected_group["group_id"], r=selected_group["red"], g=selected_group["green"], b=selected_group["blue"], diff --git a/pype/plugins/tvpaint/create/create_render_pass.py b/pype/plugins/tvpaint/create/create_render_pass.py index a28348f46a..9103bc735d 100644 --- a/pype/plugins/tvpaint/create/create_render_pass.py +++ b/pype/plugins/tvpaint/create/create_render_pass.py @@ -67,7 +67,7 @@ class CreateRenderPass(pipeline.TVPaintCreator): self.data["name"] = name # Collect selected layer ids to be stored into instance - layer_ids = [layer["id"] for layer in selected_layers] + layer_ids = [layer["layer_id"] for layer in selected_layers] self.data["layer_ids"] = layer_ids beauty_subset_name = beauty_instance["subset"] From 71236486f9e0be5fe83ce8d0da12d8a87398c535 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 5 Nov 2020 16:13:47 +0100 Subject: [PATCH 20/79] move order to "precollect" --- pype/plugins/tvpaint/publish/collect_instances.py | 2 +- pype/plugins/tvpaint/publish/collect_workfile_data.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pype/plugins/tvpaint/publish/collect_instances.py b/pype/plugins/tvpaint/publish/collect_instances.py index caf6adee5f..fcf02be154 100644 --- a/pype/plugins/tvpaint/publish/collect_instances.py +++ b/pype/plugins/tvpaint/publish/collect_instances.py @@ -6,7 +6,7 @@ from avalon.tvpaint import pipeline class CollectInstances(pyblish.api.ContextPlugin): label = "Collect Instances" - order = pyblish.api.CollectorOrder + order = pyblish.api.CollectorOrder - 1 hosts = ["tvpaint"] def process(self, context): diff --git a/pype/plugins/tvpaint/publish/collect_workfile_data.py b/pype/plugins/tvpaint/publish/collect_workfile_data.py index d81250c05b..8a3927d0f0 100644 --- a/pype/plugins/tvpaint/publish/collect_workfile_data.py +++ b/pype/plugins/tvpaint/publish/collect_workfile_data.py @@ -6,7 +6,7 @@ from avalon.tvpaint import pipeline, lib class CollectWorkfileData(pyblish.api.ContextPlugin): label = "Collect Workfile Data" - order = pyblish.api.CollectorOrder - 0.01 + order = pyblish.api.CollectorOrder - 1.01 hosts = ["tvpaint"] def process(self, context): From 07b0a692e822db4e43262af3b8edced421e93d78 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 5 Nov 2020 17:45:16 +0100 Subject: [PATCH 21/79] collect instances can collect more --- .../tvpaint/publish/collect_instances.py | 100 ++++++++++++++++-- .../tvpaint/publish/collect_workfile_data.py | 2 +- 2 files changed, 90 insertions(+), 12 deletions(-) diff --git a/pype/plugins/tvpaint/publish/collect_instances.py b/pype/plugins/tvpaint/publish/collect_instances.py index fcf02be154..76ec460091 100644 --- a/pype/plugins/tvpaint/publish/collect_instances.py +++ b/pype/plugins/tvpaint/publish/collect_instances.py @@ -19,19 +19,97 @@ class CollectInstances(pyblish.api.ContextPlugin): # TODO add validations of existing instances # - layer id exists - for workfile_instance in workfile_instances: + for instance_data in workfile_instances: + # Global instance data modifications # Fill families - family = workfile_instance["family"] - workfile_instance["families"] = [family] + family = instance_data["family"] + instance_data["families"] = [family] # Instance name - subset_name = workfile_instance["subset"] - name = workfile_instance.get("name", subset_name) - workfile_instance["name"] = name + subset_name = instance_data["subset"] + name = instance_data.get("name", subset_name) + instance_data["name"] = name - active = workfile_instance.get("active", True) - workfile_instance["active"] = active - workfile_instance["publish"] = active + active = instance_data.get("active", True) + instance_data["active"] = active + instance_data["publish"] = active - instance = context.create_instance(**workfile_instance) - self.log.debug("Created instance: {}".format(instance)) + # Different instance creation based on family + instance = None + if family == "review": + instance = context.create_instance(**instance_data) + elif family == "renderLayer": + instance = self.create_render_layer(context, instance_data) + elif family == "renderPass": + instance = self.create_render_pass(context, instance_data) + else: + raise AssertionError( + "Instance with unknown family \"{}\": {}" + ) + + if instance is not None: + self.log.debug("Created instance: {}\n{}".format( + instance, json.dumps(instance.data, indent=4) + )) + + def create_render_layer(self, context, instance_data): + layers_data = context.data["layersData"] + group_id = instance_data["group_id"] + + name = instance_data["name"] + instance_data["label"] = name + + group_layers = [] + for layer in layers_data: + if layer["group_id"] == group_id and layer["visible"]: + group_layers.append(layer) + + if not group_layers: + # Should be handled here? + self.log.warning( + f"Group with id {group_id} does not contain any layers." + f" Instance \"{name}\" not created." + ) + return None + + instance_data["layers"] = group_layers + return context.create_instance(**instance_data) + + def create_render_pass(self, context, instance_data): + # Change family to `renderLayer` + instance_data["family"] = "renderLayer" + instance_data["families"] = [instance_data["family"]] + + layers_data = context.data["layersData"] + layers_by_id = { + layer["layer_id"]: layer + for layer in layers_data + } + + group_id = instance_data["group_id"] + layer_ids = instance_data["layer_ids"] + render_pass_layers = [] + for layer_id in layer_ids: + layer = layers_by_id.get(layer_id) + if not layer: + self.log.warning(f"Layer with id {layer_id} was not found.") + continue + + # Move to validator? + if layer["group_id"] != group_id: + self.log.warning( + f"Layer with id {layer_id} is in different group." + ) + continue + render_pass_layers.append(layer) + + if not render_pass_layers: + name = instance_data["name"] + self.log.warning( + f"All layers from RenderPass \"{name}\" do not exist." + " Instance not created." + ) + return None + + instance_data["layers"] = render_pass_layers + return context.create_instance(**instance_data) diff --git a/pype/plugins/tvpaint/publish/collect_workfile_data.py b/pype/plugins/tvpaint/publish/collect_workfile_data.py index 8a3927d0f0..87076e978d 100644 --- a/pype/plugins/tvpaint/publish/collect_workfile_data.py +++ b/pype/plugins/tvpaint/publish/collect_workfile_data.py @@ -52,6 +52,6 @@ class CollectWorkfileData(pyblish.api.ContextPlugin): "fieldOrder": field_order } self.log.debug( - "Scene data: {}".format(json.dumps(sceme_data,indent=4)) + "Scene data: {}".format(json.dumps(sceme_data, indent=4)) ) context.data.update(sceme_data) From 9839e540252d77f51d243d3e5da94d7c2202495b Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 5 Nov 2020 18:26:49 +0100 Subject: [PATCH 22/79] added toggle callback to activate/deactivate instances --- pype/hosts/tvpaint/__init__.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/pype/hosts/tvpaint/__init__.py b/pype/hosts/tvpaint/__init__.py index cb02c87151..3df33fb52a 100644 --- a/pype/hosts/tvpaint/__init__.py +++ b/pype/hosts/tvpaint/__init__.py @@ -2,6 +2,7 @@ import os import logging from avalon.tvpaint.communication_server import register_localization_file +from avalon.tvpaint import pipeline import avalon.api import pyblish.api from pype import PLUGINS_DIR @@ -13,6 +14,23 @@ LOAD_PATH = os.path.join(PLUGINS_DIR, "tvpaint", "load") CREATE_PATH = os.path.join(PLUGINS_DIR, "tvpaint", "create") +def on_instance_toggle(instance, old_value, new_value): + instance_id = instance.data["id"] + found = False + current_instances = pipeline.list_instances() + for idx, workfile_instance in enumerate(current_instances): + if workfile_instance["id"] == instance_id: + found = True + break + + if not found: + return + + if "active" in current_instances[idx]: + current_instances[idx]["active"] = new_value + pipeline._write_instances(current_instances) + + def install(): log.info("Pype - Installing TVPaint integration") current_dir = os.path.dirname(os.path.abspath(__file__)) @@ -23,6 +41,12 @@ def install(): avalon.api.register_plugin_path(avalon.api.Loader, LOAD_PATH) avalon.api.register_plugin_path(avalon.api.Creator, CREATE_PATH) + registered_callbacks = ( + pyblish.api.registered_callbacks().get("instanceToggled") or [] + ) + if on_instance_toggle not in registered_callbacks: + pyblish.api.register_callback("instanceToggled", on_instance_toggle) + def uninstall(): log.info("Pype - Uninstalling TVPaint integration") From 1bb51aa0d01876297b187985ca2301a4d007c3a1 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 5 Nov 2020 18:59:51 +0100 Subject: [PATCH 23/79] always override instance --- pype/plugins/tvpaint/create/create_beauty.py | 7 ++----- pype/plugins/tvpaint/create/create_render_pass.py | 6 +----- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/pype/plugins/tvpaint/create/create_beauty.py b/pype/plugins/tvpaint/create/create_beauty.py index da7dd9aa82..30e0d4ccd8 100644 --- a/pype/plugins/tvpaint/create/create_beauty.py +++ b/pype/plugins/tvpaint/create/create_beauty.py @@ -79,12 +79,9 @@ class CreateBeauty(pipeline.TVPaintCreator): if existing_instance is not None: self.log.info( - f"Beauty instance for group id {group_id} already exists." + f"Beauty instance for group id {group_id} already exists" + ", overriding" ) - if existing_instance == self.data: - self.log.info("Instance to create is same. Did nothing.") - return - self.log.debug("Overriding beauty instance with new data.") instances[existing_instance_idx] = self.data else: instances.append(self.data) diff --git a/pype/plugins/tvpaint/create/create_render_pass.py b/pype/plugins/tvpaint/create/create_render_pass.py index 9103bc735d..3842c433e9 100644 --- a/pype/plugins/tvpaint/create/create_render_pass.py +++ b/pype/plugins/tvpaint/create/create_render_pass.py @@ -104,12 +104,8 @@ class CreateRenderPass(pipeline.TVPaintCreator): if existing_instance is not None: self.log.info( f"Render pass instance for group id {group_id}" - f" and name \"{name}\" already exists." + f" and name \"{name}\" already exists, overriding." ) - if existing_instance == self.data: - self.log.info("Instance to create is same. Did nothing.") - return - self.log.debug("Overriding beauty instance with new data.") instances[existing_instance_idx] = self.data else: instances.append(self.data) From 1a4f27291edc661c93b83ac070a0cb519e0534fa Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 5 Nov 2020 19:03:02 +0100 Subject: [PATCH 24/79] fix import after merge --- pype/plugins/tvpaint/load/load_image.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/plugins/tvpaint/load/load_image.py b/pype/plugins/tvpaint/load/load_image.py index 5ab67e3df4..51a825a0c8 100644 --- a/pype/plugins/tvpaint/load/load_image.py +++ b/pype/plugins/tvpaint/load/load_image.py @@ -1,6 +1,6 @@ from avalon import api from avalon.vendor import qargparse -from avalon.tvpaint import CommunicatorWrapper +from avalon.tvpaint import lib class ImportImage(api.Loader): From 5a96915992bf97d7588cd9199ce2c1e175ac2744 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 5 Nov 2020 19:19:07 +0100 Subject: [PATCH 25/79] use variable Creator instead of TVPaintCreator --- pype/plugins/tvpaint/create/create_beauty.py | 2 +- pype/plugins/tvpaint/create/create_render_pass.py | 2 +- pype/plugins/tvpaint/create/create_review.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pype/plugins/tvpaint/create/create_beauty.py b/pype/plugins/tvpaint/create/create_beauty.py index 30e0d4ccd8..6512ad08b0 100644 --- a/pype/plugins/tvpaint/create/create_beauty.py +++ b/pype/plugins/tvpaint/create/create_beauty.py @@ -2,7 +2,7 @@ import avalon.io from avalon.tvpaint import pipeline, lib -class CreateBeauty(pipeline.TVPaintCreator): +class CreateBeauty(pipeline.Creator): """Mark layer group as one instance.""" name = "beauty" label = "Beauty" diff --git a/pype/plugins/tvpaint/create/create_render_pass.py b/pype/plugins/tvpaint/create/create_render_pass.py index 3842c433e9..9971109840 100644 --- a/pype/plugins/tvpaint/create/create_render_pass.py +++ b/pype/plugins/tvpaint/create/create_render_pass.py @@ -3,7 +3,7 @@ import avalon.io from avalon.tvpaint import pipeline, lib -class CreateRenderPass(pipeline.TVPaintCreator): +class CreateRenderPass(pipeline.Creator): """Render pass is combination of one or more layers from same group. Requirement to create Render Pass is to have already created beauty diff --git a/pype/plugins/tvpaint/create/create_review.py b/pype/plugins/tvpaint/create/create_review.py index 0163d26160..9f7ee1396e 100644 --- a/pype/plugins/tvpaint/create/create_review.py +++ b/pype/plugins/tvpaint/create/create_review.py @@ -1,7 +1,7 @@ from avalon.tvpaint import pipeline -class CreateReview(pipeline.TVPaintCreator): +class CreateReview(pipeline.Creator): """Review for global review of all layers.""" name = "review" label = "Review" From 08bce91cd920b271a562446a39fb69fbe7d46a07 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 5 Nov 2020 19:21:48 +0100 Subject: [PATCH 26/79] use TVPaint loader in ImportImage --- pype/plugins/tvpaint/load/load_image.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pype/plugins/tvpaint/load/load_image.py b/pype/plugins/tvpaint/load/load_image.py index 51a825a0c8..3a09a76c7b 100644 --- a/pype/plugins/tvpaint/load/load_image.py +++ b/pype/plugins/tvpaint/load/load_image.py @@ -1,9 +1,8 @@ -from avalon import api from avalon.vendor import qargparse -from avalon.tvpaint import lib +from avalon.tvpaint import lib, Loader -class ImportImage(api.Loader): +class ImportImage(Loader): """Load image or image sequence to TVPaint as new layer.""" families = ["render", "image", "background", "plate"] From 88ff7ad5866b0094380c33616d3b3c0a6e48e0ad Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 5 Nov 2020 19:24:48 +0100 Subject: [PATCH 27/79] removed unused --- pype/plugins/tvpaint/create/create_render_pass.py | 2 -- pype/plugins/tvpaint/load/load_image.py | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/pype/plugins/tvpaint/create/create_render_pass.py b/pype/plugins/tvpaint/create/create_render_pass.py index 9971109840..e0e1b639e1 100644 --- a/pype/plugins/tvpaint/create/create_render_pass.py +++ b/pype/plugins/tvpaint/create/create_render_pass.py @@ -1,5 +1,3 @@ -import tempfile -import avalon.io from avalon.tvpaint import pipeline, lib diff --git a/pype/plugins/tvpaint/load/load_image.py b/pype/plugins/tvpaint/load/load_image.py index 3a09a76c7b..f77fab87f8 100644 --- a/pype/plugins/tvpaint/load/load_image.py +++ b/pype/plugins/tvpaint/load/load_image.py @@ -1,8 +1,8 @@ from avalon.vendor import qargparse -from avalon.tvpaint import lib, Loader +from avalon.tvpaint import lib, pipeline -class ImportImage(Loader): +class ImportImage(pipeline.Loader): """Load image or image sequence to TVPaint as new layer.""" families = ["render", "image", "background", "plate"] From 350fc4997847a34722fe6fe733a12a2b4b433ab0 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 5 Nov 2020 19:55:27 +0100 Subject: [PATCH 28/79] hound changes --- pype/hosts/tvpaint/__init__.py | 10 +++++----- pype/plugins/tvpaint/publish/collect_instances.py | 2 -- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/pype/hosts/tvpaint/__init__.py b/pype/hosts/tvpaint/__init__.py index 3df33fb52a..abda126ecd 100644 --- a/pype/hosts/tvpaint/__init__.py +++ b/pype/hosts/tvpaint/__init__.py @@ -16,18 +16,18 @@ CREATE_PATH = os.path.join(PLUGINS_DIR, "tvpaint", "create") def on_instance_toggle(instance, old_value, new_value): instance_id = instance.data["id"] - found = False + found_idx = None current_instances = pipeline.list_instances() for idx, workfile_instance in enumerate(current_instances): if workfile_instance["id"] == instance_id: - found = True + found_idx = idx break - if not found: + if found_idx is None: return - if "active" in current_instances[idx]: - current_instances[idx]["active"] = new_value + if "active" in current_instances[found_idx]: + current_instances[found_idx]["active"] = new_value pipeline._write_instances(current_instances) diff --git a/pype/plugins/tvpaint/publish/collect_instances.py b/pype/plugins/tvpaint/publish/collect_instances.py index 76ec460091..84fc7688f7 100644 --- a/pype/plugins/tvpaint/publish/collect_instances.py +++ b/pype/plugins/tvpaint/publish/collect_instances.py @@ -1,7 +1,5 @@ import json - import pyblish.api -from avalon.tvpaint import pipeline class CollectInstances(pyblish.api.ContextPlugin): From 23ebe56de69c26d1c80dddeb12e36cef8e252ddf Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Fri, 6 Nov 2020 09:55:29 +0100 Subject: [PATCH 29/79] instance toggle works with uuid key not with id --- pype/hosts/tvpaint/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pype/hosts/tvpaint/__init__.py b/pype/hosts/tvpaint/__init__.py index abda126ecd..7027f0fb55 100644 --- a/pype/hosts/tvpaint/__init__.py +++ b/pype/hosts/tvpaint/__init__.py @@ -15,11 +15,11 @@ CREATE_PATH = os.path.join(PLUGINS_DIR, "tvpaint", "create") def on_instance_toggle(instance, old_value, new_value): - instance_id = instance.data["id"] + instance_id = instance.data["uuid"] found_idx = None current_instances = pipeline.list_instances() for idx, workfile_instance in enumerate(current_instances): - if workfile_instance["id"] == instance_id: + if workfile_instance["uuid"] == instance_id: found_idx = idx break From f3e2354a5b2612f1e45c098a4381979a855fc5d9 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Fri, 6 Nov 2020 10:01:26 +0100 Subject: [PATCH 30/79] Renamed beauty to render layer --- pype/plugins/tvpaint/create/create_beauty.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pype/plugins/tvpaint/create/create_beauty.py b/pype/plugins/tvpaint/create/create_beauty.py index 6512ad08b0..10ac444a80 100644 --- a/pype/plugins/tvpaint/create/create_beauty.py +++ b/pype/plugins/tvpaint/create/create_beauty.py @@ -4,8 +4,8 @@ from avalon.tvpaint import pipeline, lib class CreateBeauty(pipeline.Creator): """Mark layer group as one instance.""" - name = "beauty" - label = "Beauty" + name = "render_layer" + label = "RenderLayer" family = "renderLayer" icon = "cube" defaults = ["Main"] From b3c94bbc4e06da961aa2a591d350b301bdc940fd Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Fri, 6 Nov 2020 10:34:07 +0100 Subject: [PATCH 31/79] renamed create_beauty file to create_render_layer --- .../tvpaint/create/{create_beauty.py => create_render_layer.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename pype/plugins/tvpaint/create/{create_beauty.py => create_render_layer.py} (100%) diff --git a/pype/plugins/tvpaint/create/create_beauty.py b/pype/plugins/tvpaint/create/create_render_layer.py similarity index 100% rename from pype/plugins/tvpaint/create/create_beauty.py rename to pype/plugins/tvpaint/create/create_render_layer.py From 4ea18518939ac62041c7d1c0539b98a18ef269e2 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Fri, 6 Nov 2020 10:34:21 +0100 Subject: [PATCH 32/79] removed space from RenderPass label --- pype/plugins/tvpaint/create/create_render_pass.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/plugins/tvpaint/create/create_render_pass.py b/pype/plugins/tvpaint/create/create_render_pass.py index e0e1b639e1..f6343a2b0b 100644 --- a/pype/plugins/tvpaint/create/create_render_pass.py +++ b/pype/plugins/tvpaint/create/create_render_pass.py @@ -8,7 +8,7 @@ class CreateRenderPass(pipeline.Creator): instance. Beauty instance is used as base for subset name. """ name = "render_pass" - label = "Render Pass" + label = "RenderPass" family = "renderPass" icon = "cube" defaults = ["Main"] From cdfbb496900aef8afef47439dddd67815d22c8dc Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Fri, 6 Nov 2020 16:23:17 +0100 Subject: [PATCH 33/79] render layer's templete does not contain task and pass --- pype/plugins/tvpaint/create/create_render_layer.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/pype/plugins/tvpaint/create/create_render_layer.py b/pype/plugins/tvpaint/create/create_render_layer.py index 10ac444a80..a9e20291ad 100644 --- a/pype/plugins/tvpaint/create/create_render_layer.py +++ b/pype/plugins/tvpaint/create/create_render_layer.py @@ -1,4 +1,3 @@ -import avalon.io from avalon.tvpaint import pipeline, lib @@ -12,7 +11,7 @@ class CreateBeauty(pipeline.Creator): rename_group = True - subset_template = "{family}{task}_{name}_{pass}" + subset_template = "{family}_{name}" rename_script_template = ( "tv_layercolor \"setcolor\"" " {clip_id} {group_id} {r} {g} {b} \"{name}\"" @@ -57,10 +56,7 @@ class CreateBeauty(pipeline.Creator): # Change subset name by template subset_name = self.subset_template.format(**{ "family": self.family, - # Should be task name capitalized? - "task": avalon.io.Session["AVALON_TASK"], - "name": name, - "pass": "beauty" + "name": name }) self.log.info(f"New subset name \"{subset_name}\".") self.data["subset"] = subset_name From eb0cc85dd85c54bddd269907ced4c1904af059cd Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Fri, 6 Nov 2020 16:24:56 +0100 Subject: [PATCH 34/79] render pass is not dependent on render layer subset name --- .../tvpaint/create/create_render_pass.py | 23 +++++++------------ 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/pype/plugins/tvpaint/create/create_render_pass.py b/pype/plugins/tvpaint/create/create_render_pass.py index f6343a2b0b..cde8f3880e 100644 --- a/pype/plugins/tvpaint/create/create_render_pass.py +++ b/pype/plugins/tvpaint/create/create_render_pass.py @@ -13,7 +13,7 @@ class CreateRenderPass(pipeline.Creator): icon = "cube" defaults = ["Main"] - beauty_pass_name = "beauty" + subset_template = "{family}_{render_layer}_{pass}" def process(self): self.log.debug("Query data from workfile.") @@ -54,6 +54,8 @@ class CreateRenderPass(pipeline.Creator): if beauty_instance is None: raise AssertionError("Beauty pass does not exist yet.") + render_layer = beauty_instance["name"] + # Extract entered name family = self.data["family"] name = self.data["subset"] @@ -68,21 +70,12 @@ class CreateRenderPass(pipeline.Creator): layer_ids = [layer["layer_id"] for layer in selected_layers] self.data["layer_ids"] = layer_ids - beauty_subset_name = beauty_instance["subset"] - self.log.info( - "New subset name will be created from " - f"beauty instance \"{beauty_subset_name}\"." - ) - - # Beauty instance subset name should - if not beauty_subset_name.endswith(self.beauty_pass_name): - raise AssertionError( - "BUG: Beauty subset name does not end with \"{}\"".format( - self.beauty_pass_name - ) - ) # Replace `beauty` in beauty's subset name with entered name - subset_name = beauty_subset_name[:-len(self.beauty_pass_name)] + name + subset_name = self.subset_template.format(**{ + "family": family, + "render_layer": render_layer, + "pass": name + }) self.data["subset"] = subset_name self.log.info(f"New subset name is \"{subset_name}\".") From fd8d710f7eff7694cf8a4fee851df117358eedc8 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Fri, 6 Nov 2020 16:26:58 +0100 Subject: [PATCH 35/79] modified how instance labels are shown in publish gui --- pype/plugins/tvpaint/create/create_render_pass.py | 2 +- pype/plugins/tvpaint/publish/collect_instances.py | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/pype/plugins/tvpaint/create/create_render_pass.py b/pype/plugins/tvpaint/create/create_render_pass.py index cde8f3880e..4756fe2413 100644 --- a/pype/plugins/tvpaint/create/create_render_pass.py +++ b/pype/plugins/tvpaint/create/create_render_pass.py @@ -64,7 +64,7 @@ class CreateRenderPass(pipeline.Creator): self.log.info(f"Extracted name from subset name \"{name}\".") self.data["group_id"] = group_id - self.data["name"] = name + self.data["pass"] = name # Collect selected layer ids to be stored into instance layer_ids = [layer["layer_id"] for layer in selected_layers] diff --git a/pype/plugins/tvpaint/publish/collect_instances.py b/pype/plugins/tvpaint/publish/collect_instances.py index 84fc7688f7..6dc934d6c6 100644 --- a/pype/plugins/tvpaint/publish/collect_instances.py +++ b/pype/plugins/tvpaint/publish/collect_instances.py @@ -51,12 +51,11 @@ class CollectInstances(pyblish.api.ContextPlugin): )) def create_render_layer(self, context, instance_data): + name = instance_data["name"] + instance_data["label"] = "{}_beauty".format(name) + layers_data = context.data["layersData"] group_id = instance_data["group_id"] - - name = instance_data["name"] - instance_data["label"] = name - group_layers = [] for layer in layers_data: if layer["group_id"] == group_id and layer["visible"]: @@ -74,6 +73,10 @@ class CollectInstances(pyblish.api.ContextPlugin): return context.create_instance(**instance_data) def create_render_pass(self, context, instance_data): + pass_name = instance_data["pass"] + render_layer = instance_data["render_layer"] + instance_data["label"] = "{}_{}".format(render_layer, pass_name) + # Change family to `renderLayer` instance_data["family"] = "renderLayer" instance_data["families"] = [instance_data["family"]] From 70a1ff08938ef350db61e07e01577a3fbca47c1a Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Fri, 6 Nov 2020 16:27:09 +0100 Subject: [PATCH 36/79] add origin instance data to instance --- pype/plugins/tvpaint/publish/collect_instances.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pype/plugins/tvpaint/publish/collect_instances.py b/pype/plugins/tvpaint/publish/collect_instances.py index 6dc934d6c6..8491c77b87 100644 --- a/pype/plugins/tvpaint/publish/collect_instances.py +++ b/pype/plugins/tvpaint/publish/collect_instances.py @@ -1,4 +1,5 @@ import json +import copy import pyblish.api @@ -18,6 +19,8 @@ class CollectInstances(pyblish.api.ContextPlugin): # TODO add validations of existing instances # - layer id exists for instance_data in workfile_instances: + # Store workfile instance data to instance data + instance_data["originData"] = copy.deepcopy(instance_data) # Global instance data modifications # Fill families family = instance_data["family"] From 411b33f7bfecedafa7a70d8dbdac461f1864d1f8 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Fri, 6 Nov 2020 16:32:00 +0100 Subject: [PATCH 37/79] remove already done comment --- pype/plugins/tvpaint/publish/collect_instances.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/pype/plugins/tvpaint/publish/collect_instances.py b/pype/plugins/tvpaint/publish/collect_instances.py index 8491c77b87..b5e8f941ba 100644 --- a/pype/plugins/tvpaint/publish/collect_instances.py +++ b/pype/plugins/tvpaint/publish/collect_instances.py @@ -16,8 +16,6 @@ class CollectInstances(pyblish.api.ContextPlugin): json.dumps(workfile_instances, indent=4) )) - # TODO add validations of existing instances - # - layer id exists for instance_data in workfile_instances: # Store workfile instance data to instance data instance_data["originData"] = copy.deepcopy(instance_data) From e3de8198d171313e637d87d54958ee5c41e5e91f Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Fri, 6 Nov 2020 17:04:15 +0100 Subject: [PATCH 38/79] fixed render pass creator --- pype/plugins/tvpaint/create/create_render_pass.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pype/plugins/tvpaint/create/create_render_pass.py b/pype/plugins/tvpaint/create/create_render_pass.py index 4756fe2413..585da6ec00 100644 --- a/pype/plugins/tvpaint/create/create_render_pass.py +++ b/pype/plugins/tvpaint/create/create_render_pass.py @@ -65,6 +65,7 @@ class CreateRenderPass(pipeline.Creator): self.data["group_id"] = group_id self.data["pass"] = name + self.data["render_layer"] = render_layer # Collect selected layer ids to be stored into instance layer_ids = [layer["layer_id"] for layer in selected_layers] @@ -86,7 +87,7 @@ class CreateRenderPass(pipeline.Creator): if ( instance["family"] == family and instance["group_id"] == group_id - and instance["name"] == name + and instance["pass"] == name ): existing_instance = instance existing_instance_idx = idx From ba5324fc2aef687a3fe6794b6235675552dc6530 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Fri, 6 Nov 2020 17:19:09 +0100 Subject: [PATCH 39/79] added check for same subset name existence --- .../tvpaint/create/create_render_layer.py | 44 ++++++++++++++++--- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/pype/plugins/tvpaint/create/create_render_layer.py b/pype/plugins/tvpaint/create/create_render_layer.py index a9e20291ad..f261466681 100644 --- a/pype/plugins/tvpaint/create/create_render_layer.py +++ b/pype/plugins/tvpaint/create/create_render_layer.py @@ -61,18 +61,33 @@ class CreateBeauty(pipeline.Creator): self.log.info(f"New subset name \"{subset_name}\".") self.data["subset"] = subset_name - # Check for instances for same group + # Check for instances of same group existing_instance = None existing_instance_idx = None + # Check if subset name is not already taken + same_subset_instance = None + same_subset_instance_idx = None for idx, instance in enumerate(instances): + if instance["family"] == family: + if instance["group_id"] == group_id: + existing_instance = instance + existing_instance_idx = idx + elif instance["subset"] == subset_name: + same_subset_instance = instance + same_subset_instance_idx = idx + if ( - instance["family"] == family - and instance["group_id"] == group_id + same_subset_instance_idx is not None + and existing_instance_idx is not None ): - existing_instance = instance - existing_instance_idx = idx break + if same_subset_instance_idx is not None: + if self._ask_user_subset_override(same_subset_instance): + instances.pop(same_subset_instance_idx) + else: + return + if existing_instance is not None: self.log.info( f"Beauty instance for group id {group_id} already exists" @@ -114,3 +129,22 @@ class CreateBeauty(pipeline.Creator): f"Name of group with index {group_id}" f" was changed to \"{new_group_name}\"." ) + + def _ask_user_subset_override(self, instance): + from Qt.QtWidgets import QMessageBox + + title = "Subset \"{}\" already exist".format(instance["subset"]) + text = ( + "Instance with subset name \"{}\" already exists." + "\n\nDo you want to override existing?" + ).format(instance["subset"]) + + dialog = QMessageBox() + dialog.setWindowTitle(title) + dialog.setText(text) + dialog.setStandardButtons(QMessageBox.Yes | QMessageBox.No) + dialog.setDefaultButton(QMessageBox.Yes) + dialog.exec_() + if dialog.result() == QMessageBox.Yes: + return True + return False From 79b1f5c1f82289b4a7adccebc0dc3afa8f304db8 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Fri, 6 Nov 2020 17:46:55 +0100 Subject: [PATCH 40/79] Added loader with containerization --- .../tvpaint/load/load_reference_image.py | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 pype/plugins/tvpaint/load/load_reference_image.py diff --git a/pype/plugins/tvpaint/load/load_reference_image.py b/pype/plugins/tvpaint/load/load_reference_image.py new file mode 100644 index 0000000000..3cba8d4a1a --- /dev/null +++ b/pype/plugins/tvpaint/load/load_reference_image.py @@ -0,0 +1,96 @@ +from avalon.vendor import qargparse +from avalon.tvpaint import lib, pipeline + + +class LoadImage(pipeline.Loader): + """Load image or image sequence to TVPaint as new layer.""" + + families = ["render", "image", "background", "plate"] + representations = ["*"] + + label = "Load Image" + order = 1 + icon = "image" + color = "white" + + import_script = ( + "filepath = \"{}\"\n" + "layer_name = \"{}\"\n" + "tv_loadsequence filepath {}PARSE layer_id\n" + "tv_layerrename layer_id layer_name" + ) + + defaults = { + "stretch": True, + "timestretch": True, + "preload": True + } + + options = [ + qargparse.Boolean( + "stretch", + label="Stretch to project size", + default=True, + help="Stretch loaded image/s to project resolution?" + ), + qargparse.Boolean( + "timestretch", + label="Stretch to timeline length", + default=True, + help="Clip loaded image/s to timeline length?" + ), + qargparse.Boolean( + "preload", + label="Preload loaded image/s", + default=True, + help="Preload image/s?" + ) + ] + + def load(self, context, name, namespace, options): + stretch = options.get("stretch", self.defaults["stretch"]) + timestretch = options.get("timestretch", self.defaults["timestretch"]) + preload = options.get("preload", self.defaults["preload"]) + + load_options = [] + if stretch: + load_options.append("\"STRETCH\"") + if timestretch: + load_options.append("\"TIMESTRETCH\"") + if preload: + load_options.append("\"PRELOAD\"") + + load_options_str = "" + for load_option in load_options: + load_options_str += (load_option + " ") + + # Prepare layer name + asset_name = context["asset"]["name"] + subset_name = context["subset"]["name"] + layer_name = self.get_unique_layer_name(asset_name, subset_name) + + # Fill import script with filename and layer name + # - filename mus not contain backwards slashes + george_script = self.import_script.format( + self.fname.replace("\\", "/"), + layer_name, + load_options_str + ) + + lib.execute_george_through_file(george_script) + + loaded_layer = None + layers = lib.layers_data() + for layer in layers: + if layer["name"] == layer_name: + loaded_layer = layer + break + + if loaded_layer is None: + raise AssertionError( + "Loading probably failed during execution of george script." + ) + + layer_ids = [loaded_layer["layer_id"]] + namespace = namespace or layer_name + return pipeline.containerise(name, namespace, layer_ids, context, self) From a9cd97f257d1bf58d2cd388190666af2cb90c003 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Fri, 6 Nov 2020 18:04:54 +0100 Subject: [PATCH 41/79] implemented remove method --- .../tvpaint/load/load_reference_image.py | 57 ++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/pype/plugins/tvpaint/load/load_reference_image.py b/pype/plugins/tvpaint/load/load_reference_image.py index 3cba8d4a1a..06bf1313f0 100644 --- a/pype/plugins/tvpaint/load/load_reference_image.py +++ b/pype/plugins/tvpaint/load/load_reference_image.py @@ -93,4 +93,59 @@ class LoadImage(pipeline.Loader): layer_ids = [loaded_layer["layer_id"]] namespace = namespace or layer_name - return pipeline.containerise(name, namespace, layer_ids, context, self) + return pipeline.containerise( + name=name, + namespace=namespace, + layer_ids=layer_ids, + context=context, + loader=self.__class__.__name__ + ) + + def _remove_layers(self, layers, layer_ids): + if not layer_ids: + return + + available_ids = set(layer["layer_id"] for layer in layers) + layer_ids_to_remove = [] + + for layer_id in layer_ids: + if layer_id in available_ids: + layer_ids_to_remove.append(layer_id) + + if not layer_ids_to_remove: + return + + george_script_lines = [] + for layer_id in layer_ids_to_remove: + line = "tv_layerkill {}".format(layer_id) + george_script_lines.append(line) + george_script = "\n".join(george_script_lines) + lib.execute_george_through_file(george_script) + + def remove(self, container): + layer_ids_str = container["objectName"] + layer_ids = [int(layer_id) for layer_id in layer_ids_str.split("|")] + + layers = lib.layers_data() + self._remove_layers(layers, layer_ids) + + current_containers = pipeline.ls() + pop_idx = None + for idx, cur_con in enumerate(current_containers): + if cur_con["objectName"] == layer_ids_str: + pop_idx = idx + break + + if pop_idx is None: + self.log.warning( + "Didn't found container in workfile containers. {}".format( + container + ) + ) + return + + current_containers.pop(pop_idx) + pipeline.write_workfile_metadata( + pipeline.SECTION_NAME_CONTAINERS, current_containers + ) + From f7337c9913523d511775892a71c8f26cc50bde97 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Fri, 6 Nov 2020 18:12:48 +0100 Subject: [PATCH 42/79] simplified logic --- pype/plugins/tvpaint/load/load_reference_image.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pype/plugins/tvpaint/load/load_reference_image.py b/pype/plugins/tvpaint/load/load_reference_image.py index 06bf1313f0..e3a224c283 100644 --- a/pype/plugins/tvpaint/load/load_reference_image.py +++ b/pype/plugins/tvpaint/load/load_reference_image.py @@ -101,10 +101,13 @@ class LoadImage(pipeline.Loader): loader=self.__class__.__name__ ) - def _remove_layers(self, layers, layer_ids): + def _remove_layers(self, layer_ids, layers=None): if not layer_ids: return + if layers is None: + layers = lib.layers_data() + available_ids = set(layer["layer_id"] for layer in layers) layer_ids_to_remove = [] @@ -123,16 +126,13 @@ class LoadImage(pipeline.Loader): lib.execute_george_through_file(george_script) def remove(self, container): - layer_ids_str = container["objectName"] - layer_ids = [int(layer_id) for layer_id in layer_ids_str.split("|")] - - layers = lib.layers_data() - self._remove_layers(layers, layer_ids) + layer_ids = self.layer_ids_from_container(container) + self._remove_layers(layer_ids) current_containers = pipeline.ls() pop_idx = None for idx, cur_con in enumerate(current_containers): - if cur_con["objectName"] == layer_ids_str: + if cur_con["objectName"] == container["objectName"]: pop_idx = idx break From b4ad6b68ea244d64387d4be2a0e9414d044f6d3c Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Fri, 6 Nov 2020 19:06:31 +0100 Subject: [PATCH 43/79] implemented update method in laoder --- .../tvpaint/load/load_reference_image.py | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/pype/plugins/tvpaint/load/load_reference_image.py b/pype/plugins/tvpaint/load/load_reference_image.py index e3a224c283..0fa4cefc51 100644 --- a/pype/plugins/tvpaint/load/load_reference_image.py +++ b/pype/plugins/tvpaint/load/load_reference_image.py @@ -1,3 +1,4 @@ +from avalon.pipeline import get_representation_context from avalon.vendor import qargparse from avalon.tvpaint import lib, pipeline @@ -149,3 +150,95 @@ class LoadImage(pipeline.Loader): pipeline.SECTION_NAME_CONTAINERS, current_containers ) + def switch(self, container, representation): + self.update(container, representation) + + def update(self, container, representation): + """Replace container with different version. + + New layers are loaded as first step. Then is tried to change data in + new layers with data from old layers. When that is done old layers are + removed. + """ + # Create new containers first + context = get_representation_context(representation) + name = container["name"] + namespace = container["namespace"] + new_container = self.load(context, name, namespace, {}) + new_layer_ids = self.layer_ids_from_container(new_container) + + # Get layer ids from previous container + old_layer_ids = self.layer_ids_from_container(container) + + layers = lib.layers_data() + layers_by_id = { + layer["layer_id"]: layer + for layer in layers + } + + old_layers = [] + new_layers = [] + for layer_id in old_layer_ids: + layer = layers_by_id.get(layer_id) + if layer: + old_layers.append(layer) + + for layer_id in new_layer_ids: + layer = layers_by_id.get(layer_id) + if layer: + new_layers.append(layer) + + # Prepare few data + new_start_position = None + new_group_id = None + for layer in old_layers: + position = layer["position"] + group_id = layer["group_id"] + if new_start_position is None: + new_start_position = position + elif new_start_position > position: + new_start_position = position + + if new_group_id is None: + new_group_id = group_id + elif new_group_id < 0: + continue + elif new_group_id != group_id: + new_group_id = -1 + + george_script_lines = [] + # Group new layers to same group as previous container layers had + # - all old layers must be under same group + if new_group_id is not None and new_group_id > 0: + for layer in new_layers: + line = "tv_layercolor \"set\" {} {}".format( + layer["layer_id"], new_group_id + ) + george_script_lines.append(line) + + # Rename new layer to have same name + # - only if both old and new have one layer + if len(old_layers) == 1 and len(new_layers) == 1: + layer_name = old_layers[0]["name"] + george_script_lines.append( + "tv_layerrename {} \"{}\"".format( + new_layers[0]["layer_id"], layer_name + ) + ) + + # Change position of new layer + # - this must be done before remove old layers + if len(new_layers) == 1 and new_start_position is not None: + new_layer = new_layers[0] + george_script_lines.extend([ + "tv_layerset {}".format(new_layer["layer_id"]), + "tv_layermove {}".format(new_start_position) + ]) + + # Execute george scripts if there are any + if george_script_lines: + george_script = "\n".join(george_script_lines) + lib.execute_george_through_file(george_script) + + # Remove old container + self.remove(container) From 5510904127bf6b935e018f3867bd494bb2252fb7 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 9 Nov 2020 17:06:50 +0100 Subject: [PATCH 44/79] do not change family of renderPass to renderLayer --- pype/plugins/tvpaint/publish/collect_instances.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pype/plugins/tvpaint/publish/collect_instances.py b/pype/plugins/tvpaint/publish/collect_instances.py index b5e8f941ba..e751a18495 100644 --- a/pype/plugins/tvpaint/publish/collect_instances.py +++ b/pype/plugins/tvpaint/publish/collect_instances.py @@ -78,10 +78,6 @@ class CollectInstances(pyblish.api.ContextPlugin): render_layer = instance_data["render_layer"] instance_data["label"] = "{}_{}".format(render_layer, pass_name) - # Change family to `renderLayer` - instance_data["family"] = "renderLayer" - instance_data["families"] = [instance_data["family"]] - layers_data = context.data["layersData"] layers_by_id = { layer["layer_id"]: layer From 98bcea52a554bc848558911cbc3b62130efa683a Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 10 Nov 2020 18:29:55 +0100 Subject: [PATCH 45/79] instance.data always contain all layers for the instance --- .../tvpaint/publish/collect_instances.py | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/pype/plugins/tvpaint/publish/collect_instances.py b/pype/plugins/tvpaint/publish/collect_instances.py index e751a18495..bacc5984e8 100644 --- a/pype/plugins/tvpaint/publish/collect_instances.py +++ b/pype/plugins/tvpaint/publish/collect_instances.py @@ -37,21 +37,25 @@ class CollectInstances(pyblish.api.ContextPlugin): instance = None if family == "review": instance = context.create_instance(**instance_data) + instance.data["layers"] = context.data["layersData"] elif family == "renderLayer": - instance = self.create_render_layer(context, instance_data) + instance = self.create_render_layer_instance( + context, instance_data + ) elif family == "renderPass": - instance = self.create_render_pass(context, instance_data) + instance = self.create_render_pass_instance( + context, instance_data + ) else: raise AssertionError( "Instance with unknown family \"{}\": {}" ) - if instance is not None: - self.log.debug("Created instance: {}\n{}".format( - instance, json.dumps(instance.data, indent=4) - )) + self.log.debug("Created instance: {}\n{}".format( + instance, json.dumps(instance.data, indent=4) + )) - def create_render_layer(self, context, instance_data): + def create_render_layer_instance(self, context, instance_data): name = instance_data["name"] instance_data["label"] = "{}_beauty".format(name) @@ -73,7 +77,7 @@ class CollectInstances(pyblish.api.ContextPlugin): instance_data["layers"] = group_layers return context.create_instance(**instance_data) - def create_render_pass(self, context, instance_data): + def create_render_pass_instance(self, context, instance_data): pass_name = instance_data["pass"] render_layer = instance_data["render_layer"] instance_data["label"] = "{}_{}".format(render_layer, pass_name) From 62a2346ba6cbc38b112ae7744b637992c359df41 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 10 Nov 2020 19:22:36 +0100 Subject: [PATCH 46/79] renamed key `frameRate` to `fps` --- pype/plugins/tvpaint/publish/collect_workfile_data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/plugins/tvpaint/publish/collect_workfile_data.py b/pype/plugins/tvpaint/publish/collect_workfile_data.py index 87076e978d..34709e34b0 100644 --- a/pype/plugins/tvpaint/publish/collect_workfile_data.py +++ b/pype/plugins/tvpaint/publish/collect_workfile_data.py @@ -48,7 +48,7 @@ class CollectWorkfileData(pyblish.api.ContextPlugin): "sceneHeight": height, "pixelAspect": pixel_apsect, "frameStart": frame_start, - "frameRate": frame_rate, + "fps": frame_rate, "fieldOrder": field_order } self.log.debug( From 434c684c791e85bc87883c1fb110cb63cbcce9d9 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 10 Nov 2020 19:23:50 +0100 Subject: [PATCH 47/79] frame end is set from last frame of all visible layers --- pype/plugins/tvpaint/publish/collect_workfile_data.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pype/plugins/tvpaint/publish/collect_workfile_data.py b/pype/plugins/tvpaint/publish/collect_workfile_data.py index 34709e34b0..b27eb2f693 100644 --- a/pype/plugins/tvpaint/publish/collect_workfile_data.py +++ b/pype/plugins/tvpaint/publish/collect_workfile_data.py @@ -42,12 +42,21 @@ class CollectWorkfileData(pyblish.api.ContextPlugin): width = int(workfile_info_parts.pop(-1)) workfile_path = " ".join(workfile_info_parts).replace("\"", "") + # TODO This is not porper way of getting last frame + # - but don't know better + last_frame = frame_start + for layer in layers_data: + frame_end = layer["frame_end"] + if frame_end > last_frame: + last_frame = frame_end + sceme_data = { "currentFile": workfile_path, "sceneWidth": width, "sceneHeight": height, "pixelAspect": pixel_apsect, "frameStart": frame_start, + "frameEnd": last_frame, "fps": frame_rate, "fieldOrder": field_order } From ac55207d11df3e6878a73a99979ab82cdf8ce36e Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 10 Nov 2020 19:24:07 +0100 Subject: [PATCH 48/79] instances have also set frame start and end --- pype/plugins/tvpaint/publish/collect_instances.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pype/plugins/tvpaint/publish/collect_instances.py b/pype/plugins/tvpaint/publish/collect_instances.py index bacc5984e8..d75ea83a4c 100644 --- a/pype/plugins/tvpaint/publish/collect_instances.py +++ b/pype/plugins/tvpaint/publish/collect_instances.py @@ -17,6 +17,9 @@ class CollectInstances(pyblish.api.ContextPlugin): )) for instance_data in workfile_instances: + instance_data["frameStart"] = context.data["frameStart"] + instance_data["frameEnd"] = context.data["frameEnd"] + # Store workfile instance data to instance data instance_data["originData"] = copy.deepcopy(instance_data) # Global instance data modifications From f19e2479f8742dd1cdfd1f8a20bbe70ae9542518 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 10 Nov 2020 19:24:40 +0100 Subject: [PATCH 49/79] base implementation of tvpaint extractor --- .../plugins/tvpaint/publish/extract_output.py | 249 ++++++++++++++++++ 1 file changed, 249 insertions(+) create mode 100644 pype/plugins/tvpaint/publish/extract_output.py diff --git a/pype/plugins/tvpaint/publish/extract_output.py b/pype/plugins/tvpaint/publish/extract_output.py new file mode 100644 index 0000000000..ffb9143195 --- /dev/null +++ b/pype/plugins/tvpaint/publish/extract_output.py @@ -0,0 +1,249 @@ +import os +import shutil +import tempfile + +import pyblish.api +from avalon.tvpaint import pipeline, lib + + +class ExtractOutput(pyblish.api.Extractor): + label = "Extract Output" + hosts = ["tvpaint"] + families = ["review", "renderPass", "renderLayer"] + + save_mode_to_ext = { + "avi": ".avi", + "bmp": ".bmp", + "cin": ".cin", + "deep": ".dip", + "dps": ".dps", + "dpx": ".dpx", + "flc": ".fli", + "gif": ".gif", + "ilbm": ".iff", + "jpeg": ".jpg", + "pcx": ".pcx", + "png": ".png", + "psd": ".psd", + "qt": ".qt", + "rtv": ".rtv", + "sun": ".ras", + "tiff": ".tiff", + "tga": ".tga", + "vpb": ".vpb" + } + sequential_save_mode = { + "bmp", + "dpx", + "ilbm", + "jpeg", + "png", + "sun", + "tiff", + "tga" + } + + default_save_mode = "\"PNG\"" + save_mode_for_family = { + "review": "\"PNG\"", + "renderPass": "\"PNG\"", + "renderLayer": "\"PNG\"", + } + + def process(self, instance): + # Get all layers and filter out not visible + layers = instance.data["layers"] + filtered_layers = [ + layer + for layer in layers + if layer["visible"] + ] + + family_lowered = instance.data["family"].lower() + + self._prepare_save_modes() + + save_mode = self.save_mode_for_family.get( + family_lowered, self.default_save_mode + ) + filename_template = self._get_filename_template(save_mode) + ext = os.path.splitext(filename_template)[1].replace(".", "") + + self.log.debug( + "Using save mode > {} < and file template \"{}\"".format( + save_mode, filename_template + ) + ) + + tags = ["review"] + + # TODO: This should be already collected!!! + first_frame = int(lib.execute_george("tv_firstimage")) + last_frame = int(lib.execute_george("tv_lastimage")) + + # Save to temp + output_dir = tempfile.mkdtemp().replace("\\", "/") + self.log.debug( + "Files will be rendered to folder: {}".format(output_dir) + ) + output_files_by_frame = self.render( + save_mode, filename_template, output_dir, + filtered_layers, first_frame, last_frame + ) + self.fill_missing_frames( + output_files_by_frame, + first_frame, + last_frame, + filename_template + ) + + representations = instance.data.get("representations") or [] + repre_files = [ + os.path.basename(filepath) + for filepath in output_files_by_frame.values() + ] + new_repre = { + "name": ext, + "ext": ext, + "files": repre_files, + "stagingDir": output_dir, + "frameStart": first_frame, + "frameEnd": last_frame, + "tags": tags + } + self.log.debug("Creating new representation: {}".format(new_repre)) + representations.append(new_repre) + instance.data["representations"] = representations + + def _prepare_save_modes(self): + """Lower family names in keys and skip empty values.""" + new_specifications = {} + for key, value in self.save_mode_for_family.items(): + if value: + new_specifications[key.lower()] = value + else: + self.log.warning(( + "Save mode for family \"{}\" has empty value." + " The family will use default save mode: > {} <." + ).format(key, self.default_save_mode)) + self.save_mode_for_family = new_specifications + + def _get_filename_template(self, save_mode): + """Get filetemplate for rendered files. + + This is simple template contains `{frame}{ext}` for sequential outputs + and `single_file{ext}` for single file output. Output is rendered to + temporary folder so filename should not matter as integrator change + them. + """ + _save_mode = save_mode.lower() + _save_mode = _save_mode.split(" ")[0] + _save_mode = _save_mode.replace("\"", "") + self.log.info(_save_mode) + ext = self.save_mode_to_ext.get(_save_mode) + if ext is None: + raise AssertionError(( + "Couldn't find file extension for TVPaint's save mode: > {} <" + ).format(save_mode)) + + is_sequence = bool(_save_mode in self.sequential_save_mode) + if is_sequence: + template = "{frame}" + ext + else: + template = "single_file" + ext + return template + + def render( + self, save_mode, filename_template, output_dir, layers, + first_frame, last_frame + ): + """ Export images from TVPaint. + + Args: + save_mode (str): Argument for `tv_savemode` george script function. + More about save mode in documentation. + filename_template (str): Filename template of an output. Template + should already contain extension. Template may contain only + keyword argument `{frame}` or index argument (for same value). + Extension in template must match `save_mode`. + layers (list): List of layers to be exported. + first_frame (int): Starting frame from which export will begin. + last_frame (int): On which frame export will end. + + Retruns: + dict: Mapping frame to output filepath. + """ + + # Add save mode arguments to function + save_mode = "tv_SaveMode {}".format(save_mode) + + layers_by_position = { + layer["position"]: layer + for layer in layers + } + + sorted_positions = list(reversed(sorted(layers_by_position.keys()))) + if not sorted_positions: + return + + # Create temporary layer + new_layer_id = lib.execute_george("tv_layercreate _tmp_layer") + + # Merge layers to temp layer + george_script_lines = [] + # Set duplicated layer as current + george_script_lines.append("tv_layerset {}".format(new_layer_id)) + for position in sorted_positions: + layer = layers_by_position[position] + george_script_lines.append( + "tv_layermerge {}".format(layer["layer_id"]) + ) + + lib.execute_george_through_file("\n".join(george_script_lines)) + + # Frames with keyframe + exposure_frames = lib.get_exposure_frames( + new_layer_id, first_frame, last_frame + ) + + # Restart george script lines + george_script_lines = [] + george_script_lines.append(save_mode) + + all_output_files = {} + for frame in exposure_frames: + filename = filename_template.format(frame, frame=frame) + dst_path = "/".join([output_dir, filename]) + all_output_files[frame] = os.path.normpath(dst_path) + + # Go to frame + george_script_lines.append("tv_layerImage {}".format(frame)) + # Store image to output + george_script_lines.append("tv_saveimage \"{}\"".format(dst_path)) + + # Delete temporary layer + george_script_lines.append("tv_layerkill {}".format(new_layer_id)) + + lib.execute_george_through_file("\n".join(george_script_lines)) + + return all_output_files + + def fill_missing_frames( + self, filepaths_by_frame, first_frame, last_frame, filename_template + ): + output_dir = None + previous_frame_filepath = None + for frame in range(first_frame, last_frame + 1): + if frame in filepaths_by_frame: + previous_frame_filepath = filepaths_by_frame[frame] + continue + + if output_dir is None: + output_dir = os.path.dirname(previous_frame_filepath) + + filename = filename_template.format(frame=frame) + space_filepath = os.path.normpath( + os.path.join(output_dir, filename) + ) + filepaths_by_frame[frame] = space_filepath + shutil.copy(previous_frame_filepath, space_filepath) From 439f9557fb103075ac3566afeb1b5c0c2b2846bf Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 11 Nov 2020 11:17:47 +0100 Subject: [PATCH 50/79] extractor has more checks and can export only sequences --- .../plugins/tvpaint/publish/extract_output.py | 90 +++++++++++++------ 1 file changed, 65 insertions(+), 25 deletions(-) diff --git a/pype/plugins/tvpaint/publish/extract_output.py b/pype/plugins/tvpaint/publish/extract_output.py index ffb9143195..a302e8a6e8 100644 --- a/pype/plugins/tvpaint/publish/extract_output.py +++ b/pype/plugins/tvpaint/publish/extract_output.py @@ -51,22 +51,43 @@ class ExtractOutput(pyblish.api.Extractor): } def process(self, instance): + self.log.info( + "* Processing instance \"{}\"".format(instance.data["label"]) + ) + # Get all layers and filter out not visible + # TODO what to do if all are invisible? + # - skip without output? + # - still render but empty output? layers = instance.data["layers"] filtered_layers = [ layer for layer in layers if layer["visible"] ] - - family_lowered = instance.data["family"].lower() - + layer_ids = [layer["layer_id"] for layer in filtered_layers] + self.log.debug("Instance has {} layers with ids: {}".format( + len(filtered_layers), ", ".join(layer_ids) + )) + # This is plugin attribe cleanup method self._prepare_save_modes() + family_lowered = instance.data["family"].lower() save_mode = self.save_mode_for_family.get( family_lowered, self.default_save_mode ) - filename_template = self._get_filename_template(save_mode) + save_mode_type = self._get_save_mode_type(save_mode) + + is_sequence = bool(save_mode_type in self.sequential_save_mode) + if not is_sequence: + raise AssertionError(( + "Plugin can export only sequential frame output" + " but save mode for family \"{}\" is not for sequence > {} <" + ).format(instance.data["family"], save_mode)) + + filename_template = self._get_filename_template( + save_mode_type, save_mode + ) ext = os.path.splitext(filename_template)[1].replace(".", "") self.log.debug( @@ -75,21 +96,21 @@ class ExtractOutput(pyblish.api.Extractor): ) ) - tags = ["review"] - - # TODO: This should be already collected!!! - first_frame = int(lib.execute_george("tv_firstimage")) - last_frame = int(lib.execute_george("tv_lastimage")) - # Save to temp output_dir = tempfile.mkdtemp().replace("\\", "/") self.log.debug( "Files will be rendered to folder: {}".format(output_dir) ) + + first_frame = instance.data["frameStart"] + last_frame = instance.data["frameEnd"] + + # Render output output_files_by_frame = self.render( save_mode, filename_template, output_dir, filtered_layers, first_frame, last_frame ) + # Fill gaps in sequence self.fill_missing_frames( output_files_by_frame, first_frame, @@ -97,7 +118,14 @@ class ExtractOutput(pyblish.api.Extractor): filename_template ) - representations = instance.data.get("representations") or [] + # Add representation to instance's representations + if instance.data.get("representations") is None: + instance.data["representations"] = [] + + # Fill tags + # TODO where to find out which tags should be added? + tags = ["review"] + repre_files = [ os.path.basename(filepath) for filepath in output_files_by_frame.values() @@ -112,8 +140,8 @@ class ExtractOutput(pyblish.api.Extractor): "tags": tags } self.log.debug("Creating new representation: {}".format(new_repre)) - representations.append(new_repre) - instance.data["representations"] = representations + + instance.data["representations"].append(new_repre) def _prepare_save_modes(self): """Lower family names in keys and skip empty values.""" @@ -128,7 +156,20 @@ class ExtractOutput(pyblish.api.Extractor): ).format(key, self.default_save_mode)) self.save_mode_for_family = new_specifications - def _get_filename_template(self, save_mode): + def _get_save_mode_type(self, save_mode): + """Extract type of save mode. + + Helps to define output files extension. + """ + save_mode_type = ( + save_mode.lower() + .split(" ")[0] + .replace("\"", "") + ) + self.log.debug("Save mode type is \"{}\"".format(save_mode_type)) + return save_mode_type + + def _get_filename_template(self, save_mode_type, save_mode): """Get filetemplate for rendered files. This is simple template contains `{frame}{ext}` for sequential outputs @@ -136,22 +177,13 @@ class ExtractOutput(pyblish.api.Extractor): temporary folder so filename should not matter as integrator change them. """ - _save_mode = save_mode.lower() - _save_mode = _save_mode.split(" ")[0] - _save_mode = _save_mode.replace("\"", "") - self.log.info(_save_mode) - ext = self.save_mode_to_ext.get(_save_mode) + ext = self.save_mode_to_ext.get(save_mode_type) if ext is None: raise AssertionError(( "Couldn't find file extension for TVPaint's save mode: > {} <" ).format(save_mode)) - is_sequence = bool(_save_mode in self.sequential_save_mode) - if is_sequence: - template = "{frame}" + ext - else: - template = "single_file" + ext - return template + return "{frame}" + ext def render( self, save_mode, filename_template, output_dir, layers, @@ -177,11 +209,13 @@ class ExtractOutput(pyblish.api.Extractor): # Add save mode arguments to function save_mode = "tv_SaveMode {}".format(save_mode) + # Map layers by position layers_by_position = { layer["position"]: layer for layer in layers } + # Sort layer positions in reverse order sorted_positions = list(reversed(sorted(layers_by_position.keys()))) if not sorted_positions: return @@ -231,6 +265,12 @@ class ExtractOutput(pyblish.api.Extractor): def fill_missing_frames( self, filepaths_by_frame, first_frame, last_frame, filename_template ): + """Fill not rendered frames with previous frame. + + Extractor is rendering only frames with keyframes (exposure frames) to + get output faster which means there may be gaps between frames. + This function fill the missing frames. + """ output_dir = None previous_frame_filepath = None for frame in range(first_frame, last_frame + 1): From 36e914e16d1150273e3873d23e792e84d5998819 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 11 Nov 2020 11:40:32 +0100 Subject: [PATCH 51/79] add tvpaint to extract review --- pype/plugins/global/publish/extract_review.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pype/plugins/global/publish/extract_review.py b/pype/plugins/global/publish/extract_review.py index 87afdd2b20..ffdfd3b91f 100644 --- a/pype/plugins/global/publish/extract_review.py +++ b/pype/plugins/global/publish/extract_review.py @@ -30,7 +30,8 @@ class ExtractReview(pyblish.api.InstancePlugin): "premiere", "harmony", "standalonepublisher", - "fusion" + "fusion", + "tvpaint" ] # Supported extensions From 88fbf6b10b0beae32024ff2aeca1c49fb099f5e2 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 11 Nov 2020 15:11:50 +0100 Subject: [PATCH 52/79] rename extract output to extract sequence --- .../publish/{extract_output.py => extract_sequence.py} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename pype/plugins/tvpaint/publish/{extract_output.py => extract_sequence.py} (99%) diff --git a/pype/plugins/tvpaint/publish/extract_output.py b/pype/plugins/tvpaint/publish/extract_sequence.py similarity index 99% rename from pype/plugins/tvpaint/publish/extract_output.py rename to pype/plugins/tvpaint/publish/extract_sequence.py index a302e8a6e8..1e63aab432 100644 --- a/pype/plugins/tvpaint/publish/extract_output.py +++ b/pype/plugins/tvpaint/publish/extract_sequence.py @@ -6,8 +6,8 @@ import pyblish.api from avalon.tvpaint import pipeline, lib -class ExtractOutput(pyblish.api.Extractor): - label = "Extract Output" +class ExtractSequence(pyblish.api.Extractor): + label = "Extract Sequence" hosts = ["tvpaint"] families = ["review", "renderPass", "renderLayer"] From 1aadb518cf9a4fc35a28f9e7ed08b89a54c043f4 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 11 Nov 2020 15:13:56 +0100 Subject: [PATCH 53/79] set tag properly --- pype/plugins/tvpaint/publish/extract_sequence.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pype/plugins/tvpaint/publish/extract_sequence.py b/pype/plugins/tvpaint/publish/extract_sequence.py index 1e63aab432..5021862a88 100644 --- a/pype/plugins/tvpaint/publish/extract_sequence.py +++ b/pype/plugins/tvpaint/publish/extract_sequence.py @@ -124,7 +124,10 @@ class ExtractSequence(pyblish.api.Extractor): # Fill tags # TODO where to find out which tags should be added? - tags = ["review"] + if family_lowered in ("review", "renderlayer"): + tags = ["review", "ftrack"] + else: + tags = [] repre_files = [ os.path.basename(filepath) From 1478f2559d8640275afac58075ba8e42a70b5925 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 11 Nov 2020 15:19:52 +0100 Subject: [PATCH 54/79] collect end frame for each instance individually --- pype/plugins/tvpaint/publish/collect_instances.py | 13 ++++++++++--- pype/plugins/tvpaint/publish/extract_sequence.py | 1 - 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/pype/plugins/tvpaint/publish/collect_instances.py b/pype/plugins/tvpaint/publish/collect_instances.py index d75ea83a4c..f1b3239f11 100644 --- a/pype/plugins/tvpaint/publish/collect_instances.py +++ b/pype/plugins/tvpaint/publish/collect_instances.py @@ -17,9 +17,6 @@ class CollectInstances(pyblish.api.ContextPlugin): )) for instance_data in workfile_instances: - instance_data["frameStart"] = context.data["frameStart"] - instance_data["frameEnd"] = context.data["frameEnd"] - # Store workfile instance data to instance data instance_data["originData"] = copy.deepcopy(instance_data) # Global instance data modifications @@ -54,6 +51,16 @@ class CollectInstances(pyblish.api.ContextPlugin): "Instance with unknown family \"{}\": {}" ) + frame_start = context.data["frameStart"] + frame_end = frame_start + for layer in instance.data["layers"]: + _frame_end = layer["frame_end"] + if _frame_end > frame_end: + frame_end = _frame_end + + instance.data["frameStart"] = frame_start + instance.data["frameEnd"] = frame_end + self.log.debug("Created instance: {}\n{}".format( instance, json.dumps(instance.data, indent=4) )) diff --git a/pype/plugins/tvpaint/publish/extract_sequence.py b/pype/plugins/tvpaint/publish/extract_sequence.py index 5021862a88..358e91931c 100644 --- a/pype/plugins/tvpaint/publish/extract_sequence.py +++ b/pype/plugins/tvpaint/publish/extract_sequence.py @@ -123,7 +123,6 @@ class ExtractSequence(pyblish.api.Extractor): instance.data["representations"] = [] # Fill tags - # TODO where to find out which tags should be added? if family_lowered in ("review", "renderlayer"): tags = ["review", "ftrack"] else: From 843084633c6feca4d8c609a867019310a7fb055f Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 11 Nov 2020 15:29:52 +0100 Subject: [PATCH 55/79] add pading to output template --- .../tvpaint/publish/extract_sequence.py | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/pype/plugins/tvpaint/publish/extract_sequence.py b/pype/plugins/tvpaint/publish/extract_sequence.py index 358e91931c..775e285852 100644 --- a/pype/plugins/tvpaint/publish/extract_sequence.py +++ b/pype/plugins/tvpaint/publish/extract_sequence.py @@ -85,8 +85,11 @@ class ExtractSequence(pyblish.api.Extractor): " but save mode for family \"{}\" is not for sequence > {} <" ).format(instance.data["family"], save_mode)) + frame_start = instance.data["frameStart"] + frame_end = instance.data["frameEnd"] + filename_template = self._get_filename_template( - save_mode_type, save_mode + save_mode_type, save_mode, frame_end ) ext = os.path.splitext(filename_template)[1].replace(".", "") @@ -102,19 +105,16 @@ class ExtractSequence(pyblish.api.Extractor): "Files will be rendered to folder: {}".format(output_dir) ) - first_frame = instance.data["frameStart"] - last_frame = instance.data["frameEnd"] - # Render output output_files_by_frame = self.render( save_mode, filename_template, output_dir, - filtered_layers, first_frame, last_frame + filtered_layers, frame_start, frame_end ) # Fill gaps in sequence self.fill_missing_frames( output_files_by_frame, - first_frame, - last_frame, + frame_start, + frame_end, filename_template ) @@ -137,8 +137,8 @@ class ExtractSequence(pyblish.api.Extractor): "ext": ext, "files": repre_files, "stagingDir": output_dir, - "frameStart": first_frame, - "frameEnd": last_frame, + "frameStart": frame_start, + "frameEnd": frame_end, "tags": tags } self.log.debug("Creating new representation: {}".format(new_repre)) @@ -171,7 +171,7 @@ class ExtractSequence(pyblish.api.Extractor): self.log.debug("Save mode type is \"{}\"".format(save_mode_type)) return save_mode_type - def _get_filename_template(self, save_mode_type, save_mode): + def _get_filename_template(self, save_mode_type, save_mode, frame_end): """Get filetemplate for rendered files. This is simple template contains `{frame}{ext}` for sequential outputs @@ -185,7 +185,12 @@ class ExtractSequence(pyblish.api.Extractor): "Couldn't find file extension for TVPaint's save mode: > {} <" ).format(save_mode)) - return "{frame}" + ext + frame_padding = 4 + frame_end_str_len = len(str(frame_end)) + if frame_end_str_len > frame_padding: + frame_padding = frame_end_str_len + + return "{{frame:0>{}}}".format(frame_padding) + ext def render( self, save_mode, filename_template, output_dir, layers, From 0d2ea16566e8b9ef1023021c269bf55a05dfa6d5 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 11 Nov 2020 15:47:12 +0100 Subject: [PATCH 56/79] added exporting of thumbnail and create of thumbnail representation --- .../tvpaint/publish/extract_sequence.py | 39 ++++++++++++++++++- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/pype/plugins/tvpaint/publish/extract_sequence.py b/pype/plugins/tvpaint/publish/extract_sequence.py index 775e285852..ffb79a853e 100644 --- a/pype/plugins/tvpaint/publish/extract_sequence.py +++ b/pype/plugins/tvpaint/publish/extract_sequence.py @@ -105,11 +105,17 @@ class ExtractSequence(pyblish.api.Extractor): "Files will be rendered to folder: {}".format(output_dir) ) + thumbnail_filename = "thumbnail" + # Render output output_files_by_frame = self.render( save_mode, filename_template, output_dir, - filtered_layers, frame_start, frame_end + filtered_layers, frame_start, frame_end, thumbnail_filename ) + thumbnail_fullpath = output_files_by_frame.pop( + output_files_by_frame, None + ) + # Fill gaps in sequence self.fill_missing_frames( output_files_by_frame, @@ -145,6 +151,19 @@ class ExtractSequence(pyblish.api.Extractor): instance.data["representations"].append(new_repre) + if not thumbnail_fullpath: + return + + # Create thumbnail representation + thumbnail_repre = { + "name": "thumbnail", + "ext": ext, + "files": [os.path.basename(thumbnail_fullpath)], + "stagingDir": output_dir, + "tags": ["thumbnail"] + } + instance.data["representations"].append(thumbnail_repre) + def _prepare_save_modes(self): """Lower family names in keys and skip empty values.""" new_specifications = {} @@ -194,7 +213,7 @@ class ExtractSequence(pyblish.api.Extractor): def render( self, save_mode, filename_template, output_dir, layers, - first_frame, last_frame + first_frame, last_frame, thumbnail_filename ): """ Export images from TVPaint. @@ -262,6 +281,22 @@ class ExtractSequence(pyblish.api.Extractor): # Store image to output george_script_lines.append("tv_saveimage \"{}\"".format(dst_path)) + # Export thumbnail + if thumbnail_filename: + basename, ext = os.path.splitext(thumbnail_filename) + if not ext: + ext = ".png" + thumbnail_fullpath = "/".join([output_dir, basename + ext]) + all_output_files[thumbnail_filename] = thumbnail_fullpath + # Force save mode to png for thumbnail + george_script_lines.append("tv_SaveMode \"PNG\"") + # Go to frame + george_script_lines.append("tv_layerImage {}".format(first_frame)) + # Store image to output + george_script_lines.append( + "tv_saveimage \"{}\"".format(thumbnail_fullpath) + ) + # Delete temporary layer george_script_lines.append("tv_layerkill {}".format(new_layer_id)) From 8d1679205fb766747cfdeba84543ba9aa9f0fe37 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 11 Nov 2020 16:59:34 +0100 Subject: [PATCH 57/79] instances has prepared representations and fps --- pype/plugins/tvpaint/publish/collect_instances.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pype/plugins/tvpaint/publish/collect_instances.py b/pype/plugins/tvpaint/publish/collect_instances.py index f1b3239f11..3ac2fecd5f 100644 --- a/pype/plugins/tvpaint/publish/collect_instances.py +++ b/pype/plugins/tvpaint/publish/collect_instances.py @@ -17,6 +17,8 @@ class CollectInstances(pyblish.api.ContextPlugin): )) for instance_data in workfile_instances: + instance_data["fps"] = context.data["fps"] + # Store workfile instance data to instance data instance_data["originData"] = copy.deepcopy(instance_data) # Global instance data modifications @@ -32,6 +34,8 @@ class CollectInstances(pyblish.api.ContextPlugin): active = instance_data.get("active", True) instance_data["active"] = active instance_data["publish"] = active + # Add representations key + instance_data["representations"] = [] # Different instance creation based on family instance = None From 555c9382e7994e4a33200730c4ddad66fc76717e Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 11 Nov 2020 17:00:32 +0100 Subject: [PATCH 58/79] few minor fixes --- .../tvpaint/publish/extract_sequence.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/pype/plugins/tvpaint/publish/extract_sequence.py b/pype/plugins/tvpaint/publish/extract_sequence.py index ffb79a853e..003ab673d2 100644 --- a/pype/plugins/tvpaint/publish/extract_sequence.py +++ b/pype/plugins/tvpaint/publish/extract_sequence.py @@ -65,10 +65,12 @@ class ExtractSequence(pyblish.api.Extractor): for layer in layers if layer["visible"] ] - layer_ids = [layer["layer_id"] for layer in filtered_layers] - self.log.debug("Instance has {} layers with ids: {}".format( - len(filtered_layers), ", ".join(layer_ids) - )) + layer_ids = [str(layer["layer_id"]) for layer in filtered_layers] + self.log.debug( + "Instance has {} layers with ids: {}".format( + len(layer_ids), ", ".join(layer_ids) + ) + ) # This is plugin attribe cleanup method self._prepare_save_modes() @@ -113,7 +115,7 @@ class ExtractSequence(pyblish.api.Extractor): filtered_layers, frame_start, frame_end, thumbnail_filename ) thumbnail_fullpath = output_files_by_frame.pop( - output_files_by_frame, None + thumbnail_filename, None ) # Fill gaps in sequence @@ -124,10 +126,6 @@ class ExtractSequence(pyblish.api.Extractor): filename_template ) - # Add representation to instance's representations - if instance.data.get("representations") is None: - instance.data["representations"] = [] - # Fill tags if family_lowered in ("review", "renderlayer"): tags = ["review", "ftrack"] @@ -158,7 +156,7 @@ class ExtractSequence(pyblish.api.Extractor): thumbnail_repre = { "name": "thumbnail", "ext": ext, - "files": [os.path.basename(thumbnail_fullpath)], + "files": os.path.basename(thumbnail_fullpath), "stagingDir": output_dir, "tags": ["thumbnail"] } From 601700e1caae22fd81e90207a3c14b68f95ceecf Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 11 Nov 2020 17:00:41 +0100 Subject: [PATCH 59/79] added warning message --- pype/plugins/tvpaint/publish/extract_sequence.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pype/plugins/tvpaint/publish/extract_sequence.py b/pype/plugins/tvpaint/publish/extract_sequence.py index 003ab673d2..906c183b90 100644 --- a/pype/plugins/tvpaint/publish/extract_sequence.py +++ b/pype/plugins/tvpaint/publish/extract_sequence.py @@ -318,6 +318,12 @@ class ExtractSequence(pyblish.api.Extractor): previous_frame_filepath = filepaths_by_frame[frame] continue + elif previous_frame_filepath is None: + self.log.warning( + "No frames to fill. Seems like nothing was exported." + ) + break + if output_dir is None: output_dir = os.path.dirname(previous_frame_filepath) From 4b5b725521fdc849b8bfcb3322a81cf326ffa625 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 11 Nov 2020 17:13:10 +0100 Subject: [PATCH 60/79] export first frame all the time --- pype/plugins/tvpaint/publish/extract_sequence.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pype/plugins/tvpaint/publish/extract_sequence.py b/pype/plugins/tvpaint/publish/extract_sequence.py index 906c183b90..de0a547540 100644 --- a/pype/plugins/tvpaint/publish/extract_sequence.py +++ b/pype/plugins/tvpaint/publish/extract_sequence.py @@ -264,6 +264,11 @@ class ExtractSequence(pyblish.api.Extractor): new_layer_id, first_frame, last_frame ) + # TODO what if there is not exposue frames? + # - this force to have first frame all the time + if first_frame not in exposure_frames: + exposure_frames.insert(0, first_frame) + # Restart george script lines george_script_lines = [] george_script_lines.append(save_mode) From 7c4f408e7777cd30d86d0ddd3e6a84fa2c4a1356 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 11 Nov 2020 17:39:00 +0100 Subject: [PATCH 61/79] added renderLayer and renderPass to integration --- pype/plugins/global/publish/integrate_new.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pype/plugins/global/publish/integrate_new.py b/pype/plugins/global/publish/integrate_new.py index 4dc6006076..573228f01b 100644 --- a/pype/plugins/global/publish/integrate_new.py +++ b/pype/plugins/global/publish/integrate_new.py @@ -90,7 +90,9 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): "harmony.template", "harmony.palette", "editorial", - "background" + "background", + "renderLayer", + "renderPass" ] exclude_families = ["clip"] db_representation_context_keys = [ From 0525075a694af7c03b5d4b33ed8e0c93cb5b103e Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 11 Nov 2020 17:52:24 +0100 Subject: [PATCH 62/79] use stagingDir on instance output --- pype/plugins/tvpaint/publish/extract_sequence.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/pype/plugins/tvpaint/publish/extract_sequence.py b/pype/plugins/tvpaint/publish/extract_sequence.py index de0a547540..8eef84cc9c 100644 --- a/pype/plugins/tvpaint/publish/extract_sequence.py +++ b/pype/plugins/tvpaint/publish/extract_sequence.py @@ -101,8 +101,13 @@ class ExtractSequence(pyblish.api.Extractor): ) ) - # Save to temp - output_dir = tempfile.mkdtemp().replace("\\", "/") + # Save to staging dir + output_dir = instance.data.get("stagingDir") + if not output_dir: + # Create temp folder if staging dir is not set + output_dir = tempfile.mkdtemp().replace("\\", "/") + instance.data["stagingDir"] = output_dir + self.log.debug( "Files will be rendered to folder: {}".format(output_dir) ) From 417e167c7e15c9705d45a045696ef0d07460f411 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 11 Nov 2020 18:16:12 +0100 Subject: [PATCH 63/79] added more families and removed tags --- .../tvpaint/publish/extract_sequence.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/pype/plugins/tvpaint/publish/extract_sequence.py b/pype/plugins/tvpaint/publish/extract_sequence.py index 8eef84cc9c..c4aba77f60 100644 --- a/pype/plugins/tvpaint/publish/extract_sequence.py +++ b/pype/plugins/tvpaint/publish/extract_sequence.py @@ -131,11 +131,21 @@ class ExtractSequence(pyblish.api.Extractor): filename_template ) - # Fill tags + # Fill tags and new families + tags = [] + new_families = ["review"] if family_lowered in ("review", "renderlayer"): - tags = ["review", "ftrack"] - else: - tags = [] + # QUESTION Thould this be set here or in collector? + # Add ftrack family + new_families.append("ftrack") + # Add `ftrackreview` tag + tags.append("ftrackreview") + # QUESTION we still use this? + instance.data["review"] = True + + for new_family in new_families: + if new_family not in instance.data["families"]: + instance.data["families"].append(new_family) repre_files = [ os.path.basename(filepath) From 1d35a8686be50496f475089d563f092e673f6913 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 11 Nov 2020 18:16:44 +0100 Subject: [PATCH 64/79] collect instances works more as should --- pype/plugins/tvpaint/publish/collect_instances.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/pype/plugins/tvpaint/publish/collect_instances.py b/pype/plugins/tvpaint/publish/collect_instances.py index 3ac2fecd5f..87cf52e43e 100644 --- a/pype/plugins/tvpaint/publish/collect_instances.py +++ b/pype/plugins/tvpaint/publish/collect_instances.py @@ -42,6 +42,7 @@ class CollectInstances(pyblish.api.ContextPlugin): if family == "review": instance = context.create_instance(**instance_data) instance.data["layers"] = context.data["layersData"] + elif family == "renderLayer": instance = self.create_render_layer_instance( context, instance_data @@ -82,10 +83,10 @@ class CollectInstances(pyblish.api.ContextPlugin): if not group_layers: # Should be handled here? - self.log.warning( + self.log.warning(( f"Group with id {group_id} does not contain any layers." f" Instance \"{name}\" not created." - ) + )) return None instance_data["layers"] = group_layers @@ -93,6 +94,9 @@ class CollectInstances(pyblish.api.ContextPlugin): def create_render_pass_instance(self, context, instance_data): pass_name = instance_data["pass"] + self.log.info( + "Creating render pass instance. \"{}\"".format(pass_name) + ) render_layer = instance_data["render_layer"] instance_data["label"] = "{}_{}".format(render_layer, pass_name) @@ -113,9 +117,9 @@ class CollectInstances(pyblish.api.ContextPlugin): # Move to validator? if layer["group_id"] != group_id: - self.log.warning( - f"Layer with id {layer_id} is in different group." - ) + self.log.warning(( + "Layer \"{}\" with id < {} > is in different group." + ).format(layer["name"], layer_id)) continue render_pass_layers.append(layer) From de678a89842b470fcec2a6a47d04858a2a4a1e8c Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 11 Nov 2020 19:14:25 +0100 Subject: [PATCH 65/79] removed unused import --- pype/plugins/tvpaint/publish/extract_sequence.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/plugins/tvpaint/publish/extract_sequence.py b/pype/plugins/tvpaint/publish/extract_sequence.py index c4aba77f60..63a1e57695 100644 --- a/pype/plugins/tvpaint/publish/extract_sequence.py +++ b/pype/plugins/tvpaint/publish/extract_sequence.py @@ -3,7 +3,7 @@ import shutil import tempfile import pyblish.api -from avalon.tvpaint import pipeline, lib +from avalon.tvpaint import lib class ExtractSequence(pyblish.api.Extractor): From 0788f9ae52e3fde8497dfa46bb131cc82d095cde Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 12 Nov 2020 09:41:24 +0100 Subject: [PATCH 66/79] renamed beauty creator --- pype/plugins/tvpaint/create/create_render_layer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/plugins/tvpaint/create/create_render_layer.py b/pype/plugins/tvpaint/create/create_render_layer.py index f261466681..c2921cebbe 100644 --- a/pype/plugins/tvpaint/create/create_render_layer.py +++ b/pype/plugins/tvpaint/create/create_render_layer.py @@ -1,7 +1,7 @@ from avalon.tvpaint import pipeline, lib -class CreateBeauty(pipeline.Creator): +class CreateRenderlayer(pipeline.Creator): """Mark layer group as one instance.""" name = "render_layer" label = "RenderLayer" From dfece60dbc1313128b89dcd10679c37129ed90ed Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 12 Nov 2020 09:42:48 +0100 Subject: [PATCH 67/79] changed log message --- pype/plugins/tvpaint/publish/collect_instances.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pype/plugins/tvpaint/publish/collect_instances.py b/pype/plugins/tvpaint/publish/collect_instances.py index 87cf52e43e..68d0620253 100644 --- a/pype/plugins/tvpaint/publish/collect_instances.py +++ b/pype/plugins/tvpaint/publish/collect_instances.py @@ -126,8 +126,8 @@ class CollectInstances(pyblish.api.ContextPlugin): if not render_pass_layers: name = instance_data["name"] self.log.warning( - f"All layers from RenderPass \"{name}\" do not exist." - " Instance not created." + f"None of the layers from the RenderPass \"{name}\"" + " exist anymore. Instance not created." ) return None From 0bfe5b6e61b90acbbdd71a59dfd6ca4c75ae7af8 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 12 Nov 2020 09:43:16 +0100 Subject: [PATCH 68/79] fixed typo --- pype/plugins/tvpaint/publish/collect_workfile_data.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pype/plugins/tvpaint/publish/collect_workfile_data.py b/pype/plugins/tvpaint/publish/collect_workfile_data.py index b27eb2f693..31fd97ced4 100644 --- a/pype/plugins/tvpaint/publish/collect_workfile_data.py +++ b/pype/plugins/tvpaint/publish/collect_workfile_data.py @@ -50,7 +50,7 @@ class CollectWorkfileData(pyblish.api.ContextPlugin): if frame_end > last_frame: last_frame = frame_end - sceme_data = { + scene_data = { "currentFile": workfile_path, "sceneWidth": width, "sceneHeight": height, @@ -61,6 +61,6 @@ class CollectWorkfileData(pyblish.api.ContextPlugin): "fieldOrder": field_order } self.log.debug( - "Scene data: {}".format(json.dumps(sceme_data, indent=4)) + "Scene data: {}".format(json.dumps(scene_data, indent=4)) ) - context.data.update(sceme_data) + context.data.update(scene_data) From df4ecca987bc9e0ff77be6c6a2ada29a735ccb4f Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 12 Nov 2020 09:49:25 +0100 Subject: [PATCH 69/79] moved family definition from extractor to collector --- pype/plugins/tvpaint/publish/collect_instances.py | 9 ++++++++- pype/plugins/tvpaint/publish/extract_sequence.py | 10 ---------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/pype/plugins/tvpaint/publish/collect_instances.py b/pype/plugins/tvpaint/publish/collect_instances.py index 68d0620253..169b969bc4 100644 --- a/pype/plugins/tvpaint/publish/collect_instances.py +++ b/pype/plugins/tvpaint/publish/collect_instances.py @@ -24,7 +24,8 @@ class CollectInstances(pyblish.api.ContextPlugin): # Global instance data modifications # Fill families family = instance_data["family"] - instance_data["families"] = [family] + # Add `review` family for thumbnail integration + instance_data["families"] = [family, "review"] # Instance name subset_name = instance_data["subset"] @@ -42,6 +43,8 @@ class CollectInstances(pyblish.api.ContextPlugin): if family == "review": instance = context.create_instance(**instance_data) instance.data["layers"] = context.data["layersData"] + # Add ftrack family + instance.data["families"].append("ftrack") elif family == "renderLayer": instance = self.create_render_layer_instance( @@ -90,6 +93,10 @@ class CollectInstances(pyblish.api.ContextPlugin): return None instance_data["layers"] = group_layers + + # Add ftrack family + instance_data["families"].append("ftrack") + return context.create_instance(**instance_data) def create_render_pass_instance(self, context, instance_data): diff --git a/pype/plugins/tvpaint/publish/extract_sequence.py b/pype/plugins/tvpaint/publish/extract_sequence.py index 63a1e57695..c899ecb9e6 100644 --- a/pype/plugins/tvpaint/publish/extract_sequence.py +++ b/pype/plugins/tvpaint/publish/extract_sequence.py @@ -133,19 +133,9 @@ class ExtractSequence(pyblish.api.Extractor): # Fill tags and new families tags = [] - new_families = ["review"] if family_lowered in ("review", "renderlayer"): - # QUESTION Thould this be set here or in collector? - # Add ftrack family - new_families.append("ftrack") # Add `ftrackreview` tag tags.append("ftrackreview") - # QUESTION we still use this? - instance.data["review"] = True - - for new_family in new_families: - if new_family not in instance.data["families"]: - instance.data["families"].append(new_family) repre_files = [ os.path.basename(filepath) From 426bc1e92bb739f7ee467c1d736b724ac34ef59d Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 12 Nov 2020 09:51:31 +0100 Subject: [PATCH 70/79] skip instances without visible layers --- pype/plugins/tvpaint/publish/extract_sequence.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/pype/plugins/tvpaint/publish/extract_sequence.py b/pype/plugins/tvpaint/publish/extract_sequence.py index c899ecb9e6..239dec5249 100644 --- a/pype/plugins/tvpaint/publish/extract_sequence.py +++ b/pype/plugins/tvpaint/publish/extract_sequence.py @@ -56,9 +56,6 @@ class ExtractSequence(pyblish.api.Extractor): ) # Get all layers and filter out not visible - # TODO what to do if all are invisible? - # - skip without output? - # - still render but empty output? layers = instance.data["layers"] filtered_layers = [ layer @@ -66,6 +63,13 @@ class ExtractSequence(pyblish.api.Extractor): if layer["visible"] ] layer_ids = [str(layer["layer_id"]) for layer in filtered_layers] + if not layer_ids: + self.log.info( + f"None of the layers from the instance" + " are visible. Extraction skipped." + ) + return + self.log.debug( "Instance has {} layers with ids: {}".format( len(layer_ids), ", ".join(layer_ids) From f179929662058f704092f957c2ea06744ec30cea Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 12 Nov 2020 10:24:22 +0100 Subject: [PATCH 71/79] moved validation of render pass group id to validator --- .../tvpaint/publish/collect_instances.py | 6 -- .../tvpaint/publish/validate_frame_range.py | 76 +++++++++++++++++++ 2 files changed, 76 insertions(+), 6 deletions(-) create mode 100644 pype/plugins/tvpaint/publish/validate_frame_range.py diff --git a/pype/plugins/tvpaint/publish/collect_instances.py b/pype/plugins/tvpaint/publish/collect_instances.py index 169b969bc4..3f5c1de367 100644 --- a/pype/plugins/tvpaint/publish/collect_instances.py +++ b/pype/plugins/tvpaint/publish/collect_instances.py @@ -122,12 +122,6 @@ class CollectInstances(pyblish.api.ContextPlugin): self.log.warning(f"Layer with id {layer_id} was not found.") continue - # Move to validator? - if layer["group_id"] != group_id: - self.log.warning(( - "Layer \"{}\" with id < {} > is in different group." - ).format(layer["name"], layer_id)) - continue render_pass_layers.append(layer) if not render_pass_layers: diff --git a/pype/plugins/tvpaint/publish/validate_frame_range.py b/pype/plugins/tvpaint/publish/validate_frame_range.py new file mode 100644 index 0000000000..cb9a103fa2 --- /dev/null +++ b/pype/plugins/tvpaint/publish/validate_frame_range.py @@ -0,0 +1,76 @@ +import collections +import pyblish.api + + +class ValidateLayersGroup(pyblish.api.InstancePlugin): + """Validate group ids of renderPass layers. + + Validates that all layers are in same group as they were during creation. + """ + + label = "Validate Layers Group" + order = pyblish.api.ValidatorOrder + families = ["renderPass"] + + def process(self, instance): + # Prepare layers + layers_data = instance.context.data["layersData"] + layers_by_id = { + layer["layer_id"]: layer + for layer in layers_data + } + + # Expected group id for instance layers + group_id = instance.data["group_id"] + # Layers ids of an instance + layer_ids = instance.data["layer_ids"] + # Check if all layers from render pass are in right group + invalid_layers_by_group_id = collections.defaultdict(list) + for layer_id in layer_ids: + layer = layers_by_id.get(layer_id) + _group_id = layer["group_id"] + if _group_id != group_id: + invalid_layers_by_group_id[_group_id].append(layer) + + # Everything is OK and skip exception + if not invalid_layers_by_group_id: + return + + # Exception message preparations + groups_data = instance.context.data["groupsData"] + groups_by_id = { + group["group_id"]: group + for group in groups_data + } + correct_group = groups_by_id[group_id] + + per_group_msgs = [] + for _group_id, layers in invalid_layers_by_group_id.items(): + _group = groups_by_id[_group_id] + layers_msgs = [] + for layer in layers: + layers_msgs.append( + "\"{}\" (id: {})".format(layer["name"], layer["layer_id"]) + ) + per_group_msgs.append( + "Group \"{}\" (id: {}) < {} >".format( + _group["name"], + _group["group_id"], + ", ".join(layers_msgs) + ) + ) + + # Raise an error + raise AssertionError(( + # Short message + "Layers in wrong group." + # Description what's wrong + " Layers from render pass \"{}\" must be in group {} (id: {})." + # Detailed message + " Layers in wrong group: {}" + ).format( + instance.data["label"], + correct_group["name"], + correct_group["group_id"], + " | ".join(per_group_msgs) + )) From 49f611701b3e41066578e0d15a507faa7f621792 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 12 Nov 2020 10:25:46 +0100 Subject: [PATCH 72/79] removed unused variable --- pype/plugins/tvpaint/publish/collect_instances.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pype/plugins/tvpaint/publish/collect_instances.py b/pype/plugins/tvpaint/publish/collect_instances.py index 3f5c1de367..9e8e5e7832 100644 --- a/pype/plugins/tvpaint/publish/collect_instances.py +++ b/pype/plugins/tvpaint/publish/collect_instances.py @@ -113,7 +113,6 @@ class CollectInstances(pyblish.api.ContextPlugin): for layer in layers_data } - group_id = instance_data["group_id"] layer_ids = instance_data["layer_ids"] render_pass_layers = [] for layer_id in layer_ids: From 86d1bededabd7fe0a7e15c8f7d40bea8edd2484c Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 12 Nov 2020 10:54:42 +0100 Subject: [PATCH 73/79] change family to `render` in extractor --- pype/plugins/tvpaint/publish/extract_sequence.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pype/plugins/tvpaint/publish/extract_sequence.py b/pype/plugins/tvpaint/publish/extract_sequence.py index 239dec5249..aaad88fd5d 100644 --- a/pype/plugins/tvpaint/publish/extract_sequence.py +++ b/pype/plugins/tvpaint/publish/extract_sequence.py @@ -158,6 +158,10 @@ class ExtractSequence(pyblish.api.Extractor): instance.data["representations"].append(new_repre) + if family_lowered in ("renderpass", "renderlayer"): + # Change family to render + instance.data["family"] = "render" + if not thumbnail_fullpath: return From 3212a660c75ade81c5e12b245e078131fc768710 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 12 Nov 2020 11:00:59 +0100 Subject: [PATCH 74/79] remove `is_sequence` variable --- pype/plugins/tvpaint/publish/extract_sequence.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pype/plugins/tvpaint/publish/extract_sequence.py b/pype/plugins/tvpaint/publish/extract_sequence.py index aaad88fd5d..d173ac287d 100644 --- a/pype/plugins/tvpaint/publish/extract_sequence.py +++ b/pype/plugins/tvpaint/publish/extract_sequence.py @@ -84,8 +84,7 @@ class ExtractSequence(pyblish.api.Extractor): ) save_mode_type = self._get_save_mode_type(save_mode) - is_sequence = bool(save_mode_type in self.sequential_save_mode) - if not is_sequence: + if not bool(save_mode_type in self.sequential_save_mode): raise AssertionError(( "Plugin can export only sequential frame output" " but save mode for family \"{}\" is not for sequence > {} <" From 6f91253e4181f1857dfa4503e83ca1d02224b6bb Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 12 Nov 2020 11:09:08 +0100 Subject: [PATCH 75/79] fill data in assertion error --- pype/plugins/tvpaint/publish/collect_instances.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pype/plugins/tvpaint/publish/collect_instances.py b/pype/plugins/tvpaint/publish/collect_instances.py index 9e8e5e7832..8add2f01d9 100644 --- a/pype/plugins/tvpaint/publish/collect_instances.py +++ b/pype/plugins/tvpaint/publish/collect_instances.py @@ -56,7 +56,9 @@ class CollectInstances(pyblish.api.ContextPlugin): ) else: raise AssertionError( - "Instance with unknown family \"{}\": {}" + "Instance with unknown family \"{}\": {}".format( + family, instance_data + ) ) frame_start = context.data["frameStart"] From 655c5f0463cd8f0de55af9b47655f587256ac6db Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 12 Nov 2020 11:09:28 +0100 Subject: [PATCH 76/79] change subset name for renderPass and renderLayer in instance collector --- pype/plugins/tvpaint/publish/collect_instances.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pype/plugins/tvpaint/publish/collect_instances.py b/pype/plugins/tvpaint/publish/collect_instances.py index 8add2f01d9..9a3fd67110 100644 --- a/pype/plugins/tvpaint/publish/collect_instances.py +++ b/pype/plugins/tvpaint/publish/collect_instances.py @@ -32,6 +32,15 @@ class CollectInstances(pyblish.api.ContextPlugin): name = instance_data.get("name", subset_name) instance_data["name"] = name + # Replace family in subset name with `render` + # - only for `renderPass` and `renderLayer` + if family.lower() in ("renderlayer", "renderpass"): + new_subset_name = "render".join(subset_name.split(family)) + instance_data["subset"] = new_subset_name + self.log.debug("Changed subset name \"{}\"->\"{}\"".format( + subset_name, new_subset_name + )) + active = instance_data.get("active", True) instance_data["active"] = active instance_data["publish"] = active From aaf4fadf4766d1f178bf464608c40208ad9f82c1 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 12 Nov 2020 11:12:56 +0100 Subject: [PATCH 77/79] remove renderLayer and renderPass from integrate new families --- pype/plugins/global/publish/integrate_new.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pype/plugins/global/publish/integrate_new.py b/pype/plugins/global/publish/integrate_new.py index 573228f01b..4dc6006076 100644 --- a/pype/plugins/global/publish/integrate_new.py +++ b/pype/plugins/global/publish/integrate_new.py @@ -90,9 +90,7 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): "harmony.template", "harmony.palette", "editorial", - "background", - "renderLayer", - "renderPass" + "background" ] exclude_families = ["clip"] db_representation_context_keys = [ From fae1294616b60f2e3993e24fbdd26c1b8d77e72e Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 12 Nov 2020 11:18:46 +0100 Subject: [PATCH 78/79] render layer missed beauty in subset name --- .../tvpaint/publish/collect_instances.py | 35 +++++++++++++------ 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/pype/plugins/tvpaint/publish/collect_instances.py b/pype/plugins/tvpaint/publish/collect_instances.py index 9a3fd67110..fb8702149a 100644 --- a/pype/plugins/tvpaint/publish/collect_instances.py +++ b/pype/plugins/tvpaint/publish/collect_instances.py @@ -32,15 +32,6 @@ class CollectInstances(pyblish.api.ContextPlugin): name = instance_data.get("name", subset_name) instance_data["name"] = name - # Replace family in subset name with `render` - # - only for `renderPass` and `renderLayer` - if family.lower() in ("renderlayer", "renderpass"): - new_subset_name = "render".join(subset_name.split(family)) - instance_data["subset"] = new_subset_name - self.log.debug("Changed subset name \"{}\"->\"{}\"".format( - subset_name, new_subset_name - )) - active = instance_data.get("active", True) instance_data["active"] = active instance_data["publish"] = active @@ -86,8 +77,22 @@ class CollectInstances(pyblish.api.ContextPlugin): def create_render_layer_instance(self, context, instance_data): name = instance_data["name"] - instance_data["label"] = "{}_beauty".format(name) + subset_name = instance_data["subset"] + # Add beauty to subset name (and label) + beauty_template = "{}_Beauty" + subset_name = beauty_template.format(subset_name) + instance_data["label"] = beauty_template.format(name) + # Replace family in subset name with `render` family + # - this is because final output will be `render` family + family = instance_data["family"] + new_subset_name = "render".join(subset_name.split(family)) + instance_data["subset"] = new_subset_name + self.log.debug("Changed subset name \"{}\"->\"{}\"".format( + subset_name, new_subset_name + )) + + # Get all layers for the layer layers_data = context.data["layersData"] group_id = instance_data["group_id"] group_layers = [] @@ -118,6 +123,16 @@ class CollectInstances(pyblish.api.ContextPlugin): render_layer = instance_data["render_layer"] instance_data["label"] = "{}_{}".format(render_layer, pass_name) + # Replace family in subset name with `render` family + # - this is because final output will be `render` family + family = instance_data["family"] + subset_name = instance_data["subset"] + new_subset_name = "render".join(subset_name.split(family)) + instance_data["subset"] = new_subset_name + self.log.debug("Changed subset name \"{}\"->\"{}\"".format( + subset_name, new_subset_name + )) + layers_data = context.data["layersData"] layers_by_id = { layer["layer_id"]: layer From e3b06613e1af95c658afc586e514e05c5129334e Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 12 Nov 2020 11:50:54 +0100 Subject: [PATCH 79/79] subset names are right now with task and right family --- .../tvpaint/publish/collect_instances.py | 39 ++++++++++++------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/pype/plugins/tvpaint/publish/collect_instances.py b/pype/plugins/tvpaint/publish/collect_instances.py index fb8702149a..a9c19f9c0a 100644 --- a/pype/plugins/tvpaint/publish/collect_instances.py +++ b/pype/plugins/tvpaint/publish/collect_instances.py @@ -1,6 +1,7 @@ import json import copy import pyblish.api +from avalon import io class CollectInstances(pyblish.api.ContextPlugin): @@ -41,6 +42,11 @@ class CollectInstances(pyblish.api.ContextPlugin): # Different instance creation based on family instance = None if family == "review": + # Change subset name + task_name = io.Session["AVALON_TASK"] + new_subset_name = "{}{}".format(family, task_name.capitalize()) + instance_data["subset"] = new_subset_name + instance = context.create_instance(**instance_data) instance.data["layers"] = context.data["layersData"] # Add ftrack family @@ -77,16 +83,17 @@ class CollectInstances(pyblish.api.ContextPlugin): def create_render_layer_instance(self, context, instance_data): name = instance_data["name"] + # Change label subset_name = instance_data["subset"] - # Add beauty to subset name (and label) - beauty_template = "{}_Beauty" - subset_name = beauty_template.format(subset_name) - instance_data["label"] = beauty_template.format(name) + instance_data["label"] = "{}_Beauty".format(name) - # Replace family in subset name with `render` family - # - this is because final output will be `render` family - family = instance_data["family"] - new_subset_name = "render".join(subset_name.split(family)) + # Change subset name + # Final family of an instance will be `render` + new_family = "render" + task_name = io.Session["AVALON_TASK"] + new_subset_name = "{}{}_{}_Beauty".format( + new_family, task_name.capitalize(), name + ) instance_data["subset"] = new_subset_name self.log.debug("Changed subset name \"{}\"->\"{}\"".format( subset_name, new_subset_name @@ -120,17 +127,21 @@ class CollectInstances(pyblish.api.ContextPlugin): self.log.info( "Creating render pass instance. \"{}\"".format(pass_name) ) + # Change label render_layer = instance_data["render_layer"] instance_data["label"] = "{}_{}".format(render_layer, pass_name) - # Replace family in subset name with `render` family - # - this is because final output will be `render` family - family = instance_data["family"] - subset_name = instance_data["subset"] - new_subset_name = "render".join(subset_name.split(family)) + # Change subset name + # Final family of an instance will be `render` + new_family = "render" + old_subset_name = instance_data["subset"] + task_name = io.Session["AVALON_TASK"] + new_subset_name = "{}{}_{}_{}".format( + new_family, task_name.capitalize(), render_layer, pass_name + ) instance_data["subset"] = new_subset_name self.log.debug("Changed subset name \"{}\"->\"{}\"".format( - subset_name, new_subset_name + old_subset_name, new_subset_name )) layers_data = context.data["layersData"]