From c214e7516c119e75f654e16da30183a7d5a11e65 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 11 Aug 2020 13:47:50 +0200 Subject: [PATCH 01/42] feat(ps): adding psd batch workflow to standalone publisher --- .../publish/collect_context.py | 129 ++++++++++-------- .../publish/collect_hierarchy.py | 1 + .../publish/collect_matching_asset.py | 26 ++++ .../publish/collect_project_assets.py | 21 +++ .../publish/collect_psd_instances.py | 71 ++++++++++ 5 files changed, 190 insertions(+), 58 deletions(-) create mode 100644 pype/plugins/standalonepublisher/publish/collect_matching_asset.py create mode 100644 pype/plugins/standalonepublisher/publish/collect_project_assets.py create mode 100644 pype/plugins/standalonepublisher/publish/collect_psd_instances.py diff --git a/pype/plugins/standalonepublisher/publish/collect_context.py b/pype/plugins/standalonepublisher/publish/collect_context.py index 4dcb25f927..370e00fd7f 100644 --- a/pype/plugins/standalonepublisher/publish/collect_context.py +++ b/pype/plugins/standalonepublisher/publish/collect_context.py @@ -17,10 +17,8 @@ import os import pyblish.api from avalon import io import json -import logging import clique - -log = logging.getLogger("collector") +from pprint import pformat class CollectContextDataSAPublish(pyblish.api.ContextPlugin): @@ -33,6 +31,9 @@ class CollectContextDataSAPublish(pyblish.api.ContextPlugin): order = pyblish.api.CollectorOrder - 0.49 hosts = ["standalonepublisher"] + # presets + batch_extensions = ["edl", "xml", "psd"] + def process(self, context): # get json paths from os and load them io.install() @@ -52,73 +53,80 @@ class CollectContextDataSAPublish(pyblish.api.ContextPlugin): with open(input_json_path, "r") as f: in_data = json.load(f) - self.log.debug(f"_ in_data: {in_data}") + self.log.debug(f"_ in_data: {pformat(in_data)}") self.asset_name = in_data["asset"] self.family = in_data["family"] + self.families = ["ftrack"] + self.family_preset_key = in_data["family_preset_key"] asset = io.find_one({"type": "asset", "name": self.asset_name}) context.data["asset"] = asset # exception for editorial - if "editorial" in self.family: - # avoid subset name duplicity - if not context.data.get("subsetNamesCheck"): - context.data["subsetNamesCheck"] = list() - - in_data_list = list() - representations = in_data.pop("representations") - for repr in representations: - in_data_copy = in_data.copy() - ext = repr["ext"][1:] - subset = in_data_copy["subset"] - # filter out non editorial files - if ext not in ["edl", "xml"]: - in_data_copy["representations"] = [repr] - in_data_copy["subset"] = f"{ext}{subset}" - in_data_list.append(in_data_copy) - - files = repr.pop("files") - - # delete unneeded keys - delete_repr_keys = ["frameStart", "frameEnd"] - for k in delete_repr_keys: - if repr.get(k): - repr.pop(k) - - # convert files to list if it isnt - if not isinstance(files, list): - files = [files] - - self.log.debug(f"_ files: {files}") - for index, f in enumerate(files): - index += 1 - # copy dictionaries - in_data_copy = in_data_copy.copy() - repr_new = repr.copy() - - repr_new["files"] = f - repr_new["name"] = ext - in_data_copy["representations"] = [repr_new] - - # create subset Name - new_subset = f"{ext}{index}{subset}" - while new_subset in context.data["subsetNamesCheck"]: - index += 1 - new_subset = f"{ext}{index}{subset}" - - context.data["subsetNamesCheck"].append(new_subset) - in_data_copy["subset"] = new_subset - in_data_list.append(in_data_copy) - self.log.info(f"Creating subset: {ext}{index}{subset}") + if self.family_preset_key in ["editorial", "psd_batch"]: + in_data_list = self.multiple_instances(context, in_data) else: in_data_list = [in_data] - self.log.debug(f"_ in_data_list: {in_data_list}") + self.log.debug(f"_ in_data_list: {pformat(in_data_list)}") for in_data in in_data_list: # create instance self.create_instance(context, in_data) + def multiple_instances(self, context, in_data): + # avoid subset name duplicity + if not context.data.get("subsetNamesCheck"): + context.data["subsetNamesCheck"] = list() + + in_data_list = list() + representations = in_data.pop("representations") + for repr in representations: + in_data_copy = in_data.copy() + ext = repr["ext"][1:] + subset = in_data_copy["subset"] + # filter out non editorial files + if ext not in self.batch_extensions: + in_data_copy["representations"] = [repr] + in_data_copy["subset"] = f"{ext}{subset}" + in_data_list.append(in_data_copy) + + files = repr.get("files") + + # delete unneeded keys + delete_repr_keys = ["frameStart", "frameEnd"] + for k in delete_repr_keys: + if repr.get(k): + repr.pop(k) + + # convert files to list if it isnt + if not isinstance(files, list): + files = [files] + + self.log.debug(f"_ files: {files}") + for index, f in enumerate(files): + index += 1 + # copy dictionaries + in_data_copy = in_data_copy.copy() + repr_new = repr.copy() + + repr_new["files"] = f + repr_new["name"] = ext + in_data_copy["representations"] = [repr_new] + + # create subset Name + new_subset = f"{ext}{index}{subset}" + while new_subset in context.data["subsetNamesCheck"]: + index += 1 + new_subset = f"{ext}{index}{subset}" + + context.data["subsetNamesCheck"].append(new_subset) + in_data_copy["subset"] = new_subset + in_data_list.append(in_data_copy) + self.log.info(f"Creating subset: {ext}{index}{subset}") + + return in_data_list + def create_instance(self, context, in_data): subset = in_data["subset"] @@ -138,11 +146,11 @@ class CollectContextDataSAPublish(pyblish.api.ContextPlugin): "frameEnd": in_data.get("representations", [None])[0].get( "frameEnd", None ), - "families": [self.family, "ftrack"], + "families": self.families + [self.family_preset_key], } ) - self.log.info("collected instance: {}".format(instance.data)) - self.log.info("parsing data: {}".format(in_data)) + self.log.info("collected instance: {}".format(pformat(instance.data))) + self.log.info("parsing data: {}".format(pformat(in_data))) instance.data["destination_list"] = list() instance.data["representations"] = list() @@ -165,4 +173,9 @@ class CollectContextDataSAPublish(pyblish.api.ContextPlugin): component["tags"] = ["review"] self.log.debug("Adding review family") + if "psd" in component["name"]: + instance.data["source"] = component["files"] + component["thumbnail"] = True + self.log.debug("Adding image:psd_batch family") + instance.data["representations"].append(component) diff --git a/pype/plugins/standalonepublisher/publish/collect_hierarchy.py b/pype/plugins/standalonepublisher/publish/collect_hierarchy.py index b5d37d0a6c..ac7413706a 100644 --- a/pype/plugins/standalonepublisher/publish/collect_hierarchy.py +++ b/pype/plugins/standalonepublisher/publish/collect_hierarchy.py @@ -162,6 +162,7 @@ class CollectHierarchyContext(pyblish.api.ContextPlugin): label = "Collect Hierarchy Context" order = pyblish.api.CollectorOrder + 0.102 hosts = ["standalonepublisher"] + families = ["shot"] def update_dict(self, ex_dict, new_dict): for key in ex_dict: diff --git a/pype/plugins/standalonepublisher/publish/collect_matching_asset.py b/pype/plugins/standalonepublisher/publish/collect_matching_asset.py new file mode 100644 index 0000000000..3575f581df --- /dev/null +++ b/pype/plugins/standalonepublisher/publish/collect_matching_asset.py @@ -0,0 +1,26 @@ +import os +import pyblish.api +from pprint import pformat + + +class CollectMatchingAssetToInstance(pyblish.api.InstancePlugin): + """ + Collecting temp json data sent from a host context + and path for returning json data back to hostself. + """ + + label = "Collect Matching Asset to Instance" + order = pyblish.api.CollectorOrder - 0.05 + hosts = ["standalonepublisher"] + family = ["image"] + + def process(self, instance): + project_assets = instance.context.data["projectAssets"] + source_file = os.path.basename(instance.data["source"]) + asset = next((project_assets[name] for name in project_assets + if name in source_file), None) + + if asset: + instance.data["asset"] = asset["name"] + instance.data["assetEntity"] = asset + self.log.info(f"Matching asset assigned: {pformat(asset)}") diff --git a/pype/plugins/standalonepublisher/publish/collect_project_assets.py b/pype/plugins/standalonepublisher/publish/collect_project_assets.py new file mode 100644 index 0000000000..1ca4144c81 --- /dev/null +++ b/pype/plugins/standalonepublisher/publish/collect_project_assets.py @@ -0,0 +1,21 @@ +import pyblish.api +from avalon import io +from pprint import pformat + + +class CollectProjectAssets(pyblish.api.ContextPlugin): + """ + Collect all available project assets to context data. + """ + + label = "Collect Project Assets" + order = pyblish.api.CollectorOrder - 0.1 + hosts = ["standalonepublisher"] + + def process(self, context): + project_assets = { + asset_doc["name"]: asset_doc + for asset_doc in io.find({"type": "asset"}) + } + context.data["projectAssets"] = project_assets + self.log.debug(f"_ project_assets: {pformat(project_assets)}") diff --git a/pype/plugins/standalonepublisher/publish/collect_psd_instances.py b/pype/plugins/standalonepublisher/publish/collect_psd_instances.py new file mode 100644 index 0000000000..1806439969 --- /dev/null +++ b/pype/plugins/standalonepublisher/publish/collect_psd_instances.py @@ -0,0 +1,71 @@ +import pyblish.api +from pprint import pformat + + +class CollectPsdInstances(pyblish.api.InstancePlugin): + """ + Collect all available instances from psd batch. + """ + + label = "Collect Psd Instances" + order = pyblish.api.CollectorOrder + 0.492 + hosts = ["standalonepublisher"] + families = ["psd_batch"] + + # presets + subsets = { + "imageForLayout": { + "task": "background", + "family": "imageForLayout" + }, + "imageForComp": { + "task": "background", + "family": "imageForComp" + }, + "workfileBackground": { + "task": "background", + "family": "workfile" + }, + } + + def process(self, instance): + context = instance.context + asset_data = instance.data["assetEntity"] + asset = instance.data["asset"] + anatomy_data = instance.data["anatomyData"].copy() + + for subset_name, subset_data in self.subsets.items(): + instance_name = f"{asset}_{subset_name}" + task = subset_data.get("task", "background") + + # create new instance + new_instance = context.create_instance(instance_name) + # add original instance data except name key + new_instance.data.update({k: v for k, v in instance.data.items() + if k not in "name"}) + # add subset data from preset + new_instance.data.update(subset_data) + + label = f"{instance_name}" + new_instance.data["label"] = label + new_instance.data["subset"] = subset_name + new_instance.data["families"].append("image") + + # fix anatomy data + anatomy_data_new = anatomy_data.copy() + # updating hierarchy data + anatomy_data_new.update({ + "asset": asset_data["name"], + "task": task, + "subset": subset_name + }) + new_instance.data["anatomyData"] = anatomy_data_new + + inst_data = new_instance.data + self.log.debug( + f"_ inst_data: {pformat(inst_data)}") + + self.log.info(f"Created new instance: {instance_name}") + + # delete original instance + context.remove(instance) From 96a779e67ba0c1b74d2856ef0c241257c975c956 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 11 Aug 2020 15:22:18 +0200 Subject: [PATCH 02/42] fix anatomy data copy --- .../standalonepublisher/publish/collect_psd_instances.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pype/plugins/standalonepublisher/publish/collect_psd_instances.py b/pype/plugins/standalonepublisher/publish/collect_psd_instances.py index 1806439969..46471a5fdd 100644 --- a/pype/plugins/standalonepublisher/publish/collect_psd_instances.py +++ b/pype/plugins/standalonepublisher/publish/collect_psd_instances.py @@ -1,3 +1,4 @@ +import copy import pyblish.api from pprint import pformat @@ -32,7 +33,7 @@ class CollectPsdInstances(pyblish.api.InstancePlugin): context = instance.context asset_data = instance.data["assetEntity"] asset = instance.data["asset"] - anatomy_data = instance.data["anatomyData"].copy() + anatomy_data = instance.data["anatomyData"] for subset_name, subset_data in self.subsets.items(): instance_name = f"{asset}_{subset_name}" @@ -52,7 +53,7 @@ class CollectPsdInstances(pyblish.api.InstancePlugin): new_instance.data["families"].append("image") # fix anatomy data - anatomy_data_new = anatomy_data.copy() + anatomy_data_new = copy.deepcopy(anatomy_data) # updating hierarchy data anatomy_data_new.update({ "asset": asset_data["name"], From 0c6ddf9c99098ccd441fc846c9cdde4a35727451 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 11 Aug 2020 17:58:40 +0200 Subject: [PATCH 03/42] extract layout plugin implementation --- .../publish/extract_layout_images.py | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 pype/plugins/standalonepublisher/publish/extract_layout_images.py diff --git a/pype/plugins/standalonepublisher/publish/extract_layout_images.py b/pype/plugins/standalonepublisher/publish/extract_layout_images.py new file mode 100644 index 0000000000..c3abf8d36f --- /dev/null +++ b/pype/plugins/standalonepublisher/publish/extract_layout_images.py @@ -0,0 +1,102 @@ +import os +import copy +import pype.api +import pyblish.api + +PSDImage = None + + +class ExtractImageForLayout(pype.api.Extractor): + + label = "Extract Images for Layout" + order = pyblish.api.ExtractorOrder + 0.02 + families = ["imageForLayout"] + hosts = ["standalonepublisher"] + + new_instance_family = "image" + + # Presetable + allowed_group_names = ["OL", "BG", "MG", "FG", "UL", "SKY", "Field Guide"] + + def process(self, instance): + # Check if python module `psd_tools` is installed + try: + global PSDImage + from psd_tools import PSDImage + except Exception: + raise AssertionError( + "BUG: Python module `psd-tools` is not installed!" + ) + + repres = instance.data.get("representations") + if not repres: + self.log.info("There are no representations on instance.") + return + + for repre in tuple(repres): + # Skip all non files without .psd extension + if repre["ext"] != ".psd": + continue + + # TODO add check of list + psd_filename = repre["files"] + psd_folder_path = repre["stagingDir"] + psd_filepath = os.path.join(psd_folder_path, psd_filename) + self.log.debug(f"psd_filepath: \"{psd_filepath}\"") + psd_object = PSDImage.open(psd_filepath) + + self.create_new_instances(instance, psd_object) + + # Remove the instance from context + instance.context.remove(instance) + + def create_new_instances(self, instance, psd_object): + for layer in psd_object: + if ( + not layer.is_visible() + or layer.name not in self.allowed_group_names + ): + continue + + layer_name = layer.name.replace(" ", "_") + instance_name = f"image_{layer_name}" + new_instance = instance.context.create_instance(instance_name) + for key, value in instance.data.items(): + if key not in ("name", "label", "stagingDir"): + new_instance.data[key] = copy.deepcopy(value) + + new_instance.data["label"] = " ".join( + (new_instance.data["asset"], instance_name) + ) + + new_instance.data["subset"] = instance_name + new_instance.data["anatomyData"]["subset"] = instance_name + + # Set `family` + new_instance.data["family"] = self.new_instance_family + + # Copy `families` and check if `family` is not in current families + families = new_instance.data.get("families") or list() + if families: + families = list(set(families)) + + if self.new_instance_family in families: + families.remove(self.new_instance_family) + new_instance.data["families"] = families + + # Prepare staging dir for new instance + staging_dir = self.staging_dir(new_instance) + + output_filename = "{}.png".format(layer_name) + output_filepath = os.path.join(staging_dir, output_filename) + pil_object = layer.composite(viewport=psd_object.viewbox) + pil_object.save(output_filepath, "PNG") + + new_repre = { + "name": "png", + "ext": "png", + "files": output_filename, + "stagingDir": staging_dir + } + new_instance.data["representations"] = [new_repre] + self.log.debug(new_instance.data["name"]) From f38327a25f3e95b84511b095e7e9f9e33f30b2b2 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 11 Aug 2020 18:10:55 +0200 Subject: [PATCH 04/42] ignore psd from ffprobe data getter --- .../modules/standalonepublish/widgets/widget_drop_frame.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pype/modules/standalonepublish/widgets/widget_drop_frame.py b/pype/modules/standalonepublish/widgets/widget_drop_frame.py index 57547a3d5f..785f6adce4 100644 --- a/pype/modules/standalonepublish/widgets/widget_drop_frame.py +++ b/pype/modules/standalonepublish/widgets/widget_drop_frame.py @@ -37,6 +37,7 @@ class DropDataFrame(QtWidgets.QFrame): "image_file": image_extensions, "video_file": video_extensions } + ffprobe_ignore_extensions = [".psd"] def __init__(self, parent): super().__init__() @@ -284,8 +285,10 @@ class DropDataFrame(QtWidgets.QFrame): file_info = data['file_info'] if ( - ext in self.image_extensions - or ext in self.video_extensions + ext not in self.ffprobe_ignore_extensions + and ( + ext in self.image_extensions or ext in self.video_extensions + ) ): probe_data = self.load_data_with_probe(filepath) if 'fps' not in data: From 2de402ad67fc6dd1ddf7e1a2882546c7b28ad0e5 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 11 Aug 2020 18:12:17 +0200 Subject: [PATCH 05/42] removed unnecessary db queries --- pype/plugins/standalonepublisher/publish/collect_context.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/pype/plugins/standalonepublisher/publish/collect_context.py b/pype/plugins/standalonepublisher/publish/collect_context.py index 370e00fd7f..f6d6df72b7 100644 --- a/pype/plugins/standalonepublisher/publish/collect_context.py +++ b/pype/plugins/standalonepublisher/publish/collect_context.py @@ -45,9 +45,6 @@ class CollectContextDataSAPublish(pyblish.api.ContextPlugin): presets = config.get_presets() - project = io.find_one({"type": "project"}) - context.data["project"] = project - # get json file context input_json_path = os.environ.get("SAPUBLISH_INPATH") @@ -59,9 +56,6 @@ class CollectContextDataSAPublish(pyblish.api.ContextPlugin): self.family = in_data["family"] self.families = ["ftrack"] self.family_preset_key = in_data["family_preset_key"] - asset = io.find_one({"type": "asset", "name": self.asset_name}) - context.data["asset"] = asset - # exception for editorial if self.family_preset_key in ["editorial", "psd_batch"]: in_data_list = self.multiple_instances(context, in_data) From c2696e4d4fae61a6022c34f78513b83f87c82383 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 11 Aug 2020 18:24:23 +0200 Subject: [PATCH 06/42] moved CollectProjectAssets to CollectMatchingAssetToInstance as is not used anywhere else yet --- .../publish/collect_matching_asset.py | 34 +++++++++++++++---- .../publish/collect_project_assets.py | 21 ------------ 2 files changed, 27 insertions(+), 28 deletions(-) delete mode 100644 pype/plugins/standalonepublisher/publish/collect_project_assets.py diff --git a/pype/plugins/standalonepublisher/publish/collect_matching_asset.py b/pype/plugins/standalonepublisher/publish/collect_matching_asset.py index 3575f581df..cd69eeefdc 100644 --- a/pype/plugins/standalonepublisher/publish/collect_matching_asset.py +++ b/pype/plugins/standalonepublisher/publish/collect_matching_asset.py @@ -1,5 +1,6 @@ import os import pyblish.api +from avalon import io from pprint import pformat @@ -15,12 +16,31 @@ class CollectMatchingAssetToInstance(pyblish.api.InstancePlugin): family = ["image"] def process(self, instance): - project_assets = instance.context.data["projectAssets"] source_file = os.path.basename(instance.data["source"]) - asset = next((project_assets[name] for name in project_assets - if name in source_file), None) + self.log.info("Looking for asset document for file \"{}\"".format( + instance.data["source"] + )) + project_assets = { + asset_doc["name"]: asset_doc + for asset_doc in io.find({"type": "asset"}) + } - if asset: - instance.data["asset"] = asset["name"] - instance.data["assetEntity"] = asset - self.log.info(f"Matching asset assigned: {pformat(asset)}") + matching_asset_doc = project_assets.get(source_file) + if matching_asset_doc is None: + for asset_doc in project_assets.values(): + if asset_doc["name"] in source_file: + matching_asset_doc = asset_doc + break + + if not matching_asset_doc: + # TODO better error message + raise AssertionError(( + "Filename does not contain any name of" + " asset documents in database." + )) + + instance.data["asset"] = matching_asset_doc["name"] + instance.data["assetEntity"] = matching_asset_doc + self.log.info( + f"Matching asset found: {pformat(matching_asset_doc)}" + ) diff --git a/pype/plugins/standalonepublisher/publish/collect_project_assets.py b/pype/plugins/standalonepublisher/publish/collect_project_assets.py deleted file mode 100644 index 1ca4144c81..0000000000 --- a/pype/plugins/standalonepublisher/publish/collect_project_assets.py +++ /dev/null @@ -1,21 +0,0 @@ -import pyblish.api -from avalon import io -from pprint import pformat - - -class CollectProjectAssets(pyblish.api.ContextPlugin): - """ - Collect all available project assets to context data. - """ - - label = "Collect Project Assets" - order = pyblish.api.CollectorOrder - 0.1 - hosts = ["standalonepublisher"] - - def process(self, context): - project_assets = { - asset_doc["name"]: asset_doc - for asset_doc in io.find({"type": "asset"}) - } - context.data["projectAssets"] = project_assets - self.log.debug(f"_ project_assets: {pformat(project_assets)}") From fa602cd2f5de83b10d11566432b4826cf5647c02 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 11 Aug 2020 18:24:56 +0200 Subject: [PATCH 07/42] skipped presets loading in collect standalone publisher context --- .../plugins/standalonepublisher/publish/collect_context.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/pype/plugins/standalonepublisher/publish/collect_context.py b/pype/plugins/standalonepublisher/publish/collect_context.py index f6d6df72b7..8e610364da 100644 --- a/pype/plugins/standalonepublisher/publish/collect_context.py +++ b/pype/plugins/standalonepublisher/publish/collect_context.py @@ -38,13 +38,6 @@ class CollectContextDataSAPublish(pyblish.api.ContextPlugin): # get json paths from os and load them io.install() - # Load presets - presets = context.data.get("presets") - if not presets: - from pype.api import config - - presets = config.get_presets() - # get json file context input_json_path = os.environ.get("SAPUBLISH_INPATH") From bc76f55df2b9a8145b93560a03a85959f5657e8c Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 11 Aug 2020 18:41:20 +0200 Subject: [PATCH 08/42] variable cleanup --- .../publish/collect_context.py | 23 ++++++++----------- .../publish/collect_psd_instances.py | 7 +++--- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/pype/plugins/standalonepublisher/publish/collect_context.py b/pype/plugins/standalonepublisher/publish/collect_context.py index 8e610364da..f0498cdde8 100644 --- a/pype/plugins/standalonepublisher/publish/collect_context.py +++ b/pype/plugins/standalonepublisher/publish/collect_context.py @@ -17,6 +17,7 @@ import os import pyblish.api from avalon import io import json +import copy import clique from pprint import pformat @@ -33,6 +34,7 @@ class CollectContextDataSAPublish(pyblish.api.ContextPlugin): # presets batch_extensions = ["edl", "xml", "psd"] + default_families = ["ftrack"] def process(self, context): # get json paths from os and load them @@ -45,12 +47,8 @@ class CollectContextDataSAPublish(pyblish.api.ContextPlugin): in_data = json.load(f) self.log.debug(f"_ in_data: {pformat(in_data)}") - self.asset_name = in_data["asset"] - self.family = in_data["family"] - self.families = ["ftrack"] - self.family_preset_key = in_data["family_preset_key"] # exception for editorial - if self.family_preset_key in ["editorial", "psd_batch"]: + if in_data["family_preset_key"] in ["editorial", "psd_batch"]: in_data_list = self.multiple_instances(context, in_data) else: in_data_list = [in_data] @@ -69,7 +67,7 @@ class CollectContextDataSAPublish(pyblish.api.ContextPlugin): in_data_list = list() representations = in_data.pop("representations") for repr in representations: - in_data_copy = in_data.copy() + in_data_copy = copy.deepcopy(in_data) ext = repr["ext"][1:] subset = in_data_copy["subset"] # filter out non editorial files @@ -87,15 +85,15 @@ class CollectContextDataSAPublish(pyblish.api.ContextPlugin): repr.pop(k) # convert files to list if it isnt - if not isinstance(files, list): + if not isinstance(files, (tuple, list)): files = [files] self.log.debug(f"_ files: {files}") for index, f in enumerate(files): index += 1 # copy dictionaries - in_data_copy = in_data_copy.copy() - repr_new = repr.copy() + in_data_copy = copy.deepcopy(in_data_copy) + repr_new = copy.deepcopy(repr) repr_new["files"] = f repr_new["name"] = ext @@ -118,14 +116,13 @@ class CollectContextDataSAPublish(pyblish.api.ContextPlugin): subset = in_data["subset"] instance = context.create_instance(subset) - instance.data.update( { "subset": subset, - "asset": self.asset_name, + "asset": in_data["asset"], "label": subset, "name": subset, - "family": self.family, + "family": in_data["family"], "version": in_data.get("version", 1), "frameStart": in_data.get("representations", [None])[0].get( "frameStart", None @@ -133,7 +130,7 @@ class CollectContextDataSAPublish(pyblish.api.ContextPlugin): "frameEnd": in_data.get("representations", [None])[0].get( "frameEnd", None ), - "families": self.families + [self.family_preset_key], + "families": self.default_families or [], } ) self.log.info("collected instance: {}".format(pformat(instance.data))) diff --git a/pype/plugins/standalonepublisher/publish/collect_psd_instances.py b/pype/plugins/standalonepublisher/publish/collect_psd_instances.py index 46471a5fdd..3a63230317 100644 --- a/pype/plugins/standalonepublisher/publish/collect_psd_instances.py +++ b/pype/plugins/standalonepublisher/publish/collect_psd_instances.py @@ -32,11 +32,11 @@ class CollectPsdInstances(pyblish.api.InstancePlugin): def process(self, instance): context = instance.context asset_data = instance.data["assetEntity"] - asset = instance.data["asset"] + asset_name = instance.data["asset"] anatomy_data = instance.data["anatomyData"] for subset_name, subset_data in self.subsets.items(): - instance_name = f"{asset}_{subset_name}" + instance_name = f"{asset_name}_{subset_name}" task = subset_data.get("task", "background") # create new instance @@ -47,8 +47,7 @@ class CollectPsdInstances(pyblish.api.InstancePlugin): # add subset data from preset new_instance.data.update(subset_data) - label = f"{instance_name}" - new_instance.data["label"] = label + new_instance.data["label"] = f"{instance_name}" new_instance.data["subset"] = subset_name new_instance.data["families"].append("image") From 302d4cee5bdfc6d2960126d2bc489c9138e87e71 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 11 Aug 2020 18:41:48 +0200 Subject: [PATCH 09/42] do not use `family_preset_key` for multiple_instances check --- pype/plugins/standalonepublisher/publish/collect_context.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/plugins/standalonepublisher/publish/collect_context.py b/pype/plugins/standalonepublisher/publish/collect_context.py index f0498cdde8..28cbe043ce 100644 --- a/pype/plugins/standalonepublisher/publish/collect_context.py +++ b/pype/plugins/standalonepublisher/publish/collect_context.py @@ -48,7 +48,7 @@ class CollectContextDataSAPublish(pyblish.api.ContextPlugin): self.log.debug(f"_ in_data: {pformat(in_data)}") # exception for editorial - if in_data["family_preset_key"] in ["editorial", "psd_batch"]: + if in_data["family"] in ["editorial", "psd_batch"]: in_data_list = self.multiple_instances(context, in_data) else: in_data_list = [in_data] From 9e3419424d5884298c977b326e353f9c78648f24 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 11 Aug 2020 19:04:31 +0200 Subject: [PATCH 10/42] version is updated and added few logs --- .../publish/extract_layout_images.py | 50 +++++++++++++++++-- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/pype/plugins/standalonepublisher/publish/extract_layout_images.py b/pype/plugins/standalonepublisher/publish/extract_layout_images.py index c3abf8d36f..48caa9562b 100644 --- a/pype/plugins/standalonepublisher/publish/extract_layout_images.py +++ b/pype/plugins/standalonepublisher/publish/extract_layout_images.py @@ -2,6 +2,7 @@ import os import copy import pype.api import pyblish.api +from avalon import io PSDImage = None @@ -14,6 +15,7 @@ class ExtractImageForLayout(pype.api.Extractor): hosts = ["standalonepublisher"] new_instance_family = "image" + ignored_instance_data_keys = ("name", "label", "stagingDir", "version") # Presetable allowed_group_names = ["OL", "BG", "MG", "FG", "UL", "SKY", "Field Guide"] @@ -51,6 +53,7 @@ class ExtractImageForLayout(pype.api.Extractor): instance.context.remove(instance) def create_new_instances(self, instance, psd_object): + asset_doc = instance.data["assetEntity"] for layer in psd_object: if ( not layer.is_visible() @@ -59,21 +62,37 @@ class ExtractImageForLayout(pype.api.Extractor): continue layer_name = layer.name.replace(" ", "_") - instance_name = f"image_{layer_name}" + instance_name = subset_name = f"image{layer_name}" + self.log.info( + f"Creating new instance with name \"{instance_name}\"" + ) new_instance = instance.context.create_instance(instance_name) for key, value in instance.data.items(): - if key not in ("name", "label", "stagingDir"): + if key not in self.ignored_instance_data_keys: new_instance.data[key] = copy.deepcopy(value) new_instance.data["label"] = " ".join( (new_instance.data["asset"], instance_name) ) - new_instance.data["subset"] = instance_name - new_instance.data["anatomyData"]["subset"] = instance_name + # Find latest version + version_number = self.find_latest_version(subset_name, asset_doc) + self.log.info( + "Next version of instance \"{}\" will be {}".format( + instance_name, version_number + ) + ) - # Set `family` + # Set family and subset new_instance.data["family"] = self.new_instance_family + new_instance.data["subset"] = subset_name + new_instance.data["version"] = version_number + + new_instance.data["anatomyData"].update({ + "subset": subset_name, + "family": self.new_instance_family, + "version": version_number + }) # Copy `families` and check if `family` is not in current families families = new_instance.data.get("families") or list() @@ -100,3 +119,24 @@ class ExtractImageForLayout(pype.api.Extractor): } new_instance.data["representations"] = [new_repre] self.log.debug(new_instance.data["name"]) + + def find_latest_version(self, subset_name, asset_doc): + subset_doc = io.find_one({ + "type": "subset", + "name": subset_name, + "parent": asset_doc["_id"] + }) + + if subset_doc is None: + self.log.debug("Subset entity does not exist yet.") + else: + version_doc = io.find_one( + { + "type": "version", + "parent": subset_doc["_id"] + }, + sort=[("name", -1)] + ) + if version_doc: + return int(version_doc["name"]) + 1 + return 1 From ac960623735c0c246f3eb6e8eaba890102a62d0d Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 11 Aug 2020 19:07:30 +0200 Subject: [PATCH 11/42] added initial version of extract images which only removes the instance ATM --- .../publish/extract_images_for_compositing.py | 136 ++++++++++++++++++ .../publish/extract_layout_images.py | 8 +- 2 files changed, 141 insertions(+), 3 deletions(-) create mode 100644 pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py diff --git a/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py b/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py new file mode 100644 index 0000000000..1693c86d54 --- /dev/null +++ b/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py @@ -0,0 +1,136 @@ +import os +import json +import pype.api + +PSDImage = None + + +class ExtractImagesForComp(pype.api.Extractor): + label = "Extract Images for Compositing" + families = ["imageForComp"] + hosts = ["standalonepublisher"] + + # Presetable + allowed_group_names = ["OL", "BG", "MG", "FG", "UL", "SKY", "Field Guide"] + + def process(self, instance): + instance.context.remove(instance) + self.log.info("NOT IMPLEMENTED YET") + return + + # Check if python module `psd_tools` is installed + try: + global PSDImage + from psd_tools import PSDImage + except Exception: + raise AssertionError( + "BUG: Python module `psd-tools` is not installed!" + ) + + repres = instance.data.get("representations") + if not repres: + self.log.info("There are no representations on instance.") + return + + for repre in tuple(repres): + # Skip all non files without .psd extension + if repre["ext"] != ".psd": + continue + + # Prepare staging dir + staging_dir = self.staging_dir(instance) + if not os.path.exists(staging_dir): + os.makedirs(staging_dir) + + # Prepare publish dir for transfers + publish_dir = instance.data["publishDir"] + + # Prepare json filepath where extracted metadata are stored + json_filename = "{}.json".format(instance.name) + json_full_path = os.path.join(staging_dir, json_filename) + + self.log.debug(f"`staging_dir` is \"{staging_dir}\"") + + # Prepare new repre data + new_repre = { + "name": "json", + "ext": "json", + "files": json_filename, + "stagingDir": staging_dir + } + + # TODO add check of list + psd_filename = repre["files"] + psd_folder_path = repre["stagingDir"] + psd_filepath = os.path.join(psd_folder_path, psd_filename) + self.log.debug(f"psd_filepath: \"{psd_filepath}\"") + psd_object = PSDImage.open(psd_filepath) + + json_data, transfers = self.export_compositing_images( + psd_object, staging_dir, publish_dir + ) + + with open(json_full_path, "w") as json_filestream: + json.dump(json_data, json_filestream, indent=4) + + instance.data["transfers"] = transfers + instance.data["representations"].append(new_repre) + instance.data["representations"].remove(repre) + + def export_compositing_images(self, psd_object, output_dir, publish_dir): + json_data = { + "__version__": 1, + "children_layers": [] + } + transfers = [] + for main_idx, main_layer in enumerate(psd_object): + if ( + not main_layer.is_visible() + or main_layer.name not in self.allowed_group_names + or not main_layer.is_group + ): + continue + + export_layers = [] + layers_idx = 0 + for layer in main_layer: + # TODO this way may be added also layers next to "ADJ" + if layer.name.lower() == "adj": + for _layer in layer: + export_layers.append((layers_idx, _layer)) + layers_idx += 1 + + else: + export_layers.append((layers_idx, layer)) + layers_idx += 1 + + if not export_layers: + continue + + main_layer_data = { + "index": main_idx, + "name": main_layer.name, + "children_layers": [] + } + + for layer_idx, layer in export_layers: + filename = "{:0>2}_{}_{:0>2}_{}.png".format( + main_idx + 1, main_layer.name, layer_idx + 1, layer.name + ) + layer_data = { + "index": layer_idx, + "name": layer.name, + "filename": filename + } + output_filepath = os.path.join(output_dir, filename) + dst_filepath = os.path.join(publish_dir, filename) + transfers.append((output_filepath, dst_filepath)) + + pil_object = layer.composite(viewport=psd_object.viewbox) + pil_object.save(output_filepath, "PNG") + + main_layer_data["children_layers"].append(layer_data) + + json_data["children_layers"].append(main_layer_data) + + return json_data, transfers diff --git a/pype/plugins/standalonepublisher/publish/extract_layout_images.py b/pype/plugins/standalonepublisher/publish/extract_layout_images.py index 48caa9562b..7209ec5c0e 100644 --- a/pype/plugins/standalonepublisher/publish/extract_layout_images.py +++ b/pype/plugins/standalonepublisher/publish/extract_layout_images.py @@ -36,11 +36,11 @@ class ExtractImageForLayout(pype.api.Extractor): return for repre in tuple(repres): - # Skip all non files without .psd extension + # Skip all files without .psd extension if repre["ext"] != ".psd": continue - # TODO add check of list + # TODO add check of list of "files" value psd_filename = repre["files"] psd_folder_path = repre["stagingDir"] psd_filepath = os.path.join(psd_folder_path, psd_filename) @@ -117,8 +117,10 @@ class ExtractImageForLayout(pype.api.Extractor): "files": output_filename, "stagingDir": staging_dir } + self.log.debug( + "Creating new representation: {}".format(new_repre) + ) new_instance.data["representations"] = [new_repre] - self.log.debug(new_instance.data["name"]) def find_latest_version(self, subset_name, asset_doc): subset_doc = io.find_one({ From 5c3159088684f5eef6eb028e94900e2014254b98 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 11 Aug 2020 19:25:20 +0200 Subject: [PATCH 12/42] moved back collect project assets plugin --- .../publish/collect_matching_asset.py | 5 +---- .../publish/collect_project_assets.py | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 pype/plugins/standalonepublisher/publish/collect_project_assets.py diff --git a/pype/plugins/standalonepublisher/publish/collect_matching_asset.py b/pype/plugins/standalonepublisher/publish/collect_matching_asset.py index cd69eeefdc..68f07c988d 100644 --- a/pype/plugins/standalonepublisher/publish/collect_matching_asset.py +++ b/pype/plugins/standalonepublisher/publish/collect_matching_asset.py @@ -20,11 +20,8 @@ class CollectMatchingAssetToInstance(pyblish.api.InstancePlugin): self.log.info("Looking for asset document for file \"{}\"".format( instance.data["source"] )) - project_assets = { - asset_doc["name"]: asset_doc - for asset_doc in io.find({"type": "asset"}) - } + project_assets = instance.context.data["projectAssets"] matching_asset_doc = project_assets.get(source_file) if matching_asset_doc is None: for asset_doc in project_assets.values(): diff --git a/pype/plugins/standalonepublisher/publish/collect_project_assets.py b/pype/plugins/standalonepublisher/publish/collect_project_assets.py new file mode 100644 index 0000000000..ced8772b5a --- /dev/null +++ b/pype/plugins/standalonepublisher/publish/collect_project_assets.py @@ -0,0 +1,21 @@ +import pyblish.api +from avalon import io +from pprint import pformat + + +class CollectProjectAssets(pyblish.api.ContextPlugin): + """ + Collect all available project assets to context data. + """ + + label = "Collect Project Assets" + order = pyblish.api.CollectorOrder - 0.1 + hosts = ["standalonepublisher"] + + def process(self, context): + project_assets = { + asset_doc["name"]: asset_doc + for asset_doc in io.find({"type": "asset"}) + } + context.data["projectAssets"] = project_assets + self.log.debug(f"Collected project_assets: {pformat(project_assets)}") From 5ae59c34d122e574977cb6c62444776cc4f7a5af Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 11 Aug 2020 19:25:36 +0200 Subject: [PATCH 13/42] collect project assets is only for "image" family --- .../standalonepublisher/publish/collect_project_assets.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pype/plugins/standalonepublisher/publish/collect_project_assets.py b/pype/plugins/standalonepublisher/publish/collect_project_assets.py index ced8772b5a..2bb4ca3f39 100644 --- a/pype/plugins/standalonepublisher/publish/collect_project_assets.py +++ b/pype/plugins/standalonepublisher/publish/collect_project_assets.py @@ -11,6 +11,7 @@ class CollectProjectAssets(pyblish.api.ContextPlugin): label = "Collect Project Assets" order = pyblish.api.CollectorOrder - 0.1 hosts = ["standalonepublisher"] + family = ["image"] def process(self, context): project_assets = { From 037ff552e2ef9f5c7e28a5886b2902f0c2895357 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 11 Aug 2020 19:27:13 +0200 Subject: [PATCH 14/42] collect matching assets will raise exception only if instance family is psd_batch --- .../publish/collect_matching_asset.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/pype/plugins/standalonepublisher/publish/collect_matching_asset.py b/pype/plugins/standalonepublisher/publish/collect_matching_asset.py index 68f07c988d..2c412c9271 100644 --- a/pype/plugins/standalonepublisher/publish/collect_matching_asset.py +++ b/pype/plugins/standalonepublisher/publish/collect_matching_asset.py @@ -29,15 +29,18 @@ class CollectMatchingAssetToInstance(pyblish.api.InstancePlugin): matching_asset_doc = asset_doc break - if not matching_asset_doc: + if matching_asset_doc: + instance.data["asset"] = matching_asset_doc["name"] + instance.data["assetEntity"] = matching_asset_doc + self.log.info( + f"Matching asset found: {pformat(matching_asset_doc)}" + ) + + # QUESTION exception was limited to "psd_batch" family since + # it is required for processing + elif instance.data["family"] == "psd_batch": # TODO better error message raise AssertionError(( "Filename does not contain any name of" " asset documents in database." )) - - instance.data["asset"] = matching_asset_doc["name"] - instance.data["assetEntity"] = matching_asset_doc - self.log.info( - f"Matching asset found: {pformat(matching_asset_doc)}" - ) From 3bcaeb8d074a7e66087237b61a1916d80624276f Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 12 Aug 2020 11:14:24 +0200 Subject: [PATCH 15/42] asset docs for matching asset are queried in the plugin and filtered by selected asset in standalone publisher --- .../publish/collect_matching_asset.py | 36 +++++++++++++++++++ .../publish/collect_project_assets.py | 22 ------------ 2 files changed, 36 insertions(+), 22 deletions(-) delete mode 100644 pype/plugins/standalonepublisher/publish/collect_project_assets.py diff --git a/pype/plugins/standalonepublisher/publish/collect_matching_asset.py b/pype/plugins/standalonepublisher/publish/collect_matching_asset.py index 2c412c9271..7a193d7087 100644 --- a/pype/plugins/standalonepublisher/publish/collect_matching_asset.py +++ b/pype/plugins/standalonepublisher/publish/collect_matching_asset.py @@ -44,3 +44,39 @@ class CollectMatchingAssetToInstance(pyblish.api.InstancePlugin): "Filename does not contain any name of" " asset documents in database." )) + + def selection_children_by_name(self, instance): + storing_key = "childrenDocsForSelection" + + children_docs = instance.context.data.get(storing_key) + if children_docs is None: + top_asset_doc = instance.context.data["assetEntity"] + assets_by_parent_id = self._asset_docs_by_parent_id(instance) + _children_docs = self._children_docs( + assets_by_parent_id, top_asset_doc + ) + children_docs = { + children_doc["name"].lower(): children_doc + for children_doc in _children_docs + } + instance.context.data[storing_key] = children_docs + return children_docs + + def _children_docs(self, documents_by_parent_id, parent_doc): + # Find all children in reverse order, last children is at first place. + output = [] + children = documents_by_parent_id.get(parent_doc["_id"]) or tuple() + for child in children: + output.extend( + self._children_docs(documents_by_parent_id, child) + ) + output.append(parent_doc) + return output + + def _asset_docs_by_parent_id(self, instance): + # Query all assets for project and store them by parent's id to list + asset_docs_by_parent_id = collections.defaultdict(list) + for asset_doc in io.find({"type": "asset"}): + parent_id = asset_doc["data"]["visualParent"] + asset_docs_by_parent_id[parent_id].append(asset_doc) + return asset_docs_by_parent_id diff --git a/pype/plugins/standalonepublisher/publish/collect_project_assets.py b/pype/plugins/standalonepublisher/publish/collect_project_assets.py deleted file mode 100644 index 2bb4ca3f39..0000000000 --- a/pype/plugins/standalonepublisher/publish/collect_project_assets.py +++ /dev/null @@ -1,22 +0,0 @@ -import pyblish.api -from avalon import io -from pprint import pformat - - -class CollectProjectAssets(pyblish.api.ContextPlugin): - """ - Collect all available project assets to context data. - """ - - label = "Collect Project Assets" - order = pyblish.api.CollectorOrder - 0.1 - hosts = ["standalonepublisher"] - family = ["image"] - - def process(self, context): - project_assets = { - asset_doc["name"]: asset_doc - for asset_doc in io.find({"type": "asset"}) - } - context.data["projectAssets"] = project_assets - self.log.debug(f"Collected project_assets: {pformat(project_assets)}") From 5ac4aa100abf1f1f85c637abcd3ee18fb9215094 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 12 Aug 2020 11:15:01 +0200 Subject: [PATCH 16/42] source file basename and asset names are lowered for match check --- .../publish/collect_matching_asset.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/pype/plugins/standalonepublisher/publish/collect_matching_asset.py b/pype/plugins/standalonepublisher/publish/collect_matching_asset.py index 7a193d7087..3f28b610e0 100644 --- a/pype/plugins/standalonepublisher/publish/collect_matching_asset.py +++ b/pype/plugins/standalonepublisher/publish/collect_matching_asset.py @@ -1,4 +1,5 @@ import os +import collections import pyblish.api from avalon import io from pprint import pformat @@ -16,16 +17,17 @@ class CollectMatchingAssetToInstance(pyblish.api.InstancePlugin): family = ["image"] def process(self, instance): - source_file = os.path.basename(instance.data["source"]) + source_file = os.path.basename(instance.data["source"]).lower() self.log.info("Looking for asset document for file \"{}\"".format( instance.data["source"] )) - project_assets = instance.context.data["projectAssets"] - matching_asset_doc = project_assets.get(source_file) + asset_docs_by_name = self.selection_children_by_name(instance) + + matching_asset_doc = asset_docs_by_name.get(source_file) if matching_asset_doc is None: - for asset_doc in project_assets.values(): - if asset_doc["name"] in source_file: + for asset_name_low, asset_doc in asset_docs_by_name.items(): + if asset_name_low in source_file: matching_asset_doc = asset_doc break @@ -41,9 +43,9 @@ class CollectMatchingAssetToInstance(pyblish.api.InstancePlugin): elif instance.data["family"] == "psd_batch": # TODO better error message raise AssertionError(( - "Filename does not contain any name of" - " asset documents in database." - )) + "Filename \"{}\" does not match" + " any name of asset documents in database for your selection." + ).format(instance.data["source"])) def selection_children_by_name(self, instance): storing_key = "childrenDocsForSelection" From b5cab8358faf18b280d7b9e2f671cb12d593f617 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 12 Aug 2020 12:18:01 +0200 Subject: [PATCH 17/42] extractor for compositing enhanced --- .../publish/extract_images_for_compositing.py | 55 ++++++++++++++++++- .../publish/extract_layout_images.py | 4 +- 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py b/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py index 1693c86d54..52293a8407 100644 --- a/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py +++ b/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py @@ -1,5 +1,6 @@ import os import json +import copy import pype.api PSDImage = None @@ -10,6 +11,8 @@ class ExtractImagesForComp(pype.api.Extractor): families = ["imageForComp"] hosts = ["standalonepublisher"] + new_instance_family = "image" + # Presetable allowed_group_names = ["OL", "BG", "MG", "FG", "UL", "SKY", "Field Guide"] @@ -27,11 +30,16 @@ class ExtractImagesForComp(pype.api.Extractor): "BUG: Python module `psd-tools` is not installed!" ) + self.redo_global_plugins(instance) + repres = instance.data.get("representations") if not repres: self.log.info("There are no representations on instance.") return + if not instance.data.get("transfers"): + instance.data["transfers"] = [] + for repre in tuple(repres): # Skip all non files without .psd extension if repre["ext"] != ".psd": @@ -73,7 +81,7 @@ class ExtractImagesForComp(pype.api.Extractor): with open(json_full_path, "w") as json_filestream: json.dump(json_data, json_filestream, indent=4) - instance.data["transfers"] = transfers + instance.data["transfers"].extend(transfers) instance.data["representations"].append(new_repre) instance.data["representations"].remove(repre) @@ -134,3 +142,48 @@ class ExtractImagesForComp(pype.api.Extractor): json_data["children_layers"].append(main_layer_data) return json_data, transfers + + def redo_global_plugins(self, instance): + # TODO do this in collection phase + # Copy `families` and check if `family` is not in current families + families = instance.data.get("families") or list() + if families: + families = list(set(families)) + + if self.new_instance_family in families: + families.remove(self.new_instance_family) + + self.log.debug( + "Setting new instance families {}".format(str(families)) + ) + instance.data["families"] = families + + # Override instance data with new information + instance.data["family"] = self.new_instance_family + + # Same data apply to anatomy data + instance.data["anatomyData"].update({ + "family": self.new_instance_family, + }) + + # Redo publish and resources dir + anatomy = instance.context.data["anatomy"] + template_data = copy.deepcopy(instance.data["anatomyData"]) + template_data.update({ + "frame": "FRAME_TEMP", + "representation": "TEMP" + }) + anatomy_filled = anatomy.format(template_data) + if "folder" in anatomy.templates["publish"]: + publish_folder = anatomy_filled["publish"]["folder"] + else: + publish_folder = os.path.dirname(anatomy_filled["publish"]["path"]) + + publish_folder = os.path.normpath(publish_folder) + resources_folder = os.path.join(publish_folder, "resources") + + instance.data["publishDir"] = publish_folder + instance.data["resourcesDir"] = resources_folder + + self.log.debug("publishDir: \"{}\"".format(publish_folder)) + self.log.debug("resourcesDir: \"{}\"".format(resources_folder)) diff --git a/pype/plugins/standalonepublisher/publish/extract_layout_images.py b/pype/plugins/standalonepublisher/publish/extract_layout_images.py index 7209ec5c0e..eb27a5a568 100644 --- a/pype/plugins/standalonepublisher/publish/extract_layout_images.py +++ b/pype/plugins/standalonepublisher/publish/extract_layout_images.py @@ -76,7 +76,7 @@ class ExtractImageForLayout(pype.api.Extractor): ) # Find latest version - version_number = self.find_latest_version(subset_name, asset_doc) + version_number = self.find_next_version(subset_name, asset_doc) self.log.info( "Next version of instance \"{}\" will be {}".format( instance_name, version_number @@ -122,7 +122,7 @@ class ExtractImageForLayout(pype.api.Extractor): ) new_instance.data["representations"] = [new_repre] - def find_latest_version(self, subset_name, asset_doc): + def find_next_version(self, subset_name, asset_doc): subset_doc = io.find_one({ "type": "subset", "name": subset_name, From 75efbd9a51e29a3b2f278f5fa477eb7dc1d65dac Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 12 Aug 2020 14:21:08 +0200 Subject: [PATCH 18/42] skip layers without content --- .../standalonepublisher/publish/extract_layout_images.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pype/plugins/standalonepublisher/publish/extract_layout_images.py b/pype/plugins/standalonepublisher/publish/extract_layout_images.py index eb27a5a568..95eaaaf967 100644 --- a/pype/plugins/standalonepublisher/publish/extract_layout_images.py +++ b/pype/plugins/standalonepublisher/publish/extract_layout_images.py @@ -61,6 +61,14 @@ class ExtractImageForLayout(pype.api.Extractor): ): continue + has_size = layer.width > 0 and layer.height > 0 + if not has_size: + self.log.debug(( + "Skipping layer \"{}\" because does " + "not have any content." + ).format(layer.name)) + continue + layer_name = layer.name.replace(" ", "_") instance_name = subset_name = f"image{layer_name}" self.log.info( From 46626de9731c6d3fa0e0874210f220a0207266ea Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 12 Aug 2020 14:28:29 +0200 Subject: [PATCH 19/42] set imageForComp subset to unchecked by sefault --- .../publish/collect_psd_instances.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/pype/plugins/standalonepublisher/publish/collect_psd_instances.py b/pype/plugins/standalonepublisher/publish/collect_psd_instances.py index 3a63230317..f908012fdc 100644 --- a/pype/plugins/standalonepublisher/publish/collect_psd_instances.py +++ b/pype/plugins/standalonepublisher/publish/collect_psd_instances.py @@ -26,8 +26,9 @@ class CollectPsdInstances(pyblish.api.InstancePlugin): "workfileBackground": { "task": "background", "family": "workfile" - }, + } } + unchecked_by_default = ["imageForComp"] def process(self, instance): context = instance.context @@ -41,6 +42,7 @@ class CollectPsdInstances(pyblish.api.InstancePlugin): # create new instance new_instance = context.create_instance(instance_name) + # add original instance data except name key new_instance.data.update({k: v for k, v in instance.data.items() if k not in "name"}) @@ -61,11 +63,11 @@ class CollectPsdInstances(pyblish.api.InstancePlugin): }) new_instance.data["anatomyData"] = anatomy_data_new - inst_data = new_instance.data - self.log.debug( - f"_ inst_data: {pformat(inst_data)}") + if subset_name in self.unchecked_by_default: + new_instance.data["publish"] = False self.log.info(f"Created new instance: {instance_name}") + self.log.debug(f"_ inst_data: {pformat(new_instance.data)}") # delete original instance context.remove(instance) From cef7e87b01248ee95af42fb4937ecd0fb30db78b Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 12 Aug 2020 14:44:15 +0200 Subject: [PATCH 20/42] fix hierarchy for psd --- .../plugins/global/publish/collect_anatomy_instance_data.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pype/plugins/global/publish/collect_anatomy_instance_data.py b/pype/plugins/global/publish/collect_anatomy_instance_data.py index 6528bede2e..806c71eb5f 100644 --- a/pype/plugins/global/publish/collect_anatomy_instance_data.py +++ b/pype/plugins/global/publish/collect_anatomy_instance_data.py @@ -92,6 +92,12 @@ class CollectAnatomyInstanceData(pyblish.api.InstancePlugin): "subset": subset_name, "version": version_number } + if ( + asset_entity + and asset_entity["_id"] != context_asset_entity["_id"] + ): + parents = asset_entity["data"].get("parents") or list() + anatomy_updates["hierarchy"] = "/".join(parents) task_name = instance.data.get("task") if task_name: From c53847d0fad57ca557361dd49b61fe554a453075 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 12 Aug 2020 14:48:32 +0200 Subject: [PATCH 21/42] add check for instance assetEntity --- .../global/publish/collect_anatomy_instance_data.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/pype/plugins/global/publish/collect_anatomy_instance_data.py b/pype/plugins/global/publish/collect_anatomy_instance_data.py index 806c71eb5f..44a4d43946 100644 --- a/pype/plugins/global/publish/collect_anatomy_instance_data.py +++ b/pype/plugins/global/publish/collect_anatomy_instance_data.py @@ -39,11 +39,21 @@ class CollectAnatomyInstanceData(pyblish.api.InstancePlugin): anatomy_data = copy.deepcopy(instance.context.data["anatomyData"]) project_entity = instance.context.data["projectEntity"] context_asset_entity = instance.context.data["assetEntity"] + instance_asset_entity = instance.data.get("assetEntity") asset_name = instance.data["asset"] + + # There is possibility that assetEntity on instance is already set + # which can happen in standalone publisher + if ( + instance_asset_entity + and instance_asset_entity["name"] == asset_name + ): + asset_entity = instance_asset_entity + # Check if asset name is the same as what is in context # - they may be different, e.g. in NukeStudio - if context_asset_entity["name"] == asset_name: + elif context_asset_entity["name"] == asset_name: asset_entity = context_asset_entity else: From b5a27e11210a317eaa0ee089d899b6c761a926fe Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 12 Aug 2020 15:09:24 +0200 Subject: [PATCH 22/42] fixed version for extract images for compositing --- .../publish/extract_images_for_compositing.py | 38 ++++++++++++++++++- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py b/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py index 52293a8407..c293783a53 100644 --- a/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py +++ b/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py @@ -2,6 +2,7 @@ import os import json import copy import pype.api +from avalon import io PSDImage = None @@ -77,13 +78,13 @@ class ExtractImagesForComp(pype.api.Extractor): json_data, transfers = self.export_compositing_images( psd_object, staging_dir, publish_dir ) - + self.log.info("Json file path: {}".format(json_full_path)) with open(json_full_path, "w") as json_filestream: json.dump(json_data, json_filestream, indent=4) instance.data["transfers"].extend(transfers) - instance.data["representations"].append(new_repre) instance.data["representations"].remove(repre) + instance.data["representations"].append(new_repre) def export_compositing_images(self, psd_object, output_dir, publish_dir): json_data = { @@ -161,9 +162,21 @@ class ExtractImagesForComp(pype.api.Extractor): # Override instance data with new information instance.data["family"] = self.new_instance_family + subset_name = instance.data["anatomyData"]["subset"] + asset_doc = instance.data["assetEntity"] + latest_version = self.find_last_version(subset_name, asset_doc) + if latest_version is None: + latest_version = 1 + else: + version_number = latest_version + 1 + + instance.data["latestVersion"] = latest_version + instance.data["version"] = version_number + # Same data apply to anatomy data instance.data["anatomyData"].update({ "family": self.new_instance_family, + "version": version_number }) # Redo publish and resources dir @@ -187,3 +200,24 @@ class ExtractImagesForComp(pype.api.Extractor): self.log.debug("publishDir: \"{}\"".format(publish_folder)) self.log.debug("resourcesDir: \"{}\"".format(resources_folder)) + + def find_last_version(self, subset_name, asset_doc): + subset_doc = io.find_one({ + "type": "subset", + "name": subset_name, + "parent": asset_doc["_id"] + }) + + if subset_doc is None: + self.log.debug("Subset entity does not exist yet.") + else: + version_doc = io.find_one( + { + "type": "version", + "parent": subset_doc["_id"] + }, + sort=[("name", -1)] + ) + if version_doc: + return int(version_doc["name"]) + return None From 8beda6e35358945ff51c977231f3e0b8b331b836 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 12 Aug 2020 15:14:08 +0200 Subject: [PATCH 23/42] fixed latest version for extract layout --- .../publish/extract_images_for_compositing.py | 7 +++---- .../publish/extract_layout_images.py | 13 +++++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py b/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py index c293783a53..a347620be9 100644 --- a/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py +++ b/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py @@ -165,10 +165,9 @@ class ExtractImagesForComp(pype.api.Extractor): subset_name = instance.data["anatomyData"]["subset"] asset_doc = instance.data["assetEntity"] latest_version = self.find_last_version(subset_name, asset_doc) - if latest_version is None: - latest_version = 1 - else: - version_number = latest_version + 1 + version_number = 1 + if latest_version is not None: + version_number += latest_version instance.data["latestVersion"] = latest_version instance.data["version"] = version_number diff --git a/pype/plugins/standalonepublisher/publish/extract_layout_images.py b/pype/plugins/standalonepublisher/publish/extract_layout_images.py index 95eaaaf967..a69a08f0d8 100644 --- a/pype/plugins/standalonepublisher/publish/extract_layout_images.py +++ b/pype/plugins/standalonepublisher/publish/extract_layout_images.py @@ -84,7 +84,11 @@ class ExtractImageForLayout(pype.api.Extractor): ) # Find latest version - version_number = self.find_next_version(subset_name, asset_doc) + latest_version = self.find_last_version(subset_name, asset_doc) + version_number = 1 + if latest_version is not None: + version_number += latest_version + self.log.info( "Next version of instance \"{}\" will be {}".format( instance_name, version_number @@ -95,6 +99,7 @@ class ExtractImageForLayout(pype.api.Extractor): new_instance.data["family"] = self.new_instance_family new_instance.data["subset"] = subset_name new_instance.data["version"] = version_number + new_instance.data["latestVersion"] = latest_version new_instance.data["anatomyData"].update({ "subset": subset_name, @@ -130,7 +135,7 @@ class ExtractImageForLayout(pype.api.Extractor): ) new_instance.data["representations"] = [new_repre] - def find_next_version(self, subset_name, asset_doc): + def find_last_version(self, subset_name, asset_doc): subset_doc = io.find_one({ "type": "subset", "name": subset_name, @@ -148,5 +153,5 @@ class ExtractImageForLayout(pype.api.Extractor): sort=[("name", -1)] ) if version_doc: - return int(version_doc["name"]) + 1 - return 1 + return int(version_doc["name"]) + return None From ba73ba7b6cd5aa86d094e51edf13df1e6bafab75 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 12 Aug 2020 15:22:13 +0200 Subject: [PATCH 24/42] renamed `children_layers` key to `children` --- .../publish/extract_images_for_compositing.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py b/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py index a347620be9..47d21a1af0 100644 --- a/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py +++ b/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py @@ -89,7 +89,7 @@ class ExtractImagesForComp(pype.api.Extractor): def export_compositing_images(self, psd_object, output_dir, publish_dir): json_data = { "__version__": 1, - "children_layers": [] + "children": [] } transfers = [] for main_idx, main_layer in enumerate(psd_object): @@ -119,7 +119,7 @@ class ExtractImagesForComp(pype.api.Extractor): main_layer_data = { "index": main_idx, "name": main_layer.name, - "children_layers": [] + "children": [] } for layer_idx, layer in export_layers: @@ -138,9 +138,9 @@ class ExtractImagesForComp(pype.api.Extractor): pil_object = layer.composite(viewport=psd_object.viewbox) pil_object.save(output_filepath, "PNG") - main_layer_data["children_layers"].append(layer_data) + main_layer_data["children"].append(layer_data) - json_data["children_layers"].append(main_layer_data) + json_data["children"].append(main_layer_data) return json_data, transfers From aed3f4059e7f73a0bb5dfb802105a85cf9e7e106 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 12 Aug 2020 15:41:17 +0200 Subject: [PATCH 25/42] make sure new instances does not share object values --- .../standalonepublisher/publish/collect_psd_instances.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pype/plugins/standalonepublisher/publish/collect_psd_instances.py b/pype/plugins/standalonepublisher/publish/collect_psd_instances.py index f908012fdc..9369822df2 100644 --- a/pype/plugins/standalonepublisher/publish/collect_psd_instances.py +++ b/pype/plugins/standalonepublisher/publish/collect_psd_instances.py @@ -44,8 +44,12 @@ class CollectPsdInstances(pyblish.api.InstancePlugin): new_instance = context.create_instance(instance_name) # add original instance data except name key - new_instance.data.update({k: v for k, v in instance.data.items() - if k not in "name"}) + for key, value in instance.data.items(): + if key not in ["name"]: + # Make sure value is copy since value may be object which + # can be shared across all new created objects + new_instance.data[key] = copy.deepcopy(value) + # add subset data from preset new_instance.data.update(subset_data) From e27f4b74349abec0394a0f003cac3508fd2b67c8 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 12 Aug 2020 15:44:55 +0200 Subject: [PATCH 26/42] make extor for compositing available --- .../standalonepublisher/publish/collect_psd_instances.py | 2 +- .../publish/extract_images_for_compositing.py | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/pype/plugins/standalonepublisher/publish/collect_psd_instances.py b/pype/plugins/standalonepublisher/publish/collect_psd_instances.py index 9369822df2..f7ea30e810 100644 --- a/pype/plugins/standalonepublisher/publish/collect_psd_instances.py +++ b/pype/plugins/standalonepublisher/publish/collect_psd_instances.py @@ -28,7 +28,7 @@ class CollectPsdInstances(pyblish.api.InstancePlugin): "family": "workfile" } } - unchecked_by_default = ["imageForComp"] + unchecked_by_default = [] def process(self, instance): context = instance.context diff --git a/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py b/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py index 47d21a1af0..87d6aa13cb 100644 --- a/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py +++ b/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py @@ -18,10 +18,6 @@ class ExtractImagesForComp(pype.api.Extractor): allowed_group_names = ["OL", "BG", "MG", "FG", "UL", "SKY", "Field Guide"] def process(self, instance): - instance.context.remove(instance) - self.log.info("NOT IMPLEMENTED YET") - return - # Check if python module `psd_tools` is installed try: global PSDImage From 86f51125fbec6d5bb040c32e739c3cae2d275f1b Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 12 Aug 2020 16:08:08 +0200 Subject: [PATCH 27/42] changed key __version__ in compositing json to __schema_version__ --- .../publish/extract_images_for_compositing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py b/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py index 87d6aa13cb..46787e3ad1 100644 --- a/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py +++ b/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py @@ -84,7 +84,7 @@ class ExtractImagesForComp(pype.api.Extractor): def export_compositing_images(self, psd_object, output_dir, publish_dir): json_data = { - "__version__": 1, + "__schema_version__": 1, "children": [] } transfers = [] From b68a9c2542f7ebaf89ec254165955ff994ebd3ff Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 12 Aug 2020 16:50:03 +0200 Subject: [PATCH 28/42] fix qcss bug --- pype/modules/standalonepublish/widgets/widget_drop_empty.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pype/modules/standalonepublish/widgets/widget_drop_empty.py b/pype/modules/standalonepublish/widgets/widget_drop_empty.py index a68b91da59..d352e70355 100644 --- a/pype/modules/standalonepublish/widgets/widget_drop_empty.py +++ b/pype/modules/standalonepublish/widgets/widget_drop_empty.py @@ -25,14 +25,14 @@ class DropEmpty(QtWidgets.QWidget): self._label = QtWidgets.QLabel('Drag & Drop') self._label.setFont(font) self._label.setStyleSheet( - 'background-color: rgb(255, 255, 255, 0);' + 'background-color: transparent;' ) font.setPointSize(12) self._sub_label = QtWidgets.QLabel('(drop files here)') self._sub_label.setFont(font) self._sub_label.setStyleSheet( - 'background-color: rgb(255, 255, 255, 0);' + 'background-color: transparent;' ) layout.addWidget(self._label, alignment=BottomCenterAlignment) From c8afe556b7df351754217d929433ea574965d597 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 12 Aug 2020 17:05:38 +0200 Subject: [PATCH 29/42] added more groups and made are not case sensitive now --- .../publish/extract_images_for_compositing.py | 12 ++++++++++-- .../publish/extract_layout_images.py | 11 +++++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py b/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py index 46787e3ad1..48e09d4b93 100644 --- a/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py +++ b/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py @@ -15,7 +15,10 @@ class ExtractImagesForComp(pype.api.Extractor): new_instance_family = "image" # Presetable - allowed_group_names = ["OL", "BG", "MG", "FG", "UL", "SKY", "Field Guide"] + allowed_group_names = [ + "OL", "BG", "MG", "FG", "UL", "SKY", "Field Guide", "Field_Guide", + "ANIM" + ] def process(self, instance): # Check if python module `psd_tools` is installed @@ -27,6 +30,11 @@ class ExtractImagesForComp(pype.api.Extractor): "BUG: Python module `psd-tools` is not installed!" ) + self.allowed_group_names = [ + name.lower() + for name in self.allowed_group_names + ] + self.redo_global_plugins(instance) repres = instance.data.get("representations") @@ -91,7 +99,7 @@ class ExtractImagesForComp(pype.api.Extractor): for main_idx, main_layer in enumerate(psd_object): if ( not main_layer.is_visible() - or main_layer.name not in self.allowed_group_names + or main_layer.name.lower() not in self.allowed_group_names or not main_layer.is_group ): continue diff --git a/pype/plugins/standalonepublisher/publish/extract_layout_images.py b/pype/plugins/standalonepublisher/publish/extract_layout_images.py index a69a08f0d8..d5359ca22e 100644 --- a/pype/plugins/standalonepublisher/publish/extract_layout_images.py +++ b/pype/plugins/standalonepublisher/publish/extract_layout_images.py @@ -18,7 +18,10 @@ class ExtractImageForLayout(pype.api.Extractor): ignored_instance_data_keys = ("name", "label", "stagingDir", "version") # Presetable - allowed_group_names = ["OL", "BG", "MG", "FG", "UL", "SKY", "Field Guide"] + allowed_group_names = [ + "OL", "BG", "MG", "FG", "UL", "SKY", "Field Guide", "Field_Guide", + "ANIM" + ] def process(self, instance): # Check if python module `psd_tools` is installed @@ -30,6 +33,10 @@ class ExtractImageForLayout(pype.api.Extractor): "BUG: Python module `psd-tools` is not installed!" ) + self.allowed_group_names = [ + name.lower() + for name in self.allowed_group_names + ] repres = instance.data.get("representations") if not repres: self.log.info("There are no representations on instance.") @@ -57,7 +64,7 @@ class ExtractImageForLayout(pype.api.Extractor): for layer in psd_object: if ( not layer.is_visible() - or layer.name not in self.allowed_group_names + or layer.name.lower() not in self.allowed_group_names ): continue From d7031c616e6a7126fe317da71ba1c9929dadca9b Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 12 Aug 2020 17:15:47 +0200 Subject: [PATCH 30/42] renamed `ExtractImagesForComp` to `ExtractBGForComp` and used `background` family instead of `image` --- .../publish/extract_images_for_compositing.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py b/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py index 48e09d4b93..7304a17319 100644 --- a/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py +++ b/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py @@ -7,12 +7,12 @@ from avalon import io PSDImage = None -class ExtractImagesForComp(pype.api.Extractor): - label = "Extract Images for Compositing" +class ExtractBGForComp(pype.api.Extractor): + label = "Extract Background for Compositing" families = ["imageForComp"] hosts = ["standalonepublisher"] - new_instance_family = "image" + new_instance_family = "background" # Presetable allowed_group_names = [ From 7e13ef31d8646f1071f46c8a20057d74944290dd Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 12 Aug 2020 17:16:26 +0200 Subject: [PATCH 31/42] renamed publish filename --- ...ct_images_for_compositing.py => extract_bg_for_compositing.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename pype/plugins/standalonepublisher/publish/{extract_images_for_compositing.py => extract_bg_for_compositing.py} (100%) diff --git a/pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py b/pype/plugins/standalonepublisher/publish/extract_bg_for_compositing.py similarity index 100% rename from pype/plugins/standalonepublisher/publish/extract_images_for_compositing.py rename to pype/plugins/standalonepublisher/publish/extract_bg_for_compositing.py From 9fbac5f8ff43b9680d7a1c7b91a76d276c25315a Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 12 Aug 2020 17:20:43 +0200 Subject: [PATCH 32/42] renamed extract layout images to extract images from psd and disabled it --- ...xtract_layout_images.py => extract_images_from_psd.py} | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) rename pype/plugins/standalonepublisher/publish/{extract_layout_images.py => extract_images_from_psd.py} (96%) diff --git a/pype/plugins/standalonepublisher/publish/extract_layout_images.py b/pype/plugins/standalonepublisher/publish/extract_images_from_psd.py similarity index 96% rename from pype/plugins/standalonepublisher/publish/extract_layout_images.py rename to pype/plugins/standalonepublisher/publish/extract_images_from_psd.py index d5359ca22e..2ac6001755 100644 --- a/pype/plugins/standalonepublisher/publish/extract_layout_images.py +++ b/pype/plugins/standalonepublisher/publish/extract_images_from_psd.py @@ -7,16 +7,18 @@ from avalon import io PSDImage = None -class ExtractImageForLayout(pype.api.Extractor): +class ExtractImagesFromPSD(pype.api.Extractor): + # PLUGIN is not currently enabled because was decided to use different + # approach + enabled = False - label = "Extract Images for Layout" + label = "Extract Images from PSD" order = pyblish.api.ExtractorOrder + 0.02 families = ["imageForLayout"] hosts = ["standalonepublisher"] new_instance_family = "image" ignored_instance_data_keys = ("name", "label", "stagingDir", "version") - # Presetable allowed_group_names = [ "OL", "BG", "MG", "FG", "UL", "SKY", "Field Guide", "Field_Guide", From 3d44b1cd10d5c8215215d86d56678f76636bbea1 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 12 Aug 2020 17:25:39 +0200 Subject: [PATCH 33/42] created copy of previous plugin for layout exporting --- .../publish/extract_bg_main_groups.py | 163 ++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 pype/plugins/standalonepublisher/publish/extract_bg_main_groups.py diff --git a/pype/plugins/standalonepublisher/publish/extract_bg_main_groups.py b/pype/plugins/standalonepublisher/publish/extract_bg_main_groups.py new file mode 100644 index 0000000000..fe4a2e360c --- /dev/null +++ b/pype/plugins/standalonepublisher/publish/extract_bg_main_groups.py @@ -0,0 +1,163 @@ +import os +import copy +import pype.api +import pyblish.api +from avalon import io + +PSDImage = None + + +class ExtractBGMainGroups(pype.api.Extractor): + + label = "Extract Background Main Groups" + order = pyblish.api.ExtractorOrder + 0.02 + families = ["imageForLayout"] + hosts = ["standalonepublisher"] + + new_instance_family = "background" + + # Presetable + allowed_group_names = [ + "OL", "BG", "MG", "FG", "UL", "SKY", "Field Guide", "Field_Guide", + "ANIM" + ] + + def process(self, instance): + # Check if python module `psd_tools` is installed + try: + global PSDImage + from psd_tools import PSDImage + except Exception: + raise AssertionError( + "BUG: Python module `psd-tools` is not installed!" + ) + + self.allowed_group_names = [ + name.lower() + for name in self.allowed_group_names + ] + repres = instance.data.get("representations") + if not repres: + self.log.info("There are no representations on instance.") + return + + for repre in tuple(repres): + # Skip all files without .psd extension + if repre["ext"] != ".psd": + continue + + # TODO add check of list of "files" value + psd_filename = repre["files"] + psd_folder_path = repre["stagingDir"] + psd_filepath = os.path.join(psd_folder_path, psd_filename) + self.log.debug(f"psd_filepath: \"{psd_filepath}\"") + psd_object = PSDImage.open(psd_filepath) + + self.create_new_instances(instance, psd_object) + + # Remove the instance from context + instance.context.remove(instance) + + def create_new_instances(self, instance, psd_object): + asset_doc = instance.data["assetEntity"] + for layer in psd_object: + if ( + not layer.is_visible() + or layer.name.lower() not in self.allowed_group_names + ): + continue + + has_size = layer.width > 0 and layer.height > 0 + if not has_size: + self.log.debug(( + "Skipping layer \"{}\" because does " + "not have any content." + ).format(layer.name)) + continue + + layer_name = layer.name.replace(" ", "_") + instance_name = subset_name = f"image{layer_name}" + self.log.info( + f"Creating new instance with name \"{instance_name}\"" + ) + new_instance = instance.context.create_instance(instance_name) + for key, value in instance.data.items(): + if key not in self.ignored_instance_data_keys: + new_instance.data[key] = copy.deepcopy(value) + + new_instance.data["label"] = " ".join( + (new_instance.data["asset"], instance_name) + ) + + # Find latest version + latest_version = self.find_last_version(subset_name, asset_doc) + version_number = 1 + if latest_version is not None: + version_number += latest_version + + self.log.info( + "Next version of instance \"{}\" will be {}".format( + instance_name, version_number + ) + ) + + # Set family and subset + new_instance.data["family"] = self.new_instance_family + new_instance.data["subset"] = subset_name + new_instance.data["version"] = version_number + new_instance.data["latestVersion"] = latest_version + + new_instance.data["anatomyData"].update({ + "subset": subset_name, + "family": self.new_instance_family, + "version": version_number + }) + + # Copy `families` and check if `family` is not in current families + families = new_instance.data.get("families") or list() + if families: + families = list(set(families)) + + if self.new_instance_family in families: + families.remove(self.new_instance_family) + new_instance.data["families"] = families + + # Prepare staging dir for new instance + staging_dir = self.staging_dir(new_instance) + + output_filename = "{}.png".format(layer_name) + output_filepath = os.path.join(staging_dir, output_filename) + pil_object = layer.composite(viewport=psd_object.viewbox) + pil_object.save(output_filepath, "PNG") + + new_repre = { + "name": "png", + "ext": "png", + "files": output_filename, + "stagingDir": staging_dir + } + self.log.debug( + "Creating new representation: {}".format(new_repre) + ) + new_instance.data["representations"] = [new_repre] + + def find_last_version(self, subset_name, asset_doc): + subset_doc = io.find_one({ + "type": "subset", + "name": subset_name, + "parent": asset_doc["_id"] + }) + + if subset_doc is None: + self.log.debug("Subset entity does not exist yet.") + else: + version_doc = io.find_one( + { + "type": "version", + "parent": subset_doc["_id"] + }, + sort=[("name", -1)] + ) + if version_doc: + return int(version_doc["name"]) + return None From 544f59db7f2d80a17e006d57cb845da3578382c8 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 12 Aug 2020 17:39:42 +0200 Subject: [PATCH 34/42] added checks for layers exporting --- .../publish/extract_bg_for_compositing.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/pype/plugins/standalonepublisher/publish/extract_bg_for_compositing.py b/pype/plugins/standalonepublisher/publish/extract_bg_for_compositing.py index 7304a17319..889a3cead2 100644 --- a/pype/plugins/standalonepublisher/publish/extract_bg_for_compositing.py +++ b/pype/plugins/standalonepublisher/publish/extract_bg_for_compositing.py @@ -127,6 +127,14 @@ class ExtractBGForComp(pype.api.Extractor): } for layer_idx, layer in export_layers: + has_size = layer.width > 0 and layer.height > 0 + if not has_size: + self.log.debug(( + "Skipping layer \"{}\" because does " + "not have any content." + ).format(layer.name)) + continue + filename = "{:0>2}_{}_{:0>2}_{}.png".format( main_idx + 1, main_layer.name, layer_idx + 1, layer.name ) @@ -144,7 +152,8 @@ class ExtractBGForComp(pype.api.Extractor): main_layer_data["children"].append(layer_data) - json_data["children"].append(main_layer_data) + if main_layer_data["children"]: + json_data["children"].append(main_layer_data) return json_data, transfers From 69bae8f2ae1094b11f08a4de9330b3f9975c81cc Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 12 Aug 2020 17:40:05 +0200 Subject: [PATCH 35/42] replace spaces with underscore in layer names for output filename --- .../publish/extract_bg_for_compositing.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pype/plugins/standalonepublisher/publish/extract_bg_for_compositing.py b/pype/plugins/standalonepublisher/publish/extract_bg_for_compositing.py index 889a3cead2..43d4a91964 100644 --- a/pype/plugins/standalonepublisher/publish/extract_bg_for_compositing.py +++ b/pype/plugins/standalonepublisher/publish/extract_bg_for_compositing.py @@ -135,8 +135,11 @@ class ExtractBGForComp(pype.api.Extractor): ).format(layer.name)) continue + main_layer_name = main_layer.name.replace(" ", "_") + layer_name = layer.name.replace(" ", "_") + filename = "{:0>2}_{}_{:0>2}_{}.png".format( - main_idx + 1, main_layer.name, layer_idx + 1, layer.name + main_idx + 1, main_layer_name, layer_idx + 1, layer_name ) layer_data = { "index": layer_idx, From f37da8d9314e6dc103f29f9135b6c7d179e7d577 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 12 Aug 2020 17:41:28 +0200 Subject: [PATCH 36/42] modified extract bg main groups to have similir output to extract bg for compositing --- .../publish/extract_bg_for_compositing.py | 2 +- .../publish/extract_bg_main_groups.py | 192 +++++++++++------- 2 files changed, 122 insertions(+), 72 deletions(-) diff --git a/pype/plugins/standalonepublisher/publish/extract_bg_for_compositing.py b/pype/plugins/standalonepublisher/publish/extract_bg_for_compositing.py index 43d4a91964..0c0eee7f83 100644 --- a/pype/plugins/standalonepublisher/publish/extract_bg_for_compositing.py +++ b/pype/plugins/standalonepublisher/publish/extract_bg_for_compositing.py @@ -46,7 +46,7 @@ class ExtractBGForComp(pype.api.Extractor): instance.data["transfers"] = [] for repre in tuple(repres): - # Skip all non files without .psd extension + # Skip all files without .psd extension if repre["ext"] != ".psd": continue diff --git a/pype/plugins/standalonepublisher/publish/extract_bg_main_groups.py b/pype/plugins/standalonepublisher/publish/extract_bg_main_groups.py index fe4a2e360c..4920a92ba9 100644 --- a/pype/plugins/standalonepublisher/publish/extract_bg_main_groups.py +++ b/pype/plugins/standalonepublisher/publish/extract_bg_main_groups.py @@ -1,5 +1,6 @@ import os import copy +import json import pype.api import pyblish.api from avalon import io @@ -8,7 +9,6 @@ PSDImage = None class ExtractBGMainGroups(pype.api.Extractor): - label = "Extract Background Main Groups" order = pyblish.api.ExtractorOrder + 0.02 families = ["imageForLayout"] @@ -41,105 +41,155 @@ class ExtractBGMainGroups(pype.api.Extractor): self.log.info("There are no representations on instance.") return + self.redo_global_plugins(instance) + + repres = instance.data.get("representations") + if not repres: + self.log.info("There are no representations on instance.") + return + + if not instance.data.get("transfers"): + instance.data["transfers"] = [] + for repre in tuple(repres): # Skip all files without .psd extension if repre["ext"] != ".psd": continue - # TODO add check of list of "files" value + # Prepare staging dir + staging_dir = self.staging_dir(instance) + if not os.path.exists(staging_dir): + os.makedirs(staging_dir) + + # Prepare publish dir for transfers + publish_dir = instance.data["publishDir"] + + # Prepare json filepath where extracted metadata are stored + json_filename = "{}.json".format(instance.name) + json_full_path = os.path.join(staging_dir, json_filename) + + self.log.debug(f"`staging_dir` is \"{staging_dir}\"") + + # Prepare new repre data + new_repre = { + "name": "json", + "ext": "json", + "files": json_filename, + "stagingDir": staging_dir + } + + # TODO add check of list psd_filename = repre["files"] psd_folder_path = repre["stagingDir"] psd_filepath = os.path.join(psd_folder_path, psd_filename) self.log.debug(f"psd_filepath: \"{psd_filepath}\"") psd_object = PSDImage.open(psd_filepath) - self.create_new_instances(instance, psd_object) + json_data, transfers = self.export_compositing_images( + psd_object, staging_dir, publish_dir + ) + self.log.info("Json file path: {}".format(json_full_path)) + with open(json_full_path, "w") as json_filestream: + json.dump(json_data, json_filestream, indent=4) - # Remove the instance from context - instance.context.remove(instance) + instance.data["transfers"].extend(transfers) + instance.data["representations"].remove(repre) + instance.data["representations"].append(new_repre) - def create_new_instances(self, instance, psd_object): - asset_doc = instance.data["assetEntity"] - for layer in psd_object: + def export_compositing_images(self, psd_object, output_dir, publish_dir): + json_data = { + "__schema_version__": 1, + "children": [] + } + transfers = [] + for layer_idx, layer in enumerate(psd_object): + layer_name = layer.name.replace(" ", "_") if ( not layer.is_visible() - or layer.name.lower() not in self.allowed_group_names + or layer_name.lower() not in self.allowed_group_names ): continue has_size = layer.width > 0 and layer.height > 0 if not has_size: self.log.debug(( - "Skipping layer \"{}\" because does " - "not have any content." + "Skipping layer \"{}\" because does not have any content." ).format(layer.name)) continue - layer_name = layer.name.replace(" ", "_") - instance_name = subset_name = f"image{layer_name}" - self.log.info( - f"Creating new instance with name \"{instance_name}\"" - ) - new_instance = instance.context.create_instance(instance_name) - for key, value in instance.data.items(): - if key not in self.ignored_instance_data_keys: - new_instance.data[key] = copy.deepcopy(value) + filename = "{}.png".format(layer_name) + layer_data = { + "index": layer_idx, + "name": layer.name, + "filename": filename + } - new_instance.data["label"] = " ".join( - (new_instance.data["asset"], instance_name) - ) + output_filepath = os.path.join(output_dir, filename) + dst_filepath = os.path.join(publish_dir, filename) + transfers.append((output_filepath, dst_filepath)) - # Find latest version - latest_version = self.find_last_version(subset_name, asset_doc) - version_number = 1 - if latest_version is not None: - version_number += latest_version - - self.log.info( - "Next version of instance \"{}\" will be {}".format( - instance_name, version_number - ) - ) - - # Set family and subset - new_instance.data["family"] = self.new_instance_family - new_instance.data["subset"] = subset_name - new_instance.data["version"] = version_number - new_instance.data["latestVersion"] = latest_version - - new_instance.data["anatomyData"].update({ - "subset": subset_name, - "family": self.new_instance_family, - "version": version_number - }) - - # Copy `families` and check if `family` is not in current families - families = new_instance.data.get("families") or list() - if families: - families = list(set(families)) - - if self.new_instance_family in families: - families.remove(self.new_instance_family) - new_instance.data["families"] = families - - # Prepare staging dir for new instance - staging_dir = self.staging_dir(new_instance) - - output_filename = "{}.png".format(layer_name) - output_filepath = os.path.join(staging_dir, output_filename) pil_object = layer.composite(viewport=psd_object.viewbox) pil_object.save(output_filepath, "PNG") - new_repre = { - "name": "png", - "ext": "png", - "files": output_filename, - "stagingDir": staging_dir - } - self.log.debug( - "Creating new representation: {}".format(new_repre) - ) - new_instance.data["representations"] = [new_repre] + json_data["children"].append(layer_data) + + return json_data, transfers + + def redo_global_plugins(self, instance): + # TODO do this in collection phase + # Copy `families` and check if `family` is not in current families + families = instance.data.get("families") or list() + if families: + families = list(set(families)) + + if self.new_instance_family in families: + families.remove(self.new_instance_family) + + self.log.debug( + "Setting new instance families {}".format(str(families)) + ) + instance.data["families"] = families + + # Override instance data with new information + instance.data["family"] = self.new_instance_family + + subset_name = instance.data["anatomyData"]["subset"] + asset_doc = instance.data["assetEntity"] + latest_version = self.find_last_version(subset_name, asset_doc) + version_number = 1 + if latest_version is not None: + version_number += latest_version + + instance.data["latestVersion"] = latest_version + instance.data["version"] = version_number + + # Same data apply to anatomy data + instance.data["anatomyData"].update({ + "family": self.new_instance_family, + "version": version_number + }) + + # Redo publish and resources dir + anatomy = instance.context.data["anatomy"] + template_data = copy.deepcopy(instance.data["anatomyData"]) + template_data.update({ + "frame": "FRAME_TEMP", + "representation": "TEMP" + }) + anatomy_filled = anatomy.format(template_data) + if "folder" in anatomy.templates["publish"]: + publish_folder = anatomy_filled["publish"]["folder"] + else: + publish_folder = os.path.dirname(anatomy_filled["publish"]["path"]) + + publish_folder = os.path.normpath(publish_folder) + resources_folder = os.path.join(publish_folder, "resources") + + instance.data["publishDir"] = publish_folder + instance.data["resourcesDir"] = resources_folder + + self.log.debug("publishDir: \"{}\"".format(publish_folder)) + self.log.debug("resourcesDir: \"{}\"".format(resources_folder)) def find_last_version(self, subset_name, asset_doc): subset_doc = io.find_one({ From b91695d12b32821802a605807f504746c5256106 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 12 Aug 2020 17:47:17 +0200 Subject: [PATCH 37/42] collect matching asset is only for psd_batch --- .../standalonepublisher/publish/collect_matching_asset.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pype/plugins/standalonepublisher/publish/collect_matching_asset.py b/pype/plugins/standalonepublisher/publish/collect_matching_asset.py index 3f28b610e0..ef05131417 100644 --- a/pype/plugins/standalonepublisher/publish/collect_matching_asset.py +++ b/pype/plugins/standalonepublisher/publish/collect_matching_asset.py @@ -14,7 +14,7 @@ class CollectMatchingAssetToInstance(pyblish.api.InstancePlugin): label = "Collect Matching Asset to Instance" order = pyblish.api.CollectorOrder - 0.05 hosts = ["standalonepublisher"] - family = ["image"] + family = ["psd_batch"] def process(self, instance): source_file = os.path.basename(instance.data["source"]).lower() @@ -38,9 +38,7 @@ class CollectMatchingAssetToInstance(pyblish.api.InstancePlugin): f"Matching asset found: {pformat(matching_asset_doc)}" ) - # QUESTION exception was limited to "psd_batch" family since - # it is required for processing - elif instance.data["family"] == "psd_batch": + else: # TODO better error message raise AssertionError(( "Filename \"{}\" does not match" From 801fcd7aabc5fd8fe493402f02e9c30f11695490 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 12 Aug 2020 17:47:40 +0200 Subject: [PATCH 38/42] extract images from psd is also not active by default --- .../standalonepublisher/publish/extract_images_from_psd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/plugins/standalonepublisher/publish/extract_images_from_psd.py b/pype/plugins/standalonepublisher/publish/extract_images_from_psd.py index 2ac6001755..2e7c9acb15 100644 --- a/pype/plugins/standalonepublisher/publish/extract_images_from_psd.py +++ b/pype/plugins/standalonepublisher/publish/extract_images_from_psd.py @@ -11,7 +11,7 @@ class ExtractImagesFromPSD(pype.api.Extractor): # PLUGIN is not currently enabled because was decided to use different # approach enabled = False - + active = False label = "Extract Images from PSD" order = pyblish.api.ExtractorOrder + 0.02 families = ["imageForLayout"] From dfc6aebeb262e912b9a04c3884dc1ff175be0cfb Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 12 Aug 2020 17:49:01 +0200 Subject: [PATCH 39/42] do not add "image" automatically to psd instance --- .../plugins/standalonepublisher/publish/collect_psd_instances.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pype/plugins/standalonepublisher/publish/collect_psd_instances.py b/pype/plugins/standalonepublisher/publish/collect_psd_instances.py index f7ea30e810..d70c3a638b 100644 --- a/pype/plugins/standalonepublisher/publish/collect_psd_instances.py +++ b/pype/plugins/standalonepublisher/publish/collect_psd_instances.py @@ -55,7 +55,6 @@ class CollectPsdInstances(pyblish.api.InstancePlugin): new_instance.data["label"] = f"{instance_name}" new_instance.data["subset"] = subset_name - new_instance.data["families"].append("image") # fix anatomy data anatomy_data_new = copy.deepcopy(anatomy_data) From 2ea8ad50c76a74974853e87a8ae43992d807aab2 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 12 Aug 2020 17:52:58 +0200 Subject: [PATCH 40/42] do not set psd as thumbnail --- pype/plugins/standalonepublisher/publish/collect_context.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pype/plugins/standalonepublisher/publish/collect_context.py b/pype/plugins/standalonepublisher/publish/collect_context.py index 28cbe043ce..0e2d7fe2a6 100644 --- a/pype/plugins/standalonepublisher/publish/collect_context.py +++ b/pype/plugins/standalonepublisher/publish/collect_context.py @@ -159,7 +159,6 @@ class CollectContextDataSAPublish(pyblish.api.ContextPlugin): if "psd" in component["name"]: instance.data["source"] = component["files"] - component["thumbnail"] = True self.log.debug("Adding image:psd_batch family") instance.data["representations"].append(component) From b850c0af5160a7a31306bd7104c2107160cbc9a3 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 12 Aug 2020 18:19:30 +0200 Subject: [PATCH 41/42] integrate new should process background family --- pype/plugins/global/publish/integrate_new.py | 3 ++- .../publish/extract_bg_for_compositing.py | 10 +++++----- .../publish/extract_bg_main_groups.py | 16 ++++++++-------- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/pype/plugins/global/publish/integrate_new.py b/pype/plugins/global/publish/integrate_new.py index 1d50e24e86..1c1be09a0a 100644 --- a/pype/plugins/global/publish/integrate_new.py +++ b/pype/plugins/global/publish/integrate_new.py @@ -84,7 +84,8 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): "action", "harmony.template", "harmony.palette", - "editorial" + "editorial", + "background" ] exclude_families = ["clip"] db_representation_context_keys = [ diff --git a/pype/plugins/standalonepublisher/publish/extract_bg_for_compositing.py b/pype/plugins/standalonepublisher/publish/extract_bg_for_compositing.py index 0c0eee7f83..7a1b86ef50 100644 --- a/pype/plugins/standalonepublisher/publish/extract_bg_for_compositing.py +++ b/pype/plugins/standalonepublisher/publish/extract_bg_for_compositing.py @@ -45,16 +45,16 @@ class ExtractBGForComp(pype.api.Extractor): if not instance.data.get("transfers"): instance.data["transfers"] = [] + # Prepare staging dir + staging_dir = self.staging_dir(instance) + if not os.path.exists(staging_dir): + os.makedirs(staging_dir) + for repre in tuple(repres): # Skip all files without .psd extension if repre["ext"] != ".psd": continue - # Prepare staging dir - staging_dir = self.staging_dir(instance) - if not os.path.exists(staging_dir): - os.makedirs(staging_dir) - # Prepare publish dir for transfers publish_dir = instance.data["publishDir"] diff --git a/pype/plugins/standalonepublisher/publish/extract_bg_main_groups.py b/pype/plugins/standalonepublisher/publish/extract_bg_main_groups.py index 4920a92ba9..2dc89785da 100644 --- a/pype/plugins/standalonepublisher/publish/extract_bg_main_groups.py +++ b/pype/plugins/standalonepublisher/publish/extract_bg_main_groups.py @@ -51,19 +51,19 @@ class ExtractBGMainGroups(pype.api.Extractor): if not instance.data.get("transfers"): instance.data["transfers"] = [] + # Prepare staging dir + staging_dir = self.staging_dir(instance) + if not os.path.exists(staging_dir): + os.makedirs(staging_dir) + + # Prepare publish dir for transfers + publish_dir = instance.data["publishDir"] + for repre in tuple(repres): # Skip all files without .psd extension if repre["ext"] != ".psd": continue - # Prepare staging dir - staging_dir = self.staging_dir(instance) - if not os.path.exists(staging_dir): - os.makedirs(staging_dir) - - # Prepare publish dir for transfers - publish_dir = instance.data["publishDir"] - # Prepare json filepath where extracted metadata are stored json_filename = "{}.json".format(instance.name) json_full_path = os.path.join(staging_dir, json_filename) From b76d832d952b886bb7b1195580bd6d78f29e6cb0 Mon Sep 17 00:00:00 2001 From: Milan Kolar Date: Wed, 12 Aug 2020 22:35:48 +0200 Subject: [PATCH 42/42] update families --- .../standalonepublisher/publish/collect_context.py | 4 ++-- .../publish/collect_matching_asset.py | 2 +- .../publish/collect_psd_instances.py | 10 +++++----- .../publish/extract_bg_for_compositing.py | 2 +- .../publish/extract_bg_main_groups.py | 2 +- .../publish/extract_images_from_psd.py | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/pype/plugins/standalonepublisher/publish/collect_context.py b/pype/plugins/standalonepublisher/publish/collect_context.py index 0e2d7fe2a6..a5479fdf13 100644 --- a/pype/plugins/standalonepublisher/publish/collect_context.py +++ b/pype/plugins/standalonepublisher/publish/collect_context.py @@ -48,7 +48,7 @@ class CollectContextDataSAPublish(pyblish.api.ContextPlugin): self.log.debug(f"_ in_data: {pformat(in_data)}") # exception for editorial - if in_data["family"] in ["editorial", "psd_batch"]: + if in_data["family"] in ["editorial", "background_batch"]: in_data_list = self.multiple_instances(context, in_data) else: in_data_list = [in_data] @@ -159,6 +159,6 @@ class CollectContextDataSAPublish(pyblish.api.ContextPlugin): if "psd" in component["name"]: instance.data["source"] = component["files"] - self.log.debug("Adding image:psd_batch family") + self.log.debug("Adding image:background_batch family") instance.data["representations"].append(component) diff --git a/pype/plugins/standalonepublisher/publish/collect_matching_asset.py b/pype/plugins/standalonepublisher/publish/collect_matching_asset.py index ef05131417..e8b1343c0e 100644 --- a/pype/plugins/standalonepublisher/publish/collect_matching_asset.py +++ b/pype/plugins/standalonepublisher/publish/collect_matching_asset.py @@ -14,7 +14,7 @@ class CollectMatchingAssetToInstance(pyblish.api.InstancePlugin): label = "Collect Matching Asset to Instance" order = pyblish.api.CollectorOrder - 0.05 hosts = ["standalonepublisher"] - family = ["psd_batch"] + family = ["background_batch"] def process(self, instance): source_file = os.path.basename(instance.data["source"]).lower() diff --git a/pype/plugins/standalonepublisher/publish/collect_psd_instances.py b/pype/plugins/standalonepublisher/publish/collect_psd_instances.py index d70c3a638b..9c8e2eae83 100644 --- a/pype/plugins/standalonepublisher/publish/collect_psd_instances.py +++ b/pype/plugins/standalonepublisher/publish/collect_psd_instances.py @@ -11,17 +11,17 @@ class CollectPsdInstances(pyblish.api.InstancePlugin): label = "Collect Psd Instances" order = pyblish.api.CollectorOrder + 0.492 hosts = ["standalonepublisher"] - families = ["psd_batch"] + families = ["background_batch"] # presets subsets = { - "imageForLayout": { + "backgroundLayout": { "task": "background", - "family": "imageForLayout" + "family": "backgroundLayout" }, - "imageForComp": { + "backgroundComp": { "task": "background", - "family": "imageForComp" + "family": "backgroundComp" }, "workfileBackground": { "task": "background", diff --git a/pype/plugins/standalonepublisher/publish/extract_bg_for_compositing.py b/pype/plugins/standalonepublisher/publish/extract_bg_for_compositing.py index 7a1b86ef50..d4d625097a 100644 --- a/pype/plugins/standalonepublisher/publish/extract_bg_for_compositing.py +++ b/pype/plugins/standalonepublisher/publish/extract_bg_for_compositing.py @@ -9,7 +9,7 @@ PSDImage = None class ExtractBGForComp(pype.api.Extractor): label = "Extract Background for Compositing" - families = ["imageForComp"] + families = ["backgroundComp"] hosts = ["standalonepublisher"] new_instance_family = "background" diff --git a/pype/plugins/standalonepublisher/publish/extract_bg_main_groups.py b/pype/plugins/standalonepublisher/publish/extract_bg_main_groups.py index 2dc89785da..e00f5858ed 100644 --- a/pype/plugins/standalonepublisher/publish/extract_bg_main_groups.py +++ b/pype/plugins/standalonepublisher/publish/extract_bg_main_groups.py @@ -11,7 +11,7 @@ PSDImage = None class ExtractBGMainGroups(pype.api.Extractor): label = "Extract Background Main Groups" order = pyblish.api.ExtractorOrder + 0.02 - families = ["imageForLayout"] + families = ["backgroundLayout"] hosts = ["standalonepublisher"] new_instance_family = "background" diff --git a/pype/plugins/standalonepublisher/publish/extract_images_from_psd.py b/pype/plugins/standalonepublisher/publish/extract_images_from_psd.py index 2e7c9acb15..5a2109478c 100644 --- a/pype/plugins/standalonepublisher/publish/extract_images_from_psd.py +++ b/pype/plugins/standalonepublisher/publish/extract_images_from_psd.py @@ -14,7 +14,7 @@ class ExtractImagesFromPSD(pype.api.Extractor): active = False label = "Extract Images from PSD" order = pyblish.api.ExtractorOrder + 0.02 - families = ["imageForLayout"] + families = ["backgroundLayout"] hosts = ["standalonepublisher"] new_instance_family = "image"