Esempio n. 1
0
    def saveShadingEngine(shadingEngineObj, storagePlug):
        '''Save a connection to the shading engine node in the storage plug.

        This function unconditionally connects the shading engine to the
        storage plug.  It also stores the name of the shading engine as a full
        name with the namespace path in the storage plug's node, if the shading
        engine is not in the main scene.'''

        # Store the shading engine message attribute
        fnEngine = OpenMaya.MFnDependencyNode(shadingEngineObj)
        enginePlug = fnEngine.findPlug('message', False)
        utils.connect(enginePlug, storagePlug)

        # Deal with fact that material might be in a referenced file.
        storageNode = storagePlug.node()
        storageStrPlug = plug.findPlug(storageNode,
                                       MaterialOverride.kShadingEngineNameLong)

        if fnEngine.isFromReferencedFile:
            if storageStrPlug is None:
                properties = {'type': 'String', 'connectable': False}
                storageStrPlug = plug.Plug.createAttribute(
                    storageNode, MaterialOverride.kShadingEngineNameLong,
                    MaterialOverride.kShadingEngineNameShort, properties,
                    plug.kNotUndoable)

            storageStrPlug.value = fnEngine.name()
        elif storageStrPlug is not None:
            # Remove dynamic attribute.
            fn = OpenMaya.MFnDependencyNode(storageNode)
            fn.removeAttribute(storageStrPlug.plug.attribute())
Esempio n. 2
0
    def insert(self, target, nextOvr=None):
        '''Insert self in the override chain for given target, or start the chain if none exists.'''
        destinations = (OpenMaya.MFnDependencyNode(d.node()).userNode()
                        for d in target.destinations())
        firstApplyNode = next(
            (d for d in destinations
             if d and isinstance(d, ApplyConnectionOverride)), None)

        if not firstApplyNode:
            # no apply override chain on that target => self becomes the only apply override node for that target
            self.connectTarget(target)
            self.override().doSaveOriginal(target, self.getOriginalPlug())
            return
        utils.transferPlug(firstApplyNode.getOriginalPlug(),
                           self.getOriginalPlug())

        # search where to insert
        if not nextOvr:
            prevAO, nextAO = firstApplyNode, None
        else:
            nextAO = (ao for ao in ApplyConnectionOverride.reverseGenerator(
                firstApplyNode) if ao.override() == nextOvr).next()
            prevAO = nextAO.prev()

        # insert between prevAO and nextAO
        if prevAO:
            utils.connect(prevAO.getNextPlug(), self.getPrevPlug())

        if nextAO:
            utils.connect(self.getNextPlug(), nextAO.getPrevPlug())
        else:
            # no nextAO => self becomes highest priority => must hold target
            prevAO.moveTargetTo(self)
Esempio n. 3
0
    def doAction(self, target, source):
        """ This method performs the override action for a given target and source. """
        # NOTE: doAction should never add commands in the undo stack
        shaderPlug = utils.plugSrc(source)
        if shaderPlug:
            surfaceShader = shaderPlug.node()
            shadingEngine = target.node()

            # Break any connections to old surface shader
            fnShadingEngine = OpenMaya.MFnDependencyNode(shadingEngine)
            connections = fnShadingEngine.getConnections()
            for c in connections:
                if c.isDestination:
                    fn = OpenMaya.MFnDependencyNode(c.source().node())
                    nodeClass = OpenMaya.MNodeClass(fn.typeName)
                    if 'shader/surface' in nodeClass.classification:
                        utils.disconnect(c.source(), c)

            # Make connections to new surface shader
            connections = ShaderOverride._getNewConnections(
                surfaceShader, shadingEngine)
            # Turn reference edits on if restoring the original.
            with handleRestoringOriginalCtx():
                for c in connections:
                    utils.connect(c[0], c[1])
Esempio n. 4
0
    def extract(self):
        '''Removes self from the apply override chain. This will trigger an update of the chain.'''
        prevAO, nextAO = self.prev(), self.next()

        if prevAO:
            utils.disconnect(prevAO.getNextPlug(), self.getPrevPlug())

        if nextAO:
            utils.disconnect(self.getNextPlug(), nextAO.getPrevPlug())
        elif prevAO:
            # no nextAO => prevAO becomes highest priority => must hold target
            self.moveTargetTo(prevAO)

        if prevAO and nextAO:
            utils.connect(prevAO.getNextPlug(), nextAO.getPrevPlug())

        if not prevAO and not nextAO:
            # no other apply overrides => must restablish original connection
            with guard.StateGuardCtx(isRestoringOriginal, setRestoringOriginal,
                                     True):
                self.override().doAction(self._targetHandle.src(),
                                         self.getOriginalPlug())
        else:
            # any apply override in the chain can trigger the update
            (prevAO or nextAO).update()
Esempio n. 5
0
def _transferConnectedPlug(src, dst):
    if src.isDestination:
        fromSrc = utils.plugSrc(src)
        # Turn reference edits on if restoring the original.
        with handleRestoringOriginalCtx():
            utils.connect(fromSrc, dst)
    elif src.isCompound and dst.isCompound:
        for idx in range(0, src.numChildren()):
            transferPlug(src.child(idx), dst.child(idx))
Esempio n. 6
0
 def _restoreConnection(self, dst):
     # If the source was in a referenced file, the connection to it may
     # have been broken.  To deal with this case, we also stored a
     # string representation of the source.
     srcStrPlug = self._srcStrPlug()
     if srcStrPlug is not None:
         src = commonUtils.nameToPlug(srcStrPlug.value)
         if src is not None and not src.isNull:
             utils.connect(src, dst)
Esempio n. 7
0
 def _restoreOriginalPlug(self, original):
     # If the original shading engine was in a referenced file, the
     # connection to it may have been broken.  To deal with this
     # case, we also stored the shading engine name as a string.
     originalStr = commonUtils.findPlug(
         self.thisMObject(), MaterialOverride.kShadingEngineNameLong)
     if originalStr is not None:
         originalNode = commonUtils.nameToNode(originalStr.asString())
         if not originalNode.isNull():
             fnEngine = OpenMaya.MFnDependencyNode(originalNode)
             enginePlug = fnEngine.findPlug('message', False)
             utils.connect(enginePlug, original)
Esempio n. 8
0
 def doSaveOriginal(self, target, storage):
     """ This method performs saving of original state for a given target
     and a storage plug for storing the state. """
     # Find old surface shader
     fnShadingEngine = OpenMaya.MFnDependencyNode(target.node())
     connections = fnShadingEngine.getConnections()
     for c in connections:
         if c.isDestination:
             fn = OpenMaya.MFnDependencyNode(c.source().node())
             nodeClass = OpenMaya.MNodeClass(fn.typeName)
             if 'shader/surface' in nodeClass.classification:
                 # Source surface shader found.
                 # Use the message plug to save a reference to it.
                 target = fn.findPlug('message', False)
                 utils.connect(target, storage)
                 break
Esempio n. 9
0
    def _createApplyOverride(self, target, nextOvr=None):
        name = self.name() + "_" + target.partialName(
            includeNodeName=True,
            includeNonMandatoryIndices=True,
            includeInstancedIndices=True)
        # Namespace qualifies from the original node name cannot be used
        # to rename the new apply node.  Replace the namespace qualifiers with '_'.
        name = name.replace(':', '_').replace('.', '_')
        if utils.nameToUserNode(name):
            return

        ao = ApplyConnectionOverride.create(name)
        utils.connect(self._getEnabledPlug(), ao.getEnabledPlug())
        ao.finalize(self._getAttrValuePlug())
        ao.insert(target, nextOvr)
        return ao
Esempio n. 10
0
    def connect(self, src):
        '''Connect this destination to the argument source MPlug.  If the
        source node is referenced, store a string representation of the
        source.'''

        # For non-referenced sources, simply connect.  This will trivially
        # and obviously persist the connection information.
        utils.connect(src, self.dst())

        # If src is referenced, record it as a string, as connections to
        # referenced objects are normally recorded as referenced edits,
        # which we intentionally turn off in render setup.
        srcNode = src.node()
        srcFn = OpenMaya.MFnDependencyNode(srcNode)

        if srcFn.isFromReferencedFile:
            srcStrPlug = self._srcStrPlug()
            if srcStrPlug is None:
                properties = {'type': 'String', 'connectable': False}
                srcStrPlug = plug.Plug.createAttribute(
                    self._node, self._srcStrAttrNameLong,
                    self._srcStrAttrNameShort, properties, plug.kNotUndoable)

            # Connection overrides represent a connection to a node, and
            # therefore don't need a DAG path to disambiguate between
            # different instances.  However, because DAG nodes don't have
            # unique names, we do need a DAG path to disambiguate different
            # DAG nodes with the same name.
            if srcNode.hasFn(OpenMaya.MFn.kDagNode):
                srcPath = OpenMaya.MFnDagNode(srcNode).fullPathName()
                srcAttr = src.partialName(includeNodeName=False,
                                          includeNonMandatoryIndices=True,
                                          includeInstancedIndices=True,
                                          useAlias=False,
                                          useFullAttributePath=True,
                                          useLongNames=True)
                srcFullAttrName = srcPath + "." + srcAttr
            else:
                srcFullAttrName = src.name()

            srcStrPlug.value = srcFullAttrName
Esempio n. 11
0
    def setParent(self, parentListUserNode):
        """Set the list to which this item belongs.

        To remove this item from its list, the parent node argument must be
        None."""

        # Get the parent list to which we belong, which is a destination plug,
        # and disconnect ourselves from the previous parent.
        parentListPlug = utils.findPlug(self, ListItem.parentList)
        utils.disconnectDst(parentListPlug)

        # If we're removing this item from its parent list, nothing more to do.
        if not parentListUserNode:
            return

        # We're setting a non-None parent.  Get the listItems source plug
        # from the parent, and connect ourselves up to it, which makes us
        # an item in our parent's list.
        utils.connect(
            utils.findPlug(parentListUserNode,
                           parentListUserNode._getListItemsAttr()),
            parentListPlug)
Esempio n. 12
0
    def setPrevious(self, item):
        previousPlug = utils.findPlug(self, ListItem.previous)
        nextPlug = utils.findPlug(item, ListItem.next)

        utils.connect(nextPlug, previousPlug)
Esempio n. 13
0
    def setNext(self, item):
        nextPlug = utils.findPlug(self, ListItem.next)
        previousPlug = utils.findPlug(item, ListItem.previous)

        utils.connect(nextPlug, previousPlug)