From f350d7694cf5c4d7c2598aa540db219cbf216403 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 4 Dec 2019 17:26:23 +0100 Subject: [PATCH 01/35] feat(global): print ffmpeg path --- pype/plugins/global/publish/validate_ffmpeg_installed.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pype/plugins/global/publish/validate_ffmpeg_installed.py b/pype/plugins/global/publish/validate_ffmpeg_installed.py index 6d5ffba1e1..df7c330e95 100644 --- a/pype/plugins/global/publish/validate_ffmpeg_installed.py +++ b/pype/plugins/global/publish/validate_ffmpeg_installed.py @@ -27,6 +27,8 @@ class ValidateFfmpegInstallef(pyblish.api.Validator): return True def process(self, instance): + self.log.info("ffmpeg path: `{}`".format( + os.environ.get("FFMPEG_PATH", ""))) if self.is_tool( os.path.join( os.environ.get("FFMPEG_PATH", ""), "ffmpeg")) is False: From 346e3e27bce2bc0dd71829a3a686857cdd1268d7 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 4 Dec 2019 17:27:39 +0100 Subject: [PATCH 02/35] feat(nuke): extract review will generate lut file this will remove the nuke rendering of `*.baked..mov` --- .../nuke/publish/extract_review_data_lut.py | 185 ++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 pype/plugins/nuke/publish/extract_review_data_lut.py diff --git a/pype/plugins/nuke/publish/extract_review_data_lut.py b/pype/plugins/nuke/publish/extract_review_data_lut.py new file mode 100644 index 0000000000..bba9544b13 --- /dev/null +++ b/pype/plugins/nuke/publish/extract_review_data_lut.py @@ -0,0 +1,185 @@ +import os +import nuke +import pyblish.api +from avalon.nuke import lib as anlib +import pype + + +class ExtractReviewData(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 = "Extract Review Data Lut" + + families = ["review"] + hosts = ["nuke"] + + def process(self, instance): + + self.log.debug("creating staging dir:") + self.staging_dir(instance) + + with anlib.maintained_selection(): + if "still" not in instance.data["families"]: + self.render_review_representation(instance, + representation="mov") + self.render_review_representation(instance, + representation="jpeg") + else: + self.render_review_representation(instance, representation="jpeg") + + def render_review_representation(self, + instance, + representation="mov"): + + assert instance.data['representations'][0]['files'], "Instance data files should't be empty!" + + temporary_nodes = [] + stagingDir = instance.data[ + 'representations'][0]["stagingDir"].replace("\\", "/") + self.log.debug("StagingDir `{0}`...".format(stagingDir)) + + collection = instance.data.get("collection", None) + + if collection: + # get path + fname = os.path.basename(collection.format( + "{head}{padding}{tail}")) + fhead = collection.format("{head}") + + # get first and last frame + first_frame = min(collection.indexes) + last_frame = max(collection.indexes) + else: + fname = os.path.basename(instance.data.get("path", None)) + fhead = os.path.splitext(fname)[0] + "." + first_frame = instance.data.get("frameStart", None) + last_frame = instance.data.get("frameEnd", None) + + rnode = nuke.createNode("Read") + + rnode["file"].setValue( + os.path.join(stagingDir, fname).replace("\\", "/")) + + rnode["first"].setValue(first_frame) + rnode["origfirst"].setValue(first_frame) + rnode["last"].setValue(last_frame) + rnode["origlast"].setValue(last_frame) + temporary_nodes.append(rnode) + previous_node = rnode + + # get input process and connect it to baking + ipn = self.get_view_process_node() + if ipn is not None: + ipn.setInput(0, previous_node) + previous_node = ipn + temporary_nodes.append(ipn) + + reformat_node = nuke.createNode("Reformat") + + 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) + + dag_node = nuke.createNode("OCIODisplay") + dag_node.setInput(0, previous_node) + previous_node = dag_node + temporary_nodes.append(dag_node) + + # create write node + write_node = nuke.createNode("Write") + + 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 + 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) + 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) + write_node["file_type"].setValue("jpeg") + write_node["raw"].setValue(1) + write_node.setInput(0, previous_node) + temporary_nodes.append(write_node) + tags = ["thumbnail"] + + # retime for + first_frame = int(last_frame) / 2 + last_frame = int(last_frame) / 2 + + repre = { + 'name': name, + 'ext': representation, + 'files': file, + "stagingDir": stagingDir, + "frameStart": first_frame, + "frameEnd": last_frame, + "anatomy_template": "render", + "tags": tags + } + instance.data["representations"].append(repre) + + # Render frames + nuke.execute(write_node.name(), int(first_frame), int(last_frame)) + + self.log.debug("representations: {}".format(instance.data["representations"])) + + # Clean up + for node in temporary_nodes: + nuke.delete(node) + + def get_view_process_node(self): + """ + Will get any active view process. + + Arguments: + self (class): in object definition + + Returns: + nuke.Node: copy node of Input Process node + """ + + with anlib.maintained_selection(): + ipn_orig = None + for v in [n for n in nuke.allNodes() + if "Viewer" in n.Class()]: + ip = v['input_process'].getValue() + ipn = v['input_process_node'].getValue() + if "VIEWER_INPUT" not in ipn and ip: + ipn_orig = nuke.toNode(ipn) + ipn_orig.setSelected(True) + + if ipn_orig: + # copy selected to clipboard + nuke.nodeCopy('%clipboard%') + # reset selection + anlib.reset_selection() + # paste node and selection is on it only + nuke.nodePaste('%clipboard%') + # assign to variable + ipn = nuke.selectedNode() + + return ipn From 48e5c4fd26143d78903564679f6dce15f5239da3 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 5 Dec 2019 10:36:08 +0100 Subject: [PATCH 03/35] feat(nuke): Lut exporter added to nuke.lib --- pype/nuke/lib.py | 169 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) diff --git a/pype/nuke/lib.py b/pype/nuke/lib.py index 157af9019d..960b65f769 100644 --- a/pype/nuke/lib.py +++ b/pype/nuke/lib.py @@ -6,6 +6,7 @@ from collections import OrderedDict from avalon import api, io, lib import avalon.nuke +from avalon.nuke import lib as anlib import pype.api as pype import nuke @@ -1190,3 +1191,171 @@ class BuildWorkfile(WorkfileSettings): def position_up(self, multiply=1): self.ypos -= (self.ypos_size * multiply) + self.ypos_gap + + +class Exporter_review_lut: + """ + Generator object for review lut from Nuke + + Args: + klass (pyblish.plugin): pyblish plugin parent + + + """ + _temp_nodes = [] + data = dict({ + "representations": list() + }) + + def __init__(self, + klass, + instance, + name=None, + ext=None, + lut_size=None, + lut_style=None): + + self.log = klass.log + self.instance = instance + + self.name = name or "baked_lut" + self.ext = ext or "cube" + self.lut_size = lut_size or 1024 + self.lut_style = lut_style or "linear" + + self.stagingDir = self.instance.data["stagingDir"] + self.collection = self.instance.data.get("collection", None) + + # set frame start / end and file name to self + self.get_file_info() + + self.log.info("File info was set...") + + self.file = self.fhead + self.name + ".{}".format(self.ext) + self.path = os.path.join(self.stagingDir, self.file).replace("\\", "/") + + def generate_lut(self): + # ---------- start nodes creation + + # CMSTestPattern + cms_node = nuke.createNode("CMSTestPattern") + cms_node["cube_size"].setValue(96) + # connect + self._temp_nodes.append(cms_node) + self.previous_node = cms_node + self.log.debug("CMSTestPattern... `{}`".format(self._temp_nodes)) + + # Node View Process + ipn = self.get_view_process_node() + if ipn is not None: + # connect + ipn.setInput(0, self.previous_node) + self._temp_nodes.append(ipn) + self.previous_node = ipn + self.log.debug("ViewProcess... `{}`".format(self._temp_nodes)) + + # OCIODisplay + dag_node = nuke.createNode("OCIODisplay") + # connect + dag_node.setInput(0, self.previous_node) + self._temp_nodes.append(dag_node) + self.previous_node = dag_node + self.log.debug("OCIODisplay... `{}`".format(self._temp_nodes)) + + # GenerateLUT + gen_lut_node = nuke.createNode("GenerateLUT") + gen_lut_node["file"].setValue(self.path) + gen_lut_node["file_type"].setValue(".{}".format(self.ext)) + gen_lut_node["lut1d"].setValue(self.lut_size) + gen_lut_node["style1d"].setValue(self.lut_style) + # connect + gen_lut_node.setInput(0, self.previous_node) + self._temp_nodes.append(gen_lut_node) + self.log.debug("GenerateLUT... `{}`".format(self._temp_nodes)) + + # ---------- end nodes creation + + # Export lut file + nuke.execute( + gen_lut_node.name(), + int(self.first_frame), + int(self.first_frame)) + + self.log.info("Exported...") + + # ---------- generate representation data + self.get_representation_data() + + self.log.debug("Representation... `{}`".format(self.data)) + + # ---------- Clean up + for node in self._temp_nodes: + nuke.delete(node) + self.log.info("Deleted nodes...") + + return self.data + + def get_file_info(self): + if self.collection: + self.log.debug("Collection: `{}`".format(self.collection)) + # get path + self.fname = os.path.basename(self.collection.format( + "{head}{padding}{tail}")) + self.fhead = self.collection.format("{head}") + + # get first and last frame + self.first_frame = min(self.collection.indexes) + self.last_frame = max(self.collection.indexes) + else: + self.fname = os.path.basename(self.instance.data.get("path", None)) + self.fhead = os.path.splitext(self.fname)[0] + "." + self.first_frame = self.instance.data.get("frameStart", None) + self.last_frame = self.instance.data.get("frameEnd", None) + + if "#" in self.fhead: + self.fhead = self.fhead.replace("#", "")[:-1] + + def get_representation_data(self): + + repre = { + 'name': self.name, + 'ext': self.ext, + 'files': self.file, + "stagingDir": self.stagingDir, + "anatomy_template": "publish", + "tags": [self.name.replace("_", "-")] + } + + self.data["representations"].append(repre) + + def get_view_process_node(self): + """ + Will get any active view process. + + Arguments: + self (class): in object definition + + Returns: + nuke.Node: copy node of Input Process node + """ + anlib.reset_selection() + ipn_orig = None + for v in [n for n in nuke.allNodes() + if "Viewer" in n.Class()]: + ip = v['input_process'].getValue() + ipn = v['input_process_node'].getValue() + if "VIEWER_INPUT" not in ipn and ip: + ipn_orig = nuke.toNode(ipn) + ipn_orig.setSelected(True) + + if ipn_orig: + # copy selected to clipboard + nuke.nodeCopy('%clipboard%') + # reset selection + anlib.reset_selection() + # paste node and selection is on it only + nuke.nodePaste('%clipboard%') + # assign to variable + ipn = nuke.selectedNode() + + return ipn From 49eadd8a2d8c28e73b9ef7ffc63fb12d3c87d1f6 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 5 Dec 2019 10:36:53 +0100 Subject: [PATCH 04/35] feat(global): added lut filter to ffmpeg --- pype/plugins/global/publish/extract_review.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pype/plugins/global/publish/extract_review.py b/pype/plugins/global/publish/extract_review.py index de167710a5..3ff3241812 100644 --- a/pype/plugins/global/publish/extract_review.py +++ b/pype/plugins/global/publish/extract_review.py @@ -162,6 +162,13 @@ class ExtractReview(pyblish.api.InstancePlugin): # output filename output_args.append(full_output_path) + + lut_path = instance.data.get("lutPath") + if lut_path: + lut_arg = "-vf \"lut3d=file='{}'\"".format( + lut_path) + output_args.insert(0, lut_arg) + mov_args = [ os.path.join( os.environ.get( From bd5805301b3c234f50fe8901f5a3f6a59dd09dac Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 5 Dec 2019 10:37:32 +0100 Subject: [PATCH 05/35] feat(nuke): lut extractor added to nuke plugins --- .../nuke/publish/extract_review_data_lut.py | 182 +++--------------- 1 file changed, 26 insertions(+), 156 deletions(-) diff --git a/pype/plugins/nuke/publish/extract_review_data_lut.py b/pype/plugins/nuke/publish/extract_review_data_lut.py index bba9544b13..54013af11a 100644 --- a/pype/plugins/nuke/publish/extract_review_data_lut.py +++ b/pype/plugins/nuke/publish/extract_review_data_lut.py @@ -1,185 +1,55 @@ import os -import nuke import pyblish.api from avalon.nuke import lib as anlib +from pype.nuke import lib as pnlib import pype +reload(pnlib) -class ExtractReviewData(pype.api.Extractor): +class ExtractReviewLutData(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 + order = pyblish.api.ExtractorOrder + 0.005 label = "Extract Review Data Lut" families = ["review"] hosts = ["nuke"] def process(self, instance): + self.log.debug( + "_ representations: {}".format(instance.data["representations"])) - self.log.debug("creating staging dir:") - self.staging_dir(instance) + self.log.info("Creating staging dir...") - with anlib.maintained_selection(): - if "still" not in instance.data["families"]: - self.render_review_representation(instance, - representation="mov") - self.render_review_representation(instance, - representation="jpeg") - else: - self.render_review_representation(instance, representation="jpeg") - - def render_review_representation(self, - instance, - representation="mov"): - - assert instance.data['representations'][0]['files'], "Instance data files should't be empty!" - - temporary_nodes = [] stagingDir = instance.data[ 'representations'][0]["stagingDir"].replace("\\", "/") - self.log.debug("StagingDir `{0}`...".format(stagingDir)) + instance.data["stagingDir"] = stagingDir - collection = instance.data.get("collection", None) + instance.data['representations'][0]["tags"] = ["review"] - if collection: - # get path - fname = os.path.basename(collection.format( - "{head}{padding}{tail}")) - fhead = collection.format("{head}") + self.log.info( + "StagingDir `{0}`...".format(instance.data["stagingDir"])) - # get first and last frame - first_frame = min(collection.indexes) - last_frame = max(collection.indexes) - else: - fname = os.path.basename(instance.data.get("path", None)) - fhead = os.path.splitext(fname)[0] + "." - first_frame = instance.data.get("frameStart", None) - last_frame = instance.data.get("frameEnd", None) - - rnode = nuke.createNode("Read") - - rnode["file"].setValue( - os.path.join(stagingDir, fname).replace("\\", "/")) - - rnode["first"].setValue(first_frame) - rnode["origfirst"].setValue(first_frame) - rnode["last"].setValue(last_frame) - rnode["origlast"].setValue(last_frame) - temporary_nodes.append(rnode) - previous_node = rnode - - # get input process and connect it to baking - ipn = self.get_view_process_node() - if ipn is not None: - ipn.setInput(0, previous_node) - previous_node = ipn - temporary_nodes.append(ipn) - - reformat_node = nuke.createNode("Reformat") - - 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) - - dag_node = nuke.createNode("OCIODisplay") - dag_node.setInput(0, previous_node) - previous_node = dag_node - temporary_nodes.append(dag_node) - - # create write node - write_node = nuke.createNode("Write") - - 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 - 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) - 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) - write_node["file_type"].setValue("jpeg") - write_node["raw"].setValue(1) - write_node.setInput(0, previous_node) - temporary_nodes.append(write_node) - tags = ["thumbnail"] - - # retime for - first_frame = int(last_frame) / 2 - last_frame = int(last_frame) / 2 - - repre = { - 'name': name, - 'ext': representation, - 'files': file, - "stagingDir": stagingDir, - "frameStart": first_frame, - "frameEnd": last_frame, - "anatomy_template": "render", - "tags": tags - } - instance.data["representations"].append(repre) - - # Render frames - nuke.execute(write_node.name(), int(first_frame), int(last_frame)) - - self.log.debug("representations: {}".format(instance.data["representations"])) - - # Clean up - for node in temporary_nodes: - nuke.delete(node) - - def get_view_process_node(self): - """ - Will get any active view process. - - Arguments: - self (class): in object definition - - Returns: - nuke.Node: copy node of Input Process node - """ + if "representations" not in instance.data: + instance.data["representations"] = [] with anlib.maintained_selection(): - ipn_orig = None - for v in [n for n in nuke.allNodes() - if "Viewer" in n.Class()]: - ip = v['input_process'].getValue() - ipn = v['input_process_node'].getValue() - if "VIEWER_INPUT" not in ipn and ip: - ipn_orig = nuke.toNode(ipn) - ipn_orig.setSelected(True) + exporter = pnlib.Exporter_review_lut( + self, instance + ) + data = exporter.generate_lut() - if ipn_orig: - # copy selected to clipboard - nuke.nodeCopy('%clipboard%') - # reset selection - anlib.reset_selection() - # paste node and selection is on it only - nuke.nodePaste('%clipboard%') - # assign to variable - ipn = nuke.selectedNode() + # assign to representations + instance.data["lutPath"] = os.path.join( + exporter.stagingDir, exporter.file).replace("\\", "/").replace( + "C:/", "C\\:/") + instance.data["representations"] += data["representations"] - return ipn + self.log.debug( + "_ lutPath: {}".format(instance.data["lutPath"])) + self.log.debug( + "_ representations: {}".format(instance.data["representations"])) From bf8a829eee011b9d5fecb8bb4781a2a44395f1bd Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 5 Dec 2019 10:38:06 +0100 Subject: [PATCH 06/35] fix(nuke): review extractor fixed maintained selection --- .../nuke/publish/extract_review_data.py | 34 +++++++++---------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/pype/plugins/nuke/publish/extract_review_data.py b/pype/plugins/nuke/publish/extract_review_data.py index 791b9d7969..9bb4f93582 100644 --- a/pype/plugins/nuke/publish/extract_review_data.py +++ b/pype/plugins/nuke/publish/extract_review_data.py @@ -1,5 +1,6 @@ import os import nuke +from avalon.nuke import lib as anlib import pyblish.api import pype @@ -18,28 +19,22 @@ class ExtractReviewData(pype.api.Extractor): def process(self, instance): - # 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.log.debug("creating staging dir:") - self.staging_dir(instance) + with anlib.maintained_selection(): + self.log.debug("creating staging dir:") + self.staging_dir(instance) - self.log.debug("instance: {}".format(instance)) - self.log.debug("instance.data[families]: {}".format( - instance.data["families"])) + self.log.debug("instance: {}".format(instance)) + self.log.debug("instance.data[families]: {}".format( + instance.data["families"])) - if "still" not in instance.data["families"]: - self.render_review_representation(instance, - representation="mov") - self.render_review_representation(instance, - representation="jpeg") - else: + # if "still" not in instance.data["families"]: + # self.render_review_representation(instance, + # representation="mov") + # self.render_review_representation(instance, + # representation="jpeg") + # else: 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 render_review_representation(self, instance, @@ -69,6 +64,9 @@ class ExtractReviewData(pype.api.Extractor): first_frame = instance.data.get("frameStart", None) last_frame = instance.data.get("frameEnd", None) + if "#" in fhead: + fhead = fhead.replace("#", "")[:-1] + rnode = nuke.createNode("Read") rnode["file"].setValue( From d3e36f13bc01b7234b492748653572bc5d9d3cb9 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 5 Dec 2019 10:38:42 +0100 Subject: [PATCH 07/35] feat(global): adding debug prints to assumed destination --- pype/plugins/global/publish/collect_templates.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pype/plugins/global/publish/collect_templates.py b/pype/plugins/global/publish/collect_templates.py index b80ca4ae1b..9b0c03fdee 100644 --- a/pype/plugins/global/publish/collect_templates.py +++ b/pype/plugins/global/publish/collect_templates.py @@ -85,3 +85,6 @@ class CollectTemplates(pyblish.api.InstancePlugin): instance.data["assumedDestination"] = os.path.dirname( (anatomy.format(template_data))["publish"]["path"] ) + self.log.info("Assumed Destination has been created...") + self.log.debug("__ assumedTemplateData: `{}`".format(instance.data["assumedTemplateData"])) + self.log.debug("__ template: `{}`".format(instance.data["template"])) From 1361d12452223977a14cb623b1765457ca2ea54b Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 6 Dec 2019 07:59:19 +0100 Subject: [PATCH 08/35] feat(nuke): polishing the Lut Exporter --- pype/nuke/lib.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pype/nuke/lib.py b/pype/nuke/lib.py index 960b65f769..6349f35bea 100644 --- a/pype/nuke/lib.py +++ b/pype/nuke/lib.py @@ -1212,6 +1212,7 @@ class Exporter_review_lut: instance, name=None, ext=None, + cube_size=None, lut_size=None, lut_style=None): @@ -1220,6 +1221,7 @@ class Exporter_review_lut: self.name = name or "baked_lut" self.ext = ext or "cube" + self.cube_size = cube_size or 32 self.lut_size = lut_size or 1024 self.lut_style = lut_style or "linear" @@ -1239,7 +1241,7 @@ class Exporter_review_lut: # CMSTestPattern cms_node = nuke.createNode("CMSTestPattern") - cms_node["cube_size"].setValue(96) + cms_node["cube_size"].setValue(self.cube_size) # connect self._temp_nodes.append(cms_node) self.previous_node = cms_node From 43ed9443941a136227aa694e1fd7cc84985b7ce6 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 6 Dec 2019 08:00:15 +0100 Subject: [PATCH 09/35] feat(global): implementing Lut integration into Extract Review --- pype/plugins/global/publish/extract_review.py | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/pype/plugins/global/publish/extract_review.py b/pype/plugins/global/publish/extract_review.py index 3ff3241812..59ef308f9a 100644 --- a/pype/plugins/global/publish/extract_review.py +++ b/pype/plugins/global/publish/extract_review.py @@ -165,9 +165,35 @@ class ExtractReview(pyblish.api.InstancePlugin): lut_path = instance.data.get("lutPath") if lut_path: - lut_arg = "-vf \"lut3d=file='{}'\"".format( + # removing Gama info as it is all baked in lut + gamma = next((g for g in input_args + if "-gamma" in g), None) + if gamma: + input_args.remove(gamma) + + # find all video format settings + vf_settings = [p for p in output_args + for v in ["-filter:v", "-vf"] + if v in p] + self.log.debug("_ vf_settings: `{}`".format(vf_settings)) + # remove them from output args list + for p in vf_settings: + self.log.debug("_ remove p: `{}`".format(p)) + output_args.remove(p) + self.log.debug("_ output_args: `{}`".format(output_args)) + # strip them from all flags + vf_fixed = [p.replace("-vf ", "").replace("-filter:v ", "") for p in vf_settings] + # create lut argument + lut_arg = "lut3d=file='{}',colormatrix=bt601:bt709".format( lut_path) - output_args.insert(0, lut_arg) + vf_fixed.insert(0, lut_arg) + # create new video filter setting + vf_back = "-vf " + ",".join(vf_fixed) + # add it to output_args + output_args.insert(0, vf_back) + self.log.info("Added Lut to ffmpeg command") + self.log.debug("_ output_args: `{}`".format(output_args)) + mov_args = [ os.path.join( From ec9f5b5e0405e0ba53b26d1d14adbcb78d680c20 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 6 Dec 2019 08:00:35 +0100 Subject: [PATCH 10/35] feat(nuke): adding format data to instance --- pype/plugins/nuke/publish/collect_instances.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/pype/plugins/nuke/publish/collect_instances.py b/pype/plugins/nuke/publish/collect_instances.py index 483f260295..cb98b8244d 100644 --- a/pype/plugins/nuke/publish/collect_instances.py +++ b/pype/plugins/nuke/publish/collect_instances.py @@ -23,6 +23,8 @@ class CollectNukeInstances(pyblish.api.ContextPlugin): instances = [] # creating instances per write node + root = nuke.root() + self.log.debug("nuke.allNodes(): {}".format(nuke.allNodes())) for node in nuke.allNodes(): @@ -61,7 +63,13 @@ class CollectNukeInstances(pyblish.api.ContextPlugin): family = avalon_knob_data["family"] families = [avalon_knob_data["families"]] - + + # Get format + format = root['format'].value() + resolution_width = format.width() + resolution_height = format.height() + pixel_aspect = format.pixelAspect() + if node.Class() not in "Read": if node["render"].value(): self.log.info("flagged for render") @@ -87,7 +95,10 @@ class CollectNukeInstances(pyblish.api.ContextPlugin): "avalonKnob": avalon_knob_data, "publish": node.knob('publish').value(), "step": 1, - "fps": nuke.root()['fps'].value() + "fps": nuke.root()['fps'].value(), + "resolutionWidth": resolution_width, + "resolutionHeight": resolution_height, + "pixelAspect": pixel_aspect, }) @@ -95,5 +106,4 @@ class CollectNukeInstances(pyblish.api.ContextPlugin): instances.append(instance) context.data["instances"] = instances - self.log.debug("context: {}".format(context)) From 3c90a7984023889b30c2fc7b0233b02c8a6a3bb3 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 6 Dec 2019 13:58:31 +0100 Subject: [PATCH 11/35] feat(global): extr review pixel aspect rescale --- pype/plugins/global/publish/extract_review.py | 76 ++++++++++++++----- 1 file changed, 58 insertions(+), 18 deletions(-) diff --git a/pype/plugins/global/publish/extract_review.py b/pype/plugins/global/publish/extract_review.py index 59ef308f9a..fa02826527 100644 --- a/pype/plugins/global/publish/extract_review.py +++ b/pype/plugins/global/publish/extract_review.py @@ -151,7 +151,6 @@ class ExtractReview(pyblish.api.InstancePlugin): output_args.extend(profile.get('output', [])) # letter_box - # TODO: add to documentation lb = profile.get('letter_box', None) if lb: output_args.append( @@ -163,6 +162,18 @@ class ExtractReview(pyblish.api.InstancePlugin): # output filename output_args.append(full_output_path) + # scaling none square pixels and 1920 width + # scale=320:-2 # to auto count height with output to be multiple of 2 + if profile.get('reformat', False): + pixel_aspect = instance.data["pixelAspect"] + scaling_arg = "scale=1920:'ceil((1920/{})/2)*2':flags=lanczos,setsar=1".format( + pixel_aspect) + vf_back = self.add_video_filter_args( + output_args, scaling_arg) + # add it to output_args + output_args.insert(0, vf_back) + + # baking lut file application lut_path = instance.data.get("lutPath") if lut_path: # removing Gama info as it is all baked in lut @@ -171,24 +182,15 @@ class ExtractReview(pyblish.api.InstancePlugin): if gamma: input_args.remove(gamma) - # find all video format settings - vf_settings = [p for p in output_args - for v in ["-filter:v", "-vf"] - if v in p] - self.log.debug("_ vf_settings: `{}`".format(vf_settings)) - # remove them from output args list - for p in vf_settings: - self.log.debug("_ remove p: `{}`".format(p)) - output_args.remove(p) - self.log.debug("_ output_args: `{}`".format(output_args)) - # strip them from all flags - vf_fixed = [p.replace("-vf ", "").replace("-filter:v ", "") for p in vf_settings] # create lut argument - lut_arg = "lut3d=file='{}',colormatrix=bt601:bt709".format( - lut_path) - vf_fixed.insert(0, lut_arg) - # create new video filter setting - vf_back = "-vf " + ",".join(vf_fixed) + lut_arg = "lut3d=file='{}'".format( + lut_path.replace( + "\\", "/").replace(":/", "\\:/") + ) + lut_arg += ",colormatrix=bt601:bt709" + + vf_back = self.add_video_filter_args( + output_args, lut_arg) # add it to output_args output_args.insert(0, vf_back) self.log.info("Added Lut to ffmpeg command") @@ -240,3 +242,41 @@ class ExtractReview(pyblish.api.InstancePlugin): instance.data["representations"] = representations_new self.log.debug("Families Out: `{}`".format(instance.data["families"])) + + + def add_video_filter_args(self, args, inserting_arg): + """ + Fixing video filter argumets to be one long string + + Args: + args (list): list of string arguments + inserting_arg (str): string argument we want to add + (without flag `-vf`) + + Returns: + str: long joined argument to be added back to list of arguments + + """ + # find all video format settings + vf_settings = [p for p in args + for v in ["-filter:v", "-vf"] + if v in p] + self.log.debug("_ vf_settings: `{}`".format(vf_settings)) + + # remove them from output args list + for p in vf_settings: + self.log.debug("_ remove p: `{}`".format(p)) + args.remove(p) + self.log.debug("_ args: `{}`".format(args)) + + # strip them from all flags + vf_fixed = [p.replace("-vf ", "").replace("-filter:v ", "") + for p in vf_settings] + + self.log.debug("_ vf_fixed: `{}`".format(vf_fixed)) + vf_fixed.insert(0, inserting_arg) + self.log.debug("_ vf_fixed: `{}`".format(vf_fixed)) + # create new video filter setting + vf_back = "-vf " + ",".join(vf_fixed) + + return vf_back From b79e22464b02c0b3c4ecf7224bac69ae84270ac6 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 6 Dec 2019 13:59:35 +0100 Subject: [PATCH 12/35] fix(nuke: when writes collected family should be `write` otherwise validate frames is picking it up --- pype/plugins/nuke/publish/collect_writes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/plugins/nuke/publish/collect_writes.py b/pype/plugins/nuke/publish/collect_writes.py index ba8a0534b1..5484d971bf 100644 --- a/pype/plugins/nuke/publish/collect_writes.py +++ b/pype/plugins/nuke/publish/collect_writes.py @@ -99,7 +99,7 @@ class CollectNukeWrites(pyblish.api.InstancePlugin): "subset": instance.data["subset"], "fps": instance.context.data["fps"] } - + instance.data["family"] = "write" group_node = [x for x in instance if x.Class() == "Group"][0] deadlineChunkSize = 1 if "deadlineChunkSize" in group_node.knobs(): From 78f2da25cf81c494ee6f7d1979ddf98ab67784d6 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 6 Dec 2019 14:01:42 +0100 Subject: [PATCH 13/35] feat(nuke): extract thumbnail from before Review Data (mov, jpg) --- ...ct_review_data.py => extract_thumbnail.py} | 69 ++++++------------- 1 file changed, 22 insertions(+), 47 deletions(-) rename pype/plugins/nuke/publish/{extract_review_data.py => extract_thumbnail.py} (67%) diff --git a/pype/plugins/nuke/publish/extract_review_data.py b/pype/plugins/nuke/publish/extract_thumbnail.py similarity index 67% rename from pype/plugins/nuke/publish/extract_review_data.py rename to pype/plugins/nuke/publish/extract_thumbnail.py index 9bb4f93582..5740a90924 100644 --- a/pype/plugins/nuke/publish/extract_review_data.py +++ b/pype/plugins/nuke/publish/extract_thumbnail.py @@ -4,7 +4,7 @@ from avalon.nuke import lib as anlib import pyblish.api import pype -class ExtractReviewData(pype.api.Extractor): +class ExtractThumbnail(pype.api.Extractor): """Extracts movie and thumbnail with baked in luts must be run after extract_render_local.py @@ -12,7 +12,7 @@ class ExtractReviewData(pype.api.Extractor): """ order = pyblish.api.ExtractorOrder + 0.01 - label = "Extract Review Data" + label = "Extract Thumbnail" families = ["review"] hosts = ["nuke"] @@ -20,29 +20,19 @@ class ExtractReviewData(pype.api.Extractor): def process(self, instance): with anlib.maintained_selection(): - self.log.debug("creating staging dir:") - self.staging_dir(instance) - self.log.debug("instance: {}".format(instance)) self.log.debug("instance.data[families]: {}".format( instance.data["families"])) - # if "still" not in instance.data["families"]: - # self.render_review_representation(instance, - # representation="mov") - # self.render_review_representation(instance, - # representation="jpeg") - # else: - self.render_review_representation(instance, representation="jpeg") + self.render_thumbnail(instance) - def render_review_representation(self, - instance, - representation="mov"): + def render_thumbnail(self, instance): assert instance.data['representations'][0]['files'], "Instance data files should't be empty!" temporary_nodes = [] + self.log.info("Getting staging dir...") stagingDir = instance.data[ 'representations'][0]["stagingDir"].replace("\\", "/") self.log.debug("StagingDir `{0}`...".format(stagingDir)) @@ -107,39 +97,24 @@ class ExtractReviewData(pype.api.Extractor): # create write node write_node = nuke.createNode("Write") + file = fhead + "jpeg" + name = "thumbnail" + path = os.path.join(stagingDir, 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) + tags = ["thumbnail"] - 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 - 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) - 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) - write_node["file_type"].setValue("jpeg") - write_node["raw"].setValue(1) - write_node.setInput(0, previous_node) - temporary_nodes.append(write_node) - tags = ["thumbnail"] - - # retime for - first_frame = int(last_frame) / 2 - last_frame = int(last_frame) / 2 + # retime for + first_frame = int(last_frame) / 2 + last_frame = int(last_frame) / 2 repre = { 'name': name, - 'ext': representation, + 'ext': "jpeg", 'files': file, "stagingDir": stagingDir, "frameStart": first_frame, @@ -154,9 +129,9 @@ class ExtractReviewData(pype.api.Extractor): self.log.debug("representations: {}".format(instance.data["representations"])) - # Clean up - for node in temporary_nodes: - nuke.delete(node) + # # Clean up + # for node in temporary_nodes: + # nuke.delete(node) def get_view_process_node(self): From 5754450b88e7cb5b894137d5daac0608df77ccfb Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 6 Dec 2019 14:02:37 +0100 Subject: [PATCH 14/35] fix(nuke): the path was only working with C: Also the replace was moved to Extract Review --- pype/plugins/nuke/publish/extract_review_data_lut.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pype/plugins/nuke/publish/extract_review_data_lut.py b/pype/plugins/nuke/publish/extract_review_data_lut.py index 54013af11a..910b6ee19e 100644 --- a/pype/plugins/nuke/publish/extract_review_data_lut.py +++ b/pype/plugins/nuke/publish/extract_review_data_lut.py @@ -45,8 +45,7 @@ class ExtractReviewLutData(pype.api.Extractor): # assign to representations instance.data["lutPath"] = os.path.join( - exporter.stagingDir, exporter.file).replace("\\", "/").replace( - "C:/", "C\\:/") + exporter.stagingDir, exporter.file).replace("\\", "/") instance.data["representations"] += data["representations"] self.log.debug( From f4a0b341ac5036945a9f47f0ebfe50cb030d564b Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 6 Dec 2019 14:03:16 +0100 Subject: [PATCH 15/35] fix(nuke): validator had wrong family --- pype/plugins/nuke/publish/validate_rendered_frames.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/plugins/nuke/publish/validate_rendered_frames.py b/pype/plugins/nuke/publish/validate_rendered_frames.py index e244a9b4b6..3887b5d5b7 100644 --- a/pype/plugins/nuke/publish/validate_rendered_frames.py +++ b/pype/plugins/nuke/publish/validate_rendered_frames.py @@ -28,7 +28,7 @@ class ValidateRenderedFrames(pyblish.api.InstancePlugin): """ Validates file output. """ order = pyblish.api.ValidatorOrder + 0.1 - families = ["render.no"] + families = ["render"] label = "Validate rendered frame" hosts = ["nuke", "nukestudio"] From 350dbda38ccf8d3ebf7c9322d5fa2e4a6b9cb000 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 6 Dec 2019 14:41:50 +0100 Subject: [PATCH 16/35] feat(global): atatching conditions to preset tags instead of arguments that is what they are for, isnt it? ;) --- pype/plugins/nuke/publish/extract_thumbnail.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pype/plugins/nuke/publish/extract_thumbnail.py b/pype/plugins/nuke/publish/extract_thumbnail.py index 5740a90924..126203603e 100644 --- a/pype/plugins/nuke/publish/extract_thumbnail.py +++ b/pype/plugins/nuke/publish/extract_thumbnail.py @@ -4,6 +4,7 @@ from avalon.nuke import lib as anlib import pyblish.api import pype + class ExtractThumbnail(pype.api.Extractor): """Extracts movie and thumbnail with baked in luts @@ -26,9 +27,7 @@ class ExtractThumbnail(pype.api.Extractor): self.render_thumbnail(instance) - def render_thumbnail(self, instance): - assert instance.data['representations'][0]['files'], "Instance data files should't be empty!" temporary_nodes = [] @@ -129,9 +128,9 @@ class ExtractThumbnail(pype.api.Extractor): self.log.debug("representations: {}".format(instance.data["representations"])) - # # Clean up - # for node in temporary_nodes: - # nuke.delete(node) + # Clean up + for node in temporary_nodes: + nuke.delete(node) def get_view_process_node(self): From 7f171bd11d16a806987f2a355808f2d1a59aa3c2 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 6 Dec 2019 14:49:45 +0100 Subject: [PATCH 17/35] feat(global): hook the conditions to preset tags after all that is what they are for ;) --- pype/plugins/global/publish/extract_review.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pype/plugins/global/publish/extract_review.py b/pype/plugins/global/publish/extract_review.py index 418ac39186..a002e1140d 100644 --- a/pype/plugins/global/publish/extract_review.py +++ b/pype/plugins/global/publish/extract_review.py @@ -165,7 +165,7 @@ class ExtractReview(pyblish.api.InstancePlugin): # scaling none square pixels and 1920 width # scale=320:-2 # to auto count height with output to be multiple of 2 - if profile.get('reformat', False): + if "reformat" in tags: pixel_aspect = instance.data["pixelAspect"] scaling_arg = "scale=1920:'ceil((1920/{})/2)*2':flags=lanczos,setsar=1".format( pixel_aspect) @@ -176,7 +176,7 @@ class ExtractReview(pyblish.api.InstancePlugin): # baking lut file application lut_path = instance.data.get("lutPath") - if lut_path: + if lut_path and ("bake-lut" in tags): # removing Gama info as it is all baked in lut gamma = next((g for g in input_args if "-gamma" in g), None) From b69e9629a74e462c4be36aedc42152ece9a9c0f5 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 6 Dec 2019 14:50:08 +0100 Subject: [PATCH 18/35] clean(nuke): make it nicer --- pype/plugins/nuke/publish/extract_thumbnail.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pype/plugins/nuke/publish/extract_thumbnail.py b/pype/plugins/nuke/publish/extract_thumbnail.py index 126203603e..a58dad02f5 100644 --- a/pype/plugins/nuke/publish/extract_thumbnail.py +++ b/pype/plugins/nuke/publish/extract_thumbnail.py @@ -80,7 +80,7 @@ class ExtractThumbnail(pype.api.Extractor): 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)) + self.log.debug("k, v: {0}:{1}".format(k, v)) if isinstance(v, unicode): v = str(v) reformat_node[k].setValue(v) @@ -126,7 +126,8 @@ class ExtractThumbnail(pype.api.Extractor): # Render frames nuke.execute(write_node.name(), int(first_frame), int(last_frame)) - self.log.debug("representations: {}".format(instance.data["representations"])) + self.log.debug( + "representations: {}".format(instance.data["representations"])) # Clean up for node in temporary_nodes: From 305bd6a02181744668e0360f25ba70fb801b0f27 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 6 Dec 2019 16:10:23 +0100 Subject: [PATCH 19/35] fix(global): not using correct preset tags fixing pixelAspect to by applied to letter box too --- pype/plugins/global/publish/extract_review.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/pype/plugins/global/publish/extract_review.py b/pype/plugins/global/publish/extract_review.py index a002e1140d..9de4a966f3 100644 --- a/pype/plugins/global/publish/extract_review.py +++ b/pype/plugins/global/publish/extract_review.py @@ -31,7 +31,7 @@ class ExtractReview(pyblish.api.InstancePlugin): inst_data = instance.data fps = inst_data.get("fps") start_frame = inst_data.get("frameStart") - + pixel_aspect = instance.data["pixelAspect"] self.log.debug("Families In: `{}`".format(instance.data["families"])) # get representation and loop them @@ -147,13 +147,16 @@ class ExtractReview(pyblish.api.InstancePlugin): ) output_args = [] - output_args.extend(profile.get('codec', [])) + codec_args = profile.get('codec', []) + output_args.extend(codec_args) # preset's output data output_args.extend(profile.get('output', [])) # letter_box lb = profile.get('letter_box', None) if lb: + if "reformat" not in p_tags: + lb /= pixel_aspect 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)) @@ -165,8 +168,7 @@ class ExtractReview(pyblish.api.InstancePlugin): # scaling none square pixels and 1920 width # scale=320:-2 # to auto count height with output to be multiple of 2 - if "reformat" in tags: - pixel_aspect = instance.data["pixelAspect"] + if "reformat" in p_tags: scaling_arg = "scale=1920:'ceil((1920/{})/2)*2':flags=lanczos,setsar=1".format( pixel_aspect) vf_back = self.add_video_filter_args( @@ -176,7 +178,7 @@ class ExtractReview(pyblish.api.InstancePlugin): # baking lut file application lut_path = instance.data.get("lutPath") - if lut_path and ("bake-lut" in tags): + if lut_path and ("bake-lut" in p_tags): # removing Gama info as it is all baked in lut gamma = next((g for g in input_args if "-gamma" in g), None) @@ -220,7 +222,7 @@ class ExtractReview(pyblish.api.InstancePlugin): 'files': repr_file, "tags": new_tags, "outputName": name, - "codec": profile.get('codec', []) + "codec": codec_args }) if repre_new.get('preview'): repre_new.pop("preview") From 9727a70722f11a41394f1dbdbedda6245623f23d Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 6 Dec 2019 19:00:42 +0100 Subject: [PATCH 20/35] feat(global): making collection filesequences for nuke --- .../global/publish/collect_filesequences.py | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/pype/plugins/global/publish/collect_filesequences.py b/pype/plugins/global/publish/collect_filesequences.py index 39481e216b..d0ff5722a3 100644 --- a/pype/plugins/global/publish/collect_filesequences.py +++ b/pype/plugins/global/publish/collect_filesequences.py @@ -100,6 +100,8 @@ class CollectRenderedFrames(pyblish.api.ContextPlugin): label = "RenderedFrames" def process(self, context): + pixel_aspect = 1 + lut_path = None if os.environ.get("PYPE_PUBLISH_PATHS"): paths = os.environ["PYPE_PUBLISH_PATHS"].split(os.pathsep) self.log.info("Collecting paths: {}".format(paths)) @@ -144,6 +146,12 @@ class CollectRenderedFrames(pyblish.api.ContextPlugin): self.log.info("setting session using metadata") api.Session.update(session) os.environ.update(session) + instance = metadata.get("instance") + if instance: + instance_family = instance.get("family") + pixel_aspect = instance.get("pixelAspect", 1) + lut_path = instance.get("lutPath", None) + else: # Search in directory @@ -181,6 +189,8 @@ class CollectRenderedFrames(pyblish.api.ContextPlugin): families.append("ftrack") if "review" not in families: families.append("review") + if "write" in instance_family: + families.append("write") for collection in collections: instance = context.create_instance(str(collection)) @@ -197,6 +207,11 @@ class CollectRenderedFrames(pyblish.api.ContextPlugin): start = data.get("frameStart", indices[0]) end = data.get("frameEnd", indices[-1]) + self.log.debug("Collected pixel_aspect:\n" + "{}".format(pixel_aspect)) + self.log.debug("type pixel_aspect:\n" + "{}".format(type(pixel_aspect))) + # root = os.path.normpath(root) # self.log.info("Source: {}}".format(data.get("source", ""))) @@ -212,8 +227,11 @@ class CollectRenderedFrames(pyblish.api.ContextPlugin): "frameStart": start, "frameEnd": end, "fps": fps, - "source": data.get('source', '') + "source": data.get('source', ''), + "pixelAspect": pixel_aspect, }) + if lut_path: + instance.data.update({"lutPath": lut_path}) instance.append(collection) instance.context.data['fps'] = fps From 83f506d3eb94f830eea6a79be379a4f0d958d449 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 6 Dec 2019 19:01:15 +0100 Subject: [PATCH 21/35] feat(nuke): removing families which are not needed anymore --- .../nuke/publish/extract_review_data_lut.py | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/pype/plugins/nuke/publish/extract_review_data_lut.py b/pype/plugins/nuke/publish/extract_review_data_lut.py index 910b6ee19e..dfc10952cd 100644 --- a/pype/plugins/nuke/publish/extract_review_data_lut.py +++ b/pype/plugins/nuke/publish/extract_review_data_lut.py @@ -20,23 +20,23 @@ class ExtractReviewLutData(pype.api.Extractor): hosts = ["nuke"] def process(self, instance): - self.log.debug( - "_ representations: {}".format(instance.data["representations"])) - + families = instance.data["families"] self.log.info("Creating staging dir...") - - stagingDir = instance.data[ - 'representations'][0]["stagingDir"].replace("\\", "/") - instance.data["stagingDir"] = stagingDir - - instance.data['representations'][0]["tags"] = ["review"] + if "representations" in instance.data: + staging_dir = instance.data[ + "representations"][0]["stagingDir"].replace("\\", "/") + instance.data["stagingDir"] = staging_dir + instance.data["representations"][0]["tags"] = ["review"] + else: + instance.data["representations"] = [] + # get output path + render_path = instance.data['path'] + staging_dir = os.path.normpath(os.path.dirname(render_path)) + instance.data["stagingDir"] = staging_dir self.log.info( "StagingDir `{0}`...".format(instance.data["stagingDir"])) - if "representations" not in instance.data: - instance.data["representations"] = [] - with anlib.maintained_selection(): exporter = pnlib.Exporter_review_lut( self, instance @@ -48,6 +48,10 @@ class ExtractReviewLutData(pype.api.Extractor): exporter.stagingDir, exporter.file).replace("\\", "/") instance.data["representations"] += data["representations"] + if "render.farm" in families: + instance.data["families"].remove("review") + instance.data["families"].remove("ftrack") + self.log.debug( "_ lutPath: {}".format(instance.data["lutPath"])) self.log.debug( From 75145a4095b1ecaaa593488e6f82ecb1374cad19 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 6 Dec 2019 19:01:43 +0100 Subject: [PATCH 22/35] feat(nuke): make thumbnail exporter available for render farm --- .../plugins/nuke/publish/extract_thumbnail.py | 50 ++++++++++++------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/pype/plugins/nuke/publish/extract_thumbnail.py b/pype/plugins/nuke/publish/extract_thumbnail.py index a58dad02f5..3886fda569 100644 --- a/pype/plugins/nuke/publish/extract_thumbnail.py +++ b/pype/plugins/nuke/publish/extract_thumbnail.py @@ -15,7 +15,7 @@ class ExtractThumbnail(pype.api.Extractor): order = pyblish.api.ExtractorOrder + 0.01 label = "Extract Thumbnail" - families = ["review"] + families = ["review", "render.farm"] hosts = ["nuke"] def process(self, instance): @@ -28,14 +28,24 @@ class ExtractThumbnail(pype.api.Extractor): self.render_thumbnail(instance) def render_thumbnail(self, instance): - assert instance.data['representations'][0]['files'], "Instance data files should't be empty!" + node = instance[0] # group node + self.log.info("Creating staging dir...") + if "representations" not in instance.data: + staging_dir = instance.data[ + "representations"][0]["stagingDir"].replace("\\", "/") + instance.data["stagingDir"] = staging_dir + instance.data["representations"][0]["tags"] = ["review"] + else: + instance.data["representations"] = [] + # get output path + render_path = instance.data['path'] + staging_dir = os.path.normpath(os.path.dirname(render_path)) + instance.data["stagingDir"] = staging_dir + + self.log.info( + "StagingDir `{0}`...".format(instance.data["stagingDir"])) temporary_nodes = [] - self.log.info("Getting staging dir...") - stagingDir = instance.data[ - 'representations'][0]["stagingDir"].replace("\\", "/") - self.log.debug("StagingDir `{0}`...".format(stagingDir)) - collection = instance.data.get("collection", None) if collection: @@ -56,17 +66,21 @@ class ExtractThumbnail(pype.api.Extractor): if "#" in fhead: fhead = fhead.replace("#", "")[:-1] - rnode = nuke.createNode("Read") + path_render = os.path.join(staging_dir, fname).replace("\\", "/") + # check if file exist otherwise connect to write node + if os.path.isfile(path_render): + rnode = nuke.createNode("Read") - rnode["file"].setValue( - os.path.join(stagingDir, fname).replace("\\", "/")) + rnode["file"].setValue(path_render) - rnode["first"].setValue(first_frame) - rnode["origfirst"].setValue(first_frame) - rnode["last"].setValue(last_frame) - rnode["origlast"].setValue(last_frame) - temporary_nodes.append(rnode) - previous_node = rnode + rnode["first"].setValue(first_frame) + rnode["origfirst"].setValue(first_frame) + rnode["last"].setValue(last_frame) + rnode["origlast"].setValue(last_frame) + temporary_nodes.append(rnode) + previous_node = rnode + else: + previous_node = node # get input process and connect it to baking ipn = self.get_view_process_node() @@ -98,7 +112,7 @@ class ExtractThumbnail(pype.api.Extractor): write_node = nuke.createNode("Write") file = fhead + "jpeg" name = "thumbnail" - path = os.path.join(stagingDir, file).replace("\\", "/") + path = os.path.join(staging_dir, file).replace("\\", "/") instance.data["thumbnail"] = path write_node["file"].setValue(path) write_node["file_type"].setValue("jpeg") @@ -115,7 +129,7 @@ class ExtractThumbnail(pype.api.Extractor): 'name': name, 'ext': "jpeg", 'files': file, - "stagingDir": stagingDir, + "stagingDir": staging_dir, "frameStart": first_frame, "frameEnd": last_frame, "anatomy_template": "render", From 532e485e5d6588db1d4a0bfa9464da21fdc09cbc Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 6 Dec 2019 19:01:59 +0100 Subject: [PATCH 23/35] feat(nuke): fixing deadline submiter --- .../nuke/publish/submit_nuke_deadline.py | 50 ++++++++----------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/pype/plugins/nuke/publish/submit_nuke_deadline.py b/pype/plugins/nuke/publish/submit_nuke_deadline.py index 4044026b5e..d9207d2bfc 100644 --- a/pype/plugins/nuke/publish/submit_nuke_deadline.py +++ b/pype/plugins/nuke/publish/submit_nuke_deadline.py @@ -1,9 +1,7 @@ import os import json import getpass - -import nuke - + from avalon import api from avalon.vendor import requests import re @@ -27,40 +25,36 @@ class NukeSubmitDeadline(pyblish.api.InstancePlugin): def process(self, instance): - node = None - for x in instance: - if x.Class() == "Write": - node = x - - if node is None: - return + node = instance[0] + # for x in instance: + # if x.Class() == "Write": + # node = x + # + # if node is None: + # return DEADLINE_REST_URL = os.environ.get("DEADLINE_REST_URL", "http://localhost:8082") assert DEADLINE_REST_URL, "Requires DEADLINE_REST_URL" context = instance.context - workspace = os.path.dirname(context.data["currentFile"]) - filepath = None - # get path - path = nuke.filename(node) - output_dir = instance.data['outputDir'] + # get output path + render_path = instance.data['path'] + render_dir = os.path.normpath(os.path.dirname(render_path)) - filepath = context.data["currentFile"] + script_path = context.data["currentFile"] - self.log.debug(filepath) - - filename = os.path.basename(filepath) + script_name = os.path.basename(script_path) comment = context.data.get("comment", "") - dirname = os.path.join(workspace, "renders") + deadline_user = context.data.get("deadlineUser", getpass.getuser()) - jobname = "%s - %s" % (filename, instance.name) + jobname = "%s - %s" % (script_name, instance.name) ver = re.search(r"\d+\.\d+", context.data.get("hostVersion")) try: # Ensure render folder exists - os.makedirs(dirname) + os.makedirs(render_dir) except OSError: pass @@ -71,7 +65,7 @@ class NukeSubmitDeadline(pyblish.api.InstancePlugin): payload = { "JobInfo": { # Top-level group name - "BatchName": filename, + "BatchName": script_name, # Job name, as seen in Monitor "Name": jobname, @@ -95,20 +89,20 @@ class NukeSubmitDeadline(pyblish.api.InstancePlugin): }, "PluginInfo": { # Input - "SceneFile": filepath, + "SceneFile": script_path, # Output directory and filename - "OutputFilePath": dirname.replace("\\", "/"), + "OutputFilePath": render_dir.replace("\\", "/"), # "OutputFilePrefix": render_variables["filename_prefix"], # Mandatory for Deadline "Version": ver.group(), # Resolve relative references - "ProjectPath": workspace, - + "ProjectPath": script_path, + "AWSAssetFile0": render_path, # Only the specific write node is rendered. - "WriteNode": instance[0].name() + "WriteNode": node.name() }, # Mandatory for Deadline, may be empty From ac875a9306257eb078f5f2d971ce53dbd1f1f834 Mon Sep 17 00:00:00 2001 From: Milan Kolar Date: Fri, 6 Dec 2019 22:44:50 +0100 Subject: [PATCH 24/35] use automatic preset loading --- pype/plugins/global/publish/extract_review.py | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/pype/plugins/global/publish/extract_review.py b/pype/plugins/global/publish/extract_review.py index 9de4a966f3..96c01fffb2 100644 --- a/pype/plugins/global/publish/extract_review.py +++ b/pype/plugins/global/publish/extract_review.py @@ -22,16 +22,17 @@ class ExtractReview(pyblish.api.InstancePlugin): families = ["review"] hosts = ["nuke", "maya", "shell"] + outputs = {} + ext_filter = [] + def process(self, instance): - # adding plugin attributes from presets - publish_presets = config.get_presets()["plugins"]["global"]["publish"] - plugin_attrs = publish_presets[self.__class__.__name__] - output_profiles = plugin_attrs.get("outputs", {}) + + output_profiles = self.outputs or {} inst_data = instance.data fps = inst_data.get("fps") start_frame = inst_data.get("frameStart") - pixel_aspect = instance.data["pixelAspect"] + pixel_aspect = instance.data.get("pixelAspect") or 1 self.log.debug("Families In: `{}`".format(instance.data["families"])) # get representation and loop them @@ -40,7 +41,7 @@ class ExtractReview(pyblish.api.InstancePlugin): # filter out mov and img sequences representations_new = representations[:] for repre in representations: - if repre['ext'] in plugin_attrs["ext_filter"]: + if repre['ext'] in self.ext_filter: tags = repre.get("tags", []) self.log.info("Try repre: {}".format(repre)) @@ -92,8 +93,9 @@ class ExtractReview(pyblish.api.InstancePlugin): self.log.info("p_tags: `{}`".format(p_tags)) # add families [instance.data["families"].append(t) - for t in p_tags - if t not in instance.data["families"]] + for t in p_tags + if t not in instance.data["families"]] + # add to [new_tags.append(t) for t in p_tags if t not in new_tags] @@ -199,7 +201,6 @@ class ExtractReview(pyblish.api.InstancePlugin): self.log.info("Added Lut to ffmpeg command") self.log.debug("_ output_args: `{}`".format(output_args)) - mov_args = [ os.path.join( os.environ.get( @@ -247,7 +248,6 @@ class ExtractReview(pyblish.api.InstancePlugin): self.log.debug("Families Out: `{}`".format(instance.data["families"])) - def add_video_filter_args(self, args, inserting_arg): """ Fixing video filter argumets to be one long string From 0f50ead66153922a856c1ebf1623d88db97464a9 Mon Sep 17 00:00:00 2001 From: Milan Kolar Date: Fri, 6 Dec 2019 22:47:54 +0100 Subject: [PATCH 25/35] remove unnecesary import --- pype/plugins/global/publish/extract_review.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pype/plugins/global/publish/extract_review.py b/pype/plugins/global/publish/extract_review.py index 96c01fffb2..7554c080a0 100644 --- a/pype/plugins/global/publish/extract_review.py +++ b/pype/plugins/global/publish/extract_review.py @@ -3,7 +3,6 @@ import os import pyblish.api import clique import pype.api -from pypeapp import config class ExtractReview(pyblish.api.InstancePlugin): From c069f36d954a93f5786503aa8e3efcb43e8e3df8 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Sat, 7 Dec 2019 18:06:54 +0100 Subject: [PATCH 26/35] fix(global): reformat was not counting with ratio of format --- pype/plugins/global/publish/extract_review.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pype/plugins/global/publish/extract_review.py b/pype/plugins/global/publish/extract_review.py index 9de4a966f3..936ae74c6f 100644 --- a/pype/plugins/global/publish/extract_review.py +++ b/pype/plugins/global/publish/extract_review.py @@ -32,6 +32,8 @@ class ExtractReview(pyblish.api.InstancePlugin): fps = inst_data.get("fps") start_frame = inst_data.get("frameStart") pixel_aspect = instance.data["pixelAspect"] + resolution_width = instance.data["resolutionWidth"] + resolution_height = instance.data["resolutionHeight"] self.log.debug("Families In: `{}`".format(instance.data["families"])) # get representation and loop them @@ -167,10 +169,9 @@ class ExtractReview(pyblish.api.InstancePlugin): output_args.append(full_output_path) # scaling none square pixels and 1920 width - # scale=320:-2 # to auto count height with output to be multiple of 2 if "reformat" in p_tags: scaling_arg = "scale=1920:'ceil((1920/{})/2)*2':flags=lanczos,setsar=1".format( - pixel_aspect) + (lb/pixel_aspect * (resolution_width / resolution_height))) vf_back = self.add_video_filter_args( output_args, scaling_arg) # add it to output_args From 8bf0874a4ad9368a21dde16be9759c906afde9ef Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Mon, 9 Dec 2019 12:12:27 +0100 Subject: [PATCH 27/35] fix(global): LetterBox can be 0 rather then None --- pype/plugins/global/publish/extract_review.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pype/plugins/global/publish/extract_review.py b/pype/plugins/global/publish/extract_review.py index 77b00d52ec..a3707f4e59 100644 --- a/pype/plugins/global/publish/extract_review.py +++ b/pype/plugins/global/publish/extract_review.py @@ -156,8 +156,8 @@ class ExtractReview(pyblish.api.InstancePlugin): output_args.extend(profile.get('output', [])) # letter_box - lb = profile.get('letter_box', None) - if lb: + lb = profile.get('letter_box', 0) + if lb is not 0: if "reformat" not in p_tags: lb /= pixel_aspect output_args.append( From 101c3bc190d2785e9d337b4f4e1d4b0b7945d000 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Mon, 9 Dec 2019 13:25:34 +0100 Subject: [PATCH 28/35] fix(nuke): backward compatibility if avalon knob `ak:` --- pype/plugins/nuke/publish/collect_instances.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/plugins/nuke/publish/collect_instances.py b/pype/plugins/nuke/publish/collect_instances.py index fbff28b282..3f3042ec46 100644 --- a/pype/plugins/nuke/publish/collect_instances.py +++ b/pype/plugins/nuke/publish/collect_instances.py @@ -34,7 +34,7 @@ class CollectNukeInstances(pyblish.api.ContextPlugin): # get data from avalon knob self.log.debug("node[name]: {}".format(node['name'].value())) - avalon_knob_data = get_avalon_knob_data(node) + avalon_knob_data = get_avalon_knob_data(node, ["avalon:", "ak:"]) self.log.debug("avalon_knob_data: {}".format(avalon_knob_data)) From b2e7c60c28cb4917c7aca4f36a35f50b46a5ffdf Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 10 Dec 2019 02:02:57 +0100 Subject: [PATCH 29/35] fix(global): reformat now works on width and height --- pype/plugins/global/publish/extract_review.py | 36 ++++++++++++++++--- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/pype/plugins/global/publish/extract_review.py b/pype/plugins/global/publish/extract_review.py index a3707f4e59..786df95fc1 100644 --- a/pype/plugins/global/publish/extract_review.py +++ b/pype/plugins/global/publish/extract_review.py @@ -1,5 +1,5 @@ import os - +import math import pyblish.api import clique import pype.api @@ -31,8 +31,8 @@ class ExtractReview(pyblish.api.InstancePlugin): inst_data = instance.data fps = inst_data.get("fps") start_frame = inst_data.get("frameStart") - resolution_height = instance.dataget("resolutionHeight", 1080) - resolution_width = instance.dataget("resolutionWidth", 1920) + resolution_height = instance.data.get("resolutionHeight", 1080) + resolution_width = instance.data.get("resolutionWidth", 1920) pixel_aspect = instance.data.get("pixelAspect", 1) self.log.debug("Families In: `{}`".format(instance.data["families"])) @@ -169,10 +169,36 @@ class ExtractReview(pyblish.api.InstancePlugin): # output filename output_args.append(full_output_path) + self.log.debug("__ pixel_aspect: `{}`".format(pixel_aspect)) + self.log.debug("__ resolution_width: `{}`".format(resolution_width)) + self.log.debug("__ resolution_height: `{}`".format(resolution_height)) # scaling none square pixels and 1920 width if "reformat" in p_tags: - scaling_arg = "scale=1920:'ceil((1920/{})/2)*2':flags=lanczos,setsar=1".format( - (lb/pixel_aspect * (resolution_width / resolution_height))) + width_scale = 1920 + width_half_pad = 0 + res_w = int(float(resolution_width) * pixel_aspect) + height_half_pad = int(( + (res_w - 1920) / ( + res_w * .01) * ( + 1080 * .01)) / 2 + ) + height_scale = 1080 - (height_half_pad * 2) + if height_scale > 1080: + height_half_pad = 0 + height_scale = 1080 + width_half_pad = (1920 - (float(resolution_width) * (1080 / float(resolution_height))) ) / 2 + width_scale = int(1920 - (width_half_pad * 2)) + + self.log.debug("__ width_scale: `{}`".format(width_scale)) + self.log.debug("__ width_half_pad: `{}`".format(width_half_pad)) + self.log.debug("__ height_scale: `{}`".format(height_scale)) + self.log.debug("__ height_half_pad: `{}`".format(height_half_pad)) + + + scaling_arg = "scale={0}x{1}:flags=lanczos,pad=1920:1080:{2}:{3}:black,setsar=1".format( + width_scale, height_scale, width_half_pad, height_half_pad + ) + vf_back = self.add_video_filter_args( output_args, scaling_arg) # add it to output_args From 3faef65e44338e9380a208d8b1eabbf6c2d38afd Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 10 Dec 2019 02:04:05 +0100 Subject: [PATCH 30/35] fix(nuke): little bits --- pype/plugins/global/publish/integrate_new.py | 2 +- pype/plugins/nuke/publish/collect_writes.py | 3 ++- pype/plugins/nuke/publish/extract_thumbnail.py | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pype/plugins/global/publish/integrate_new.py b/pype/plugins/global/publish/integrate_new.py index 9021a3f997..c723631679 100644 --- a/pype/plugins/global/publish/integrate_new.py +++ b/pype/plugins/global/publish/integrate_new.py @@ -414,7 +414,7 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): } if sequence_repre and repre.get("frameStart"): - representation['context']['frame'] = src_padding_exp % repre.get("frameStart") + representation['context']['frame'] = src_padding_exp % int(repre.get("frameStart")) self.log.debug("__ representation: {}".format(representation)) destination_list.append(dst) diff --git a/pype/plugins/nuke/publish/collect_writes.py b/pype/plugins/nuke/publish/collect_writes.py index 5484d971bf..c9c516c888 100644 --- a/pype/plugins/nuke/publish/collect_writes.py +++ b/pype/plugins/nuke/publish/collect_writes.py @@ -76,7 +76,8 @@ class CollectNukeWrites(pyblish.api.InstancePlugin): } try: - collected_frames = os.listdir(output_dir) + collected_frames = [f for f in os.listdir(output_dir) + if ext in f] if collected_frames: representation['frameStart'] = "%0{}d".format( len(str(last_frame))) % first_frame diff --git a/pype/plugins/nuke/publish/extract_thumbnail.py b/pype/plugins/nuke/publish/extract_thumbnail.py index 3886fda569..450bb39928 100644 --- a/pype/plugins/nuke/publish/extract_thumbnail.py +++ b/pype/plugins/nuke/publish/extract_thumbnail.py @@ -30,7 +30,7 @@ class ExtractThumbnail(pype.api.Extractor): def render_thumbnail(self, instance): node = instance[0] # group node self.log.info("Creating staging dir...") - if "representations" not in instance.data: + if "representations" in instance.data: staging_dir = instance.data[ "representations"][0]["stagingDir"].replace("\\", "/") instance.data["stagingDir"] = staging_dir From 37792d0829c9bf340ee5fa872a1da3809d115443 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 10 Dec 2019 13:22:26 +0100 Subject: [PATCH 31/35] implemented tray_exit method to stop threads and clear signals on tray exit in idle manager service --- pype/services/idle_manager/idle_manager.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pype/services/idle_manager/idle_manager.py b/pype/services/idle_manager/idle_manager.py index 64cafcd193..86caa9ddd2 100644 --- a/pype/services/idle_manager/idle_manager.py +++ b/pype/services/idle_manager/idle_manager.py @@ -29,6 +29,13 @@ class IdleManager(QtCore.QThread): def tray_start(self): self.start() + def tray_exit(self): + self.stop() + try: + self.time_signals = {} + except Exception: + pass + def add_time_signal(self, emit_time, signal): """ If any module want to use IdleManager, need to use add_time_signal :param emit_time: time when signal will be emitted From 5a0eed0d76ab6554beeca6698b87ab6c7576e173 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 10 Dec 2019 13:22:43 +0100 Subject: [PATCH 32/35] import cleanup in idle manager service --- pype/services/idle_manager/idle_manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/services/idle_manager/idle_manager.py b/pype/services/idle_manager/idle_manager.py index 86caa9ddd2..0897245049 100644 --- a/pype/services/idle_manager/idle_manager.py +++ b/pype/services/idle_manager/idle_manager.py @@ -1,6 +1,6 @@ import time import collections -from Qt import QtCore, QtGui, QtWidgets +from Qt import QtCore from pynput import mouse, keyboard from pypeapp import Logger From 310c7672441c96207c746c4e3db2db7bae26599d Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 10 Dec 2019 19:06:16 +0100 Subject: [PATCH 33/35] added replaced svg images of trash and menu with pngs --- pype/standalonepublish/resources/menu.png | Bin 0 -> 1629 bytes pype/standalonepublish/resources/menu.svg | 12 --------- .../resources/menu_disabled.png | Bin 0 -> 1629 bytes .../resources/menu_hover.png | Bin 0 -> 1626 bytes .../resources/menu_pressed.png | Bin 0 -> 1626 bytes .../resources/menu_pressed_hover.png | Bin 0 -> 1488 bytes pype/standalonepublish/resources/trash.png | Bin 0 -> 1235 bytes pype/standalonepublish/resources/trash.svg | 23 ------------------ .../resources/trash_disabled.png | Bin 0 -> 1235 bytes .../resources/trash_hover.png | Bin 0 -> 1232 bytes .../resources/trash_pressed.png | Bin 0 -> 1232 bytes .../resources/trash_pressed_hover.png | Bin 0 -> 1094 bytes 12 files changed, 35 deletions(-) create mode 100644 pype/standalonepublish/resources/menu.png delete mode 100644 pype/standalonepublish/resources/menu.svg create mode 100644 pype/standalonepublish/resources/menu_disabled.png create mode 100644 pype/standalonepublish/resources/menu_hover.png create mode 100644 pype/standalonepublish/resources/menu_pressed.png create mode 100644 pype/standalonepublish/resources/menu_pressed_hover.png create mode 100644 pype/standalonepublish/resources/trash.png delete mode 100644 pype/standalonepublish/resources/trash.svg create mode 100644 pype/standalonepublish/resources/trash_disabled.png create mode 100644 pype/standalonepublish/resources/trash_hover.png create mode 100644 pype/standalonepublish/resources/trash_pressed.png create mode 100644 pype/standalonepublish/resources/trash_pressed_hover.png diff --git a/pype/standalonepublish/resources/menu.png b/pype/standalonepublish/resources/menu.png new file mode 100644 index 0000000000000000000000000000000000000000..da83b4524468dff7e927baac8927e655e004632b GIT binary patch literal 1629 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+yeRz~mX=6XFWw0zpGVLuhCykW5QU z1Cl^cSXc-oOG-+BWLa4mkSs4RFDNLetgI|9E(Vf7sj8}~($Z2O2~<#BT@4|DvK18- zKv^IOl!cH$DWDdh2|&d_5-1Ll0*V6_z-1v)5E3p0Q2-=?;t)fCdV#V)E|3HQWCajq zKtYHsgoFsfNw6l6E}$%&glNI49-<7*OrRhfzzqS4K-h58;3CLskd1;H0%yQgA{&BB z7ONVFVoaC74FNJBvdAKou>b%6&)f007MPL_mIV0)GcYnSv#_#paB^|;@bd8s2#bh{ ziAzXINz2H}D<~={tEj4LY3t}37#W+GnweYK*xK1UIyt+zdU$$y`}p|>1Obje8tLDtJkbuzhUF1&0Dwa*tL7l{sRXO9XWdJ_{meJ&zw7d;o_ysSFT;ZefQq| z2M-@VefIpt%hzw-zI*@S zB;xSi=|7`+6Ge`nf2-v!IBBg?blE0#EluxfDW_-YTx@b`aXBe;vs_nYiFfACy8+=} zexCnx;IPl#nbyYND{Ja!S)MMxSNv?x`|7?9HmB<;G3)X&UcSi4T%mW;Lr!&>f%SGd z)2jPV&KSM2&AD#fFzYI=<_)-)Vo%{QER>p7X^06Yt9e@NEAT`D^L{$Jra5 zHp;ej*XDj!xLmPRu4!@BNj8hTW!L-+1OHP;OtUVk-yn3;kU!I zjw>sJGPsVf5afKDx-zs$qRQP%>78O2XH%8OgxV`zsaH0-uM0?;yI_iU(BZn*EHgt+ zx^Ih6zu~pmB67Ldt;K0sN~hLs^IaHw=g8{Tr&ZMpeR5|vMDG(`E*5uLdB>`4y~}Sq za|jBX2wv20F)N(#%v(r$$*Jx4e>in%ZuJW|S9#z2=JT^Af7A`bIKw_E-}uga^t*Dd zl}og81WT}u>}%F^lfVZrBfkGllDxAjOK;NYk_CHiab-yT_+G?oJin2%UO${OZ|NZ$ z$EW*W$C^1Uiu}Lzl-|j2BFj(mDc)I{Q<$=-`}nh2Ytk(aPi?v}KW4M^_wDh|k0)(? z!SF;<-GZ_D_o+_{Pb7#ipF7<7FYs<#Qu5hvqANap(5+Uy;!^d!e@*MpAHGRn!Q&278>FVdQ&MBb@0KA_L4*&oF literal 0 HcmV?d00001 diff --git a/pype/standalonepublish/resources/menu.svg b/pype/standalonepublish/resources/menu.svg deleted file mode 100644 index ac1e728011..0000000000 --- a/pype/standalonepublish/resources/menu.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - diff --git a/pype/standalonepublish/resources/menu_disabled.png b/pype/standalonepublish/resources/menu_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..e4758f0b199c554da8bd0932cea2d13b2d2bcced GIT binary patch literal 1629 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+yeRz~mX=6XFWwLO^I}sDp!pv9YnX zwl$>*?tM+1A$9=H})=E|6_zW(HJbYiny|Wd#&8H8lmYfeL`?fm}ONQ=qto zg@v7&nT?GNkPQ(BDzG&-2a*sGh#DIt5gQ8&ph{#BxMHAbK85AR7YLh)@hS0j3_P2CEjh zULfQD|NkdRQ@5x&}tZCZ=ZQRyMYF_Kr@@F0LM)Ufw=_{sBS3A)#U65z#TRafvCZY3UhRd4(mV zW#yGMb@dI6P0cN>Z5^Fm-95d1{SzimnmlFdjG43M&0nx^(c&dbmn~nha@FcJYu9hs zxM}m&Z98`D-n0L}!9z!m9y@;W)af(l&R@8A>GG9p*KgmwcmKh|$4{RDTZ?yo{GGGBQ`_o%E1XU1ngtUCy-X{*yCCuWWO!TQ|(R zo+`Og)6-LPCHtvYRSfsu$z&aMek`sbfA*GX^SR%0-YeR2iZjy8 zf0m>9gS?LKI_-DbUo-zc&79{vasR~oG66i>e?|V9dcbk^MyHLkZQZrGpA{}wER}0o zoOP1TB5&C>|3g(ztDlI=@fkQj_|FpFqO@Z9mL9|HcaLrT_#$4)>`;+mr-iG)!L?Jm zGw&?1d~yD9+`c|@e}R9!ck9J2oD^(T+WBdon$~2Iwwo69`ia)Di$y<4l?1FklWcz5 z#bwDnr>B<|^}k5icj=SPdKZ^x2Vyq1R2n$D6jkJJc1!r}Fs}QYjqd9LlIAX$;vICj?lsHIkdyA)BGhkqEw+eUE_Q2i zT9(qOb=!Ow#@;!yy7g&Q^+KQA*$vVAgqMrOT~^+)YFqE}+s+(20o?BcQQa`>I@fy!>dbw;qTi-pMwSV`&F}9hp>bc!pMHBst z*V^xXwkx@NQGchY@2}+h%dg%`;<N{%q*;I9GqO- zJiL7T0>UDqV&W2#QqnTA@(PMd$||brTG~3g21dpvre@|=Hnw*5j!w=lt{$FV-adZ* z0YSkbp<&?>(J`@ci7BaR=^0shg(anB<&`yc^$m?p%`L5M9i3g>J-vPX6DCfYJZ0*P znX~52U$Ah|;w4L$Enl&6)#^2C*KgRkY4g@?J9h2fv;V-sLr0DtJAU%i=`-ifU$}Vb z@|A1XZ{NLl|G~q@PoF)1@$&VXx9{G6`1s}9_a8rh{r>a!pRdp7O+e2uCV9KNF#c!K zy$8%IUp-wMLn03Eo&GbLH&NvH`L|l$f|J%NMVD<-*V6Q!mU4QQ&c!CD7MGJkH_LTZ zmUw6Gyc-by<>&c72M+t(ooQ|Sy|Si$mgVX4d&ST8ysz%-U~{^j60Ht%oTbk zJ>*oE8CY+ZGp)M+{ojDv*)dUD`N{1 zd+v!Ji)+ZAy=B^b?zf!xing5Mj5PC~dy0MGVc zk-w%MaGbr-X`^ggcWv%xh07I7<(d{}on*7fTXxO=P}S4wC*pE^2F?%uvxK)OtysRL z$8h`IV_QGIh?g=uRAks`;VN)&?Ue4!J4-BIoPQj*ug~0H;9u|Eda(;91zVMNewwGI zHCd$XrbWGeqIK+I(N9t(0c+1Bo8NYESu)S*>7_;eFB0}$`lPeo#pT(7n2jx!2F@-; z75SUp5`H^O>$tKqD1+&u|A$kT=2pLebCvhKZ$3Y3@<-h;j5F+$ z@{RAzN53oQTDe3kN3aCj$i8MxHwk?3GUEH+B*{Cgvh*gME?KbW7FUMUkMBji#`7CF z>-EDq^Ohd6aeTV}b*!1wqR9VSPwAcfCbIk_pW>aRIfW^Ux{p7bwIS-~DflZDy=`ZueHvME~No_Pd|$O733N-)ZXmEBXHNtM`(4?%Z8xTd{4a xwB^C(OIzLU%QpT`{}I;nzt6A0vgG*x_!Q-*UelL+F$LxZ22WQ%mvv4FO#m7ceop`Z literal 0 HcmV?d00001 diff --git a/pype/standalonepublish/resources/menu_pressed.png b/pype/standalonepublish/resources/menu_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..a5f931b2c4107986d389c1df0fe910cae0145d0d GIT binary patch literal 1626 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+yeRz~mO-6XFWw{s)6qt5)sbzyHjc zGgq%(1u~8uI|gK5ym%4FJ#ys8i4!M)-1FzppFDXI$T)ZI98d}C-@|vuDo&xj;5h9H1Obje8tLDtJkbuzhUF1&0Dwa*tL7l{sRXO z9XWdJ_{meJ&zw7d;o_ysSFT;ZefQq|2M-@VefIpt%hzw-zI*@SlFzi8#D>`p;&~JgEwON2BZ`8!c3^6kg@7?ixX=%gnJ500LuO3n|-;)3B^5^+~gm!&8 zp1tz0U+Lk`p11z3j4ep)xhH-st|5Q+mTB|3-*Vn7+H#6B(#(IBqxplpj_*3{ciLYw z|31x}=R9%$#QQP1jk0aswYi@aE>|p-Yg(LjlFcG-*){(|RZpv* zh|BRAI6wH$65gV;V)>RH!|ivEZT#V(u_Y*pI%X`Y(aWRbR;7WMjx*0GC4KS`AYtUZ%#e%r-m$vmg0mlpNENZ5Dj zlg@e8XnV|>jIMIE|}sSbhz#{%gm6I?%N{NZ+I=Xh+HmqYjIkZ(y4XZd>6*vIkLL- zX;t+?pWN9E(ffp#i^W}5-mz+1@ABKu9D>3of*18$%nBzw^A?g`a%%hiA5LAGTm1sg zRo?f$`TVTOA9cep&ah9)H@-6;{jQvAB=MH!N3%uKwlzjG^ z=!y>?bgLDwxKw@bU(XC+ z=Sb9bF>#kQr=mIs?JZFRdZ+xS2IM_AAQKEDFXlH>p5Q7%TxdW literal 0 HcmV?d00001 diff --git a/pype/standalonepublish/resources/menu_pressed_hover.png b/pype/standalonepublish/resources/menu_pressed_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..51503add0fbc0c7352c764623632509e14dd669b GIT binary patch literal 1488 zcmV;>1uy!EP)^iQUvsuG)vNbl17y^pOCa!(l3&>NZKyx zu%sidy|<)3k_J23QIbYWswva6Mba`!FB@a_hvJ?Jz(C*`U~k#oYX;^6lYxF!=&c2& zxVyitOm`bF7Z{L*Pn8mkfLXvEkJwRQ8E`!i^683z3BYn^BgSsv0U!!xt5QN&0N;2- z4g-sUOLDM11b7KJ;@STi7?HK@n7~ZuaE#Z1i*hmEp2x+`c8tG(`?E9{VZZGD<2N-k zgO&5T18DVl%?tVZ#YXx7?|Mc)2I_+vNdcf9_{8J)4$wQ4@?O9Pp7P~D&mhVJ!tq?; z@q8~ePxsir=_!3G_~R82fWiKfW4w`yFR;*4Ha8&GOaVOY@qV^iCHHzto)641a{w=R z{O?XGJRI2Pgg*nyr=*=8Ku=(U^Pvs6tWrS(eCY)Lq=0{XC;)?j7U#?QioOTH4DZpo zH3y!V0=T{6R{^L4cDc@P=fp8{0Bf92JAm3Vb)4fm9wdi(eO>^DVyDUgv;8*Xb*huJ zO;UeJ^NcZ1Brwn@8wbd1f^=NcGGolDN(F%Vk{*+^N77JZ%z^R_kGc^$3|yFm4X}~? z@ohqmgDI^bAC9m4Pe7BTv65aj#>`Bpe7vM7Nn`@xePhgqBm%%vNi!t{}y-J z5XmMW!@Mo0ID3@1W5Wlh5Whhcp%6CxOcHR1);nV`?^1p)Z$JC6-1^8#PN>Zk!;n5 zRGJWV2gJVq9LW|WNu>!4pNi<%J3E_@gmqZyXU?=Z@3<>mf0fW~}S{hH+l7aC{-`asY6n=jRy7 z6(SmAz6UnRhQ;rZ^hH9&<0Va3zKM~QNyFl@zDYJLzPVis|0hN`M|L_}FKLl6=8*)- z8ztSDgirviN|+jZQPM+_c1Rj#j5%_;PJVK9NI0&=0=S$GlB4Av{q*?S964qR;6vxr znbYI0vtJ;QcaS4EfV(_@&R#1-`x2Q}x^SHUwl1K}`BGVlj1wH@34Tu3Et2}myOBea zDws@Zjj$RU`0Nq@dSJ_C!Or<_s#ejH-utsKFwe{YEb@5INvmwJr)+s=ejR`s;5Co$ zq7X`Z(!N-F1)aB8dZov6ZLpi=-lVuhKW;Tv02_@F^>jp9dnEwz|DCX9|ElNj2FFW>Z3etpN`CQV7o^o?`?B`0C}%M z|3$7JFx!0-d^D5Y#>p1oaRNlKL*AuYNe{{vB4)XDcB!N##+WqO>})}I+&tY8IQ{nd qfs*QE3$rC@ucUpFb}Q%Y^M3=%H32mG5YMLo0000loC1qBrq6+rRI%F5#6Vju~WEiEmruC4~E0g^yLpaLKO z3Iaud3LqpfhdNP5S4KCa5Y%PA&!BoL1y5QLRLnQ z{r~^}Jl8k+z!;rb666=mz{teR!p6?Q$;Hjf$1fl#BrGB-CLt{&E3c%Ys;;4_rLCi@ zZ)jp+X=P()@8st0;pye$>lY9d91Yt&-Rdys|!-6E|Kmp&7BYi6bcOR3B=9!q_%IacbmgDJh;&c9A1@ptbn$<-{6LV=V`Wv)qa0X?H@S*o&Rl)VuyYa#|I|4)t8w{q-Lb$XMBy|I&dUz z_2XV=gUMOhtIlTT@0ouf;N*p0`~Uv#eampt`R2d5nlhSiPu}{fapC%=Q@IP;o(X(7 zx=*0JF*|ix^b;$7neDA|PFrr(OkVA#kkq}WE!wZIQ{FANF>%L3mI6MzTTK2BT7?~0 z;%+k8CG_vCXD>J@7CEu$J^SgiZ&H8nbE=waTOsz~_5p9SzS2r{=u8x_y zynfd0$NMBLmtEuea#wHFhbyxWEz@-f{-_$myJaea>H&MkH&w6JPg2?0yjNS*Q&fC@ zr7Xj-2MsDO)$UAHdD|8*daR*nf%hblmVamV+HYskVDxGbdSK78L#QBRl1RhxNlW-< z%t)wfy2kYOsQk3t z1IO;j@0DojVt(gPRQE1~!6J0Yv+`2Lhc+jViG29;q?75@JN8SJ@fVWQLX*n>F_uY* s%-*Qnx-6nTamR!AxiwEV-G29jH(IMB%le*t6R2$RboFyt=akR{07G6oeE - - - - - - - - - - diff --git a/pype/standalonepublish/resources/trash_disabled.png b/pype/standalonepublish/resources/trash_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..06f5ae5276d22663eeceeb4099b87d86f8ecf9df GIT binary patch literal 1235 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+yeRz<4phC&U%Vg@Dk|PzMJGZEbB& zPfsAj($dn{*jP_b&)VAB+}s?<1`68P*Z{@N%*-5&jcsjht*op}O-+F!Km~TDra&%4 z0gwyS1r)ciu&@QQfl@#&L>4Fo1W*xka|i=SLKr}0))p2(1t9f6hJ^)01g-!iYheN5 zf*245mX>hs5D}09h%&GOI2ULdL?zHc2)%Gaz=CiEAgjR$t{B7s`vt^6HUTUS6oHrz z)CE@nVu1C)1wm?H2*C!cfr~@5AhjQiW^f>W3|F44i;a<(^pAUMBE$5frFF$8|JMDYy$_BI8%Fi!9Klr+K z);zI0$w7O&mp_iT@^ZWQ^xWU8&JLe0O5SfSd=T54?7(kuL&5VjTf=I-OV)l9tP^@qD?fx9Y={*@u?tIs|`I zjp5xgl|l7@J>#3ISL-LK>}=kvt?DT%KEG0y;n;%)m6vLFrmDPcix)lCP_)2%l1R(H zGkfi~vuH4SH3&VhXW1cC5Hd-m;rOH_d^2XG)~)>ZVV~cmEwy5w1TDdR(% zlgC6p{CU#J^y(e^rONmV$!VcU<^LGVq(o+KRBl}sQJ=Wu!Ta2rC!21+`@tKn)sba= SPreCMG(?(`x)jJ*w{G3CWy>H8APEF(*REZ@ zd^wN=0w8zInl%t|#flZk3?LUM1q2ZB)vH$nWmm3T2_%64$c3;W3^*4k2xkKs$SNV~ z(M$lUfdjY#AOixxR)Oq-m;*NrC<0Uf=Rz0|WkB{&0piollYuchvn0qbn1PXrnT3s= zgOiJ!mycgSP)JxrR7^rzMpj-)MO9rxQ%hS%SKrXY!qUpd&fdw*-NVz%$JZ|)C^#fE zJUS*eJ|QVNEj>H8pt!8Oy0)RYv#Ymn!oGpI?4{ z@OAC1d17~xgZ6eWe;jY+<#zGuxxZJP9X?%@yx&~-AhtKzf#2YUg6Cz%V!@FfFgX#f$#y3^3)=yH|*}PX<)l*b_ex)qKu?Gz*FV*f$Re9SMFM6z@Xo2@6 zk(PgF_S$b}(O~py5PD$GvO}mKWRgh3@kvYgX3R*fTlww7KEFv@Y^P;RSJAD>{#*5l z+04IE{M8zvWo7e1nRI97tYM5QX1d1o_Ne@{+ylq%$nTYC>0*B8P*nFWguxRW{xNrfe z0LTD}oIZW}?AfzGl|Tki4Ui2K1WG};5CuRIE)FpVr~oJeQ4eGQ6$1f~0bxVLA%bu< zm{JfCAPG?eB!ODcNMv0=DIkE0ps^ubkO~-ptAsNkGH6_wa)il11#m%HGnjs4%>>5i z%#t9#U_=Ke7wDj!Ug5t9B>e`0p&aU3R2@@wznL2&O%vrPN%w4c_ z)#^2C*KgdkdCS&q+js2RyZ`W!qsNY)I&=2o}GwI%AU|{0*ba4!cIQ({cdT_9#M5}*>7FXGk zhz$#poC5`XLyq*V5ZrxCE}Cazf-9?wiCK=P$BEDRe-+FR_i9%Ee9&WTIlt_F`8ng; zY2Ra4Hkid$et!A+!Pm93=84@&4%*wj{BgXMm)pgs=l))GcKCEr@_uvSgV^3=2Y!Pa z3ZAFg8dm%LHMM`>{CEDhIf@~1mnKWG(pV2QiQWS7vtv!1=+ zq*&y{ruXcp&%R0hz0av?u5E?bgWCtZg?kx)Y+f-nFhk(ow;%75v|M(L z=gVEaRUfX*KD12NA^4+e4DXhy45|n08Q)aBT0co;XY*cdRZmgz`IWK^#~w7Oyi~h0 zRpo74yy&rpq6OZQL|Xox*=xU@MT60+LFj=!%MPJ}kVzs9$0se}n=vD`ZsoTR`}`(t zv7MGNT}8Jh`)}1JW;6dv@mFhvmX*y5WzwCQvxYIMnCTkR+oST+at|E4BfnRorHlEU zLs8wk5C)6TCC|!B86Vo5JSOtt&y!B3SMS&_RmNXPP76&c|HoJ+B{F-Xa_h2)`otX% i-sjdl*>wBe58i04jx6hY@=d@r!r{^^}<`IdjNGca2VJUHJ=5(0*(LzTY-Cl3nR@j;HD75blo0nMSUgr z=^jzHE}`439?ogsO5wRO)Qiu7iTcm9lK>VKXx4-u?oQaNC6^Ysf z@JDof}kz8BS-i~4k02)znClWU#^ej;0B^cy3hM~cZkEF8-;wU|0?j*-=KTWALy_i;y5vuJeYF&B zePI&+PhRxv?z%2DtAI5tu(l-4Ga$8r)HDI4HjtVofYb(3(*%&(Kx&!*QX5E36F_PM zsc8a8Z6GyG0I3b6rU@Xmfz;Fyz#=doofj1-%yy|+BrANVl*$7LAqebgo&E}ZP$1n$ zHovCNSv?ZKz7RsXDi!sPZVDvSjcVIX73wAGWgRp_>Qx;yH{`tC-%cOX&5n_O za_1YCRJ8~p9Pf0&G8NpdI;Gz_$TsHAt1sPASF1Bo%9E83vP{(dk*@{y^123kFL$fG zV8Rl5v(otIa-P2E<{DjXoK#22HbKVKqTiD}tmc>OR3C$6n=QwpHi6qi2#0DLRo!j> z@_cO*&xNo{J)L^C5i{!3J(+wI!Y1`~^{8ofmCc*&3VA~vS?)ak14O|_7j^>z%K!iX M07*qoM6N<$fz>% literal 0 HcmV?d00001 From 69c1ae5990620b5e81e36e832cdea85418b89690 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 10 Dec 2019 19:07:42 +0100 Subject: [PATCH 34/35] created png button with png factory --- .../widgets/widget_component_item.py | 171 +++++++++++++++++- 1 file changed, 170 insertions(+), 1 deletion(-) diff --git a/pype/standalonepublish/widgets/widget_component_item.py b/pype/standalonepublish/widgets/widget_component_item.py index 78287ccf37..f519164c6b 100644 --- a/pype/standalonepublish/widgets/widget_component_item.py +++ b/pype/standalonepublish/widgets/widget_component_item.py @@ -1,6 +1,5 @@ import os from . import QtCore, QtGui, QtWidgets -from . import SvgButton from . import get_resource from pypeapp import style @@ -362,3 +361,173 @@ class LightingButton(QtWidgets.QPushButton): height = preview_font_metrics.height() + 5 self.setMaximumWidth(width) self.setMaximumHeight(height) + + +class PngFactory: + png_names = { + "trash": { + "normal": QtGui.QIcon(get_resource("trash.png")), + "hover": QtGui.QIcon(get_resource("trash_hover.png")), + "pressed": QtGui.QIcon(get_resource("trash_pressed.png")), + "pressed_hover": QtGui.QIcon( + get_resource("trash_pressed_hover.png") + ), + "disabled": QtGui.QIcon(get_resource("trash_disabled.png")) + }, + + "menu": { + "normal": QtGui.QIcon(get_resource("menu.png")), + "hover": QtGui.QIcon(get_resource("menu_hover.png")), + "pressed": QtGui.QIcon(get_resource("menu_pressed.png")), + "pressed_hover": QtGui.QIcon( + get_resource("menu_pressed_hover.png") + ), + "disabled": QtGui.QIcon(get_resource("menu_disabled.png")) + } + } + + +class PngButton(QtWidgets.QPushButton): + png_button_style = """ + QPushButton { + border: none; + background-color: transparent; + padding-top: 0px; + padding-bottom: 0px; + padding-left: 0px; + padding-right: 0px; + } + QPushButton:hover {} + QPushButton:pressed {} + QPushButton:disabled {} + QPushButton:checked {} + QPushButton:checked:hover {} + QPushButton:checked:pressed {} + """ + + def __init__( + self, name=None, path=None, hover_path=None, pressed_path=None, + hover_pressed_path=None, disabled_path=None, + size=None, *args, **kwargs + ): + self._hovered = False + self._pressed = False + super(PngButton, self).__init__(*args, **kwargs) + self.setStyleSheet(self.png_button_style) + + png_dict = {} + if name: + png_dict = PngFactory.png_names.get(name) or {} + if not png_dict: + print(( + "WARNING: There is not set icon with name \"{}\"" + "in PngFactory!" + ).format(name)) + + ico_normal = png_dict.get("normal") + ico_hover = png_dict.get("hover") + ico_pressed = png_dict.get("pressed") + ico_hover_pressed = png_dict.get("pressed_hover") + ico_disabled = png_dict.get("disabled") + + if path: + ico_normal = QtGui.QIcon(path) + if hover_path: + ico_hover = QtGui.QIcon(hover_path) + + if pressed_path: + ico_pressed = QtGui.QIcon(hover_path) + + if hover_pressed_path: + ico_hover_pressed = QtGui.QIcon(hover_pressed_path) + + if disabled_path: + ico_disabled = QtGui.QIcon(disabled_path) + + self.setIcon(ico_normal) + if size: + self.setIconSize(size) + self.setMaximumSize(size) + + self.ico_normal = ico_normal + self.ico_hover = ico_hover + self.ico_pressed = ico_pressed + self.ico_hover_pressed = ico_hover_pressed + self.ico_disabled = ico_disabled + + def setDisabled(self, in_bool): + super(PngButton, self).setDisabled(in_bool) + icon = self.ico_normal + if in_bool and self.ico_disabled: + icon = self.ico_disabled + self.setIcon(icon) + + def enterEvent(self, event): + self._hovered = True + if not self.isEnabled(): + return + icon = self.ico_normal + if self.ico_hover: + icon = self.ico_hover + + if self._pressed and self.ico_hover_pressed: + icon = self.ico_hover_pressed + + if self.icon() != icon: + self.setIcon(icon) + + def mouseMoveEvent(self, event): + super(PngButton, self).mouseMoveEvent(event) + if self._pressed: + mouse_pos = event.pos() + hovering = self.rect().contains(mouse_pos) + if hovering and not self._hovered: + self.enterEvent(event) + elif not hovering and self._hovered: + self.leaveEvent(event) + + def leaveEvent(self, event): + self._hovered = False + if not self.isEnabled(): + return + icon = self.ico_normal + if self._pressed and self.ico_pressed: + icon = self.ico_pressed + + if self.icon() != icon: + self.setIcon(icon) + + def mousePressEvent(self, event): + self._pressed = True + if not self.isEnabled(): + return + icon = self.ico_hover + if self.ico_pressed: + icon = self.ico_pressed + + if self.ico_hover_pressed: + mouse_pos = event.pos() + if self.rect().contains(mouse_pos): + icon = self.ico_hover_pressed + + if icon is None: + icon = self.ico_normal + + if self.icon() != icon: + self.setIcon(icon) + + def mouseReleaseEvent(self, event): + if not self.isEnabled(): + return + if self._pressed: + self._pressed = False + mouse_pos = event.pos() + if self.rect().contains(mouse_pos): + self.clicked.emit() + + icon = self.ico_normal + if self._hovered and self.ico_hover: + icon = self.ico_hover + + if self.icon() != icon: + self.setIcon(icon) From 43d5dbbe744ea08645b33466d3a32b0def1d6fe9 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 10 Dec 2019 19:08:02 +0100 Subject: [PATCH 35/35] replaced svg buttons with pngs --- .../widgets/widget_component_item.py | 25 +++++++------------ 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/pype/standalonepublish/widgets/widget_component_item.py b/pype/standalonepublish/widgets/widget_component_item.py index f519164c6b..daf8f5d773 100644 --- a/pype/standalonepublish/widgets/widget_component_item.py +++ b/pype/standalonepublish/widgets/widget_component_item.py @@ -5,10 +5,6 @@ from pypeapp import style class ComponentItem(QtWidgets.QFrame): - C_NORMAL = '#777777' - C_HOVER = '#ffffff' - C_ACTIVE = '#4BB543' - C_ACTIVE_HOVER = '#4BF543' signal_remove = QtCore.Signal(object) signal_thumbnail = QtCore.Signal(object) @@ -57,10 +53,8 @@ class ComponentItem(QtWidgets.QFrame): self.icon.setText("") self.icon.setScaledContents(True) - self.btn_action_menu = SvgButton( - get_resource('menu.svg'), 22, 22, - [self.C_NORMAL, self.C_HOVER], - frame_image_info, False + self.btn_action_menu = PngButton( + name="menu", size=QtCore.QSize(22, 22) ) self.action_menu = QtWidgets.QMenu() @@ -87,7 +81,9 @@ class ComponentItem(QtWidgets.QFrame): self.file_info.setStyleSheet('padding-left:3px;') - expanding_sizePolicy.setHeightForWidth(self.name.sizePolicy().hasHeightForWidth()) + expanding_sizePolicy.setHeightForWidth( + self.name.sizePolicy().hasHeightForWidth() + ) frame_name_repre = QtWidgets.QFrame(frame) @@ -103,7 +99,8 @@ class ComponentItem(QtWidgets.QFrame): layout.addWidget(self.ext, alignment=QtCore.Qt.AlignRight) frame_name_repre.setSizePolicy( - QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding + QtWidgets.QSizePolicy.MinimumExpanding, + QtWidgets.QSizePolicy.MinimumExpanding ) # Repre + icons @@ -155,12 +152,7 @@ class ComponentItem(QtWidgets.QFrame): layout_main.addWidget(frame_middle) - self.remove = SvgButton( - get_resource('trash.svg'), 22, 22, - [self.C_NORMAL, self.C_HOVER], - frame, False - ) - + self.remove = PngButton(name="trash", size=QtCore.QSize(22, 22)) layout_main.addWidget(self.remove) layout = QtWidgets.QVBoxLayout(self) @@ -350,6 +342,7 @@ class LightingButton(QtWidgets.QPushButton): color: #4BF543; } """ + def __init__(self, text, *args, **kwargs): super().__init__(text, *args, **kwargs) self.setStyleSheet(self.lightingbtnstyle)