From c608e1335fa9b700eab426caa5238ac34c398df8 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 18 Dec 2018 12:59:49 +0100 Subject: [PATCH] implemented review [mov, thumbnail], upversioning script sinchronized with publishing write --- pype/plugins/ftrack/integrate_ftrack_api.py | 2 +- .../ftrack/integrate_ftrack_instances.py | 2 +- .../global/publish/collect_templates.py | 12 +- pype/plugins/global/publish/integrate.py | 3 +- .../_publish_unused/collect_render_target.py | 47 ----- .../extract_nuke_baked_colorspace.py | 107 ---------- pype/plugins/nuke/publish/collect_families.py | 14 +- pype/plugins/nuke/publish/collect_review.py | 27 +++ pype/plugins/nuke/publish/collect_script.py | 14 +- pype/plugins/nuke/publish/collect_writes.py | 7 +- pype/plugins/nuke/publish/extract_frames.py | 21 ++ .../nuke/publish/extract_render_local.py | 16 +- pype/plugins/nuke/publish/extract_review.py | 186 ++++++++++++++++++ pype/plugins/nuke/publish/extract_script.py | 29 ++- .../nuke/publish/integrate_rendered_frames.py | 30 ++- .../nuke/publish/integrate_script_version.py | 7 +- .../nuke/publish/validate_collection.py | 28 ++- 17 files changed, 326 insertions(+), 226 deletions(-) delete mode 100644 pype/plugins/nuke/_publish_unused/collect_render_target.py delete mode 100644 pype/plugins/nuke/_publish_unused/extract_nuke_baked_colorspace.py create mode 100644 pype/plugins/nuke/publish/collect_review.py create mode 100644 pype/plugins/nuke/publish/extract_frames.py create mode 100644 pype/plugins/nuke/publish/extract_review.py diff --git a/pype/plugins/ftrack/integrate_ftrack_api.py b/pype/plugins/ftrack/integrate_ftrack_api.py index 279dfb9b54..ce827dba04 100644 --- a/pype/plugins/ftrack/integrate_ftrack_api.py +++ b/pype/plugins/ftrack/integrate_ftrack_api.py @@ -281,7 +281,7 @@ class IntegrateFtrackApi(pyblish.api.InstancePlugin): # Inform user about no changes to the database. if (component_entity and not component_overwrite and - not new_component): + not new_component): data["component"] = component_entity self.log.info( "Found existing component, and no request to overwrite. " diff --git a/pype/plugins/ftrack/integrate_ftrack_instances.py b/pype/plugins/ftrack/integrate_ftrack_instances.py index 5e0c108442..4c68855fd3 100644 --- a/pype/plugins/ftrack/integrate_ftrack_instances.py +++ b/pype/plugins/ftrack/integrate_ftrack_instances.py @@ -24,7 +24,7 @@ class IntegrateFtrackInstance(pyblish.api.InstancePlugin): 'pointcache': 'cache', 'write': 'img', 'render': 'render', - 'script': 'comp', + 'nukescript': 'comp', 'review': 'mov'} exclude = [] diff --git a/pype/plugins/global/publish/collect_templates.py b/pype/plugins/global/publish/collect_templates.py index 48b6c448e3..fb6de894bd 100644 --- a/pype/plugins/global/publish/collect_templates.py +++ b/pype/plugins/global/publish/collect_templates.py @@ -1,7 +1,5 @@ -from app.api import ( - Templates -) +import pype.api as pype import pyblish.api @@ -13,8 +11,6 @@ class CollectTemplates(pyblish.api.ContextPlugin): label = "Collect Templates" def process(self, context): - """Inject the current working file""" - templates = Templates( - type=["anatomy"] - ) - context.data['anatomy'] = templates.anatomy + pype.load_data_from_templates() + context.data['anatomy'] = pype.Anatomy + self.log.info("Anatomy templates collected...") diff --git a/pype/plugins/global/publish/integrate.py b/pype/plugins/global/publish/integrate.py index 2dbdb13ced..0d3aca32aa 100644 --- a/pype/plugins/global/publish/integrate.py +++ b/pype/plugins/global/publish/integrate.py @@ -36,7 +36,7 @@ class IntegrateAsset(pyblish.api.InstancePlugin): "vrayproxy", "yetiRig", "yeticache", - "script", + "nukescript", "review"] def process(self, instance): @@ -47,7 +47,6 @@ class IntegrateAsset(pyblish.api.InstancePlugin): self.integrate(instance) def register(self, instance): - # Required environment variables PROJECT = api.Session["AVALON_PROJECT"] ASSET = instance.data.get("asset") or api.Session["AVALON_ASSET"] diff --git a/pype/plugins/nuke/_publish_unused/collect_render_target.py b/pype/plugins/nuke/_publish_unused/collect_render_target.py deleted file mode 100644 index 86a38f26b6..0000000000 --- a/pype/plugins/nuke/_publish_unused/collect_render_target.py +++ /dev/null @@ -1,47 +0,0 @@ -import pyblish.api - - -class CollectNukeRenderMode(pyblish.api.InstancePlugin): - # TODO: rewrite docstring to nuke - """Collect current comp's render Mode - - Options: - local - deadline - - Note that this value is set for each comp separately. When you save the - comp this information will be stored in that file. If for some reason the - available tool does not visualize which render mode is set for the - current comp, please run the following line in the console (Py2) - - comp.GetData("rendermode") - - This will return the name of the current render mode as seen above under - Options. - - """ - - order = pyblish.api.CollectorOrder + 0.4 - label = "Collect Render Mode" - hosts = ["nuke"] - families = ["write", "render.local"] - - def process(self, instance): - """Collect all image sequence tools""" - options = ["local", "deadline"] - - node = instance[0] - - if bool(node["render_local"].getValue()): - rendermode = "local" - else: - rendermode = "deadline" - - assert rendermode in options, "Must be supported render mode" - - # Append family - instance.data["families"].remove("render") - family = "render.{0}".format(rendermode) - instance.data["families"].append(family) - - self.log.info("Render mode: {0}".format(rendermode)) diff --git a/pype/plugins/nuke/_publish_unused/extract_nuke_baked_colorspace.py b/pype/plugins/nuke/_publish_unused/extract_nuke_baked_colorspace.py deleted file mode 100644 index f2561bd7c5..0000000000 --- a/pype/plugins/nuke/_publish_unused/extract_nuke_baked_colorspace.py +++ /dev/null @@ -1,107 +0,0 @@ -import os -import tempfile -import shutil - -import nuke - -import pyblish.api - - -class ExtractNukeBakedColorspace(pyblish.api.InstancePlugin): - """Extracts movie with baked in luts - - V:\Remote Apps\ffmpeg\bin>ffmpeg -y -i - V:/FUGA/VFX_OUT/VFX_070010/v02/VFX_070010_comp_v02._baked.mov - -pix_fmt yuv420p - -crf 18 - -timecode 00:00:00:01 - V:/FUGA/VFX_OUT/VFX_070010/v02/VFX_070010_comp_v02..mov - - """ - - order = pyblish.api.ExtractorOrder - label = "Baked Colorspace" - optional = True - families = ["review"] - hosts = ["nuke"] - - def process(self, instance): - - if "collection" not in instance.data.keys(): - return - - # Store selection - selection = [i for i in nuke.allNodes() if i["selected"].getValue()] - - # Deselect all nodes to prevent external connections - [i["selected"].setValue(False) for i in nuke.allNodes()] - - temporary_nodes = [] - - # Create nodes - first_frame = min(instance.data["collection"].indexes) - last_frame = max(instance.data["collection"].indexes) - - temp_dir = tempfile.mkdtemp() - for f in instance.data["collection"]: - shutil.copy(f, os.path.join(temp_dir, os.path.basename(f))) - - node = previous_node = nuke.createNode("Read") - node["file"].setValue( - os.path.join(temp_dir, - os.path.basename(instance.data["collection"].format( - "{head}{padding}{tail}"))).replace("\\", "/")) - - node["first"].setValue(first_frame) - node["origfirst"].setValue(first_frame) - node["last"].setValue(last_frame) - node["origlast"].setValue(last_frame) - temporary_nodes.append(node) - - reformat_node = nuke.createNode("Reformat") - reformat_node["format"].setValue("HD_1080") - reformat_node["resize"].setValue("fit") - reformat_node["filter"].setValue("Lanczos6") - reformat_node["black_outside"].setValue(True) - reformat_node.setInput(0, previous_node) - previous_node = reformat_node - temporary_nodes.append(reformat_node) - - viewer_process_node = nuke.ViewerProcess.node() - dag_node = None - if viewer_process_node: - dag_node = nuke.createNode(viewer_process_node.Class()) - dag_node.setInput(0, previous_node) - previous_node = dag_node - temporary_nodes.append(dag_node) - # Copy viewer process values - excludedKnobs = ["name", "xpos", "ypos"] - for item in viewer_process_node.knobs().keys(): - if item not in excludedKnobs and item in dag_node.knobs(): - x1 = viewer_process_node[item] - x2 = dag_node[item] - x2.fromScript(x1.toScript(False)) - else: - self.log.warning("No viewer node found.") - - write_node = nuke.createNode("Write") - path = instance.data["collection"].format("{head}_baked.mov") - instance.data["baked_colorspace_movie"] = path - write_node["file"].setValue(path.replace("\\", "/")) - write_node["file_type"].setValue("mov") - write_node["raw"].setValue(1) - write_node.setInput(0, previous_node) - temporary_nodes.append(write_node) - - # Render frames - nuke.execute(write_node.name(), int(first_frame), int(last_frame)) - - # Clean up - for node in temporary_nodes: - nuke.delete(node) - - shutil.rmtree(temp_dir) - - # Restore selection - [i["selected"].setValue(False) for i in nuke.allNodes()] - [i["selected"].setValue(True) for i in selection] diff --git a/pype/plugins/nuke/publish/collect_families.py b/pype/plugins/nuke/publish/collect_families.py index a361ceceab..226df3b168 100644 --- a/pype/plugins/nuke/publish/collect_families.py +++ b/pype/plugins/nuke/publish/collect_families.py @@ -23,20 +23,20 @@ class CollectInstanceFamilies(pyblish.api.ContextPlugin): node = instance[0] if not node["render"].value(): - families = "{}.frames".format( - instance.data["avalonKnob"]["families"]) + families = ["{}.frames".format( + instance.data["avalonKnob"]["families"])] # to ignore staging dir op in integrate instance.data['transfer'] = False else: # dealing with local/farm rendering if node["render_farm"].value(): - families = "{}.farm".format( - instance.data["avalonKnob"]["families"]) + families = ["{}.farm".format( + instance.data["avalonKnob"]["families"])] else: - families = "{}.local".format( - instance.data["avalonKnob"]["families"]) + families = ["{}.local".format( + instance.data["avalonKnob"]["families"])] - instance.data["families"].append(families) + instance.data["families"].extend(families) # Sort/grouped by family (preserving local index) context[:] = sorted(context, key=self.sort_by_family) diff --git a/pype/plugins/nuke/publish/collect_review.py b/pype/plugins/nuke/publish/collect_review.py new file mode 100644 index 0000000000..03f5437e86 --- /dev/null +++ b/pype/plugins/nuke/publish/collect_review.py @@ -0,0 +1,27 @@ +import pyblish.api + + +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 = ["write"] + + family_targets = [".local", ".frames"] + + def process(self, instance): + families = [(f, search) for f in instance.data["families"] + for search in self.family_targets + if search in f][0] + + if families: + root_femilies = families[0].replace(families[1], "") + instance.data["families"].append(".".join([ + root_femilies, + self.family + ])) + self.log.info("Review collected: `{}`".format(instance)) diff --git a/pype/plugins/nuke/publish/collect_script.py b/pype/plugins/nuke/publish/collect_script.py index 099217c8bb..92557b2665 100644 --- a/pype/plugins/nuke/publish/collect_script.py +++ b/pype/plugins/nuke/publish/collect_script.py @@ -2,7 +2,6 @@ from avalon import api, io import nuke import pyblish.api import os -import tempfile from avalon.nuke.lib import ( add_publish_knob, add_avalon_tab_knob @@ -25,10 +24,11 @@ class CollectScript(pyblish.api.ContextPlugin): add_avalon_tab_knob(root) add_publish_knob(root) + family = "nukescript" # creating instances per write node file_path = root['name'].value() base_name = os.path.basename(file_path) - subset = base_name.split("_v")[0] + subset = "{0}_{1}".format(os.getenv("AVALON_TASK", None), family) # Get frame range first_frame = int(root["first_frame"].getValue()) @@ -38,25 +38,19 @@ class CollectScript(pyblish.api.ContextPlugin): instance = context.create_instance(subset) instance.add(root) - # adding stage dir for faster local renderings - staging_dir = tempfile.mkdtemp().replace("\\", "/") - instance.data.update({"stagingDir": staging_dir}) - self.log.info('nukescript: staging_dir: {}'.format(staging_dir)) - instance.data.update({ - "subset": os.getenv("AVALON_TASK", None), + "subset": subset, "asset": os.getenv("AVALON_ASSET", None), "label": base_name, "name": base_name, "startFrame": first_frame, "endFrame": last_frame, "publish": root.knob('publish').value(), - "family": "nukescript", + "family": family, "representation": "nk", "handles": int(asset_data["data"].get("handles", 0)), "step": 1, "fps": int(root['fps'].value()), - "files": base_name }) self.log.info('Publishing script version') context.data["instances"].append(instance) diff --git a/pype/plugins/nuke/publish/collect_writes.py b/pype/plugins/nuke/publish/collect_writes.py index 96f14c7eaa..dd3247ae8f 100644 --- a/pype/plugins/nuke/publish/collect_writes.py +++ b/pype/plugins/nuke/publish/collect_writes.py @@ -68,16 +68,11 @@ class CollectNukeWrites(pyblish.api.ContextPlugin): try: collected_frames = os.listdir(output_dir) self.log.debug("collected_frames: {}".format(label)) - instance.data["files"].append(collected_frames) + except Exception: pass - # adding stage dir for faster local renderings - staging_dir = tempfile.mkdtemp().replace("\\", "/") - instance.data.update({"stagingDir": staging_dir}) - self.log.debug('staging_dir: {}'.format(staging_dir)) - instance.data.update({ "path": path, "outputDir": output_dir, diff --git a/pype/plugins/nuke/publish/extract_frames.py b/pype/plugins/nuke/publish/extract_frames.py new file mode 100644 index 0000000000..bdbcb75cea --- /dev/null +++ b/pype/plugins/nuke/publish/extract_frames.py @@ -0,0 +1,21 @@ +import pyblish + + +class ExtractFramesToIntegrate(pyblish.api.InstancePlugin): + """Extract rendered frames for integrator + """ + + order = pyblish.api.ExtractorOrder + label = "Extract rendered frames" + hosts = ["nuke"] + families = ["render.frames", "prerender.frames", "still.frames"] + + def process(self, instance): + + staging_dir = instance.data.get('stagingDir', None) + output_dir = instance.data.get('outputDir', None) + + if not staging_dir: + staging_dir = output_dir + instance.data['stagingDir'] = staging_dir + instance.data['transfer'] = False diff --git a/pype/plugins/nuke/publish/extract_render_local.py b/pype/plugins/nuke/publish/extract_render_local.py index 95733b1d85..6feab98786 100644 --- a/pype/plugins/nuke/publish/extract_render_local.py +++ b/pype/plugins/nuke/publish/extract_render_local.py @@ -1,10 +1,10 @@ import pyblish.api import nuke -import shutil import os +import pype -class NukeRenderLocal(pyblish.api.InstancePlugin): +class NukeRenderLocal(pype.api.Extractor): # TODO: rewrite docstring to nuke """Render the current Fusion composition locally. @@ -36,7 +36,7 @@ class NukeRenderLocal(pyblish.api.InstancePlugin): node_subset_name = instance.data.get("name", None) # swap path to stageDir - temp_dir = instance.data.get("stagingDir") + temp_dir = self.staging_dir(instance).replace("\\", "/") output_dir = instance.data.get("outputDir") path = node['file'].value() node['file'].setValue(path.replace(output_dir, temp_dir)) @@ -56,4 +56,14 @@ class NukeRenderLocal(pyblish.api.InstancePlugin): path = node['file'].value() node['file'].setValue(path.replace(temp_dir, output_dir)) + if "files" not in instance.data: + instance.data["files"] = list() + + instance.data["files"].append(os.listdir(temp_dir)) + + self.log.info("Extracted instance '{0}' to: {1}".format( + instance.name, + output_dir + )) + self.log.info('Finished render') diff --git a/pype/plugins/nuke/publish/extract_review.py b/pype/plugins/nuke/publish/extract_review.py new file mode 100644 index 0000000000..6541774c3b --- /dev/null +++ b/pype/plugins/nuke/publish/extract_review.py @@ -0,0 +1,186 @@ +import os +import nuke +import pyblish.api +import pype + + +class ExtractDataForReview(pype.api.Extractor): + """Extracts movie and thumbnail with baked in luts + + must be run after extract_render_local.py + + """ + + order = pyblish.api.ExtractorOrder + 0.01 + label = "Data for review" + optional = True + + families = ["write"] + hosts = ["nuke"] + family_targets = [".local", ".review"] + + def process(self, instance): + + families = [f for f in instance.data["families"] + for search in self.family_targets + if search in f] + if not families: + return + + # Store selection + selection = [i for i in nuke.allNodes() if i["selected"].getValue()] + + # Deselect all nodes to prevent external connections + [i["selected"].setValue(False) for i in nuke.allNodes()] + + self.staging_dir(instance) + self.render_review_representation(instance, + representation="mov") + self.transcode_mov(instance) + self.render_review_representation(instance, + representation="jpeg") + # Restore selection + [i["selected"].setValue(False) for i in nuke.allNodes()] + [i["selected"].setValue(True) for i in selection] + + def transcode_mov(self, instance): + import subprocess + + collection = instance.data["collection"] + staging_dir = instance.data["stagingDir"] + file_name = collection.format("{head}mov") + + review_mov = os.path.join(staging_dir, file_name) + + if instance.data.get("baked_colorspace_movie"): + args = [ + "ffmpeg", "-y", + "-i", instance.data["baked_colorspace_movie"], + "-pix_fmt", "yuv420p", + "-crf", "18", + "-timecode", "00:00:00:01", + ] + + args.append(review_mov) + + self.log.debug("Executing args: {0}".format(args)) + + self.log.info("transcoding review mov: {0}".format(review_mov)) + p = subprocess.Popen( + args, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + stdin=subprocess.PIPE, + cwd=os.path.dirname(args[-1]) + ) + + output = p.communicate()[0] + + if p.returncode != 0: + raise ValueError(output) + + self.log.debug("Removing `{0}`...".format( + instance.data["baked_colorspace_movie"])) + os.remove(instance.data["baked_colorspace_movie"]) + + instance.data["files"].append(file_name) + + def render_review_representation(self, + instance, + representation="mov"): + + assert instance.data['files'], "Instance data files should't be empty!" + + import clique + import nuke + temporary_nodes = [] + staging_dir = instance.data["stagingDir"] + + collection = instance.data.get("collection", None) + + if not collection: + collections, remainder = clique.assemble(*instance.data['files']) + collection = collections[0] + instance.data["collection"] = collection + + # Create nodes + first_frame = min(collection.indexes) + last_frame = max(collection.indexes) + + self.log.warning("first_frame: {}".format(first_frame)) + self.log.warning("last_frame: {}".format(last_frame)) + + node = previous_node = nuke.createNode("Read") + + node["file"].setValue( + os.path.join(staging_dir, + os.path.basename(collection.format( + "{head}{padding}{tail}"))).replace("\\", "/")) + + node["first"].setValue(first_frame) + node["origfirst"].setValue(first_frame) + node["last"].setValue(last_frame) + node["origlast"].setValue(last_frame) + temporary_nodes.append(node) + + reformat_node = nuke.createNode("Reformat") + reformat_node["format"].setValue("HD_1080") + reformat_node["resize"].setValue("fit") + reformat_node["filter"].setValue("Lanczos6") + reformat_node["black_outside"].setValue(True) + reformat_node.setInput(0, previous_node) + previous_node = reformat_node + temporary_nodes.append(reformat_node) + + viewer_process_node = nuke.ViewerProcess.node() + dag_node = None + if viewer_process_node: + dag_node = nuke.createNode(viewer_process_node.Class()) + dag_node.setInput(0, previous_node) + previous_node = dag_node + temporary_nodes.append(dag_node) + # Copy viewer process values + excludedKnobs = ["name", "xpos", "ypos"] + for item in viewer_process_node.knobs().keys(): + if item not in excludedKnobs and item in dag_node.knobs(): + x1 = viewer_process_node[item] + x2 = dag_node[item] + x2.fromScript(x1.toScript(False)) + else: + self.log.warning("No viewer node found.") + + # create write node + write_node = nuke.createNode("Write") + + if representation in "mov": + file = collection.format("{head}baked.mov") + path = os.path.join(staging_dir, file).replace("\\", "/") + instance.data["baked_colorspace_movie"] = path + write_node["file"].setValue(path) + write_node["file_type"].setValue("mov") + write_node["raw"].setValue(1) + write_node.setInput(0, previous_node) + temporary_nodes.append(write_node) + + elif representation in "jpeg": + file = collection.format("{head}jpeg") + path = os.path.join(staging_dir, file).replace("\\", "/") + instance.data["thumbnail"] = path + write_node["file"].setValue(path) + write_node["file_type"].setValue("jpeg") + write_node["raw"].setValue(1) + write_node.setInput(0, previous_node) + temporary_nodes.append(write_node) + + # retime for + first_frame = int(last_frame)/2 + last_frame = int(last_frame)/2 + # add into files for integration as representation + instance.data["files"].append(file) + + # Render frames + nuke.execute(write_node.name(), int(first_frame), int(last_frame)) + + # Clean up + for node in temporary_nodes: + nuke.delete(node) diff --git a/pype/plugins/nuke/publish/extract_script.py b/pype/plugins/nuke/publish/extract_script.py index 573fb9598a..f0ed438094 100644 --- a/pype/plugins/nuke/publish/extract_script.py +++ b/pype/plugins/nuke/publish/extract_script.py @@ -1,21 +1,34 @@ -import nuke + import pyblish.api import os +import pype +import shutil -class ExtractScript(pyblish.api.InstancePlugin): +class ExtractScript(pype.api.Extractor): """Publish script """ label = 'Extract Script' order = pyblish.api.ExtractorOrder - 0.05 + optional = True hosts = ['nuke'] - families = ["script"] + families = ["nukescript"] def process(self, instance): + self.log.debug("instance extracting: {}".format(instance.data)) + current_script = instance.context.data["currentFile"] - self.log.info('Extracting script') - staging_dir = instance.data["stagingDir"] - file_name = instance.data["name"] - path = os.path.join(staging_dir, file_name) + # Define extract output file path + dir_path = self.staging_dir(instance) + filename = "{0}".format(instance.data["name"]) + path = os.path.join(dir_path, filename) - nuke.scriptSaveAs(path) + self.log.info("Performing extraction..") + shutil.copy(current_script, path) + + if "files" not in instance.data: + instance.data["files"] = list() + + instance.data["files"].append(filename) + + self.log.info("Extracted instance '%s' to: %s" % (instance.name, path)) diff --git a/pype/plugins/nuke/publish/integrate_rendered_frames.py b/pype/plugins/nuke/publish/integrate_rendered_frames.py index 9472cdf36b..6d1434a77f 100644 --- a/pype/plugins/nuke/publish/integrate_rendered_frames.py +++ b/pype/plugins/nuke/publish/integrate_rendered_frames.py @@ -24,14 +24,21 @@ class IntegrateFrames(pyblish.api.InstancePlugin): label = "Integrate Frames" order = pyblish.api.IntegratorOrder - families = ["render.frames", "still.frames", "prerender.frames", - "render.local", "still.local", "prerender.local"] + family_targets = [".frames", ".local", ".review"] def process(self, instance): + families = [f for f in instance.data["families"] + for search in self.family_targets + if search in f] + + if not families: + return + self.register(instance) self.log.info("Integrating Asset in to the database ...") + self.log.info("instance.data: {}".format(instance.data)) if instance.data.get('transfer', True): self.integrate(instance) @@ -97,7 +104,7 @@ class IntegrateFrames(pyblish.api.InstancePlugin): self.log.info("Verifying version from assumed destination") assumed_data = instance.data["assumedTemplateData"] - assumed_version = assumed_data["version"] + assumed_version = assumed_data["VERSION"] if assumed_version != next_version: raise AttributeError("Assumed version 'v{0:03d}' does not match" "next version in database " @@ -149,7 +156,8 @@ class IntegrateFrames(pyblish.api.InstancePlugin): # Each should be a single representation (as such, a single extension) representations = [] destination_list = [] - + self.log.debug("integrate_frames:instance.data[files]: {}".format( + instance.data["files"])) for files in instance.data["files"]: # Collection # _______ @@ -167,7 +175,7 @@ class IntegrateFrames(pyblish.api.InstancePlugin): dst_collection = [] for fname in collection: - + self.log.warning("fname: {}".format(fname)) filename, ext = os.path.splitext(fname) _, frame = os.path.splitext(filename) @@ -195,7 +203,12 @@ class IntegrateFrames(pyblish.api.InstancePlugin): # | | # |_______| # + + if template_data.get("frame"): + template_data.pop("frame") + fname = files + self.log.info("fname: {}".format(fname)) assert not os.path.isabs(fname), ( "Given file name is a full path" @@ -205,9 +218,11 @@ class IntegrateFrames(pyblish.api.InstancePlugin): template_data["representation"] = ext[1:] src = os.path.join(stagingdir, fname) + anatomy_filled = anatomy.format(template_data) dst = anatomy_filled.render.path template = anatomy.render.path + instance.data["transfers"].append([src, dst]) representation = { @@ -254,6 +269,11 @@ class IntegrateFrames(pyblish.api.InstancePlugin): transfers = instance.data["transfers"] for src, dest in transfers: + src = os.path.normpath(src) + dest = os.path.normpath(dest) + if src in dest: + continue + self.log.info("Copying file .. {} -> {}".format(src, dest)) self.copy_file(src, dest) diff --git a/pype/plugins/nuke/publish/integrate_script_version.py b/pype/plugins/nuke/publish/integrate_script_version.py index c664cbb05d..aa37101af0 100644 --- a/pype/plugins/nuke/publish/integrate_script_version.py +++ b/pype/plugins/nuke/publish/integrate_script_version.py @@ -3,18 +3,17 @@ import nuke import pyblish.api -class IncrementScriptVersion(pyblish.api.InstancePlugin): +class IncrementScriptVersion(pyblish.api.ContextPlugin): """Increment current script version.""" order = pyblish.api.IntegratorOrder + 0.9 label = "Increment Current Script Version" optional = True hosts = ['nuke'] - families = ["render.frames"] + families = ["nukescript", "render.local", "render.frames"] - def process(self, instance): + def process(self, context): from pype.lib import version_up - context = instance.context path = context.data["currentFile"] nuke.scriptSaveAs(version_up(path)) self.log.info('Incrementing script version') diff --git a/pype/plugins/nuke/publish/validate_collection.py b/pype/plugins/nuke/publish/validate_collection.py index 09498c58de..54b3537055 100644 --- a/pype/plugins/nuke/publish/validate_collection.py +++ b/pype/plugins/nuke/publish/validate_collection.py @@ -38,28 +38,22 @@ class ValidateCollection(pyblish.api.InstancePlugin): collections, remainder = clique.assemble(*instance.data['files']) self.log.info('collections: {}'.format(str(collections))) + collection = collections[0] + frame_length = instance.data["endFrame"] \ - instance.data["startFrame"] + 1 if frame_length is not 1: - assert len(collections) == 1, self.log.info( - "There are multiple collections in the folder") - assert collections[0].is_contiguous(), self.log.info("Some frames appear to be missing") + assert len(collections) == 1, "There are multiple collections in the folder" + assert collection.is_contiguous(), "Some frames appear to be missing" - assert remainder is not None, self.log.info("There are some extra files in folder") - - basename, ext = os.path.splitext(list(collections[0])[0]) - assert all(ext == os.path.splitext(name)[1] - for name in collections[0]), self.log.info( - "Files had varying suffixes" - ) - - assert not any(os.path.isabs(name) - for name in collections[0]), self.log.info("some file name are absolute") + assert remainder is not None, "There are some extra files in folder" self.log.info('frame_length: {}'.format(frame_length)) - self.log.info('len(list(instance.data["files"])): {}'.format( - len(list(instance.data["files"][0])))) + self.log.info('len(collection.indexes): {}'.format( + len(collection.indexes))) - assert len(list(instance.data["files"][0])) is frame_length, self.log.info( - "{} missing frames. Use repair to render all frames".format(__name__)) + assert len( + collection.indexes + ) is frame_length, "{} missing frames. Use " + "repair to render all frames".format(__name__)