diff --git a/pype/maya/action.py b/pype/maya/action.py index 6281a82409..2dcdb82dc9 100644 --- a/pype/maya/action.py +++ b/pype/maya/action.py @@ -125,4 +125,4 @@ class SelectInvalidAction(pyblish.api.Action): cmds.select(invalid, replace=True, noExpand=True) else: self.log.info("No invalid nodes found.") - cmds.select(deselect=True) \ No newline at end of file + cmds.select(deselect=True) diff --git a/pype/nuke/__init__.py b/pype/nuke/__init__.py index 8fc7cd3599..948645fd0d 100644 --- a/pype/nuke/__init__.py +++ b/pype/nuke/__init__.py @@ -87,6 +87,7 @@ def reload_config(): "app.api", "{}.api".format(AVALON_CONFIG), "{}.templates".format(AVALON_CONFIG), + "{}.nuke.actions".format(AVALON_CONFIG), "{}.nuke.templates".format(AVALON_CONFIG), "{}.nuke.menu".format(AVALON_CONFIG) ): diff --git a/pype/nuke/actions.py b/pype/nuke/actions.py new file mode 100644 index 0000000000..640e41a7de --- /dev/null +++ b/pype/nuke/actions.py @@ -0,0 +1,58 @@ +# absolute_import is needed to counter the `module has no cmds error` in Maya +from __future__ import absolute_import + +import pyblish.api + +from avalon.nuke.lib import ( + reset_selection, + select_nodes +) + +from ..action import get_errored_instances_from_context + + +class SelectInvalidAction(pyblish.api.Action): + """Select invalid nodes in Maya when plug-in failed. + + To retrieve the invalid nodes this assumes a static `get_invalid()` + method is available on the plugin. + + """ + label = "Select invalid nodes" + on = "failed" # This action is only available on a failed plug-in + icon = "search" # Icon from Awesome Icon + + def process(self, context, plugin): + + try: + import nuke + except ImportError: + raise ImportError("Current host is not Nuke") + + errored_instances = get_errored_instances_from_context(context) + + # Apply pyblish.logic to get the instances for the plug-in + instances = pyblish.api.instances_by_plugin(errored_instances, plugin) + + # Get the invalid nodes for the plug-ins + self.log.info("Finding invalid nodes..") + invalid = list() + for instance in instances: + invalid_nodes = plugin.get_invalid(instance) + + if invalid_nodes: + if isinstance(invalid_nodes, (list, tuple)): + invalid.append(invalid_nodes[0]) + else: + self.log.warning("Plug-in returned to be invalid, " + "but has no selectable nodes.") + + # Ensure unique (process each node only once) + invalid = list(set(invalid)) + + if invalid: + self.log.info("Selecting invalid nodes: {}".format(invalid)) + reset_selection() + select_nodes(invalid) + else: + self.log.info("No invalid nodes found.") diff --git a/pype/nuke/lib.py b/pype/nuke/lib.py index f4b317e252..2f002ce130 100644 --- a/pype/nuke/lib.py +++ b/pype/nuke/lib.py @@ -1,5 +1,4 @@ import sys -import os from collections import OrderedDict from pprint import pprint from avalon.vendor.Qt import QtGui diff --git a/pype/plugins/maya/publish/validate_joints_hidden.py b/pype/plugins/maya/publish/validate_joints_hidden.py index 4e35cd8c74..acc1dd07a7 100644 --- a/pype/plugins/maya/publish/validate_joints_hidden.py +++ b/pype/plugins/maya/publish/validate_joints_hidden.py @@ -19,7 +19,7 @@ class ValidateJointsHidden(pyblish.api.InstancePlugin): order = pype.api.ValidateContentsOrder hosts = ['maya'] - families = ["rig'] + families = ["rig"] category = 'rig' version = (0, 1, 0) label = "Joints Hidden" diff --git a/pype/plugins/nuke/publish/collect_script.py b/pype/plugins/nuke/publish/collect_script.py index 1a933186de..099217c8bb 100644 --- a/pype/plugins/nuke/publish/collect_script.py +++ b/pype/plugins/nuke/publish/collect_script.py @@ -3,7 +3,10 @@ import nuke import pyblish.api import os import tempfile -from avalon.nuke.lib import add_publish_knob +from avalon.nuke.lib import ( + add_publish_knob, + add_avalon_tab_knob +) class CollectScript(pyblish.api.ContextPlugin): @@ -16,9 +19,10 @@ class CollectScript(pyblish.api.ContextPlugin): def process(self, context): asset_data = io.find_one({"type": "asset", "name": api.Session["AVALON_ASSET"]}) - self.log.debug("asset_data: {}".format(asset_data["data"])) + self.log.info("asset_data: {}".format(asset_data["data"])) root = nuke.root() + add_avalon_tab_knob(root) add_publish_knob(root) # creating instances per write node @@ -37,18 +41,18 @@ class CollectScript(pyblish.api.ContextPlugin): # adding stage dir for faster local renderings staging_dir = tempfile.mkdtemp().replace("\\", "/") instance.data.update({"stagingDir": staging_dir}) - self.log.debug('staging_dir: {}'.format(staging_dir)) + self.log.info('nukescript: staging_dir: {}'.format(staging_dir)) instance.data.update({ - "subset": subset, - "asset": os.environ["AVALON_ASSET"], + "subset": os.getenv("AVALON_TASK", None), + "asset": os.getenv("AVALON_ASSET", None), "label": base_name, "name": base_name, - "subset": subset, "startFrame": first_frame, "endFrame": last_frame, "publish": root.knob('publish').value(), - "family": "script", + "family": "nukescript", + "representation": "nk", "handles": int(asset_data["data"].get("handles", 0)), "step": 1, "fps": int(root['fps'].value()), diff --git a/pype/plugins/nuke/publish/validate_collection.py b/pype/plugins/nuke/publish/validate_collection.py index 44b6825883..09498c58de 100644 --- a/pype/plugins/nuke/publish/validate_collection.py +++ b/pype/plugins/nuke/publish/validate_collection.py @@ -32,6 +32,9 @@ class ValidateCollection(pyblish.api.InstancePlugin): def process(self, instance): self.log.debug('instance.data["files"]: {}'.format(instance.data['files'])) + if not instance.data["files"]: + return + collections, remainder = clique.assemble(*instance.data['files']) self.log.info('collections: {}'.format(str(collections))) diff --git a/pype/plugins/nuke/publish/validate_write_families.py b/pype/plugins/nuke/publish/validate_write_families.py index 238c9bc2ee..1dfdbc06d5 100644 --- a/pype/plugins/nuke/publish/validate_write_families.py +++ b/pype/plugins/nuke/publish/validate_write_families.py @@ -1,19 +1,21 @@ -import os + import pyblish.api -import clique +import pype.api +import pype.nuke.actions -@pyblish.api.log class RepairWriteFamiliesAction(pyblish.api.Action): label = "Fix Write's render attributes" on = "failed" icon = "wrench" - def process(self, context, plugin): - context[0][0]["render"].setValue(True) + def process(self, instance, plugin): + self.log.info("instance {}".format(instance)) + instance["render"].setValue(True) self.log.info("Rendering toggled ON") +@pyblish.api.log class ValidateWriteFamilies(pyblish.api.InstancePlugin): """ Validates write families. """ @@ -21,18 +23,29 @@ class ValidateWriteFamilies(pyblish.api.InstancePlugin): label = "Check correct writes families" hosts = ["nuke"] families = ["write"] - actions = [RepairWriteFamiliesAction] - - def process(self, instance): - self.log.debug('instance.data["files"]: {}'.format(instance.data['files'])) + actions = [pype.nuke.actions.SelectInvalidAction, pype.api.RepairAction] + @staticmethod + def get_invalid(instance): if not [f for f in instance.data["families"] if ".frames" in f]: return - assert instance.data["files"], self.log.info( - "`{}`: Swith `Render` on! \n" - "No available frames to add to database. \n" - "Use repair to render all frames".format(__name__)) + if not instance.data["files"]: + return (instance) + + def process(self, instance): + self.log.debug('instance.data["files"]: {}'.format(instance.data['files'])) + invalid = self.get_invalid(instance) + + if invalid: + raise ValueError(str("`{}`: Switch `Render` on! " + "> {}".format(__name__, invalid))) self.log.info("Checked correct writes families") + + @classmethod + def repair(cls, instance): + cls.log.info("instance {}".format(instance)) + instance[0]["render"].setValue(True) + cls.log.info("Rendering toggled ON")