diff --git a/pype/nuke/lib.py b/pype/nuke/lib.py index a9aac47228..6a57704fff 100644 --- a/pype/nuke/lib.py +++ b/pype/nuke/lib.py @@ -343,8 +343,6 @@ def reset_frame_range_handles(): """Set frame range to current asset""" root = nuke.root() - fps = float(api.Session.get("AVALON_FPS", 25)) - root["fps"].setValue(fps) name = api.Session["AVALON_ASSET"] asset = io.find_one({"name": name, "type": "asset"}) @@ -356,7 +354,7 @@ def reset_frame_range_handles(): data = asset["data"] missing_cols = [] - check_cols = ["fstart", "fend", "handle_start", "handle_end"] + check_cols = ["fps", "fstart", "fend", "handle_start", "handle_end"] for col in check_cols: if col not in data: @@ -373,20 +371,29 @@ def reset_frame_range_handles(): handles = avalon.nuke.get_handles(asset) handle_start, handle_end = pype.get_handle_irregular(asset) - log.info("__ handles: `{}`".format(handles)) - log.info("__ handle_start: `{}`".format(handle_start)) - log.info("__ handle_end: `{}`".format(handle_end)) - + fps = asset["data"]["fps"] edit_in = int(asset["data"]["fstart"]) - handle_start edit_out = int(asset["data"]["fend"]) + handle_end + root["fps"].setValue(fps) root["first_frame"].setValue(edit_in) root["last_frame"].setValue(edit_out) + log.info("__ handles: `{}`".format(handles)) + log.info("__ handle_start: `{}`".format(handle_start)) + log.info("__ handle_end: `{}`".format(handle_end)) + log.info("__ edit_in: `{}`".format(edit_in)) + log.info("__ edit_out: `{}`".format(edit_out)) + log.info("__ fps: `{}`".format(fps)) + # setting active viewers nuke.frame(int(asset["data"]["fstart"])) - vv = nuke.activeViewer().node() + try: + vv = nuke.activeViewer().node() + except AttributeError: + log.error("No active viewer. Select any node and hit num `1`") + return range = '{0}-{1}'.format( int(asset["data"]["fstart"]), diff --git a/pype/plugins/ftrack/publish/integrate_ftrack_instances.py b/pype/plugins/ftrack/publish/integrate_ftrack_instances.py index ef2ea6f6ca..02455454bb 100644 --- a/pype/plugins/ftrack/publish/integrate_ftrack_instances.py +++ b/pype/plugins/ftrack/publish/integrate_ftrack_instances.py @@ -56,6 +56,7 @@ class IntegrateFtrackInstance(pyblish.api.InstancePlugin): component_data = { "name": "thumbnail" # Default component name is "main". } + comp['thumbnail'] = True elif comp.get('preview') or ("preview" in comp.get('tags', [])): ''' Ftrack bug requirement: diff --git a/pype/plugins/global/publish/extract_burnin.py b/pype/plugins/global/publish/extract_burnin.py index 0559325ff2..5f16cc91f2 100644 --- a/pype/plugins/global/publish/extract_burnin.py +++ b/pype/plugins/global/publish/extract_burnin.py @@ -28,15 +28,14 @@ class ExtractBurnin(pype.api.Extractor): if instance.context.data.get('version'): version = "v" + str(instance.context.data['version']) - burnin_data = { + prep_data = { "username": instance.context.data['user'], "asset": os.environ['AVALON_ASSET'], "task": os.environ['AVALON_TASK'], "start_frame": int(instance.data['startFrame']), "version": version } - - self.log.debug("__ burnin_data1: {}".format(burnin_data)) + self.log.debug("__ prep_data: {}".format(prep_data)) for i, repre in enumerate(instance.data["representations"]): self.log.debug("__ i: `{}`, repre: `{}`".format(i, repre)) @@ -56,7 +55,7 @@ class ExtractBurnin(pype.api.Extractor): burnin_data = { "input": full_movie_path.replace("\\", "/"), "output": full_burnin_path.replace("\\", "/"), - "burnin_data": burnin_data + "burnin_data": prep_data } self.log.debug("__ burnin_data2: {}".format(burnin_data)) @@ -76,14 +75,17 @@ class ExtractBurnin(pype.api.Extractor): ) p.wait() if not os.path.isfile(full_burnin_path): - self.log.error( - "Burnin file wasn't created succesfully") + raise RuntimeError("File not existing: {}".format(full_burnin_path)) except Exception as e: raise RuntimeError("Burnin script didn't work: `{}`".format(e)) if os.path.exists(full_burnin_path): repre_update = { "files": movieFileBurnin, - "name": repre["name"] + name + "name": repre["name"] } 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)) diff --git a/pype/plugins/global/publish/extract_review.py b/pype/plugins/global/publish/extract_review.py index 62a2eb0bd4..3a764b19c3 100644 --- a/pype/plugins/global/publish/extract_review.py +++ b/pype/plugins/global/publish/extract_review.py @@ -36,7 +36,7 @@ class ExtractReview(pyblish.api.InstancePlugin): representations = instance.data["representations"] # filter out mov and img sequences - representations_new = representations.copy() + representations_new = representations[:] for repre in representations: if repre['ext'] in plugin_attrs["ext_filter"]: tags = repre.get("tags", []) @@ -46,10 +46,19 @@ class ExtractReview(pyblish.api.InstancePlugin): if "review" in tags: staging_dir = repre["stagingDir"] for name, profile in output_profiles.items(): + self.log.debug("Profile name: {}".format(name)) + + ext = profile.get("ext", None) + if not ext: + ext = "mov" + self.log.warning( + "`ext` attribute not in output profile. Setting to default ext: `mov`") + + self.log.debug("instance.families: {}".format(instance.data['families'])) + self.log.debug("profile.families: {}".format(profile['families'])) + if any(item in instance.data['families'] for item in profile['families']): if isinstance(repre["files"], list): - # if "mov" not in repre['ext']: - # get output presets and loop them collections, remainder = clique.assemble( repre["files"]) @@ -62,27 +71,26 @@ class ExtractReview(pyblish.api.InstancePlugin): if filename.endswith('.'): filename = filename[:-1] else: - self.log.info("1: {}".format(full_input_path)) full_input_path = os.path.join( staging_dir, repre["files"]) filename = repre["files"].split(".")[0] - mov_file = filename + "_{0}.{1}".format(name, "mov") + repr_file = filename + "_{0}.{1}".format(name, ext) - full_output_path = os.path.join(staging_dir, mov_file) + full_output_path = os.path.join( + staging_dir, repr_file) self.log.info("input {}".format(full_input_path)) self.log.info("output {}".format(full_output_path)) repre_new = repre.copy() - self.log.debug("Profile name: {}".format(name)) - new_tags = tags[:] 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 + [instance.data["families"].append(t) + for t in p_tags if t not in instance.data["families"]] # add to [new_tags.append(t) for t in p_tags @@ -101,16 +109,22 @@ class ExtractReview(pyblish.api.InstancePlugin): # necessary input data # adds start arg only if image sequence if "mov" not in repre_new['ext']: - input_args.append("-start_number {}".format( - start_frame)) + input_args.append("-start_number {0} -framerate {1}".format( + start_frame, fps)) input_args.append("-i {}".format(full_input_path)) - input_args.append("-framerate {}".format(fps)) output_args = [] # preset's output data output_args.extend(profile.get('output', [])) + # letter_box + # TODO: add to documentation + lb = profile.get('letter_box', None) + if lb: + output_args.append( + "-filter:v drawbox=0:0:iw:round((ih-(iw*(1/{0})))/2):t=fill:c=black,drawbox=0:ih-round((ih-(iw*(1/{0})))/2):iw:round((ih-(iw*(1/{0})))/2):t=fill:c=black".format(lb)) + # output filename output_args.append(full_output_path) mov_args = [ @@ -118,25 +132,25 @@ class ExtractReview(pyblish.api.InstancePlugin): " ".join(input_args), " ".join(output_args) ] - subprocess_mov = " ".join(mov_args) + subprcs_cmd = " ".join(mov_args) # run subprocess - sub_proc = subprocess.Popen(subprocess_mov) + self.log.debug("{}".format(subprcs_cmd)) + sub_proc = subprocess.Popen(subprcs_cmd) sub_proc.wait() if not os.path.isfile(full_output_path): - self.log.error( + raise FileExistsError( "Quicktime wasn't created succesfully") # create representation data repre_new.update({ 'name': name, - 'ext': 'mov', - 'files': mov_file, + 'ext': ext, + 'files': repr_file, "tags": new_tags, "outputName": name }) - if repre_new.get('preview'): repre_new.pop("preview") if repre_new.get('thumbnail'): @@ -144,12 +158,15 @@ class ExtractReview(pyblish.api.InstancePlugin): # adding representation representations_new.append(repre_new) + # if "delete" in tags: + # if "mov" in full_input_path: + # os.remove(full_input_path) + # self.log.debug("Removed: `{}`".format(full_input_path)) else: continue else: continue - self.log.debug( "new representations: {}".format(representations_new)) instance.data["representations"] = representations_new diff --git a/pype/plugins/global/publish/integrate_new.py b/pype/plugins/global/publish/integrate_new.py index d9e4f3f533..e758789c37 100644 --- a/pype/plugins/global/publish/integrate_new.py +++ b/pype/plugins/global/publish/integrate_new.py @@ -99,18 +99,18 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): # \ / # o __/ # - for result in context.data["results"]: - if not result["success"]: - self.log.debug(result) - exc_type, exc_value, exc_traceback = result["error_info"] - extracted_traceback = traceback.extract_tb(exc_traceback)[-1] - self.log.debug( - "Error at line {}: \"{}\"".format( - extracted_traceback[1], result["error"] - ) - ) - assert all(result["success"] for result in context.data["results"]), ( - "Atomicity not held, aborting.") + # for result in context.data["results"]: + # if not result["success"]: + # self.log.debug(result) + # exc_type, exc_value, exc_traceback = result["error_info"] + # extracted_traceback = traceback.extract_tb(exc_traceback)[-1] + # self.log.debug( + # "Error at line {}: \"{}\"".format( + # extracted_traceback[1], result["error"] + # ) + # ) + # assert all(result["success"] for result in context.data["results"]), ( + # "Atomicity not held, aborting.") # Assemble # @@ -225,17 +225,6 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): # hierarchy = os.path.sep.join(hierarchy) hierarchy = os.path.join(*parents) - template_data = {"root": root, - "project": {"name": PROJECT, - "code": project['data']['code']}, - "silo": asset['silo'], - "task": TASK, - "asset": ASSET, - "family": instance.data['family'], - "subset": subset["name"], - "version": int(version["name"]), - "hierarchy": hierarchy} - anatomy = instance.context.data['anatomy'] # Find the representations to transfer amongst the files @@ -257,6 +246,17 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): # | || # |_______| # + # create template data for Anatomy + template_data = {"root": root, + "project": {"name": PROJECT, + "code": project['data']['code']}, + "silo": asset['silo'], + "task": TASK, + "asset": ASSET, + "family": instance.data['family'], + "subset": subset["name"], + "version": int(version["name"]), + "hierarchy": hierarchy} files = repre['files'] if repre.get('stagingDir'): @@ -286,7 +286,7 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): os.path.normpath( anatomy_filled[template_name]["path"]) ) - + self.log.debug( "test_dest_files: {}".format(str(test_dest_files))) diff --git a/pype/plugins/nuke/publish/collect_instances.py b/pype/plugins/nuke/publish/collect_instances.py index 35673c5ff3..cca5a861ff 100644 --- a/pype/plugins/nuke/publish/collect_instances.py +++ b/pype/plugins/nuke/publish/collect_instances.py @@ -64,7 +64,7 @@ class CollectNukeInstances(pyblish.api.ContextPlugin): "name": node.name(), "subset": subset, "family": avalon_knob_data["family"], - "families": [family], + "families": [avalon_knob_data["family"], family], "avalonKnob": avalon_knob_data, "publish": node.knob('publish').value(), "step": 1, diff --git a/pype/plugins/nuke/publish/collect_writes.py b/pype/plugins/nuke/publish/collect_writes.py index 216160616b..f98a3a0f7d 100644 --- a/pype/plugins/nuke/publish/collect_writes.py +++ b/pype/plugins/nuke/publish/collect_writes.py @@ -66,19 +66,20 @@ class CollectNukeWrites(pyblish.api.InstancePlugin): instance.data['families'].append('ftrack') if "representations" not in instance.data: instance.data["representations"] = list() - try: - collected_frames = os.listdir(output_dir) representation = { 'name': ext, 'ext': ext, - 'files': collected_frames, "stagingDir": output_dir, "anatomy_template": "render" } - instance.data["representations"].append(representation) + try: + collected_frames = os.listdir(output_dir) + representation['files'] = collected_frames + instance.data["representations"].append(representation) except Exception: + instance.data["representations"].append(representation) self.log.debug("couldn't collect frames: {}".format(label)) if 'render.local' in instance.data['families']: diff --git a/pype/plugins/nuke/publish/extract_render_local.py b/pype/plugins/nuke/publish/extract_render_local.py index 1d6550024f..2b185720a6 100644 --- a/pype/plugins/nuke/publish/extract_render_local.py +++ b/pype/plugins/nuke/publish/extract_render_local.py @@ -28,12 +28,6 @@ class NukeRenderLocal(pype.api.Extractor): last_frame = instance.data.get("endFrame", None) node_subset_name = instance.data.get("name", None) - # swap path to stageDir - 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)) - self.log.info("Starting render") self.log.info("Start frame: {}".format(first_frame)) self.log.info("End frame: {}".format(last_frame)) @@ -45,27 +39,26 @@ class NukeRenderLocal(pype.api.Extractor): int(last_frame) ) - # swap path back to publish path path = node['file'].value() - node['file'].setValue(path.replace(temp_dir, output_dir)) + out_dir = os.path.dirname(path) ext = node["file_type"].value() if "representations" not in instance.data: instance.data["representations"] = [] - collected_frames = os.listdir(temp_dir) + collected_frames = os.listdir(out_dir) repre = { 'name': ext, 'ext': ext, 'files': collected_frames, - "stagingDir": temp_dir, + "stagingDir": out_dir, "anatomy_template": "render" } instance.data["representations"].append(repre) self.log.info("Extracted instance '{0}' to: {1}".format( instance.name, - temp_dir + out_dir )) instance.data['family'] = 'render' diff --git a/pype/plugins/nuke/publish/extract_review_data.py b/pype/plugins/nuke/publish/extract_review_data.py index 552aa0cdb0..69df0ab31f 100644 --- a/pype/plugins/nuke/publish/extract_review_data.py +++ b/pype/plugins/nuke/publish/extract_review_data.py @@ -82,10 +82,15 @@ class ExtractReviewData(pype.api.Extractor): 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) + + ref_node = self.nodes.get("Reformat", None) + if ref_node: + for k, v in ref_node: + self.log.debug("k,v: {0}:{1}".format(k,v)) + if isinstance(v, unicode): + v = str(v) + reformat_node[k].setValue(v) + reformat_node.setInput(0, previous_node) previous_node = reformat_node temporary_nodes.append(reformat_node) @@ -112,6 +117,7 @@ class ExtractReviewData(pype.api.Extractor): if representation in "mov": file = fhead + "baked.mov" + name = "baked" path = os.path.join(stagingDir, file).replace("\\", "/") self.log.debug("Path: {}".format(path)) instance.data["baked_colorspace_movie"] = path @@ -120,12 +126,11 @@ class ExtractReviewData(pype.api.Extractor): write_node["raw"].setValue(1) write_node.setInput(0, previous_node) temporary_nodes.append(write_node) - thumbnail = False - preview = True - tags = ["review"] + tags = ["review", "delete"] elif representation in "jpeg": file = fhead + "jpeg" + name = "thumbnail" path = os.path.join(stagingDir, file).replace("\\", "/") instance.data["thumbnail"] = path write_node["file"].setValue(path) @@ -133,8 +138,6 @@ class ExtractReviewData(pype.api.Extractor): write_node["raw"].setValue(1) write_node.setInput(0, previous_node) temporary_nodes.append(write_node) - thumbnail = True - preview = False tags = ["thumbnail"] # retime for @@ -142,15 +145,13 @@ class ExtractReviewData(pype.api.Extractor): last_frame = int(last_frame) / 2 repre = { - 'name': representation, + 'name': name, 'ext': representation, 'files': file, "stagingDir": stagingDir, "startFrame": first_frame, "endFrame": last_frame, "anatomy_template": "render", - "thumbnail": thumbnail, - "preview": preview, "tags": tags } instance.data["representations"].append(repre) diff --git a/pype/plugins/nuke/publish/validate_rendered_frames.py b/pype/plugins/nuke/publish/validate_rendered_frames.py index 841001ef43..93eb84f304 100644 --- a/pype/plugins/nuke/publish/validate_rendered_frames.py +++ b/pype/plugins/nuke/publish/validate_rendered_frames.py @@ -11,9 +11,12 @@ class RepairCollectionAction(pyblish.api.Action): icon = "wrench" def process(self, context, plugin): - + self.log.info(context[0]) files_remove = [os.path.join(context[0].data["outputDir"], f) - for f in context[0].data["files"]] + for r in context[0].data.get("representations", []) + for f in r.get("files", []) + ] + self.log.info(files_remove) for f in files_remove: os.remove(f) self.log.debug("removing file: {}".format(f)) @@ -38,7 +41,7 @@ class ValidateRenderedFrames(pyblish.api.InstancePlugin): if not repre.get('files'): msg = ("no frames were collected, " "you need to render them") - self.log.error(msg) + self.log.warning(msg) raise ValidationException(msg) collections, remainder = clique.assemble(repre["files"]) diff --git a/pype/plugins/nuke/publish/validate_script.py b/pype/plugins/nuke/publish/validate_script.py index 4ad76b898b..efb0537246 100644 --- a/pype/plugins/nuke/publish/validate_script.py +++ b/pype/plugins/nuke/publish/validate_script.py @@ -24,7 +24,7 @@ class ValidateScript(pyblish.api.InstancePlugin): # These attributes will be checked attributes = [ "fps", "fstart", "fend", - "resolution_width", "resolution_height", "pixel_aspect", "handle_start", "handle_end" + "resolution_width", "resolution_height", "handle_start", "handle_end" ] # Value of these attributes can be found on parents