From 1ddf61a7ce98de34b0ddeb9b5ef273acd5f1f489 Mon Sep 17 00:00:00 2001 From: Milan Kolar Date: Tue, 3 Dec 2019 16:24:10 +0100 Subject: [PATCH 01/38] assemblies were not loading correctly --- pype/plugins/global/publish/integrate.py | 2 +- pype/plugins/global/publish/integrate_new.py | 3 ++- pype/plugins/maya/load/load_reference.py | 8 ++++--- pype/plugins/maya/publish/extract_assembly.py | 24 +++++++++++++++---- 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/pype/plugins/global/publish/integrate.py b/pype/plugins/global/publish/integrate.py index 59e05ee2aa..b2f273ec5c 100644 --- a/pype/plugins/global/publish/integrate.py +++ b/pype/plugins/global/publish/integrate.py @@ -24,7 +24,7 @@ class IntegrateAsset(pyblish.api.InstancePlugin): label = "Integrate Asset" order = pyblish.api.IntegratorOrder - families = ["assembly"] + families = [] exclude_families = ["clip"] def process(self, instance): diff --git a/pype/plugins/global/publish/integrate_new.py b/pype/plugins/global/publish/integrate_new.py index fce6b0b5c7..0a1a1fd031 100644 --- a/pype/plugins/global/publish/integrate_new.py +++ b/pype/plugins/global/publish/integrate_new.py @@ -70,7 +70,8 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): "audio", "yetiRig", "yeticache", - "source" + "source", + "assembly" ] exclude_families = ["clip"] diff --git a/pype/plugins/maya/load/load_reference.py b/pype/plugins/maya/load/load_reference.py index 55db019cf4..c17538c57d 100644 --- a/pype/plugins/maya/load/load_reference.py +++ b/pype/plugins/maya/load/load_reference.py @@ -43,14 +43,16 @@ class ReferenceLoader(pype.maya.plugin.ReferenceLoader): namespace = cmds.referenceQuery(nodes[0], namespace=True) shapes = cmds.ls(nodes, shapes=True, long=True) - print(shapes) newNodes = (list(set(nodes) - set(shapes))) - print(newNodes) + + current_namespace = pm.namespaceInfo(currentNamespace=True) + + if current_namespace != ":": + groupName = current_namespace + ":" + groupName groupNode = pm.PyNode(groupName) roots = set() - print(nodes) for node in newNodes: try: diff --git a/pype/plugins/maya/publish/extract_assembly.py b/pype/plugins/maya/publish/extract_assembly.py index 26b16a73c4..c12d57e836 100644 --- a/pype/plugins/maya/publish/extract_assembly.py +++ b/pype/plugins/maya/publish/extract_assembly.py @@ -22,11 +22,11 @@ class ExtractAssembly(pype.api.Extractor): def process(self, instance): - parent_dir = self.staging_dir(instance) + staging_dir = self.staging_dir(instance) hierarchy_filename = "{}.abc".format(instance.name) - hierarchy_path = os.path.join(parent_dir, hierarchy_filename) + hierarchy_path = os.path.join(staging_dir, hierarchy_filename) json_filename = "{}.json".format(instance.name) - json_path = os.path.join(parent_dir, json_filename) + json_path = os.path.join(staging_dir, json_filename) self.log.info("Dumping scene data for debugging ..") with open(json_path, "w") as filepath: @@ -46,8 +46,24 @@ class ExtractAssembly(pype.api.Extractor): "uvWrite": True, "selection": True}) - instance.data["files"] = [json_filename, hierarchy_filename] + if "representations" not in instance.data: + instance.data["representations"] = [] + representation_abc = { + 'name': 'abc', + 'ext': 'abc', + 'files': hierarchy_filename, + "stagingDir": staging_dir + } + instance.data["representations"].append(representation_abc) + + representation_json = { + 'name': 'json', + 'ext': 'json', + 'files': json_filename, + "stagingDir": staging_dir + } + instance.data["representations"].append(representation_json) # Remove data instance.data.pop("scenedata", None) From b69e839cfc4e7842e04e7ed477e88ebe68aebde6 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Sat, 25 Jan 2020 14:18:39 +0100 Subject: [PATCH 02/38] feat(global): adding review to sequence functionality --- pype/plugins/global/publish/extract_review.py | 41 ++++++++++++++++--- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/pype/plugins/global/publish/extract_review.py b/pype/plugins/global/publish/extract_review.py index a11f681e61..2e79d86c38 100644 --- a/pype/plugins/global/publish/extract_review.py +++ b/pype/plugins/global/publish/extract_review.py @@ -53,10 +53,21 @@ class ExtractReview(pyblish.api.InstancePlugin): if "review" in tags: staging_dir = repre["stagingDir"] + + # iterating preset output profiles for name, profile in output_profiles.items(): + repre_new = repre.copy() + ext = profile.get("ext", None) + p_tags = profile.get('tags', []) + self.log.info("p_tags: `{}`".format(p_tags)) + + # adding control for presets to be sequence + # or single file + is_sequence = ("sequence" in p_tags) and (ext in ( + "png", "jpg", "jpeg")) + self.log.debug("Profile name: {}".format(name)) - ext = profile.get("ext", None) if not ext: ext = "mov" self.log.warning( @@ -88,18 +99,22 @@ class ExtractReview(pyblish.api.InstancePlugin): filename = repre["files"].split(".")[0] repr_file = filename + "_{0}.{1}".format(name, ext) - full_output_path = os.path.join( staging_dir, repr_file) + if is_sequence: + filename_base = filename + "_{0}".format(name) + repr_file = filename_base + ".%08d.{0}".format( + ext) + repre_new["sequence_file"] = repr_file + full_output_path = os.path.join( + staging_dir, filename_base, repr_file) + self.log.info("input {}".format(full_input_path)) self.log.info("output {}".format(full_output_path)) - repre_new = repre.copy() - new_tags = [x for x in tags if x != "delete"] - p_tags = profile.get('tags', []) - self.log.info("p_tags: `{}`".format(p_tags)) + # add families [instance.data["families"].append(t) for t in p_tags @@ -288,6 +303,14 @@ class ExtractReview(pyblish.api.InstancePlugin): self.log.debug( "_ output_args: `{}`".format(output_args)) + if is_sequence: + stg_dir = os.path.dirname(full_output_path) + + if not os.path.exists(stg_dir): + self.log.debug( + "creating dir: {}".format(stg_dir)) + os.mkdir(stg_dir) + mov_args = [ os.path.join( os.environ.get( @@ -315,6 +338,12 @@ class ExtractReview(pyblish.api.InstancePlugin): "resolutionHeight": resolution_height, "resolutionWidth": resolution_width, }) + if is_sequence: + repre_new.update({ + "stagingDir": stg_dir, + "files": os.listdir(stg_dir) + }) + if repre_new.get('preview'): repre_new.pop("preview") if repre_new.get('thumbnail'): From 533037b0c407c6035af97ae6b5d1648a7e971017 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Sat, 25 Jan 2020 14:19:21 +0100 Subject: [PATCH 03/38] wip(global): extract burnins to sequence --- pype/plugins/global/publish/extract_burnin.py | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/pype/plugins/global/publish/extract_burnin.py b/pype/plugins/global/publish/extract_burnin.py index 8f5a4aa000..4988f0d042 100644 --- a/pype/plugins/global/publish/extract_burnin.py +++ b/pype/plugins/global/publish/extract_burnin.py @@ -77,19 +77,31 @@ class ExtractBurnin(pype.api.Extractor): if "burnin" not in repre.get("tags", []): continue + is_sequence = "sequence" in repre.get("tags", []) + stagingdir = repre["stagingDir"] filename = "{0}".format(repre["files"]) + if is_sequence: + filename = repre["sequence_file"] + name = "_burnin" ext = os.path.splitext(filename)[1] movieFileBurnin = filename.replace(ext, "") + name + ext + if is_sequence: + fn_splt = filename.split(".") + movieFileBurnin = ".".join( + ((fn_splt[0] + name), fn_splt[-2], fn_splt[-1])) + + self.log.debug("__ movieFileBurnin: `{}`".format(movieFileBurnin)) + full_movie_path = os.path.join( - os.path.normpath(stagingdir), repre["files"] - ) + os.path.normpath(stagingdir), filename) full_burnin_path = os.path.join( - os.path.normpath(stagingdir), movieFileBurnin - ) + os.path.normpath(stagingdir), movieFileBurnin) + + self.log.debug("__ full_movie_path: {}".format(full_movie_path)) self.log.debug("__ full_burnin_path: {}".format(full_burnin_path)) # create copy of prep_data for anatomy formatting From 3e4fa756568037848c6ad78d24ba4fd71d1c979b Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 29 Jan 2020 13:46:42 +0100 Subject: [PATCH 04/38] fix(global): integrate new was mixing padding number src to dst --- pype/plugins/global/publish/integrate_new.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/pype/plugins/global/publish/integrate_new.py b/pype/plugins/global/publish/integrate_new.py index e577c477c3..1be712c14a 100644 --- a/pype/plugins/global/publish/integrate_new.py +++ b/pype/plugins/global/publish/integrate_new.py @@ -339,10 +339,6 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): for i in src_collection.indexes: src_padding = src_padding_exp % i - # for adding first frame into db - if not dst_start_frame: - dst_start_frame = src_padding - src_file_name = "{0}{1}{2}".format( src_head, src_padding, src_tail) @@ -364,6 +360,11 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): self.log.debug("source: {}".format(src)) instance.data["transfers"].append([src, dst]) + # for adding first frame into db + if not dst_start_frame: + dst_start_frame = dst_padding + + dst = "{0}{1}{2}".format( dst_head, dst_start_frame, From 153dcba79cf8a0aba9869e84a0a61c3a9be255f8 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 29 Jan 2020 13:53:36 +0100 Subject: [PATCH 05/38] feat(scripts): otio_burnin is able to render image sequence --- pype/scripts/otio_burnin.py | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/pype/scripts/otio_burnin.py b/pype/scripts/otio_burnin.py index d5bc2594a4..f128352974 100644 --- a/pype/scripts/otio_burnin.py +++ b/pype/scripts/otio_burnin.py @@ -5,6 +5,7 @@ import json import opentimelineio_contrib.adapters.ffmpeg_burnins as ffmpeg_burnins from pypeapp.lib import config from pype import api as pype +from subprocess import Popen, PIPE # FFmpeg in PATH is required @@ -21,6 +22,7 @@ else: FFMPEG = ( '{} -loglevel panic -i %(input)s %(filters)s %(args)s%(output)s' ).format(os.path.normpath(ffmpeg_path + "ffmpeg")) + FFPROBE = ( '{} -v quiet -print_format json -show_format -show_streams %(source)s' ).format(os.path.normpath(ffmpeg_path + "ffprobe")) @@ -248,6 +250,33 @@ class ModifiedBurnins(ffmpeg_burnins.Burnins): 'filters': filters }).strip() + def render(self, output, args=None, overwrite=False, **kwargs): + """ + Render the media to a specified destination. + + :param str output: output file + :param str args: additional FFMPEG arguments + :param bool overwrite: overwrite the output if it exists + """ + if not overwrite and os.path.exists(output): + raise RuntimeError("Destination '%s' exists, please " + "use overwrite" % output) + + is_sequence = "%" in output + + command = self.command(output=output, + args=args, + overwrite=overwrite) + proc = Popen(command, shell=True) + proc.communicate() + if proc.returncode != 0: + raise RuntimeError("Failed to render '%s': %s'" + % (output, command)) + if is_sequence: + output = output % kwargs.get("duration") + if not os.path.exists(output): + raise RuntimeError("Failed to generate this fucking file '%s'" % output) + def example(input_path, output_path): options_init = { @@ -349,7 +378,7 @@ def burnins_from_data(input_path, codec_data, output_path, data, overwrite=True) frame_start = data.get("frame_start") frame_start_tc = data.get('frame_start_tc', frame_start) - + stream = burnin._streams[0] if "resolution_width" not in data: data["resolution_width"] = stream.get("width", "Unknown") @@ -436,7 +465,7 @@ def burnins_from_data(input_path, codec_data, output_path, data, overwrite=True) if codec_data is not []: codec_args = " ".join(codec_data) - burnin.render(output_path, args=codec_args, overwrite=overwrite) + burnin.render(output_path, args=codec_args, overwrite=overwrite, **data) if __name__ == '__main__': From 862faa8325446ba8d734832be8b0deee1d236624 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 29 Jan 2020 13:54:27 +0100 Subject: [PATCH 06/38] feat(global): burnin extracting into image sequence --- pype/plugins/global/publish/extract_burnin.py | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/pype/plugins/global/publish/extract_burnin.py b/pype/plugins/global/publish/extract_burnin.py index 4988f0d042..26f6d34e91 100644 --- a/pype/plugins/global/publish/extract_burnin.py +++ b/pype/plugins/global/publish/extract_burnin.py @@ -156,15 +156,35 @@ class ExtractBurnin(pype.api.Extractor): self.log.debug("Output: {}".format(output)) repre_update = { + "anatomy_template": "render", "files": movieFileBurnin, "name": repre["name"], "tags": [x for x in repre["tags"] if x != "delete"] } + + if is_sequence: + burnin_seq_files = list() + for frame_index in range(_prep_data["duration"] + 1): + if frame_index == 0: + continue + burnin_seq_files.append(movieFileBurnin % frame_index) + repre_update.update({ + "files": burnin_seq_files + }) + instance.data["representations"][i].update(repre_update) # removing the source mov file - os.remove(full_movie_path) - self.log.debug("Removed: `{}`".format(full_movie_path)) + if is_sequence: + for frame_index in range(_prep_data["duration"] + 1): + if frame_index == 0: + continue + rm_file = full_movie_path % frame_index + os.remove(rm_file) + self.log.debug("Removed: `{}`".format(rm_file)) + else: + os.remove(full_movie_path) + self.log.debug("Removed: `{}`".format(full_movie_path)) # Remove any representations tagged for deletion. for repre in instance.data["representations"]: From b715990e1e081741408358f572055bfa4e8a10a5 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 30 Jan 2020 14:10:36 +0100 Subject: [PATCH 07/38] fix(nuke): created too many backdrops --- pype/nuke/lib.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pype/nuke/lib.py b/pype/nuke/lib.py index db1a5919c3..01b63392cd 100644 --- a/pype/nuke/lib.py +++ b/pype/nuke/lib.py @@ -1103,9 +1103,9 @@ class BuildWorkfile(WorkfileSettings): # move position self.position_right() - bdn = self.create_backdrop(label="Loaded Reads", - color='0x2d7702ff', layer=-1, - nodes=nodes_backdrop) + self.create_backdrop(label="Loaded Reads", + color='0x2d7702ff', layer=-1, + nodes=nodes_backdrop) def read_loader(self, representation): """ From a46773450f9a618ad757b233d1ab48fe107a39f2 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 30 Jan 2020 14:11:00 +0100 Subject: [PATCH 08/38] feat(nuke): added support for `png` --- pype/nuke/lib.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pype/nuke/lib.py b/pype/nuke/lib.py index 01b63392cd..64ac83ba81 100644 --- a/pype/nuke/lib.py +++ b/pype/nuke/lib.py @@ -1013,7 +1013,8 @@ class BuildWorkfile(WorkfileSettings): def process(self, regex_filter=None, version=None, - representations=["exr", "dpx", "lutJson", "mov", "preview"]): + representations=["exr", "dpx", "lutJson", "mov", + "preview", "png"]): """ A short description. From 34515cf14965b96a8658d90e3316f474de769bab Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 30 Jan 2020 14:11:36 +0100 Subject: [PATCH 09/38] feat(nuke): feat(nuke): reads mov are now in colorspace presets --- pype/plugins/nuke/load/load_mov.py | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/pype/plugins/nuke/load/load_mov.py b/pype/plugins/nuke/load/load_mov.py index e598839405..d4a3a7f6b9 100644 --- a/pype/plugins/nuke/load/load_mov.py +++ b/pype/plugins/nuke/load/load_mov.py @@ -1,8 +1,9 @@ +import re +import nuke import contextlib from avalon import api, io - -import nuke +from pype.nuke import presets from pype.api import Logger log = Logger().get_logger(__name__, "nuke") @@ -24,7 +25,7 @@ def preserve_trim(node): offset_frame = None if node['frame_mode'].value() == "start at": start_at_frame = node['frame'].value() - if node['frame_mode'].value() is "offset": + if node['frame_mode'].value() == "offset": offset_frame = node['frame'].value() try: @@ -122,7 +123,6 @@ class LoadMov(api.Loader): repr_cont["subset"], repr_cont["representation"]) - # Create the Loader with the filename path set with viewer_update_and_undo_stop(): # TODO: it might be universal read to img/geo/camera @@ -139,7 +139,20 @@ class LoadMov(api.Loader): read_node["last"].setValue(last) read_node["frame_mode"].setValue("start at") read_node["frame"].setValue(str(offset_frame)) - # add additional metadata from the version to imprint to Avalon knob + + # load nuke presets for Read's colorspace + read_clrs_presets = presets.get_colorspace_preset().get( + "nuke", {}).get("read", {}) + + # check if any colorspace presets for read is mathing + preset_clrsp = next((read_clrs_presets[k] + for k in read_clrs_presets + if bool(re.search(k, file))), + None) + if preset_clrsp is not None: + read_node["colorspace"].setValue(str(preset_clrsp)) + + # add additional metadata from the version to imprint Avalon knob add_keys = [ "frameStart", "frameEnd", "handles", "source", "author", "fps", "version", "handleStart", "handleEnd" @@ -147,7 +160,7 @@ class LoadMov(api.Loader): data_imprint = {} for key in add_keys: - if key is 'version': + if key == 'version': data_imprint.update({ key: context["version"]['name'] }) From a35969f0df62542bfd9f2b870c9566335254d913 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 30 Jan 2020 14:11:56 +0100 Subject: [PATCH 10/38] feat(nuke): reads sequences are now in colorspace presets --- pype/plugins/nuke/load/load_sequence.py | 26 +++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/pype/plugins/nuke/load/load_sequence.py b/pype/plugins/nuke/load/load_sequence.py index 8f01d4511b..5d853d10d3 100644 --- a/pype/plugins/nuke/load/load_sequence.py +++ b/pype/plugins/nuke/load/load_sequence.py @@ -1,10 +1,12 @@ +import re +import nuke import contextlib from avalon import api, io - -import nuke +from pype.nuke import presets from pype.api import Logger + log = Logger().get_logger(__name__, "nuke") @@ -24,7 +26,7 @@ def preserve_trim(node): offset_frame = None if node['frame_mode'].value() == "start at": start_at_frame = node['frame'].value() - if node['frame_mode'].value() is "offset": + if node['frame_mode'].value() == "offset": offset_frame = node['frame'].value() try: @@ -134,20 +136,32 @@ class LoadSequence(api.Loader): if colorspace is not None: r["colorspace"].setValue(str(colorspace)) + # load nuke presets for Read's colorspace + read_clrs_presets = presets.get_colorspace_preset().get( + "nuke", {}).get("read", {}) + + # check if any colorspace presets for read is mathing + preset_clrsp = next((read_clrs_presets[k] + for k in read_clrs_presets + if bool(re.search(k, file))), + None) + if preset_clrsp is not None: + r["colorspace"].setValue(str(preset_clrsp)) + loader_shift(r, first, relative=True) r["origfirst"].setValue(int(first)) r["first"].setValue(int(first)) r["origlast"].setValue(int(last)) r["last"].setValue(int(last)) - # add additional metadata from the version to imprint to Avalon knob + # add additional metadata from the version to imprint Avalon knob add_keys = ["frameStart", "frameEnd", "source", "colorspace", "author", "fps", "version", "handleStart", "handleEnd"] data_imprint = {} for k in add_keys: - if k is 'version': + if k == 'version': data_imprint.update({k: context["version"]['name']}) else: data_imprint.update( @@ -179,7 +193,7 @@ class LoadSequence(api.Loader): rtn["after"].setValue("continue") rtn["input.first_lock"].setValue(True) rtn["input.first"].setValue( - self.handle_start + self.first_frame + self.handle_start + self.first_frame ) if time_warp_nodes != []: From be7dbb115172357fdfcdef6587429eff8a948bff Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 30 Jan 2020 18:18:01 +0100 Subject: [PATCH 11/38] fix(nuke): printing objects and docstring --- pype/nuke/lib.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/pype/nuke/lib.py b/pype/nuke/lib.py index 64ac83ba81..fdbd578a76 100644 --- a/pype/nuke/lib.py +++ b/pype/nuke/lib.py @@ -1055,9 +1055,10 @@ class BuildWorkfile(WorkfileSettings): wn["render"].setValue(True) vn.setInput(0, wn) - bdn = self.create_backdrop(label="Render write \n\n\n\nOUTPUT", - color='0xcc1102ff', layer=-1, - nodes=[wn]) + # adding backdrop under write + self.create_backdrop(label="Render write \n\n\n\nOUTPUT", + color='0xcc1102ff', layer=-1, + nodes=[wn]) # move position self.position_up(4) @@ -1071,10 +1072,12 @@ class BuildWorkfile(WorkfileSettings): version=version, representations=representations) - log.info("__ subsets: `{}`".format(subsets)) + for name, subset in subsets.items(): + log.debug("___________________") + log.debug(name) + log.debug(subset["version"]) nodes_backdrop = list() - for name, subset in subsets.items(): if "lut" in name: continue @@ -1104,6 +1107,7 @@ class BuildWorkfile(WorkfileSettings): # move position self.position_right() + # adding backdrop under all read nodes self.create_backdrop(label="Loaded Reads", color='0x2d7702ff', layer=-1, nodes=nodes_backdrop) From 0e807f05dac35655dd1793523f8674edd3b7a74c Mon Sep 17 00:00:00 2001 From: Milan Kolar Date: Fri, 31 Jan 2020 12:05:07 +0100 Subject: [PATCH 12/38] remove obsolete backwards compatibility --- pype/ftrack/events/event_user_assigment.py | 7 ++----- pype/plugins/global/publish/extract_burnin.py | 7 +------ 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/pype/ftrack/events/event_user_assigment.py b/pype/ftrack/events/event_user_assigment.py index efdfb7665d..eaacfd959a 100644 --- a/pype/ftrack/events/event_user_assigment.py +++ b/pype/ftrack/events/event_user_assigment.py @@ -208,11 +208,8 @@ class UserAssigmentEvent(BaseEvent): work_dir = anatomy.format(data)['avalon']['work'] # we also need publish but not whole filled_all = anatomy.format_all(data) - if "partial" not in filled_all: - publish = filled_all['avalon']['publish'] - else: - # Backwards compatibility - publish = filled_all["partial"]['avalon']['publish'] + publish = filled_all['avalon']['publish'] + # now find path to {asset} m = re.search("(^.+?{})".format(data['asset']), publish) diff --git a/pype/plugins/global/publish/extract_burnin.py b/pype/plugins/global/publish/extract_burnin.py index a3df47518c..8a96e66d27 100644 --- a/pype/plugins/global/publish/extract_burnin.py +++ b/pype/plugins/global/publish/extract_burnin.py @@ -96,12 +96,7 @@ class ExtractBurnin(pype.api.Extractor): _prep_data = copy.deepcopy(prep_data) _prep_data["representation"] = repre["name"] filled_anatomy = anatomy.format_all(_prep_data) - if hasattr(filled_anatomy, "get_solved"): - _filled_anatomy = filled_anatomy.get_solved() - else: - # Backwards compatibility - _filled_anatomy = filled_anatomy.get("solved") - _prep_data["anatomy"] = _filled_anatomy or {} + _prep_data["anatomy"] = filled_anatomy.get_solved() burnin_data = { "input": full_movie_path.replace("\\", "/"), From 35a7040930ee9a5013ffefb82f5165e5615a53da Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 31 Jan 2020 14:43:02 +0100 Subject: [PATCH 13/38] fix(nuke): new way of imprinting data --- pype/nuke/lib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/nuke/lib.py b/pype/nuke/lib.py index db1a5919c3..1c5601f34f 100644 --- a/pype/nuke/lib.py +++ b/pype/nuke/lib.py @@ -374,7 +374,7 @@ def create_write_node(name, data, input=None, prenodes=None): now_node.setInput(0, prev_node) # imprinting group node - GN = avalon.nuke.imprint(GN, data["avalon"]) + avalon.nuke.imprint(GN, data["avalon"], tab="Pype") divider = nuke.Text_Knob('') GN.addKnob(divider) From 68f28ce4574c5234451e945d844fb84b042914d7 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 31 Jan 2020 18:57:16 +0100 Subject: [PATCH 14/38] fix(nuke): refactoring loaders --- pype/plugins/nuke/load/load_mov.py | 67 +++++++++++++------------ pype/plugins/nuke/load/load_sequence.py | 53 +++++++++---------- 2 files changed, 62 insertions(+), 58 deletions(-) diff --git a/pype/plugins/nuke/load/load_mov.py b/pype/plugins/nuke/load/load_mov.py index e598839405..917abdf098 100644 --- a/pype/plugins/nuke/load/load_mov.py +++ b/pype/plugins/nuke/load/load_mov.py @@ -24,7 +24,7 @@ def preserve_trim(node): offset_frame = None if node['frame_mode'].value() == "start at": start_at_frame = node['frame'].value() - if node['frame_mode'].value() is "offset": + if node['frame_mode'].value() == "offset": offset_frame = node['frame'].value() try: @@ -85,30 +85,26 @@ class LoadMov(api.Loader): containerise, viewer_update_and_undo_stop ) - version = context['version'] version_data = version.get("data", {}) - orig_first = version_data.get("frameStart", None) - orig_last = version_data.get("frameEnd", None) + orig_first = version_data.get("frameStart") + orig_last = version_data.get("frameEnd") diff = orig_first - 1 - # set first to 1 + first = orig_first - diff last = orig_last - diff - handles = version_data.get("handles", None) - handle_start = version_data.get("handleStart", None) - handle_end = version_data.get("handleEnd", None) - repr_cont = context["representation"]["context"] - # fix handle start and end if none are available - if not handle_start and not handle_end: - handle_start = handles - handle_end = handles + handle_start = version_data.get("handleStart") + handle_end = version_data.get("handleEnd") + + colorspace = version_data.get("colorspace") + repr_cont = context["representation"]["context"] # create handles offset (only to last, because of mov) last += handle_start + handle_end # offset should be with handles so it match orig frame range - offset_frame = orig_first + handle_start + offset_frame = orig_first - handle_start # Fallback to asset name when namespace is None if namespace is None: @@ -122,10 +118,8 @@ class LoadMov(api.Loader): repr_cont["subset"], repr_cont["representation"]) - # Create the Loader with the filename path set with viewer_update_and_undo_stop(): - # TODO: it might be universal read to img/geo/camera read_node = nuke.createNode( "Read", "name {}".format(read_name) @@ -139,7 +133,11 @@ class LoadMov(api.Loader): read_node["last"].setValue(last) read_node["frame_mode"].setValue("start at") read_node["frame"].setValue(str(offset_frame)) - # add additional metadata from the version to imprint to Avalon knob + + if colorspace: + read_node["colorspace"].setValue(str(colorspace)) + + # add additional metadata from the version to imprint Avalon knob add_keys = [ "frameStart", "frameEnd", "handles", "source", "author", "fps", "version", "handleStart", "handleEnd" @@ -147,7 +145,7 @@ class LoadMov(api.Loader): data_imprint = {} for key in add_keys: - if key is 'version': + if key == 'version': data_imprint.update({ key: context["version"]['name'] }) @@ -186,10 +184,10 @@ class LoadMov(api.Loader): ) node = nuke.toNode(container['objectName']) - # TODO: prepare also for other Read img/geo/camera + assert node.Class() == "Read", "Must be Read" - file = api.get_representation_path(representation) + file = self.fname.replace("\\", "/") # Get start frame from version data version = io.find_one({ @@ -207,15 +205,17 @@ class LoadMov(api.Loader): version_data = version.get("data", {}) - orig_first = version_data.get("frameStart", None) - orig_last = version_data.get("frameEnd", None) + orig_first = version_data.get("frameStart") + orig_last = version_data.get("frameEnd") diff = orig_first - 1 + # set first to 1 first = orig_first - diff last = orig_last - diff handles = version_data.get("handles", 0) handle_start = version_data.get("handleStart", 0) handle_end = version_data.get("handleEnd", 0) + colorspace = version_data.get("colorspace") if first is None: log.warning("Missing start frame for updated version" @@ -231,11 +231,11 @@ class LoadMov(api.Loader): # create handles offset (only to last, because of mov) last += handle_start + handle_end # offset should be with handles so it match orig frame range - offset_frame = orig_first + handle_start + offset_frame = orig_first - handle_start # Update the loader's path whilst preserving some values with preserve_trim(node): - node["file"].setValue(file["path"]) + node["file"].setValue(file) log.info("__ node['file']: {}".format(node["file"].value())) # Set the global in to the start frame of the sequence @@ -247,19 +247,22 @@ class LoadMov(api.Loader): node["frame_mode"].setValue("start at") node["frame"].setValue(str(offset_frame)) + if colorspace: + node["colorspace"].setValue(str(colorspace)) + updated_dict = {} updated_dict.update({ "representation": str(representation["_id"]), - "frameStart": version_data.get("frameStart"), - "frameEnd": version_data.get("frameEnd"), - "version": version.get("name"), + "frameStart": str(first), + "frameEnd": str(last), + "version": str(version.get("name")), + "colorspace": version_data.get("colorspace"), "source": version_data.get("source"), - "handles": version_data.get("handles"), - "handleStart": version_data.get("handleStart"), - "handleEnd": version_data.get("handleEnd"), - "fps": version_data.get("fps"), + "handleStart": str(handle_start), + "handleEnd": str(handle_end), + "fps": str(version_data.get("fps")), "author": version_data.get("author"), - "outputDir": version_data.get("outputDir"), + "outputDir": version_data.get("outputDir") }) # change color of node diff --git a/pype/plugins/nuke/load/load_sequence.py b/pype/plugins/nuke/load/load_sequence.py index 76599c3351..67d1f75dc8 100644 --- a/pype/plugins/nuke/load/load_sequence.py +++ b/pype/plugins/nuke/load/load_sequence.py @@ -24,7 +24,7 @@ def preserve_trim(node): offset_frame = None if node['frame_mode'].value() == "start at": start_at_frame = node['frame'].value() - if node['frame_mode'].value() is "offset": + if node['frame_mode'].value() == "offset": offset_frame = node['frame'].value() try: @@ -93,7 +93,6 @@ class LoadSequence(api.Loader): self.first_frame = int(nuke.root()["first_frame"].getValue()) self.handle_start = version_data.get("handleStart", 0) - self.handle_start = version_data.get("handleStart", 0) self.handle_end = version_data.get("handleEnd", 0) first = version_data.get("frameStart", None) @@ -108,7 +107,10 @@ class LoadSequence(api.Loader): file = self.fname.replace("\\", "/") - log.info("file: {}\n".format(self.fname)) + if "#" not in file: + frame = repr_cont.get("frame") + padding = len(frame) + file = file.replace(frame, "#"*padding) repr_cont = context["representation"]["context"] read_name = "Read_{0}_{1}_{2}".format( @@ -116,11 +118,6 @@ class LoadSequence(api.Loader): repr_cont["subset"], repr_cont["representation"]) - if "#" not in file: - frame = repr_cont.get("frame") - padding = len(frame) - file = file.replace(frame, "#"*padding) - # Create the Loader with the filename path set with viewer_update_and_undo_stop(): # TODO: it might be universal read to img/geo/camera @@ -130,8 +127,8 @@ class LoadSequence(api.Loader): r["file"].setValue(file) # Set colorspace defined in version data - colorspace = context["version"]["data"].get("colorspace", None) - if colorspace is not None: + colorspace = context["version"]["data"].get("colorspace") + if colorspace: r["colorspace"].setValue(str(colorspace)) loader_shift(r, first, relative=True) @@ -140,14 +137,14 @@ class LoadSequence(api.Loader): r["origlast"].setValue(int(last)) r["last"].setValue(int(last)) - # add additional metadata from the version to imprint to Avalon knob + # add additional metadata from the version to imprint Avalon knob add_keys = ["frameStart", "frameEnd", "source", "colorspace", "author", "fps", "version", "handleStart", "handleEnd"] data_imprint = {} for k in add_keys: - if k is 'version': + if k == 'version': data_imprint.update({k: context["version"]['name']}) else: data_imprint.update( @@ -179,7 +176,7 @@ class LoadSequence(api.Loader): rtn["after"].setValue("continue") rtn["input.first_lock"].setValue(True) rtn["input.first"].setValue( - self.handle_start + self.first_frame + self.handle_start + self.first_frame ) if time_warp_nodes != []: @@ -210,16 +207,20 @@ class LoadSequence(api.Loader): """ from avalon.nuke import ( - ls_img_sequence, update_container ) node = nuke.toNode(container['objectName']) - # TODO: prepare also for other Read img/geo/camera + assert node.Class() == "Read", "Must be Read" - path = api.get_representation_path(representation) - file = ls_img_sequence(path) + repr_cont = representation["context"] + file = self.fname.replace("\\", "/") + + if "#" not in file: + frame = repr_cont.get("frame") + padding = len(frame) + file = file.replace(frame, "#"*padding) # Get start frame from version data version = io.find_one({ @@ -241,8 +242,8 @@ class LoadSequence(api.Loader): self.handle_start = version_data.get("handleStart", 0) self.handle_end = version_data.get("handleEnd", 0) - first = version_data.get("frameStart", None) - last = version_data.get("frameEnd", None) + first = version_data.get("frameStart") + last = version_data.get("frameEnd") if first is None: log.warning("Missing start frame for updated version" @@ -255,7 +256,7 @@ class LoadSequence(api.Loader): # Update the loader's path whilst preserving some values with preserve_trim(node): - node["file"].setValue(file["path"]) + node["file"].setValue(file) log.info("__ node['file']: {}".format(node["file"].value())) # Set the global in to the start frame of the sequence @@ -268,14 +269,14 @@ class LoadSequence(api.Loader): updated_dict = {} updated_dict.update({ "representation": str(representation["_id"]), - "frameStart": version_data.get("frameStart"), - "frameEnd": version_data.get("frameEnd"), - "version": version.get("name"), + "frameStart": str(first), + "frameEnd": str(last), + "version": str(version.get("name")), "colorspace": version_data.get("colorspace"), "source": version_data.get("source"), - "handleStart": version_data.get("handleStart"), - "handleEnd": version_data.get("handleEnd"), - "fps": version_data.get("fps"), + "handleStart": str(self.handle_start), + "handleEnd": str(self.handle_end), + "fps": str(version_data.get("fps")), "author": version_data.get("author"), "outputDir": version_data.get("outputDir"), }) From 8e9b44817359f02f30eecbd775bc500e3f492cbe Mon Sep 17 00:00:00 2001 From: Milan Kolar Date: Fri, 31 Jan 2020 21:06:16 +0100 Subject: [PATCH 15/38] get padding from anatomy --- pype/plugins/global/publish/integrate_new.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pype/plugins/global/publish/integrate_new.py b/pype/plugins/global/publish/integrate_new.py index 2b8aa5b0fc..739cbc30ad 100644 --- a/pype/plugins/global/publish/integrate_new.py +++ b/pype/plugins/global/publish/integrate_new.py @@ -326,8 +326,7 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): index_frame_start = None if repre.get("frameStart"): - frame_start_padding = len(str( - repre.get("frameEnd"))) + frame_start_padding = anatomy.templates["render"]["padding"] index_frame_start = int(repre.get("frameStart")) # exception for slate workflow From 5bceb794413381d7c1a1378de87cb9efaade4041 Mon Sep 17 00:00:00 2001 From: Milan Kolar Date: Fri, 31 Jan 2020 22:48:29 +0100 Subject: [PATCH 16/38] hotfix submit publish job --- pype/plugins/global/publish/submit_publish_job.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pype/plugins/global/publish/submit_publish_job.py b/pype/plugins/global/publish/submit_publish_job.py index faf4aaef93..a9fa8febd4 100644 --- a/pype/plugins/global/publish/submit_publish_job.py +++ b/pype/plugins/global/publish/submit_publish_job.py @@ -256,6 +256,8 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin): """ # Get a submission job data = instance.data.copy() + if hasattr(instance, "_log"): + data['_log'] = instance._log render_job = data.pop("deadlineSubmissionJob", None) submission_type = "deadline" From dc497be92313401bc243127d6cf47c7c230b58a8 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Sat, 1 Feb 2020 00:16:20 +0100 Subject: [PATCH 17/38] feat(nuke): anatomy templates and version data family to render --- pype/nuke/lib.py | 2 +- pype/plugins/nuke/publish/collect_writes.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pype/nuke/lib.py b/pype/nuke/lib.py index db1a5919c3..3b3586cfe6 100644 --- a/pype/nuke/lib.py +++ b/pype/nuke/lib.py @@ -1269,7 +1269,7 @@ class ExporterReview: 'ext': self.ext, 'files': self.file, "stagingDir": self.staging_dir, - "anatomy_template": "publish", + "anatomy_template": "render", "tags": [self.name.replace("_", "-")] + add_tags } diff --git a/pype/plugins/nuke/publish/collect_writes.py b/pype/plugins/nuke/publish/collect_writes.py index 3eff527d47..8e86e12c2a 100644 --- a/pype/plugins/nuke/publish/collect_writes.py +++ b/pype/plugins/nuke/publish/collect_writes.py @@ -97,7 +97,7 @@ class CollectNukeWrites(pyblish.api.InstancePlugin): "frameEnd": last_frame - handle_end, "version": int(instance.data['version']), "colorspace": node["colorspace"].value(), - "families": [instance.data["family"]], + "families": ["render"], "subset": instance.data["subset"], "fps": instance.context.data["fps"] } From de93ef648ea3d99f0a390113da7f59ba317b73a9 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Sat, 1 Feb 2020 00:17:03 +0100 Subject: [PATCH 18/38] feat(nuke): adding render2d for review --- pype/plugins/nuke/publish/collect_review.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pype/plugins/nuke/publish/collect_review.py b/pype/plugins/nuke/publish/collect_review.py index 7e7cbedd6c..e41b55bbbd 100644 --- a/pype/plugins/nuke/publish/collect_review.py +++ b/pype/plugins/nuke/publish/collect_review.py @@ -1,12 +1,12 @@ import pyblish.api import nuke + class CollectReview(pyblish.api.InstancePlugin): """Collect review instance from rendered frames """ order = pyblish.api.CollectorOrder + 0.3 - family = "review" label = "Collect Review" hosts = ["nuke"] families = ["render", "render.local", "render.farm"] @@ -25,4 +25,7 @@ class CollectReview(pyblish.api.InstancePlugin): instance.data["families"].append("review") instance.data['families'].append('ftrack') + instance.data["families"].append("render2d") + self.log.info("Review collected: `{}`".format(instance)) + self.log.debug("__ instance.data: `{}`".format(instance.data)) From 3a09ff2059e5fbc08f1b04a3777badffcf2c2590 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Sat, 1 Feb 2020 00:17:38 +0100 Subject: [PATCH 19/38] feat(global): rename burnin plugin --- pype/plugins/global/publish/extract_burnin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/plugins/global/publish/extract_burnin.py b/pype/plugins/global/publish/extract_burnin.py index a3df47518c..f0e4b70d19 100644 --- a/pype/plugins/global/publish/extract_burnin.py +++ b/pype/plugins/global/publish/extract_burnin.py @@ -16,7 +16,7 @@ class ExtractBurnin(pype.api.Extractor): `tags` including `burnin` """ - label = "Quicktime with burnins" + label = "Extract burnins" order = pyblish.api.ExtractorOrder + 0.03 families = ["review", "burnin"] hosts = ["nuke", "maya", "shell"] From c25a70d72ddcc785beaeb10de1ca0167193bd3a2 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Sat, 1 Feb 2020 00:18:13 +0100 Subject: [PATCH 20/38] fix(global): ftrack attributes validator failing --- .../plugins/global/publish/validate_custom_ftrack_attributes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/plugins/global/publish/validate_custom_ftrack_attributes.py b/pype/plugins/global/publish/validate_custom_ftrack_attributes.py index 2386b359e4..1e8b239b33 100644 --- a/pype/plugins/global/publish/validate_custom_ftrack_attributes.py +++ b/pype/plugins/global/publish/validate_custom_ftrack_attributes.py @@ -47,7 +47,7 @@ class ValidateFtrackAttributes(pyblish.api.InstancePlugin): host = pyblish.api.current_host() to_check = context.data["presets"].get( - host, {}).get("ftrack_attributes") + host, {}).get("ftrack_custom_attributes") if not to_check: self.log.warning("ftrack_attributes preset not found") return From e0d288cdef324078efa8a19a221f664ffb61736b Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Sat, 1 Feb 2020 00:18:58 +0100 Subject: [PATCH 21/38] fix(nuke): some nodes are failing due disable knob --- pype/plugins/nuke/publish/collect_instances.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pype/plugins/nuke/publish/collect_instances.py b/pype/plugins/nuke/publish/collect_instances.py index 5b123ed7b9..cbbef70e4a 100644 --- a/pype/plugins/nuke/publish/collect_instances.py +++ b/pype/plugins/nuke/publish/collect_instances.py @@ -28,12 +28,15 @@ class CollectNukeInstances(pyblish.api.ContextPlugin): self.log.debug("nuke.allNodes(): {}".format(nuke.allNodes())) for node in nuke.allNodes(): + if node.Class() in ["Viewer", "Dot"]: + continue + try: if node["disable"].value(): continue except Exception as E: self.log.warning(E) - + # get data from avalon knob self.log.debug("node[name]: {}".format(node['name'].value())) From f177185a73b0d260098932e0547843460bd6504f Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Sat, 1 Feb 2020 00:58:26 +0100 Subject: [PATCH 22/38] fix(nuke): moving `render2d` to more global level --- pype/plugins/nuke/publish/collect_review.py | 1 - pype/plugins/nuke/publish/collect_writes.py | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pype/plugins/nuke/publish/collect_review.py b/pype/plugins/nuke/publish/collect_review.py index e41b55bbbd..c95c94541d 100644 --- a/pype/plugins/nuke/publish/collect_review.py +++ b/pype/plugins/nuke/publish/collect_review.py @@ -25,7 +25,6 @@ class CollectReview(pyblish.api.InstancePlugin): instance.data["families"].append("review") instance.data['families'].append('ftrack') - instance.data["families"].append("render2d") self.log.info("Review collected: `{}`".format(instance)) self.log.debug("__ instance.data: `{}`".format(instance.data)) diff --git a/pype/plugins/nuke/publish/collect_writes.py b/pype/plugins/nuke/publish/collect_writes.py index 8e86e12c2a..bf1c6a4b66 100644 --- a/pype/plugins/nuke/publish/collect_writes.py +++ b/pype/plugins/nuke/publish/collect_writes.py @@ -14,6 +14,8 @@ class CollectNukeWrites(pyblish.api.InstancePlugin): families = ["write"] def process(self, instance): + # adding 2d focused rendering + instance.data["families"].append("render2d") node = None for x in instance: From ac53d4345f7ed5e7ef1aa26fd9910c6b4ffae901 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Sat, 1 Feb 2020 01:02:14 +0100 Subject: [PATCH 23/38] fix(nuke): loader failing --- pype/plugins/nuke/load/load_sequence.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/plugins/nuke/load/load_sequence.py b/pype/plugins/nuke/load/load_sequence.py index 22caa9d6b0..9f3d09186c 100644 --- a/pype/plugins/nuke/load/load_sequence.py +++ b/pype/plugins/nuke/load/load_sequence.py @@ -109,12 +109,12 @@ class LoadSequence(api.Loader): file = self.fname.replace("\\", "/") + repr_cont = context["representation"]["context"] if "#" not in file: frame = repr_cont.get("frame") padding = len(frame) file = file.replace(frame, "#"*padding) - repr_cont = context["representation"]["context"] read_name = "Read_{0}_{1}_{2}".format( repr_cont["asset"], repr_cont["subset"], From 1f6d63d6a540409d57326bf09df7ed4ecef7c2d2 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 3 Feb 2020 18:07:08 +0100 Subject: [PATCH 24/38] added collect datetime plugin --- .../global/publish/collect_datetime_data.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 pype/plugins/global/publish/collect_datetime_data.py diff --git a/pype/plugins/global/publish/collect_datetime_data.py b/pype/plugins/global/publish/collect_datetime_data.py new file mode 100644 index 0000000000..f04f924e18 --- /dev/null +++ b/pype/plugins/global/publish/collect_datetime_data.py @@ -0,0 +1,18 @@ +"""These data *must* be collected only once during publishing process. + +Provides: + context -> datetimeData +""" + +import pyblish.api +from pypeapp import config + + +class CollectDateTimeData(pyblish.api.ContextPlugin): + order = pyblish.api.CollectorOrder + label = "Collect DateTime data" + + def process(self, context): + key = "datetimeData" + if key not in context.data: + context.data[key] = config.get_datetime_data() From 7bdb43852253826dc6b8c52e1fae88321740b574 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 3 Feb 2020 18:08:09 +0100 Subject: [PATCH 25/38] extract burnin uses datetime data from context --- pype/plugins/global/publish/extract_burnin.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pype/plugins/global/publish/extract_burnin.py b/pype/plugins/global/publish/extract_burnin.py index 4efe02ca3a..85757c101b 100644 --- a/pype/plugins/global/publish/extract_burnin.py +++ b/pype/plugins/global/publish/extract_burnin.py @@ -45,7 +45,8 @@ class ExtractBurnin(pype.api.Extractor): } # Add datetime data to preparation data - prep_data.update(config.get_datetime_data()) + datetime_data = isntance.context.data.get("datetimeData") or {} + prep_data.update(datetime_data) slate_frame_start = frame_start slate_frame_end = frame_end From eacc1ff0bee5d71d8c48c01eca917f5609f82a90 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 3 Feb 2020 18:21:34 +0100 Subject: [PATCH 26/38] integrate new uses anatomy's used_values --- pype/plugins/global/publish/integrate_new.py | 37 ++++++++++---------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/pype/plugins/global/publish/integrate_new.py b/pype/plugins/global/publish/integrate_new.py index 9729716a50..81b37d0555 100644 --- a/pype/plugins/global/publish/integrate_new.py +++ b/pype/plugins/global/publish/integrate_new.py @@ -80,6 +80,10 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): "assembly" ] exclude_families = ["clip"] + repre_context_stable_keys = [ + "project", "asset", "task", "subset", "version", "representation", + "family", "hierarchy", "task", "username" + ] def process(self, instance): @@ -288,7 +292,7 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): anatomy.templates[template_name]["path"]) sequence_repre = isinstance(files, list) - + repre_context = None if sequence_repre: src_collections, remainder = clique.assemble(files) self.log.debug( @@ -311,10 +315,12 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): template_data["representation"] = repre['ext'] template_data["frame"] = src_padding_exp % i anatomy_filled = anatomy.format(template_data) + template_filled = anatomy_filled[template_name]["path"] + if repre_context is None: + repre_context = template_filled.used_values test_dest_files.append( - os.path.normpath( - anatomy_filled[template_name]["path"]) + os.path.normpath(template_filled) ) self.log.debug( @@ -394,14 +400,21 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): src = os.path.join(stagingdir, fname) anatomy_filled = anatomy.format(template_data) - dst = os.path.normpath( - anatomy_filled[template_name]["path"]).replace("..", ".") + template_filled = anatomy_filled[template_name]["path"] + repre_context = template_filled.used_values + dst = os.path.normpath(template_filled).replace("..", ".") instance.data["transfers"].append([src, dst]) repre['published_path'] = self.unc_convert(dst) self.log.debug("__ dst: {}".format(dst)) + for key in self.repre_context_stable_keys: + value = template_data.get(key) + if not value: + continue + repre_context[key] = template_data[key] + representation = { "_id": io.ObjectId(), "schema": "pype:representation-2.0", @@ -413,19 +426,7 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): # Imprint shortcut to context # for performance reasons. - "context": { - "root": root, - "project": {"name": PROJECT, - "code": project['data']['code']}, - 'task': TASK, - "silo": asset.get('silo'), - "asset": ASSET, - "family": instance.data['family'], - "subset": subset["name"], - "version": version["name"], - "hierarchy": hierarchy, - "representation": repre['ext'] - } + "context": repre_context } if repre.get("outputName"): From ebb5b3b84974fc49e5400eff390321eede39dc9d Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 3 Feb 2020 18:23:39 +0100 Subject: [PATCH 27/38] datetime data are added to template data --- pype/plugins/global/publish/integrate_new.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pype/plugins/global/publish/integrate_new.py b/pype/plugins/global/publish/integrate_new.py index 81b37d0555..c192804833 100644 --- a/pype/plugins/global/publish/integrate_new.py +++ b/pype/plugins/global/publish/integrate_new.py @@ -272,6 +272,11 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): "version": int(version["name"]), "hierarchy": hierarchy} + + # Add datetime data to template data + datetime_data = context.data.get("datetimeData") or {} + template_data.update(datetime_data) + resolution_width = repre.get("resolutionWidth") resolution_height = repre.get("resolutionHeight") fps = instance.data.get("fps") From 13de5280887dbb07f5172c5b45c05e945473682f Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 3 Feb 2020 18:25:42 +0100 Subject: [PATCH 28/38] removed line --- pype/plugins/global/publish/integrate_new.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pype/plugins/global/publish/integrate_new.py b/pype/plugins/global/publish/integrate_new.py index c192804833..bba93ed658 100644 --- a/pype/plugins/global/publish/integrate_new.py +++ b/pype/plugins/global/publish/integrate_new.py @@ -272,7 +272,6 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): "version": int(version["name"]), "hierarchy": hierarchy} - # Add datetime data to template data datetime_data = context.data.get("datetimeData") or {} template_data.update(datetime_data) From 908f9887952c610a8707d91953f92b5ce849a6f6 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 3 Feb 2020 18:26:50 +0100 Subject: [PATCH 29/38] datetime data added to collect templates --- pype/plugins/global/publish/collect_templates.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pype/plugins/global/publish/collect_templates.py b/pype/plugins/global/publish/collect_templates.py index 383944e293..0c272a6044 100644 --- a/pype/plugins/global/publish/collect_templates.py +++ b/pype/plugins/global/publish/collect_templates.py @@ -90,6 +90,10 @@ class CollectTemplates(pyblish.api.InstancePlugin): "hierarchy": hierarchy.replace("\\", "/"), "representation": "TEMP")} + # Add datetime data to template data + datetime_data = context.data.get("datetimeData") or {} + template_data.update(datetime_data) + resolution_width = instance.data.get("resolutionWidth") resolution_height = instance.data.get("resolutionHeight") fps = instance.data.get("fps") From 40aa0c2f5b97f32fdeed4837d4ca50c1e3ec59bd Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 3 Feb 2020 18:27:01 +0100 Subject: [PATCH 30/38] typo fix in collect templates --- pype/plugins/global/publish/collect_templates.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/plugins/global/publish/collect_templates.py b/pype/plugins/global/publish/collect_templates.py index 0c272a6044..46d2898875 100644 --- a/pype/plugins/global/publish/collect_templates.py +++ b/pype/plugins/global/publish/collect_templates.py @@ -88,7 +88,7 @@ class CollectTemplates(pyblish.api.InstancePlugin): "subset": subset_name, "version": version_number, "hierarchy": hierarchy.replace("\\", "/"), - "representation": "TEMP")} + "representation": "TEMP"} # Add datetime data to template data datetime_data = context.data.get("datetimeData") or {} From ed280250c4c39df742a52f29deaa0b237053b4ee Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 3 Feb 2020 18:29:45 +0100 Subject: [PATCH 31/38] fixed variable typo --- pype/plugins/global/publish/extract_burnin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/plugins/global/publish/extract_burnin.py b/pype/plugins/global/publish/extract_burnin.py index 85757c101b..e50ba891d2 100644 --- a/pype/plugins/global/publish/extract_burnin.py +++ b/pype/plugins/global/publish/extract_burnin.py @@ -45,7 +45,7 @@ class ExtractBurnin(pype.api.Extractor): } # Add datetime data to preparation data - datetime_data = isntance.context.data.get("datetimeData") or {} + datetime_data = instance.context.data.get("datetimeData") or {} prep_data.update(datetime_data) slate_frame_start = frame_start From fd42c048b36e1c527dc5ccd9d55f16e80b21850e Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 3 Feb 2020 18:36:37 +0100 Subject: [PATCH 32/38] collect templates fix there is not defined context --- pype/plugins/global/publish/collect_templates.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/plugins/global/publish/collect_templates.py b/pype/plugins/global/publish/collect_templates.py index 46d2898875..f065b3c246 100644 --- a/pype/plugins/global/publish/collect_templates.py +++ b/pype/plugins/global/publish/collect_templates.py @@ -91,7 +91,7 @@ class CollectTemplates(pyblish.api.InstancePlugin): "representation": "TEMP"} # Add datetime data to template data - datetime_data = context.data.get("datetimeData") or {} + datetime_data = instance.context.data.get("datetimeData") or {} template_data.update(datetime_data) resolution_width = instance.data.get("resolutionWidth") From 75b6cdd1489c94ee41b2cf94d5aeb99dbe2eac9f Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 3 Feb 2020 18:58:29 +0100 Subject: [PATCH 33/38] renamed repre_context_stable_keys to db_representation_context_keys --- pype/plugins/global/publish/integrate_new.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pype/plugins/global/publish/integrate_new.py b/pype/plugins/global/publish/integrate_new.py index bba93ed658..7d95534897 100644 --- a/pype/plugins/global/publish/integrate_new.py +++ b/pype/plugins/global/publish/integrate_new.py @@ -80,7 +80,7 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): "assembly" ] exclude_families = ["clip"] - repre_context_stable_keys = [ + db_representation_context_keys = [ "project", "asset", "task", "subset", "version", "representation", "family", "hierarchy", "task", "username" ] @@ -413,7 +413,7 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): repre['published_path'] = self.unc_convert(dst) self.log.debug("__ dst: {}".format(dst)) - for key in self.repre_context_stable_keys: + for key in self.db_representation_context_keys: value = template_data.get(key) if not value: continue From 25a6cd2c13ea0da2af2698c6e4b0442fc438e6e9 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 4 Feb 2020 00:12:09 +0100 Subject: [PATCH 34/38] fixed avalon entity check for nukestudio publish --- pype/ftrack/events/event_sync_to_avalon.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/ftrack/events/event_sync_to_avalon.py b/pype/ftrack/events/event_sync_to_avalon.py index 23284a2ae6..1b245efaa8 100644 --- a/pype/ftrack/events/event_sync_to_avalon.py +++ b/pype/ftrack/events/event_sync_to_avalon.py @@ -1437,7 +1437,7 @@ class SyncToAvalonEvent(BaseEvent): .get("name", {}) .get("new") ) - avalon_ent_by_name = self.avalon_ents_by_name.get(name) + avalon_ent_by_name = self.avalon_ents_by_name.get(name) or {} avalon_ent_by_name_ftrack_id = ( avalon_ent_by_name .get("data", {}) From f44011268cca59f593402b13b37e5c3a0cefe4db Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 4 Feb 2020 16:25:45 +0100 Subject: [PATCH 35/38] delete action tries to find entities by name and parents if ftrackId is not set in data --- pype/ftrack/actions/action_delete_asset.py | 37 ++++++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/pype/ftrack/actions/action_delete_asset.py b/pype/ftrack/actions/action_delete_asset.py index 7eb9126fca..5d177748cd 100644 --- a/pype/ftrack/actions/action_delete_asset.py +++ b/pype/ftrack/actions/action_delete_asset.py @@ -99,6 +99,7 @@ class DeleteAssetSubset(BaseAction): # Filter event even more (skip task entities) # - task entities are not relevant for avalon + entity_mapping = {} for entity in entities: ftrack_id = entity["id"] if ftrack_id not in ftrack_ids: @@ -107,6 +108,8 @@ class DeleteAssetSubset(BaseAction): if entity.entity_type.lower() == "task": ftrack_ids.remove(ftrack_id) + entity_mapping[ftrack_id] = entity + if not ftrack_ids: # It is bug if this happens! return { @@ -122,11 +125,39 @@ class DeleteAssetSubset(BaseAction): project_name = project["full_name"] self.dbcon.Session["AVALON_PROJECT"] = project_name - selected_av_entities = self.dbcon.find({ + selected_av_entities = list(self.dbcon.find({ "type": "asset", "data.ftrackId": {"$in": ftrack_ids} - }) - selected_av_entities = [ent for ent in selected_av_entities] + })) + if len(selected_av_entities) != len(ftrack_ids): + found_ftrack_ids = [ + ent["data"]["ftrackId"] for ent in selected_av_entities + ] + for ftrack_id, entity in entity_mapping.items(): + if ftrack_id in found_ftrack_ids: + continue + + av_ents_by_name = list(self.dbcon.find({ + "type": "asset", + "name": entity["name"] + })) + if not av_ents_by_name: + continue + + ent_path_items = [ent["name"] for ent in entity["link"]] + parents = ent_path_items[1:len(ent_path_items)-1:] + # TODO we should say to user that + # few of them are missing in avalon + for av_ent in av_ents_by_name: + if av_ent["data"]["parents"] != parents: + continue + + # TODO we should say to user that found entity + # with same name does not match same ftrack id? + if "ftrackId" not in av_ent["data"]: + selected_av_entities.append(av_ent) + break + if not selected_av_entities: return { "success": False, From d57586c76b22e9d57b56e9abf831cb49e4e570db Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 4 Feb 2020 16:47:26 +0100 Subject: [PATCH 36/38] added mapping for avalon -> ftrack id if ftrackId is not in entity's data --- pype/ftrack/actions/action_delete_asset.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/pype/ftrack/actions/action_delete_asset.py b/pype/ftrack/actions/action_delete_asset.py index 5d177748cd..fc9e66e4f8 100644 --- a/pype/ftrack/actions/action_delete_asset.py +++ b/pype/ftrack/actions/action_delete_asset.py @@ -129,6 +129,7 @@ class DeleteAssetSubset(BaseAction): "type": "asset", "data.ftrackId": {"$in": ftrack_ids} })) + found_without_ftrack_id = {} if len(selected_av_entities) != len(ftrack_ids): found_ftrack_ids = [ ent["data"]["ftrackId"] for ent in selected_av_entities @@ -156,6 +157,7 @@ class DeleteAssetSubset(BaseAction): # with same name does not match same ftrack id? if "ftrackId" not in av_ent["data"]: selected_av_entities.append(av_ent) + found_without_ftrack_id[str(av_ent["_id"])] = ftrack_id break if not selected_av_entities: @@ -186,7 +188,8 @@ class DeleteAssetSubset(BaseAction): "created_at": datetime.now(), "project_name": project_name, "subset_ids_by_name": {}, - "subset_ids_by_parent": {} + "subset_ids_by_parent": {}, + "without_ftrack_id": found_without_ftrack_id } id_item = { @@ -444,14 +447,21 @@ class DeleteAssetSubset(BaseAction): asset_ids_to_archive = [] ftrack_ids_to_delete = [] if len(assets_to_delete) > 0: + map_av_ftrack_id = spec_data["without_ftrack_id"] # Prepare data when deleting whole avalon asset avalon_assets = self.dbcon.find({"type": "asset"}) avalon_assets_by_parent = collections.defaultdict(list) for asset in avalon_assets: + asset_id = asset["_id"] parent_id = asset["data"]["visualParent"] avalon_assets_by_parent[parent_id].append(asset) - if asset["_id"] in assets_to_delete: - ftrack_id = asset["data"]["ftrackId"] + if asset_id in assets_to_delete: + ftrack_id = map_av_ftrack_id.get(str(asset_id)) + if not ftrack_id: + ftrack_id = asset["data"].get("ftrackId") + + if not ftrack_id: + continue ftrack_ids_to_delete.append(ftrack_id) children_queue = Queue() From 569bd6165859670365dce17fbe891af9dc56711f Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 4 Feb 2020 17:36:46 +0100 Subject: [PATCH 37/38] fix(nk, nks): some fixes for loading sequence and mov --- .../global/publish/collect_templates.py | 4 ++- pype/plugins/nuke/load/load_mov.py | 34 +++++++++++++++++-- pype/plugins/nuke/load/load_sequence.py | 21 ++++++++++-- 3 files changed, 53 insertions(+), 6 deletions(-) diff --git a/pype/plugins/global/publish/collect_templates.py b/pype/plugins/global/publish/collect_templates.py index 383944e293..5ad7aa7320 100644 --- a/pype/plugins/global/publish/collect_templates.py +++ b/pype/plugins/global/publish/collect_templates.py @@ -78,6 +78,8 @@ class CollectTemplates(pyblish.api.InstancePlugin): if hierarchy: # hierarchy = os.path.sep.join(hierarchy) hierarchy = os.path.join(*hierarchy) + else: + hierarchy = "" template_data = {"root": api.Session["AVALON_PROJECTS"], "project": {"name": project_name, @@ -88,7 +90,7 @@ class CollectTemplates(pyblish.api.InstancePlugin): "subset": subset_name, "version": version_number, "hierarchy": hierarchy.replace("\\", "/"), - "representation": "TEMP")} + "representation": "TEMP"} resolution_width = instance.data.get("resolutionWidth") resolution_height = instance.data.get("resolutionHeight") diff --git a/pype/plugins/nuke/load/load_mov.py b/pype/plugins/nuke/load/load_mov.py index 655937b9a8..fccba4c573 100644 --- a/pype/plugins/nuke/load/load_mov.py +++ b/pype/plugins/nuke/load/load_mov.py @@ -111,8 +111,15 @@ class LoadMov(api.Loader): if namespace is None: namespace = context['asset']['name'] - file = self.fname.replace("\\", "/") - log.info("file: {}\n".format(self.fname)) + file = self.fname + + if not file: + repr_id = context["representation"]["_id"] + log.warning( + "Representation id `{}` is failing to load".format(repr_id)) + return + + file = file.replace("\\", "/") read_name = "Read_{0}_{1}_{2}".format( repr_cont["asset"], @@ -200,7 +207,15 @@ class LoadMov(api.Loader): assert node.Class() == "Read", "Must be Read" - file = self.fname.replace("\\", "/") + file = self.fname + + if not file: + repr_id = representation["_id"] + log.warning( + "Representation id `{}` is failing to load".format(repr_id)) + return + + file = file.replace("\\", "/") # Get start frame from version data version = io.find_one({ @@ -263,6 +278,19 @@ class LoadMov(api.Loader): if colorspace: node["colorspace"].setValue(str(colorspace)) + # load nuke presets for Read's colorspace + read_clrs_presets = presets.get_colorspace_preset().get( + "nuke", {}).get("read", {}) + + # check if any colorspace presets for read is mathing + preset_clrsp = next((read_clrs_presets[k] + for k in read_clrs_presets + if bool(re.search(k, file))), + None) + if preset_clrsp is not None: + node["colorspace"].setValue(str(preset_clrsp)) + + updated_dict = {} updated_dict.update({ "representation": str(representation["_id"]), diff --git a/pype/plugins/nuke/load/load_sequence.py b/pype/plugins/nuke/load/load_sequence.py index 9f3d09186c..76ff7d2cb6 100644 --- a/pype/plugins/nuke/load/load_sequence.py +++ b/pype/plugins/nuke/load/load_sequence.py @@ -107,7 +107,15 @@ class LoadSequence(api.Loader): first -= self.handle_start last += self.handle_end - file = self.fname.replace("\\", "/") + file = self.fname + + if not file: + repr_id = context["representation"]["_id"] + log.warning( + "Representation id `{}` is failing to load".format(repr_id)) + return + + file = file.replace("\\", "/") repr_cont = context["representation"]["context"] if "#" not in file: @@ -229,7 +237,16 @@ class LoadSequence(api.Loader): assert node.Class() == "Read", "Must be Read" repr_cont = representation["context"] - file = self.fname.replace("\\", "/") + + file = self.fname + + if not file: + repr_id = representation["_id"] + log.warning( + "Representation id `{}` is failing to load".format(repr_id)) + return + + file = file.replace("\\", "/") if "#" not in file: frame = repr_cont.get("frame") From 38b563495506e028f92b6078e1988235bca30c7c Mon Sep 17 00:00:00 2001 From: Milan Kolar Date: Wed, 5 Feb 2020 14:07:29 +0100 Subject: [PATCH 38/38] update nukestudio init to new install way --- pype/nukestudio/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/nukestudio/__init__.py b/pype/nukestudio/__init__.py index 097f077e15..75825d188a 100644 --- a/pype/nukestudio/__init__.py +++ b/pype/nukestudio/__init__.py @@ -51,7 +51,7 @@ if os.getenv("PYBLISH_GUI", None): pyblish.register_gui(os.getenv("PYBLISH_GUI", None)) -def install(config): +def install(): """ Installing Nukestudio integration for avalon