diff --git a/pype/ftrack/actions/action_rv.py b/pype/ftrack/actions/action_rv.py index 69c6624b71..e32997e5a9 100644 --- a/pype/ftrack/actions/action_rv.py +++ b/pype/ftrack/actions/action_rv.py @@ -15,6 +15,7 @@ log = Logger().get_logger(__name__) class RVAction(BaseAction): """ Launch RV action """ + ignore_me = "rv" not in config.get_presets() identifier = "rv.launch.action" label = "rv" description = "rv Launcher" @@ -42,8 +43,9 @@ class RVAction(BaseAction): ) else: # if not, fallback to config file location - self.config_data = config.get_presets()['rv']['config'] - self.set_rv_path() + if "rv" in config.get_presets(): + self.config_data = config.get_presets()['rv']['config'] + self.set_rv_path() if self.rv_path is None: return diff --git a/pype/ftrack/events/event_thumbnail_updates.py b/pype/ftrack/events/event_thumbnail_updates.py index ae6f8adb5e..620d1a5b72 100644 --- a/pype/ftrack/events/event_thumbnail_updates.py +++ b/pype/ftrack/events/event_thumbnail_updates.py @@ -20,7 +20,8 @@ class ThumbnailEvents(BaseEvent): if parent.get('thumbnail') and not task.get('thumbnail'): task['thumbnail'] = parent['thumbnail'] self.log.info('>>> Updated thumbnail on [ %s/%s ]'.format( - parent['name'], task['name'])) + parent['name'], task['name'] + )) # Update task thumbnail from published version # if (entity['entityType'] == 'assetversion' and @@ -32,18 +33,24 @@ class ThumbnailEvents(BaseEvent): version = session.get('AssetVersion', entity['entityId']) thumbnail = version.get('thumbnail') - task = version['task'] - if thumbnail: - task['thumbnail'] = thumbnail - task['parent']['thumbnail'] = thumbnail - self.log.info('>>> Updating thumbnail for task and shot\ - [ {} ]'.format(task['name'])) + parent = version['asset']['parent'] + task = version['task'] + parent['thumbnail_id'] = version['thumbnail_id'] + if parent.entity_type.lower() == "project": + name = parent["full_name"] + else: + name = parent["name"] + msg = '>>> Updating thumbnail for shot [ {} ]'.format(name) + + if task: + task['thumbnail_id'] = version['thumbnail_id'] + msg += " and task [ {} ]".format(task["name"])) + + self.log.info(msg) session.commit() - pass - def register(session, plugins_presets): '''Register plugin. Called when used as an plugin.''' diff --git a/pype/nuke/lib.py b/pype/nuke/lib.py index f182088457..28e813c449 100644 --- a/pype/nuke/lib.py +++ b/pype/nuke/lib.py @@ -8,7 +8,9 @@ import avalon.nuke import pype.api as pype import nuke -from .templates import ( + + +from .presets import ( get_colorspace_preset, get_node_dataflow_preset, get_node_colorspace_preset @@ -55,7 +57,8 @@ def checkInventoryVersions(): if container: node = container["_node"] - avalon_knob_data = avalon.nuke.get_avalon_knob_data(node) + avalon_knob_data = avalon.nuke.get_avalon_knob_data( + node, ['avalon:', 'ak:']) # get representation from io representation = io.find_one({ @@ -101,7 +104,8 @@ def writes_version_sync(): for each in nuke.allNodes(): if each.Class() == 'Write': - avalon_knob_data = avalon.nuke.get_avalon_knob_data(each) + avalon_knob_data = avalon.nuke.get_avalon_knob_data( + each, ['avalon:', 'ak:']) try: if avalon_knob_data['families'] not in ["render"]: @@ -134,7 +138,8 @@ def get_render_path(node): ''' Generate Render path from presets regarding avalon knob data ''' data = dict() - data['avalon'] = avalon.nuke.get_avalon_knob_data(node) + data['avalon'] = avalon.nuke.get_avalon_knob_data( + node, ['avalon:', 'ak:']) data_preset = { "class": data['avalon']['family'], @@ -379,6 +384,10 @@ def add_rendering_knobs(node): knob = nuke.Boolean_Knob("render_farm", "Render on Farm") knob.setValue(False) node.addKnob(knob) + if "review" not in node.knobs(): + knob = nuke.Boolean_Knob("review", "Review") + knob.setValue(True) + node.addKnob(knob) return node @@ -389,6 +398,14 @@ def add_deadline_tab(node): knob.setValue(1) node.addKnob(knob) + knob = nuke.Int_Knob("deadlinePriority", "Priority") + knob.setValue(50) + node.addKnob(knob) + + +def get_deadline_knob_names(): + return ["Deadline", "deadlineChunkSize", "deadlinePriority"] + def create_backdrop(label="", color=None, layer=0, nodes=None): @@ -543,17 +560,34 @@ class WorkfileSettings(object): assert isinstance(root_dict, dict), log.error( "set_root_colorspace(): argument should be dictionary") + log.debug(">> root_dict: {}".format(root_dict)) + # first set OCIO if self._root_node["colorManagement"].value() \ not in str(root_dict["colorManagement"]): self._root_node["colorManagement"].setValue( str(root_dict["colorManagement"])) + log.debug("nuke.root()['{0}'] changed to: {1}".format( + "colorManagement", root_dict["colorManagement"])) + root_dict.pop("colorManagement") # second set ocio version if self._root_node["OCIO_config"].value() \ not in str(root_dict["OCIO_config"]): self._root_node["OCIO_config"].setValue( str(root_dict["OCIO_config"])) + log.debug("nuke.root()['{0}'] changed to: {1}".format( + "OCIO_config", root_dict["OCIO_config"])) + root_dict.pop("OCIO_config") + + # third set ocio custom path + if root_dict.get("customOCIOConfigPath"): + self._root_node["customOCIOConfigPath"].setValue( + str(root_dict["customOCIOConfigPath"]).format(**os.environ) + ) + log.debug("nuke.root()['{}'] changed to: {}".format( + "customOCIOConfigPath", root_dict["customOCIOConfigPath"])) + root_dict.pop("customOCIOConfigPath") # then set the rest for knob, value in root_dict.items(): @@ -798,10 +832,12 @@ def get_write_node_template_attr(node): ''' # get avalon data from node data = dict() - data['avalon'] = avalon.nuke.get_avalon_knob_data(node) + data['avalon'] = avalon.nuke.get_avalon_knob_data( + node, ['avalon:', 'ak:']) data_preset = { "class": data['avalon']['family'], - "preset": data['avalon']['families'] + "families": data['avalon']['families'], + "preset": data['avalon']['families'] # omit < 2.0.0v } # get template data @@ -927,7 +963,7 @@ class BuildWorkfile(WorkfileSettings): def process(self, regex_filter=None, version=None, - representations=["exr", "dpx", "lutJson"]): + representations=["exr", "dpx", "lutJson", "mov", "preview"]): """ A short description. @@ -984,6 +1020,8 @@ class BuildWorkfile(WorkfileSettings): version=version, representations=representations) + log.info("__ subsets: `{}`".format(subsets)) + nodes_backdrop = list() for name, subset in subsets.items(): diff --git a/pype/nuke/templates.py b/pype/nuke/presets.py similarity index 75% rename from pype/nuke/templates.py rename to pype/nuke/presets.py index 6434d73f1d..a3f62764c8 100644 --- a/pype/nuke/templates.py +++ b/pype/nuke/presets.py @@ -25,16 +25,22 @@ def get_node_dataflow_preset(**kwarg): log.info(kwarg) host = kwarg.get("host", "nuke") cls = kwarg.get("class", None) - preset = kwarg.get("preset", None) - assert any([host, cls]), log.error("nuke.templates.get_node_dataflow_preset(): \ - Missing mandatory kwargs `host`, `cls`") + 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_dataflow = get_dataflow_preset().get(str(host), None) nuke_dataflow_nodes = nuke_dataflow.get('nodes', None) nuke_dataflow_node = nuke_dataflow_nodes.get(str(cls), None) - if preset: + if preset: # omit < 2.0.0v 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) log.info("Dataflow: {}".format(nuke_dataflow_node)) return nuke_dataflow_node @@ -47,8 +53,8 @@ def get_node_colorspace_preset(**kwarg): host = kwarg.get("host", "nuke") cls = kwarg.get("class", None) preset = kwarg.get("preset", None) - assert any([host, cls]), log.error("nuke.templates.get_node_colorspace_preset(): \ - Missing mandatory kwargs `host`, `cls`") + 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) diff --git a/pype/plugins/global/publish/integrate_new.py b/pype/plugins/global/publish/integrate_new.py index a82ebdd5a6..4ef2616cda 100644 --- a/pype/plugins/global/publish/integrate_new.py +++ b/pype/plugins/global/publish/integrate_new.py @@ -314,8 +314,14 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): index_frame_start = int(repre.get("frameStart")) dst_padding_exp = src_padding_exp + dst_start_frame = None for i in src_collection.indexes: src_padding = src_padding_exp % i + + # for adding first frame into db + if not dst_start_frame: + dst_start_frame = src_padding + src_file_name = "{0}{1}{2}".format( src_head, src_padding, src_tail) @@ -326,19 +332,22 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): dst_padding = dst_padding_exp % index_frame_start index_frame_start += 1 - dst = "{0}{1}{2}".format(dst_head, dst_padding, dst_tail).replace("..", ".") + dst = "{0}{1}{2}".format( + dst_head, + dst_padding, + dst_tail).replace("..", ".") + self.log.debug("destination: `{}`".format(dst)) src = os.path.join(stagingdir, src_file_name) + self.log.debug("source: {}".format(src)) instance.data["transfers"].append([src, dst]) - repre['published_path'] = "{0}{1}{2}".format(dst_head, - dst_padding_exp, - dst_tail) - # for imagesequence version data - hashes = '#' * len(dst_padding) - dst = os.path.normpath("{0}{1}{2}".format( - dst_head, hashes, dst_tail)) + dst = "{0}{1}{2}".format( + dst_head, + dst_start_frame, + dst_tail).replace("..", ".") + repre['published_path'] = dst else: # Single file diff --git a/pype/plugins/global/publish/submit_publish_job.py b/pype/plugins/global/publish/submit_publish_job.py index 0130eaf0c4..1072f95b8e 100644 --- a/pype/plugins/global/publish/submit_publish_job.py +++ b/pype/plugins/global/publish/submit_publish_job.py @@ -174,7 +174,8 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin): "JobDependency0": job["_id"], "UserName": job["Props"]["User"], "Comment": instance.context.data.get("comment", ""), - "InitialStatus": state + "InitialStatus": state, + "Priority": job["Props"]["Pri"] }, "PluginInfo": { "Version": "3.6", diff --git a/pype/plugins/global/publish/validate_custom_ftrack_attributes.py b/pype/plugins/global/publish/validate_custom_ftrack_attributes.py index 0d0eb2a7f0..2386b359e4 100644 --- a/pype/plugins/global/publish/validate_custom_ftrack_attributes.py +++ b/pype/plugins/global/publish/validate_custom_ftrack_attributes.py @@ -46,7 +46,8 @@ class ValidateFtrackAttributes(pyblish.api.InstancePlugin): "Missing FTrack Task entity in context") host = pyblish.api.current_host() - to_check = context.data["presets"][host].get("ftrack_attributes") + to_check = context.data["presets"].get( + host, {}).get("ftrack_attributes") if not to_check: self.log.warning("ftrack_attributes preset not found") return diff --git a/pype/plugins/maya/load/load_ass.py b/pype/plugins/maya/load/load_ass.py index 979d4b5767..2960e4403e 100644 --- a/pype/plugins/maya/load/load_ass.py +++ b/pype/plugins/maya/load/load_ass.py @@ -1,7 +1,6 @@ from avalon import api import pype.maya.plugin import os -import pymel.core as pm from pypeapp import config @@ -70,6 +69,7 @@ class AssProxyLoader(pype.maya.plugin.ReferenceLoader): import os from maya import cmds + import pymel.core as pm node = container["objectName"] diff --git a/pype/plugins/maya/load/load_gpucache.py b/pype/plugins/maya/load/load_gpucache.py index b98ca8b7f4..9e7938777e 100644 --- a/pype/plugins/maya/load/load_gpucache.py +++ b/pype/plugins/maya/load/load_gpucache.py @@ -2,7 +2,6 @@ from avalon import api import pype.maya.plugin import os from pypeapp import config -import pymel.core as pm reload(config) diff --git a/pype/plugins/maya/load/load_image_plane.py b/pype/plugins/maya/load/load_image_plane.py index e2d94ac82e..e95ea6cd8f 100644 --- a/pype/plugins/maya/load/load_image_plane.py +++ b/pype/plugins/maya/load/load_image_plane.py @@ -1,5 +1,3 @@ -import pymel.core as pc - from avalon import api from Qt import QtWidgets @@ -14,6 +12,8 @@ class ImagePlaneLoader(api.Loader): color = "orange" def load(self, context, name, namespace, data): + import pymel.core as pc + new_nodes = [] image_plane_depth = 1000 diff --git a/pype/plugins/maya/load/load_reference.py b/pype/plugins/maya/load/load_reference.py index a754c3be98..55db019cf4 100644 --- a/pype/plugins/maya/load/load_reference.py +++ b/pype/plugins/maya/load/load_reference.py @@ -1,8 +1,6 @@ - import pype.maya.plugin import os from pypeapp import config -import pymel.core as pm reload(config) import pype.maya.plugin reload(pype.maya.plugin) @@ -20,9 +18,10 @@ class ReferenceLoader(pype.maya.plugin.ReferenceLoader): color = "orange" def process_reference(self, context, name, namespace, data): - import maya.cmds as cmds from avalon import maya + import pymel.core as pm + try: family = context["representation"]["context"]["family"] diff --git a/pype/plugins/maya/load/load_yeti_rig.py b/pype/plugins/maya/load/load_yeti_rig.py index eb75ff6bdc..a3e03e8a6c 100644 --- a/pype/plugins/maya/load/load_yeti_rig.py +++ b/pype/plugins/maya/load/load_yeti_rig.py @@ -1,9 +1,17 @@ -import pype.maya.plugin import os +from collections import defaultdict + from pypeapp import config +import pype.maya.plugin +from pype.maya import lib class YetiRigLoader(pype.maya.plugin.ReferenceLoader): + """ + This loader will load Yeti rig. You can select something in scene and if it + has same ID as mesh published with rig, their shapes will be linked + together. + """ families = ["yetiRig"] representations = ["ma"] @@ -18,6 +26,32 @@ class YetiRigLoader(pype.maya.plugin.ReferenceLoader): import maya.cmds as cmds from avalon import maya + # get roots of selected hierarchies + selected_roots = [] + for sel in cmds.ls(sl=True, long=True): + selected_roots.append(sel.split("|")[1]) + + # get all objects under those roots + selected_hierarchy = [] + for root in selected_roots: + selected_hierarchy.append(cmds.listRelatives( + root, + allDescendents=True) or []) + + # flatten the list and filter only shapes + shapes_flat = [] + for root in selected_hierarchy: + shapes = cmds.ls(root, long=True, type="mesh") or [] + for shape in shapes: + shapes_flat.append(shape) + + # create dictionary of cbId and shape nodes + scene_lookup = defaultdict(list) + for node in shapes_flat: + cb_id = lib.get_id(node) + scene_lookup[cb_id] = node + + # load rig with maya.maintained_selection(): nodes = cmds.file(self.fname, namespace=namespace, @@ -26,6 +60,20 @@ class YetiRigLoader(pype.maya.plugin.ReferenceLoader): groupReference=True, groupName="{}:{}".format(namespace, name)) + # for every shape node we've just loaded find matching shape by its + # cbId in selection. If found outMesh of scene shape will connect to + # inMesh of loaded shape. + for destination_node in nodes: + source_node = scene_lookup[lib.get_id(destination_node)] + if source_node: + self.log.info("found: {}".format(source_node)) + self.log.info( + "creating connection to {}".format(destination_node)) + + cmds.connectAttr("{}.outMesh".format(source_node), + "{}.inMesh".format(destination_node), + force=True) + groupName = "{}:{}".format(namespace, name) presets = config.get_presets(project=os.environ['AVALON_PROJECT']) @@ -38,6 +86,4 @@ class YetiRigLoader(pype.maya.plugin.ReferenceLoader): c[0], c[1], c[2]) self[:] = nodes - self.log.info("Yeti Rig Connection Manager will be available soon") - return nodes diff --git a/pype/plugins/maya/publish/extract_yeti_rig.py b/pype/plugins/maya/publish/extract_yeti_rig.py index b575c07cf4..892bc0bea6 100644 --- a/pype/plugins/maya/publish/extract_yeti_rig.py +++ b/pype/plugins/maya/publish/extract_yeti_rig.py @@ -126,6 +126,18 @@ class ExtractYetiRig(pype.api.Extractor): with open(settings_path, "w") as fp: json.dump(settings, fp, ensure_ascii=False) + # add textures to transfers + if 'transfers' not in instance.data: + instance.data['transfers'] = [] + + for resource in instance.data.get('resources', []): + for file in resource['files']: + src = file + dst = os.path.join(image_search_path, os.path.basename(file)) + instance.data['transfers'].append([src, dst]) + + self.log.info("adding transfer {} -> {}". format(src, dst)) + # Ensure the imageSearchPath is being remapped to the publish folder attr_value = {"%s.imageSearchPath" % n: str(image_search_path) for n in yeti_nodes} diff --git a/pype/plugins/nuke/publish/extract_frames.py b/pype/plugins/nuke/_publish_unused/extract_frames.py similarity index 100% rename from pype/plugins/nuke/publish/extract_frames.py rename to pype/plugins/nuke/_publish_unused/extract_frames.py diff --git a/pype/plugins/nuke/load/load_sequence.py b/pype/plugins/nuke/load/load_sequence.py index 2946857e09..e1c75584d7 100644 --- a/pype/plugins/nuke/load/load_sequence.py +++ b/pype/plugins/nuke/load/load_sequence.py @@ -110,6 +110,7 @@ class LoadSequence(api.Loader): last += self.handle_end file = self.fname.replace("\\", "/") + log.info("file: {}\n".format(self.fname)) repr_cont = context["representation"]["context"] @@ -118,6 +119,11 @@ class LoadSequence(api.Loader): repr_cont["subset"], repr_cont["representation"]) + if "#" not in file: + frame = repr_cont.get("frame") + padding = len(frame) + file = file.replace(frame, "#"*padding) + # Create the Loader with the filename path set with viewer_update_and_undo_stop(): # TODO: it might be universal read to img/geo/camera diff --git a/pype/plugins/nuke/publish/collect_review.py b/pype/plugins/nuke/publish/collect_review.py index 0ab5424434..7e7cbedd6c 100644 --- a/pype/plugins/nuke/publish/collect_review.py +++ b/pype/plugins/nuke/publish/collect_review.py @@ -1,5 +1,5 @@ import pyblish.api - +import nuke class CollectReview(pyblish.api.InstancePlugin): """Collect review instance from rendered frames @@ -9,9 +9,20 @@ class CollectReview(pyblish.api.InstancePlugin): family = "review" label = "Collect Review" hosts = ["nuke"] - families = ["render", "render.local"] + families = ["render", "render.local", "render.farm"] def process(self, instance): - if instance.data["families"]: - instance.data["families"].append("review") - self.log.info("Review collected: `{}`".format(instance)) + + node = instance[0] + + if "review" not in node.knobs(): + knob = nuke.Boolean_Knob("review", "Review") + knob.setValue(True) + node.addKnob(knob) + + if not node["review"].value(): + return + + instance.data["families"].append("review") + instance.data['families'].append('ftrack') + self.log.info("Review collected: `{}`".format(instance)) diff --git a/pype/plugins/nuke/publish/collect_writes.py b/pype/plugins/nuke/publish/collect_writes.py index 29ae6cb929..28470c94de 100644 --- a/pype/plugins/nuke/publish/collect_writes.py +++ b/pype/plugins/nuke/publish/collect_writes.py @@ -65,7 +65,6 @@ class CollectNukeWrites(pyblish.api.InstancePlugin): ) if 'render' in instance.data['families']: - instance.data['families'].append('ftrack') if "representations" not in instance.data: instance.data["representations"] = list() @@ -78,22 +77,22 @@ class CollectNukeWrites(pyblish.api.InstancePlugin): try: collected_frames = os.listdir(output_dir) + if collected_frames: + representation['frameStart'] = "%0{}d".format( + len(str(last_frame))) % first_frame representation['files'] = collected_frames instance.data["representations"].append(representation) except Exception: instance.data["representations"].append(representation) self.log.debug("couldn't collect frames: {}".format(label)) - if 'render.local' in instance.data['families']: - instance.data['families'].append('ftrack') - # Add version data to instance version_data = { "handles": handle_start, "handleStart": handle_start, "handleEnd": handle_end, - "frameStart": first_frame, - "frameEnd": last_frame, + "frameStart": first_frame + handle_start, + "frameEnd": last_frame - handle_end, "version": int(version), "colorspace": node["colorspace"].value(), "families": [instance.data["family"]], @@ -106,6 +105,10 @@ class CollectNukeWrites(pyblish.api.InstancePlugin): if "deadlineChunkSize" in group_node.knobs(): deadlineChunkSize = group_node["deadlineChunkSize"].value() + deadlinePriority = 50 + if "deadlinePriority" in group_node.knobs(): + deadlinePriority = group_node["deadlinePriority"].value() + instance.data.update({ "versionData": version_data, "path": path, @@ -117,7 +120,8 @@ class CollectNukeWrites(pyblish.api.InstancePlugin): "frameEnd": last_frame, "outputType": output_type, "colorspace": node["colorspace"].value(), - "deadlineChunkSize": deadlineChunkSize + "deadlineChunkSize": deadlineChunkSize, + "deadlinePriority": deadlinePriority }) self.log.debug("instance.data: {}".format(instance.data)) diff --git a/pype/plugins/nuke/publish/extract_render_local.py b/pype/plugins/nuke/publish/extract_render_local.py index 29de347288..825db67e9d 100644 --- a/pype/plugins/nuke/publish/extract_render_local.py +++ b/pype/plugins/nuke/publish/extract_render_local.py @@ -58,6 +58,7 @@ class NukeRenderLocal(pype.api.Extractor): repre = { 'name': ext, 'ext': ext, + 'frameStart': "%0{}d".format(len(str(last_frame))) % first_frame, 'files': collected_frames, "stagingDir": out_dir, "anatomy_template": "render" diff --git a/pype/plugins/nuke/publish/submit_nuke_deadline.py b/pype/plugins/nuke/publish/submit_nuke_deadline.py index ef971f3a37..4044026b5e 100644 --- a/pype/plugins/nuke/publish/submit_nuke_deadline.py +++ b/pype/plugins/nuke/publish/submit_nuke_deadline.py @@ -85,6 +85,7 @@ class NukeSubmitDeadline(pyblish.api.InstancePlugin): end=int(instance.data["frameEnd"]) ), "ChunkSize": instance.data["deadlineChunkSize"], + "Priority": instance.data["deadlinePriority"], "Comment": comment, diff --git a/pype/plugins/nuke/publish/validate_write_deadline_tab.py b/pype/plugins/nuke/publish/validate_write_deadline_tab.py index 0c222a164a..4e63e14a7f 100644 --- a/pype/plugins/nuke/publish/validate_write_deadline_tab.py +++ b/pype/plugins/nuke/publish/validate_write_deadline_tab.py @@ -22,6 +22,13 @@ class RepairNukeWriteDeadlineTab(pyblish.api.Action): for instance in instances: group_node = [x for x in instance if x.Class() == "Group"][0] + + # Remove exising knobs. + knob_names = pype.nuke.lib.get_deadline_knob_names() + for name, knob in group_node.knobs().iteritems(): + if name in knob_names: + group_node.removeKnob(knob) + pype.nuke.lib.add_deadline_tab(group_node) @@ -38,5 +45,9 @@ class ValidateNukeWriteDeadlineTab(pyblish.api.InstancePlugin): def process(self, instance): group_node = [x for x in instance if x.Class() == "Group"][0] - msg = "Deadline tab missing on \"{}\"".format(group_node.name()) - assert "Deadline" in group_node.knobs(), msg + knob_names = pype.nuke.lib.get_deadline_knob_names() + missing_knobs = [] + for name in knob_names: + if name not in group_node.knobs().keys(): + missing_knobs.append(name) + assert not missing_knobs, "Missing knobs: {}".format(missing_knobs) diff --git a/pype/plugins/nukestudio/publish/collect_plates.py b/pype/plugins/nukestudio/publish/collect_plates.py index 2ebbfde551..f9eb126772 100644 --- a/pype/plugins/nukestudio/publish/collect_plates.py +++ b/pype/plugins/nukestudio/publish/collect_plates.py @@ -196,12 +196,14 @@ class CollectPlatesData(api.InstancePlugin): thumb_file = head + ".png" thumb_path = os.path.join(staging_dir, thumb_file) + thumb_frame = instance.data["sourceIn"] + ((instance.data["sourceOut"] - instance.data["sourceIn"])/2) - thumbnail = item.thumbnail(instance.data["sourceIn"]).save( + thumbnail = item.thumbnail(thumb_frame).save( thumb_path, format='png' ) - self.log.debug("__ thumbnail: {}".format(thumbnail)) + self.log.debug("__ sourceIn: `{}`".format(instance.data["sourceIn"])) + self.log.debug("__ thumbnail: `{}`, frame: `{}`".format(thumbnail, thumb_frame)) thumb_representation = { 'files': thumb_file, diff --git a/pype/plugins/nukestudio/publish/collect_reviews.py b/pype/plugins/nukestudio/publish/collect_reviews.py index 9fab0f0741..f9032b2ca4 100644 --- a/pype/plugins/nukestudio/publish/collect_reviews.py +++ b/pype/plugins/nukestudio/publish/collect_reviews.py @@ -106,7 +106,6 @@ class CollectReviews(api.InstancePlugin): def create_thumbnail(self, instance): item = instance.data["item"] - source_in = instance.data["sourceIn"] source_path = instance.data["sourcePath"] source_file = os.path.basename(source_path) @@ -119,11 +118,17 @@ class CollectReviews(api.InstancePlugin): thumb_file = head + ".png" thumb_path = os.path.join(staging_dir, thumb_file) self.log.debug("__ thumb_path: {}".format(thumb_path)) - self.log.debug("__ source_in: {}".format(source_in)) - thumbnail = item.thumbnail(source_in).save( + + thumb_frame = instance.data["sourceIn"] + ((instance.data["sourceOut"] - instance.data["sourceIn"])/2) + + thumbnail = item.thumbnail(thumb_frame).save( thumb_path, format='png' ) + + self.log.debug("__ sourceIn: `{}`".format(instance.data["sourceIn"])) + self.log.debug("__ thumbnail: `{}`, frame: `{}`".format(thumbnail, thumb_frame)) + self.log.debug("__ thumbnail: {}".format(thumbnail)) thumb_representation = {