Source code for nukescripts.readviewscheck

# -*- coding: utf-8 -*-

""" Check for multiple views in files when a read node is created, by
looking for a VIEW_NAMES entry in the node's metadata.
Most file types won't specify views but EXR/SXR and potentially other
files may do.
Registers for callbacks when a Read node is created, or its 'file' knob
is changed.  If there are multiple views, and they do not exist on the
root node, the user is asked if they should be created.
"""

import nuke_internal as nuke
from PySide2.QtCore import QTimer
from PySide2.QtWidgets import QApplication, QMessageBox

# Global for storing when the user says no
UserAlreadySaidNo = False

[docs]def createViews(views): """ Add the views in a list to the root node. """ for view in views: # Set "left" and "right" colours to match "setup views for stereo" behaviour if view == "left": nuke.root().addView(view, "#FF0000") elif view == "right": nuke.root().addView(view, "#00FF00") else: nuke.root().addView(view)
[docs]def getViews(read): """ Attempt to get the views from a read node's metadata. Returns an empty list if no views were found or if the node is disabled. """ # disabled nodes return None when calling metadata() if read['disable'].value(): return [] readMetadata = read.metadata() if type(readMetadata) is not dict: return [] # Try to read the expected key. Catch KeyError and return an empty list if # not present try: # If present, the metadata value is a list of view names separated by # newlines. views = readMetadata[nuke.VIEW_NAMES].split('\n') # Now exclude any views that are wrapped in [], which indicate they're generic views rather # than explicitly specified named views (e.g. we're reading from a multitrack QuickTime file # and hence they're just some placeholder names generated by the reader). # rick: This shouldn't be necessary when we support view-to-track mapping for QuickTimes, etc. trueViews = [] for view in views: if not (view.startswith('[') and view.endswith(']')): trueViews += [view] return trueViews except KeyError: return []
[docs]def checkReadNodeViews(read): """ Check if a read has multiple views, and if so, ask the user if they want to add them to the root node. """ global UserAlreadySaidNo # Check we have a nuke read node rather than a timeline read node as the view checks # for timeline read nodes are carried out in MediaSearch::promptUserToCreateViews() # Because this callback happens asynchronously, it is possible that when called, the # node no longer exists. An exception will be thrown in this case. try: isNukeReadNode = (read.rootNode() is nuke.root()) except: isNukeReadNode = False if not UserAlreadySaidNo and isNukeReadNode: views = getViews(read) if views: # Find the views in the read that do not exist on the Root node and if # there are any, ask the user what to do. rootViews = nuke.views() missingViews = [ view for view in views if view not in rootViews ] if missingViews: userChoice = nuke.showCreateViewsDialog(missingViews) if userChoice is nuke.DONT_CREATE_VIEWS: UserAlreadySaidNo = True elif userChoice is nuke.REPLACE_VIEWS: viewsToDelete = [ view for view in rootViews if view not in views ] # Create all views in the clip createViews(views) # Remove the views that are not in views for existingView in viewsToDelete: nuke.root().deleteView(existingView) elif userChoice is nuke.ADD_VIEWS: # Create only the missing views createViews(missingViews)
[docs]def onReadNodeCreated(): """ Callback when a Read node is created. Note that the knob values don't seem to be set when this callback occurs. Defer the check with a QTimer, which will cause the views check to be done when the Qt event loop next sends events. """ read = nuke.thisNode() QTimer.singleShot(0, lambda: checkReadNodeViews(read))
[docs]def onReadNodeKnobChanged(): """ Callback when a Read node knob changes. If it's the file knob, check for multi views. """ if nuke.thisKnob().name() == "file": checkReadNodeViews(nuke.thisNode())
# Register the callbacks nuke.addKnobChanged(onReadNodeKnobChanged, nodeClass="Read") nuke.addOnUserCreate(onReadNodeCreated, nodeClass="Read")