diff --git a/pype/nuke/__init__.py b/pype/nuke/__init__.py index 42ca633e40..b7dbf69510 100644 --- a/pype/nuke/__init__.py +++ b/pype/nuke/__init__.py @@ -80,17 +80,21 @@ def reload_config(): for module in ( "{}.api".format(AVALON_CONFIG), "{}.nuke.actions".format(AVALON_CONFIG), - "{}.nuke.templates".format(AVALON_CONFIG), + "{}.nuke.presets".format(AVALON_CONFIG), "{}.nuke.menu".format(AVALON_CONFIG), + "{}.nuke.plugin".format(AVALON_CONFIG), "{}.nuke.lib".format(AVALON_CONFIG), ): log.info("Reloading module: {}...".format(module)) + + module = importlib.import_module(module) + try: - module = importlib.import_module(module) - reload(module) - except Exception as e: - log.warning("Cannot reload module: {}".format(e)) importlib.reload(module) + except AttributeError as e: + log.warning("Cannot reload module: {}".format(e)) + reload(module) + def install(): diff --git a/pype/nuke/lib.py b/pype/nuke/lib.py index 28e813c449..9030ea43fb 100644 --- a/pype/nuke/lib.py +++ b/pype/nuke/lib.py @@ -16,7 +16,7 @@ from .presets import ( get_node_colorspace_preset ) -from .templates import ( +from .presets import ( get_anatomy ) # TODO: remove get_anatomy and import directly Anatomy() here @@ -174,8 +174,13 @@ def format_anatomy(data): anatomy = get_anatomy() log.debug("__ anatomy.templates: {}".format(anatomy.templates)) - # TODO: perhaps should be in try! - padding = int(anatomy.templates['render']['padding']) + try: + padding = int(anatomy.templates['render']['padding']) + except KeyError as e: + log.error("`padding` key is not in `render` " + "Anatomy template. Please, add it there and restart " + "the pipeline (padding: \"4\"): `{}`".format(e)) + version = data.get("version", None) if not version: file = script_name() @@ -212,12 +217,13 @@ def add_button_write_to_read(node): node.addKnob(k) -def create_write_node(name, data, prenodes=None): +def create_write_node(name, data, input=None, prenodes=None): ''' Creating write node which is group node Arguments: name (str): name of node data (dict): data to be imprinted + input (node): selected node to connect to prenodes (list, optional): list of lists, definitions for nodes to be created before write @@ -229,9 +235,9 @@ def create_write_node(name, data, prenodes=None): ("knobName", "knobValue"), ("knobName", "knobValue") ), - ( # list inputs - "firstPrevNodeName", - "secondPrevNodeName" + ( # list outputs + "firstPostNodeName", + "secondPostNodeName" ) ) ] @@ -273,28 +279,44 @@ def create_write_node(name, data, prenodes=None): }) # adding dataflow template + log.debug("nuke_dataflow_writes: `{}`".format(nuke_dataflow_writes)) {_data.update({k: v}) for k, v in nuke_dataflow_writes.items() if k not in ["_id", "_previous"]} - # adding dataflow template + # adding colorspace template + log.debug("nuke_colorspace_writes: `{}`".format(nuke_colorspace_writes)) {_data.update({k: v}) for k, v in nuke_colorspace_writes.items()} _data = avalon.nuke.lib.fix_data_for_node_create(_data) - log.debug(_data) + log.debug("_data: `{}`".format(_data)) - _data["frame_range"] = data.get("frame_range", None) + if "frame_range" in data.keys(): + _data["frame_range"] = data.get("frame_range", None) + log.debug("_data[frame_range]: `{}`".format(_data["frame_range"])) - # todo: hange this to new way GN = nuke.createNode("Group", "name {}".format(name)) prev_node = None with GN: + connections = list() + if input: + # if connected input node was defined + connections.append({ + "node": input, + "inputName": input.name()}) + prev_node = nuke.createNode( + "Input", "name {}".format(input.name())) + else: + # generic input node connected to nothing + prev_node = nuke.createNode( + "Input", "name {}".format("rgba")) + # creating pre-write nodes `prenodes` if prenodes: - for name, klass, properties, set_input_to in prenodes: + for name, klass, properties, set_output_to in prenodes: # create node now_node = nuke.createNode(klass, "name {}".format(name)) @@ -304,34 +326,41 @@ def create_write_node(name, data, prenodes=None): now_node[k].serValue(str(v)) # connect to previous node - if set_input_to: - if isinstance(set_input_to, (tuple or list)): - for i, node_name in enumerate(set_input_to): - input_node = nuke.toNode(node_name) + if set_output_to: + if isinstance(set_output_to, (tuple or list)): + for i, node_name in enumerate(set_output_to): + input_node = nuke.createNode( + "Input", "name {}".format(node_name)) + connections.append({ + "node": nuke.toNode(node_name), + "inputName": node_name}) now_node.setInput(1, input_node) - elif isinstance(set_input_to, str): - input_node = nuke.toNode(set_input_to) + elif isinstance(set_output_to, str): + input_node = nuke.createNode( + "Input", "name {}".format(node_name)) + connections.append({ + "node": nuke.toNode(set_output_to), + "inputName": set_output_to}) now_node.setInput(0, input_node) else: now_node.setInput(0, prev_node) # swith actual node to previous prev_node = now_node - else: - prev_node = nuke.createNode("Input", "name rgba") # creating write node - now_node = avalon.nuke.lib.add_write_node("inside_{}".format(name), - **_data - ) - write_node = now_node + write_node = now_node = avalon.nuke.lib.add_write_node( + "inside_{}".format(name), + **_data + ) + # connect to previous node now_node.setInput(0, prev_node) # swith actual node to previous prev_node = now_node - now_node = nuke.createNode("Output", "name write") + now_node = nuke.createNode("Output", "name Output1") # connect to previous node now_node.setInput(0, prev_node) diff --git a/pype/nuke/plugin.py b/pype/nuke/plugin.py new file mode 100644 index 0000000000..d4b5110d6e --- /dev/null +++ b/pype/nuke/plugin.py @@ -0,0 +1,14 @@ +import re +import avalon.api +import avalon.nuke +from pype import api as pype +from pypeapp import config + +class PypeCreator(avalon.nuke.pipeline.Creator): + """Pype Nuke Creator class wrapper + """ + def __init__(self, *args, **kwargs): + super(PypeCreator, self).__init__(*args, **kwargs) + self.presets = config.get_presets()['plugins']["nuke"]["create"].get( + self.__class__.__name__, {} + ) diff --git a/pype/nuke/presets.py b/pype/nuke/presets.py index a3f62764c8..e0c12e2671 100644 --- a/pype/nuke/presets.py +++ b/pype/nuke/presets.py @@ -39,8 +39,9 @@ def get_node_dataflow_preset(**kwarg): nuke_dataflow_node = nuke_dataflow_node.get(str(preset), None) # omit < 2.0.0v - for family in families: - nuke_dataflow_node = nuke_dataflow_node.get(str(family), None) + if families: + for family in families: + nuke_dataflow_node = nuke_dataflow_node.get(str(family), None) log.info("Dataflow: {}".format(nuke_dataflow_node)) return nuke_dataflow_node @@ -52,14 +53,22 @@ def get_node_colorspace_preset(**kwarg): log.info(kwarg) host = kwarg.get("host", "nuke") cls = kwarg.get("class", None) - preset = kwarg.get("preset", None) + families = kwarg.get("families", []) + preset = kwarg.get("preset", None) # omit < 2.0.0v + assert any([host, cls]), log.error( "`{}`: Missing mandatory kwargs `host`, `cls`".format(__file__)) nuke_colorspace = get_colorspace_preset().get(str(host), None) nuke_colorspace_node = nuke_colorspace.get(str(cls), None) - if preset: + + if preset: # omit < 2.0.0v nuke_colorspace_node = nuke_colorspace_node.get(str(preset), None) + # omit < 2.0.0v + + if families: + for family in families: + nuke_colorspace_node = nuke_colorspace_node.get(str(family), None) log.info("Colorspace: {}".format(nuke_colorspace_node)) return nuke_colorspace_node diff --git a/pype/plugins/nuke/create/create_write.py b/pype/plugins/nuke/create/create_write.py index c3da555259..1634af22ab 100644 --- a/pype/plugins/nuke/create/create_write.py +++ b/pype/plugins/nuke/create/create_write.py @@ -1,8 +1,8 @@ from collections import OrderedDict import avalon.api import avalon.nuke -from pype.nuke.lib import create_write_node from pype import api as pype +from pype.nuke import plugin from pypeapp import config import nuke @@ -11,135 +11,167 @@ import nuke log = pype.Logger().get_logger(__name__, "nuke") -def subset_to_families(subset, family, families): - subset_sufx = str(subset).replace(family, "") - new_subset = families + subset_sufx - return "{}.{}".format(family, new_subset) - -class CreateWriteRender(avalon.nuke.Creator): +class CreateWriteRender(plugin.PypeCreator): # change this to template preset - preset = "render" - name = "WriteRender" label = "Create Write Render" hosts = ["nuke"] - family = "{}_write".format(preset) - families = preset + nClass = "write" + family = "render" icon = "sign-out" defaults = ["Main", "Mask"] def __init__(self, *args, **kwargs): super(CreateWriteRender, self).__init__(*args, **kwargs) - self.presets = config.get_presets()['plugins']["nuke"]["create"].get( - self.__class__.__name__, {} - ) self.name = self.data["subset"] data = OrderedDict() - data["family"] = self.family.split("_")[-1] - data["families"] = self.families + data["family"] = self.nClass + data["families"] = self.family + + for k, v in self.data.items(): + if k not in data.keys(): + data.update({k: v}) - {data.update({k: v}) for k, v in self.data.items() - if k not in data.keys()} self.data = data + self.log.info("self.data: '{}'".format(self.data)) def process(self): + from pype.nuke import lib as pnlib + reload(pnlib) - family = self.family - node = 'write' - + inputs = [] + outputs = [] instance = nuke.toNode(self.data["subset"]) + selected_node = None - if not instance: - write_data = { - "class": node, - "preset": self.preset, - "avalon": self.data - } + # use selection + if (self.options or {}).get("useSelection"): + nodes = nuke.selectedNodes() - if self.presets.get('fpath_template'): - self.log.info("Adding template path from preset") - write_data.update( - {"fpath_template": self.presets["fpath_template"]} - ) - else: - self.log.info("Adding template path from plugin") - write_data.update({ - "fpath_template": "{work}/renders/nuke/{subset}/{subset}.{frame}.{ext}"}) + assert len(nodes) == 1, self.log.error("Select only one node. The node you want to connect to, or tick off `Use selection`") - return create_write_node(self.data["subset"], write_data) + selected_node = nodes[0] + inputs = [selected_node] + outputs = selected_node.dependent() + if instance: + if (instance.name() in selected_node.name()): + selected_node = instance.dependencies()[0] -class CreateWritePrerender(avalon.nuke.Creator): - # change this to template preset - preset = "prerender" + # if node already exist + if instance: + # collect input / outputs + inputs = instance.dependencies() + outputs = instance.dependent() + selected_node = inputs[0] + # remove old one + nuke.delete(instance) - name = "WritePrerender" - label = "Create Write Prerender" - hosts = ["nuke"] - family = "{}_write".format(preset) - families = preset - icon = "sign-out" - defaults = ["Main", "Mask"] + # recreate new + write_data = { + "class": self.nClass, + "families": [self.family], + "avalon": self.data + } - def __init__(self, *args, **kwargs): - super(CreateWritePrerender, self).__init__(*args, **kwargs) - self.presets = config.get_presets()['plugins']["nuke"]["create"].get( - self.__class__.__name__, {} - ) + if self.presets.get('fpath_template'): + self.log.info("Adding template path from preset") + write_data.update( + {"fpath_template": self.presets["fpath_template"]} + ) + else: + self.log.info("Adding template path from plugin") + write_data.update({ + "fpath_template": "{work}/renders/nuke/{subset}/{subset}.{frame}.{ext}"}) - data = OrderedDict() + write_node = pnlib.create_write_node( + self.data["subset"], + write_data, + input=selected_node) - data["family"] = self.family.split("_")[1] - data["families"] = self.families + # relinking to collected connections + for i, input in enumerate(inputs): + write_node.setInput(i, input) - {data.update({k: v}) for k, v in self.data.items() - if k not in data.keys()} - self.data = data + write_node.autoplace() - def process(self): - self.name = self.data["subset"] + for output in outputs: + output.setInput(0, write_node) - instance = nuke.toNode(self.data["subset"]) - node = 'write' + return True - if not instance: - write_data = { - "class": node, - "preset": self.preset, - "avalon": self.data - } - - if self.presets.get('fpath_template'): - self.log.info("Adding template path from preset") - write_data.update( - {"fpath_template": self.presets["fpath_template"]} - ) - else: - self.log.info("Adding template path from plugin") - write_data.update({ - "fpath_template": "{work}/prerenders/{subset}/{subset}.{frame}.{ext}"}) - - # get group node - group_node = create_write_node(self.data["subset"], write_data) - - # open group node - group_node.begin() - for n in nuke.allNodes(): - # get write node - if n.Class() in "Write": - write_node = n - group_node.end() - - # linking knobs to group property panel - linking_knobs = ["first", "last", "use_limit"] - for k in linking_knobs: - lnk = nuke.Link_Knob(k) - lnk.makeLink(write_node.name(), k) - lnk.setName(k.replace('_', ' ').capitalize()) - lnk.clearFlag(nuke.STARTLINE) - group_node.addKnob(lnk) - - return +# +# class CreateWritePrerender(avalon.nuke.Creator): +# # change this to template preset +# preset = "prerender" +# +# name = "WritePrerender" +# label = "Create Write Prerender" +# hosts = ["nuke"] +# family = "{}_write".format(preset) +# families = preset +# icon = "sign-out" +# defaults = ["Main", "Mask"] +# +# def __init__(self, *args, **kwargs): +# super(CreateWritePrerender, self).__init__(*args, **kwargs) +# self.presets = config.get_presets()['plugins']["nuke"]["create"].get( +# self.__class__.__name__, {} +# ) +# +# data = OrderedDict() +# +# data["family"] = self.family.split("_")[1] +# data["families"] = self.families +# +# {data.update({k: v}) for k, v in self.data.items() +# if k not in data.keys()} +# self.data = data +# +# def process(self): +# self.name = self.data["subset"] +# +# instance = nuke.toNode(self.data["subset"]) +# node = 'write' +# +# if not instance: +# write_data = { +# "class": node, +# "preset": self.preset, +# "avalon": self.data +# } +# +# if self.presets.get('fpath_template'): +# self.log.info("Adding template path from preset") +# write_data.update( +# {"fpath_template": self.presets["fpath_template"]} +# ) +# else: +# self.log.info("Adding template path from plugin") +# write_data.update({ +# "fpath_template": "{work}/prerenders/{subset}/{subset}.{frame}.{ext}"}) +# +# # get group node +# group_node = create_write_node(self.data["subset"], write_data) +# +# # open group node +# group_node.begin() +# for n in nuke.allNodes(): +# # get write node +# if n.Class() in "Write": +# write_node = n +# group_node.end() +# +# # linking knobs to group property panel +# linking_knobs = ["first", "last", "use_limit"] +# for k in linking_knobs: +# lnk = nuke.Link_Knob(k) +# lnk.makeLink(write_node.name(), k) +# lnk.setName(k.replace('_', ' ').capitalize()) +# lnk.clearFlag(nuke.STARTLINE) +# group_node.addKnob(lnk) +# +# return diff --git a/setup/nuke/nuke_path/write_to_read.py b/setup/nuke/nuke_path/write_to_read.py index 9667dccab6..2cf6598b3b 100644 --- a/setup/nuke/nuke_path/write_to_read.py +++ b/setup/nuke/nuke_path/write_to_read.py @@ -38,7 +38,7 @@ def evaluate_filepath_new(k_value, k_eval, project_dir, first_frame): filepath = os.path.abspath(filepath) except Exception as E: log.error("Cannot create Read node. Perhaps it needs to be rendered first :) Error: `{}`".format(E)) - return + return None filepath = filepath.replace('\\', '/') current_frame = re.findall(r'\d+', filepath)[-1] @@ -114,12 +114,16 @@ def write_to_read(gn): n = group_writes[0] if n.knob('file') is not None: - myfiletranslated, firstFrame, lastFrame = evaluate_filepath_new( + file_path_new = evaluate_filepath_new( n.knob('file').getValue(), n.knob('file').evaluate(), project_dir, comp_start ) + if not file_path_new: + return + + myfiletranslated, firstFrame, lastFrame = file_path_new # get node data ndata = { 'filepath': myfiletranslated,