def multiplyDivide(input1, input2, operation, name): """Creates a multiply divide node with the given and setups the input connections. List of operations:: no operation = 0, multipy = 1, divide = 2, power = 3 :param input1:the node attribute to connect to the input1 value or use int for value :type input1: MPlug or MVector :param input2:the node attribute to connect to the input2 value or use int for value :type input2: MPlug or MVector :param operation: the int value for operation :type operation: int :return, the multiplyDivide node MObject :rtype: MObject """ mult = om2.MFnDependencyNode(nodes.createDGNode(name, "multiplyDivide")) # assume connection type if isinstance(input1, om2.MPlug): plugs.connectPlugs(input1, mult.findPlug("input1", False)) # plug set else: plugs.setPlugValue(mult.findPlug("input1", False), input1) if isinstance(input2, om2.MPlug): plugs.connectPlugs(input2, mult.findPlug("input2", False)) else: plugs.setPlugValue(mult.findPlug("input2", False), input1) plugs.setPlugValue(mult.findPlug("operation", False), operation) return mult.object()
def distanceBetween(firstNode, secondNode, name): """Creates a distance between node and connects the 'firstNode' and 'secondNode' world space matrices. :param firstNode: The start transform node :type firstNode: MObject :param secondNode: The second transform node :type secondNode: MObject :return: the Three nodes created by the function in the form of a tuple, the first element \ is the distance between node, the second is the start node decompose matrix, the third element \ is the second node decompose matrix. :rtype: tuple(om2.MObject, om2.MObject, om2.MObject) """ firstFn = om2.MFnDependencyNode(firstNode) secondFn = om2.MFnDependencyNode(secondNode) distanceBetweenNode = nodes.createDGNode(name, "distanceBetween") distFn = om2.MFnDependencyNode(distanceBetweenNode) firstFnWorldMat = firstFn.findPlug("worldMatrix", False) firstFnWorldMat.evaluateNumElements() secondFnWorldMat = secondFn.findPlug("worldMatrix", False) secondFnWorldMat.evaluateNumElements() plugs.connectPlugs(firstFnWorldMat.elementByPhysicalIndex(0), distFn.findPlug("inMatrix1", False)) plugs.connectPlugs(secondFnWorldMat.elementByPhysicalIndex(0), distFn.findPlug("inMatrix2", False)) return distanceBetweenNode
def createPlusMinusAverage2D(name, inputs, output=None, operation=1): """ Create's a plusMinusAverage node and connects the 2D inputs and outputs. :param name: the plus minus average node name :type name: str :param inputs: tuple of MPlugs and/or float values, each value will be applied to / a new Input2D element. If the value is MPlug then it will be connected :type inputs: iterable(plug or float) :param output: A tuple of downstream MPlugs to connect to. :type output: iterable(plug) :return: The plus minus average MObject :rtype: om2.MObject """ pma = nodes.createDGNode(name, "plusMinusAverage") fn = om2.MFnDependencyNode(pma) inPlug = fn.findPlug("input2D", False) fn.findPlug("operation", False).setInt(operation) for i, p in enumerate(inputs): if p is None: continue child = plugs.nextAvailableElementPlug(inPlug) if isinstance(p, om2.MPlug): plugs.connectPlugs(p, child) continue plugs.setPlugValue(child, p) if output is not None: ouPlug = fn.findPlug("output2D", False) for index, out in enumerate(output): if out is None: continue plugs.connectPlugs(ouPlug, out) return pma
def attachNodeToCurveAtParam(curve, node, param, name): """Attaches the given node to the curve using a motion path node. :param curve: nurbsCurve Shape to attach to :type curve: om2.MObject :param node: the node to attach to the curve :type node: om2.MObject :param param: the parameter float value along the curve :type param: float :param name: the motion path node name to use :type name: str :return: motion path node :rtype: om2.MObject """ nodeFn = om2.MFnDependencyNode(node) crvFn = om2.MFnDependencyNode(curve) mp = nodes.createDGNode(name, "motionPath") mpFn = om2.MFnDependencyNode(mp) plugs.connectVectorPlugs(mpFn.findPlug("rotate", False), nodeFn.findPlug("rotate", False), (True, True, True)) plugs.connectVectorPlugs(mpFn.findPlug("allCoordinates", False), nodeFn.findPlug("translate", False), (True, True, True)) crvWorld = crvFn.findPlug("worldSpace", False) plugs.connectPlugs(crvWorld.elementByLogicalIndex(0), mpFn.findPlug("geometryPath", False)) mpFn.findPlug("uValue", False).setFloat(param) mpFn.findPlug("frontAxis", False).setInt(0) mpFn.findPlug("upAxis", False).setInt(1) return mp
def floatMath(floatA, floatB, operation, name): """Creates a floatMath node from the lookdev kit builtin plugin :param floatA: If the type is a MPlug then the floatA plug on the new node\ will be connected the given plug. :type floatA: float or om2.MPlug :param floatB: If the type is a MPlug then the floatB plug on the new node\ will be connected the given plug. :type floatB: float or om2.MPlug :param operation: The operation attributes value :type operation: int :param name: The new floatMath node name. :type name: str :return: The floatMath node MObject :rtype: om2.MObject """ floatMathFn = om2.MFnDependencyNode(nodes.createDGNode(name, "floatMath")) if isinstance(floatA, om2.MPlug): plugs.connectPlugs(floatA, floatMathFn.findPlug("floatA", False)) else: plugs.setPlugValue(floatMathFn.findPlug("floatA", False), floatA) if isinstance(floatB, om2.MPlug): plugs.connectPlugs(floatB, floatMathFn.findPlug("floatB", False)) else: plugs.setPlugValue(floatMathFn.findPlug("floatB", False), floatB) plugs.setPlugValue(floatMathFn.findPlug("operation", False), operation) return floatMathFn.object()
def connectToByPlug(self, sourcePlug, node, nodeAttributeName=None): nodeAttributeName = nodeAttributeName or "metaNode" dep = om2.MFnDependencyNode(node) if not dep.hasAttribute(nodeAttributeName): destinationPlug = dep.findPlug( nodes.addAttribute(node, nodeAttributeName, nodeAttributeName, attrtypes.kMFnMessageAttribute).object(), False) else: destinationPlug = dep.findPlug(nodeAttributeName, False) plugs.disconnectPlug(destinationPlug) with plugs.setLockedContext(sourcePlug): destIsLock = False sourceIsLock = False if destinationPlug.isLocked: destinationPlug.isLocked = False destIsLock = True if sourcePlug.isLocked: sourcePlug.isLocked = False sourceIsLock = True plugs.connectPlugs(sourcePlug, destinationPlug) if sourceIsLock: sourcePlug.isLocked = True if destIsLock: destinationPlug.isLocked = True return destinationPlug
def addParent(self, parent): """Sets the parent meta node for this node, removes the previous parent if its attached :param parent: The meta node to add as the parent of this meta node :type parent: MetaBase """ parentPlug = self._mfn.findPlug(MPARENT_ATTR_NAME, False) nextElement = plugs.nextAvailableDestElementPlug(parentPlug) with plugs.setLockedContext(parentPlug): plugs.connectPlugs(parent.findPlug(MCHILDREN_ATTR_NAME, False), nextElement)
def test_connectPlugs(self): node = cmds.createNode("transform") plugSource = plugs.asMPlug(self.node + ".translate") plugdestination = plugs.asMPlug(node + ".translate") plugs.connectPlugs(plugSource, plugdestination) self.assertTrue(plugSource.isConnected) self.assertTrue(plugSource.isSource) self.assertTrue(plugdestination.isConnected) self.assertTrue(plugdestination.isDestination) connections = plugSource.connectedTo(False, True) self.assertTrue(connections[0] == plugdestination) self.assertEquals(plugdestination.connectedTo(True, False)[0].name(), plugSource.name())
def floatMath(floatA, floatB, operation, name): floatMathFn = om2.MFnDependencyNode(nodes.createDGNode(name, "floatMath")) if isinstance(floatA, om2.MPlug): plugs.connectPlugs(floatA, floatMathFn.findPlug("floatA", False)) else: plugs.setPlugValue(floatMathFn.findPlug("floatA", False), floatA) if isinstance(floatB, om2.MPlug): plugs.connectPlugs(floatB, floatMathFn.findPlug("floatB", False)) else: plugs.setPlugValue(floatMathFn.findPlug("floatB", False), floatB) plugs.setPlugValue(floatMathFn.findPlug("operation", False), operation) return floatMathFn.object()
def createControllerTag(node, name, parent=None, visibilityPlug=None): """Create a maya kControllerTag and connects it up to the 'node'. :param node: The Dag node MObject to tag :type node: om2.MObject :param name: The name for the kControllerTag :type name: str :param parent: The Parent kControllerTag mObject or None :type parent: om2.MObject or None :param visibilityPlug: The Upstream Plug to connect to the visibility mode Plug :type visibilityPlug: om2.MPlug or None :return: The newly created kController node as a MObject :rtype: om.MObject """ ctrl = nodes.createDGNode(name, "controller") fn = om2.MFnDependencyNode(ctrl) plugs.connectPlugs( om2.MFnDependencyNode(node).findPlug("message", False), fn.findPlug("controllerObject", False)) if visibilityPlug is not None: plugs.connectPlugs(visibilityPlug, fn.findPlug("visibilityMode", False)) if parent is not None: parentFn = om2.MFnDependencyNode(parent) plugs.connectPlugs( fn.findPlug("parent", False), plugs.nextAvailableDestElementPlug( parentFn.findPlug("children", False))) plugs.connectPlugs(parentFn.findPlug("prepopulate", False), fn.findPlug("prepopulate", False)) return ctrl
def addParent(self, parent): """Sets the parent meta node for this node, removes the previous parent if its attached :param parent: The meta node to add as the parent of this meta node :type parent: MetaBase :todo: change the method name to setParent since we should only allow one parent """ metaParent = self.metaParent() if metaParent is not None or metaParent == parent: self.removeParent() parentPlug = self._mfn.findPlug(MPARENT_ATTR_NAME, False) with plugs.setLockedContext(parentPlug): plugs.connectPlugs(parent.findPlug(MCHILDREN_ATTR_NAME, False), parentPlug)
def createMultMatrix(name, inputs, output): multMatrix = nodes.createDGNode(name, "multMatrix") fn = om2.MFnDependencyNode(multMatrix) plugs.connectPlugs(fn.findPlug("matrixSum", False), output) compound = fn.findPlug("matrixIn", False) compound.evaluateNumElements() for i in xrange(len(inputs)): inp = inputs[i] if isinstance(inp, om2.MPlug): plugs.connectPlugs(inp, compound.elementByLogicalIndex(i)) continue plugs.setPlugValue(compound.elementByLogicalIndex(i), inp) return multMatrix
def createPlusMinusAverage3D(name, inputs, output=None, operation=1): """ Create's a plusMinusAverage node and connects the 3D inputs and outputs. :param name: the plus minus average node name. :type name: str :param inputs: tuple of MPlugs and/or float values, each value will be applied to / a new Input3D element. If the value is MPlug then it will be connected. :type inputs: iterable(plug or float) :param output: A tuple of downstream MPlugs to connect to. :type output: iterable(plug) or None :return: The plus minus average MObject. :rtype: om2.MObject .. code-block:: python one = nodes.createDagNode("one", "transform") two = nodes.createDagNode("two", "transform") end = nodes.createDagNode("end", "transform") oneFn = om2.MFnDagNode(one) twoFn = om2.MFnDagNode(two) endFn = om2.MFnDagNode(end) inputs = [oneFn.findPlug("translate", False), twoFn.findPlug("translate", False)] outputs = [endFn.findPlug("translate", False)] pma = creation.createPlusMinusAverage3D("test_pma", inputs, outputs) # Result: <OpenMaya.MObject object at 0x000002AECB23AE50> # """ pma = nodes.createDGNode(name, "plusMinusAverage") fn = om2.MFnDependencyNode(pma) inPlug = fn.findPlug("input3D", False) fn.findPlug("operation", False).setInt(operation) for i, p in enumerate(inputs): if p is None: continue child = plugs.nextAvailableElementPlug(inPlug) if isinstance(p, om2.MPlug): plugs.connectPlugs(p, child) continue plugs.setPlugValue(child, p) if output is not None: ouPlug = fn.findPlug("output3D", False) for index, out in enumerate(output): if out is None: continue plugs.connectPlugs(ouPlug, out) return pma
def test_disconnect(self): node2 = cmds.createNode("transform") node3 = cmds.createNode("transform") plugSource = plugs.asMPlug(node2 + ".translate") plugMid = plugs.asMPlug(self.node + ".translate") plugDest = plugs.asMPlug(node3 + ".translate") plugs.connectPlugs(plugSource, plugMid) plugs.connectPlugs(plugMid, plugDest) plugSource.isLocked = True plugMid.isLocked = True plugDest.isLocked = True self.assertTrue(plugs.disconnectPlug(plugMid)) self.assertFalse(plugSource.isSource) self.assertFalse(plugMid.isSource) self.assertFalse(plugDest.isSource) self.assertFalse(plugDest.isDestination)
def create(self, driver, driven, skipScale=None, skipRotate=None, skipTranslate=None, maintainOffset=False, space=om2.MFn.kWorld): composename = "_".join([self.name, "wMtxCompose"]) multMatrix = None if maintainOffset: offset = nodes.getOffsetMatrix(driver, driven) offsetname = "_".join([self.name, "wMtxOffset"]) parentInverse = nodes.parentInverseMatrixPlug( driven) if self.dynamic else plugs.getPlugValue( nodes.parentInverseMatrixPlug(driven)) multMatrix = creation.createMultMatrix( offsetname, inputs=(offset, nodes.worldMatrixPlug(driver), parentInverse), output=None) outputPlug = om2.MFnDependencyNode(multMatrix).findPlug( "matrixSum", False) else: outputPlug = nodes.worldMatrixPlug(driver) decompose = creation.createDecompose(composename, destination=driven, translateValues=skipTranslate, scaleValues=skipScale, rotationValues=skipRotate) decomposeFn = om2.MFnDependencyNode(decompose) plugs.connectPlugs(outputPlug, decomposeFn.findPlug("inputMatrix", False)) self.node = om2.MObjectHandle(decompose) mapping = dict(skipScale=skipScale, skipRotate=skipRotate, skipTranslate=skipTranslate, maintainOffset=maintainOffset) kwargsMap = json.dumps(mapping) addConstraintMap(driver, (driven, ), (decompose, multMatrix), kwargsMap=kwargsMap) return decompose, multMatrix
def addConstraintMap(node, driven, utilities, kwargsMap=None): """Adds a mapping of drivers and utilities to the constraint compound array attribute :param node: The node to add or has the constraint map , typically this would be the driver node \ of the constraint. :type node: om2.MObject :param driven: a list of driven transform nodes. :type driven: tuple(om2.MObject) :param utilities: a list of utilities/support nodes that make up the constraint, this could be the \ constraint node itself or any math node etc. :type utilities: tuple(om2.MObject) """ kwargsmap = kwargsMap or "" mfn = om2.MFnDependencyNode(node) if not mfn.hasAttribute("constraints"): compoundPlug = addConstraintAttribute(node) else: compoundPlug = mfn.findPlug("constraints", False) availPlug = plugs.nextAvailableElementPlug(compoundPlug) drivenPlug = availPlug.child(0) # lets add the driven nodes to the xth of the element compound for drive in iter(driven): if drive is None: continue drivenFn = om2.MFnDependencyNode(drive) if drivenFn.hasAttribute("constraint"): p = drivenFn.findPlug("constraint", False) elementP = plugs.nextAvailableElementPlug(p) plugs.connectPlugs(drivenPlug, elementP) continue attr = nodes.addAttribute(drive, "constraint", "constraint", attrtypes.kMFnMessageAttribute, isArray=True) attrP = om2.MPlug(drive, attr.object()) plugs.connectPlugs(drivenPlug, attrP.elementByLogicalIndex(0)) utilPlug = availPlug.child(1) # add all the utilities for i in iter(utilities): if i is None: continue utilFn = om2.MFnDependencyNode(i) if utilFn.hasAttribute("constraint"): p = utilFn.findPlug("constraint", False) if p.isDestination: continue plugs.connectPlugs(utilPlug, p) continue attr = nodes.addAttribute(i, "constraint", "constraint", attrtypes.kMFnMessageAttribute) plugs.connectPlugs(utilPlug, om2.MPlug(i, attr.object())) # set the kwargs map plug, so we know how the constraint was created plugs.setPlugValue(availPlug.child(2), kwargsmap) return compoundPlug
def __setattr__(self, key, value): if key.startswith("_"): super(MetaBase, self).__setattr__(key, value) return if self._mfn.hasAttribute(key): plug = self._mfn.findPlug(key, False) if not plug.isNull: if isinstance(value, om2.MPlug): plugs.connectPlugs(plug, value) elif isinstance(value, MetaBase): self.addChild(value) elif isinstance(value, om2.MObject) and not value.hasFn(om2.MFn.kAttribute): self.connectTo(key, value) else: self.setAttribute(plug, value) else: super(MetaBase, self).__setattr__(key, value)
def createDecompose(name, destination, translateValues, scaleValues, rotationValues, inputMatrixPlug=None): """Creates a decompose node and connects it to the destination node. :param name: the decompose Matrix name. :type name: str :param destination: the node to connect to :type destination: om2.MObject :param translateValues: the x,y,z to apply must have all three if all three are true then the compound will be \ connected. :type translateValues: list(str) :param scaleValues: the x,y,z to apply must have all three if all three are true then the compound will be \ connected. :type scaleValues: list(str) :param rotationValues: the x,y,z to apply must have all three if all three are true then the compound will be \ connected. :type rotationValues: list(str) :param inputMatrixPlug: The input matrix plug to connect from. :type inputMatrixPlug: om2.MPlug :return: the decompose node :rtype: om2.MObject """ decompose = nodes.createDGNode(name, "decomposeMatrix") mfn = om2.MFnDependencyNode(decompose) if inputMatrixPlug is not None: plugs.connectPlugs(inputMatrixPlug, mfn.findPlug("inputMatrix", False)) if destination: destFn = om2.MFnDependencyNode(destination) # translation plugs.connectVectorPlugs(mfn.findPlug("outputTranslate", False), destFn.findPlug("translate", False), translateValues) plugs.connectVectorPlugs(mfn.findPlug("outputRotate", False), destFn.findPlug("rotate", False), rotationValues) plugs.connectVectorPlugs(mfn.findPlug("outputScale", False), destFn.findPlug("scale", False), scaleValues) return decompose
def create(self, driver, driven, skipScale=None, skipRotate=None, skipTranslate=None, maintainOffset=False): composename = "_".join([self.name, "wMtxCompose"]) decompose = creation.createDecompose(composename, destination=driven, translateValues=skipTranslate, scaleValues=skipScale, rotationValues=skipRotate) decomposeFn = om2.MFnDependencyNode(decompose) multMatrix = None if maintainOffset: offsetname = "_".join([self.name, "wMtxOffset"]) offset = nodes.getOffsetMatrix(driver, driven) multMatrix = creation.createMultMatrix(offsetname, inputs=(offset, nodes.worldMatrixPlug(driver), nodes.parentInverseMatrixPlug(driven)), output=decomposeFn.findPlug("inputMatrix", False)) else: plugs.connectPlugs(nodes.worldMatrixPlug(driver), decomposeFn.findPlug("inputMatrix", False)) self.node = om2.MObjectHandle(decompose) return decompose, multMatrix
def _deserializeConnections(self, connections): # plugList = om2.MSelectionList() for conn in connections: sourceNode = conn["source"] destinationNode = conn["destination"] if sourceNode is None or destinationNode is None: continue # connect the source and destination plug try: sourcePlug = plugs.asMPlug(conn["sourcePlug"]) destinationPlug = plugs.asMPlug(conn["destinationPlug"]) if destinationPlug.isDestination: continue with contextlib.nested( plugs.setLockedContext(sourcePlug), plugs.setLockedContext(destinationPlug)): plugs.connectPlugs(sourcePlug, destinationPlug, force=False) except RuntimeError: continue
def connectTo(self, attributeName, node, nodeAttributeName=None): """Connects one plug to another by attribute name :param attributeName: the meta attribute name to connect from, if it doesn't exist it will be created :type attributeName: str :param node: the destination node :type node: MObject :param nodeAttributeName: the destination node attribute name, if one doesn't exist one will be created :type nodeAttributeName: str :return: the destination plug :rtype: om2.MPlug """ nodeAttributeName = nodeAttributeName or "metaNode" dep = om2.MFnDependencyNode(node) self.disconnectFromNode(node) if not dep.hasAttribute(nodeAttributeName): destinationPlug = dep.findPlug( nodes.addAttribute(node, nodeAttributeName, nodeAttributeName, attrtypes.kMFnMessageAttribute).object(), False) else: destinationPlug = dep.findPlug(nodeAttributeName, False) plugs.disconnectPlug(destinationPlug) if self._mfn.hasAttribute(attributeName): # we should have been disconnected from the destination control above sourcePlug = self._mfn.findPlug(attributeName, False) else: newAttr = self.addAttribute(attributeName, None, attrtypes.kMFnMessageAttribute) if newAttr is not None: sourcePlug = newAttr else: sourcePlug = self._mfn.findPlug(attributeName, False) with plugs.setLockedContext(sourcePlug): if destinationPlug.isLocked: destinationPlug.isLocked = False plugs.connectPlugs(sourcePlug, destinationPlug) destinationPlug.isLocked = True return destinationPlug
def blendColors(color1, color2, name, blender): """Creates a blend colors node. :param color1: If the type is a MPlug then the color1 plug on the new node\ will be connected the given plug. :type color1: om2.MColor or om2.MPlug :param color2: If the type is a MPlug then the color2 plug on the new node\ will be connected the given plug. :type color2: om2.MColor or om2.MPlug :param name: The new floatMath node name. :type name: str :param blender: If the type is a MPlug then the blender plug on the new node\ will be connected the given plug. :type blender: float or om2.MPlug :return: The new colorBlend node as a MObject :rtype: om2.MObject """ blendFn = om2.MFnDependencyNode(nodes.createDGNode(name, "blendColors")) if isinstance(color1, om2.MPlug): plugs.connectPlugs(color1, blendFn.findPlug("color1", False)) else: plugs.setPlugValue(blendFn.findPlug("color1", False), color1) if isinstance(color2, om2.MPlug): plugs.connectPlugs(color2, blendFn.findPlug("color2", False)) else: plugs.setPlugValue(blendFn.findPlug("color2", False), color2) if isinstance(blender, om2.MPlug): plugs.connectPlugs(blender, blendFn.findPlug("blender", False)) else: plugs.setPlugValue(blendFn.findPlug("blender", False), blender) return blendFn.object()
def blendTwoAttr(input1, input2, blender, name): fn = om2.MFnDependencyNode(nodes.createDGNode(name, "blendTwoAttr")) inputArray = fn.findPlug("input", False) plugs.connectPlugs(input1, inputArray.elementByLogicalIndex(-1)) plugs.connectPlugs(input2, inputArray.elementByLogicalIndex(-1)) plugs.connectPlugs(blender, fn.findPlug("attributesBlender", False)) return fn.object()
def createReverse(name, inputs, outputs): """ Create a Reverse Node :param name: The name for the reverse node to have, must be unique :type name: str :param inputs: If Plug then the plug must be a compound. :type inputs: om2.MPlug or tuple :param outputs: If Plug then the plug must be a compound. :type outputs: om2.MPlug or tuple :return: OpenMaya 2.0 MObject representing the reverse node :rtype: om2.MObject :raises: ValueError if the inputs or outputs is not an om2.MPlug """ rev = nodes.createDGNode(name, "reverse") fn = om2.MFnDependencyNode(rev) inPlug = fn.findPlug("input", False) ouPlug = fn.findPlug("output", False) if isinstance(inputs, om2.MPlug): if inputs.isCompound: plugs.connectPlugs(inputs, inPlug) return rev else: raise ValueError( "Inputs Argument must be a compound when passing a single plug" ) elif isinstance(outputs, om2.MPlug): if outputs.isCompound: plugs.connectPlugs(outputs, ouPlug) return rev else: raise ValueError( "Outputs Argument must be a compound when passing a single plug" ) # passed the dealings with om2.MPlug so deal with seq type for childIndex in range(len(inputs)): inA = inputs[childIndex] if inA is None: continue plugs.connectPlugs(inputs[childIndex], inPlug.child(childIndex)) for childIndex in range(len(outputs)): inA = outputs[childIndex] if inA is None: continue plugs.connectPlugs(ouPlug.child(childIndex), outputs[childIndex]) return rev
def distanceBetween(firstNode, secondNode, name): """Creates a distance between node and connects the 'firstNode' and 'secondNode' world space matrices. :param firstNode: The start transform node :type firstNode: MObject :param secondNode: The second transform node :type secondNode: MObject :return: the Three nodes created by the function in the form of a tuple, the first element is the distance between node, the second is the start node decompose matrix, the third element is the second node decompose matrix :rtype: tuple(om2.MObject, om2.MObject, om2.MObject) """ firstFn = om2.MFnDependencyNode(firstNode) secondFn = om2.MFnDependencyNode(secondNode) distanceBetweenNode = nodes.createDGNode(name, "distanceBetween") distFn = om2.MFnDependencyNode(distanceBetweenNode) firstFnWorldMat = firstFn.findPlug("worldMatrix", False) firstFnWorldMat.evaluateNumElements() secondFnWorldMat = secondFn.findPlug("worldMatrix", False) secondFnWorldMat.evaluateNumElements() startDecomposeMat = nodes.createDGNode( "_".join([firstFn.name(), secondFn.name(), "start_decomp"]), "decomposeMatrix") endDecomposeMat = nodes.createDGNode( "_".join([firstFn.name(), secondFn.name(), "end_decomp"]), "decomposeMatrix") startDecomFn = om2.MFnDependencyNode(startDecomposeMat) endDecomFn = om2.MFnDependencyNode(endDecomposeMat) plugs.connectPlugs(firstFnWorldMat.elementByPhysicalIndex(0), startDecomFn.findPlug("inputMatrix", False)) plugs.connectPlugs(secondFnWorldMat.elementByPhysicalIndex(0), endDecomFn.findPlug("inputMatrix", False)) plugs.connectPlugs(startDecomFn.findPlug("outputTranslate", False), distFn.findPlug("point1", False)) plugs.connectPlugs(endDecomFn.findPlug("outputTranslate", False), distFn.findPlug("point2", False)) return distanceBetweenNode, startDecomposeMat, endDecomposeMat
def blendColors(color1, color2, name, blender): blendFn = om2.MFnDependencyNode(nodes.createDGNode(name, "blendColors")) if isinstance(color1, om2.MPlug): plugs.connectPlugs(color1, blendFn.findPlug("color1", False)) else: plugs.setPlugValue(blendFn.findPlug("color1", False), color1) if isinstance(color2, om2.MPlug): plugs.connectPlugs(color2, blendFn.findPlug("color2", False)) else: plugs.setPlugValue(blendFn.findPlug("color2", False), color2) if isinstance(blender, om2.MPlug): plugs.connectPlugs(blender, blendFn.findPlug("blender", False)) else: plugs.setPlugValue(blendFn.findPlug("blender", False), blender) return blendFn.object()
def createSetRange(name, value, min_, max_, oldMin, oldMax, outValue=None): """ Generates and connects a setRange node. input/output arguments take an iterable, possibles values are om2.MPlug, float or None. if a value is None it will be skipped this is useful when you want some not connected or set to a value but the other is left to the default state. If MPlug is passed and its a compound it'll be connected. :param name: the new name for the set Range node :type name: str :param value: :type value: iterable(om2.MPlug or float or None) :param min_: :type min_: iterable(om2.MPlug or float or None) :param max_: :type max_: iterable(om2.MPlug or float or None) :param oldMin: :type oldMin: iterable(om2.MPlug or float or None) :param oldMax: :type oldMax: iterable(om2.MPlug or float or None) :param outValue: :type outValue: iterable(om2.MPlug or float or None) :return: the created setRange node :rtype: om2.MObject .. code-block:: python one = nodes.createDagNode("one", "transform") two = nodes.createDagNode("two", "transform") end = nodes.createDagNode("end", "transform") oneFn = om2.MFnDagNode(one) twoFn = om2.MFnDagNode(two) endFn = om2.MFnDagNode(end) values = [oneFn.findPlug("translate", False)] min_ = [twoFn.findPlug("translate", False)] max_ = [twoFn.findPlug("translate", False)] oldMax = [0.0,180,360] oldMin = [-10,-720,-360] reload(creation) outValues = [endFn.findPlug("translateX", False), endFn.findPlug("translateY", False), None] pma = creation.createSetRange("test_pma", values, min_, max_, oldMin, oldMax, outValues) """ setRange = nodes.createDGNode(name, "setRange") fn = om2.MFnDependencyNode(setRange) valuePlug = fn.findPlug("value", False) oldMinPlug = fn.findPlug("oldMin", False) oldMaxPlug = fn.findPlug("oldMax", False) minPlug = fn.findPlug("min", False) maxPlug = fn.findPlug("max", False) # deal with all the inputs # source list, destination plug for source, destination in ((value, valuePlug), (min_, minPlug), (max_, maxPlug), (oldMin, oldMinPlug), (oldMax, oldMaxPlug)): if source is None: continue for index, inner in enumerate(source): if inner is None: continue elif isinstance(inner, om2.MPlug): if inner.isCompound: plugs.connectPlugs(inner, destination) break child = destination.child(index) plugs.connectPlugs(inner, child) continue child = destination.child(index) plugs.setPlugValue(child, inner) if outValue is None: return setRange outPlug = fn.findPlug("outValue", False) # now the outputs for index, out in enumerate(outValue): if out is None: continue if isinstance(out, om2.MPlug): if out.isCompound: plugs.connectPlugs(outPlug, out) break child = outPlug.child(index) plugs.connectPlugs(child, out) continue child = outPlug.child(index) # not a plug must be a plug value plugs.setPlugValue(child, out) return setRange
def conditionVector(firstTerm, secondTerm, colorIfTrue, colorIfFalse, operation, name): """ :param firstTerm: :type firstTerm: om2.MPlug or float :param secondTerm: :type secondTerm: om2.MPlug or float :param colorIfTrue: seq of MPlugs or a single MPlug(compound) :type colorIfTrue: om2.MPlug or list(om2.Plug) or om2.MVector :param colorIfFalse: seq of MPlugs or a single MPlug(compound) :type colorIfFalse: om2.MPlug or list(om2.Plug) or om2.MVector :param operation: the comparsion operator :type operation: int :param name: the new name for the node :type name: str :return: :rtype: om2.MObject """ condNode = om2.MFnDependencyNode(nodes.createDGNode(name, "condition")) if isinstance(operation, int): plugs.setPlugValue(condNode.findPlug("operation", False), operation) else: plugs.connectPlugs(operation, condNode.findPlug("operation", False)) if isinstance(firstTerm, float): plugs.setPlugValue(condNode.findPlug("firstTerm", False), firstTerm) else: plugs.connectPlugs(firstTerm, condNode.findPlug("firstTerm", False)) if isinstance(secondTerm, float): plugs.setPlugValue(condNode.findPlug("secondTerm", False), secondTerm) else: plugs.connectPlugs(secondTerm, condNode.findPlug("secondTerm", False)) if isinstance(colorIfTrue, om2.MPlug): plugs.connectPlugs(colorIfTrue, condNode.findPlug("colorIfTrue", False)) elif isinstance(colorIfTrue, om2.MVector): plugs.setPlugValue(condNode.findPlug("colorIfTrue", False), colorIfTrue) else: color = condNode.findPlug("colorIfTrue", False) # expecting seq of plugs for i, p in enumerate(colorIfTrue): if p is None: continue child = color.child(i) if isinstance(p, om2.MPlug): plugs.connectPlugs(p, child) continue plugs.setPlugValue(child, p) if isinstance(colorIfFalse, om2.MPlug): plugs.connectPlugs(colorIfFalse, condNode.findPlug("colorIfFalse", False)) elif isinstance(colorIfFalse, om2.MVector): plugs.setPlugValue(condNode.findPlug("colorIfFalse", False), colorIfFalse) else: color = condNode.findPlug("colorIfFalse", False) # expecting seq of plugs for i, p in enumerate(colorIfFalse): if p is None: continue child = color.child(i) if isinstance(p, om2.MPlug): plugs.connectPlugs(p, child) continue plugs.setPlugValue(child, p) return condNode.object()
def buildConstraint(source, targets, maintainOffset=False, constraintType=om2.MFn.kParentConstraint, **kwargs): """This Function build a space switching constraint. Currently Supporting types of kParentConstraint kPointConstraint kOrientConstraint :param source: The transform to drive :param source: om2.MObject :param targets: A dict containing the target information(see below example) :param targets: dict or None :param: maintainOffset: whether or not the constraint should maintain offset :type maintainOffset: bool :param constraintType: The maya api kType eg. om2.MFn.kParentConstraint, defaults to kParentConstraint :type constraintType: om2.MFn.kType :param kwargs: The cmds.kconstraintType extra arguments to use :type kwargs: dict .. code-block: python targets = [] for n in ("locator1", "locator2", "locator3"): targets.append((n, nodes.createDagNode(n, "locator"))) spaceNode =nodes.createDagNode("control", "locator") drivenNode = nodes.createDagNode("driven", "locator") spaces = {"spaceNode": spaceNode, "attributeName": "parentSpace", "targets": targets} constraint, conditions = build(drivenNode, targets=spaces) # lets add to the existing system spaces = {"spaceNode": spaceNode, "attributeName": "parentSpace", "targets": ( ("locator8", nodes.createDagNode("locator8", "locator")),)} constraint, conditions = build(drivenNode, targets=spaces) ) """ # make sure we support the constrainttype the user wants assert constraintType in APITOCMDS_CONSTRAINT_MAP, "No Constraint of type: {}, supported".format(constraintType) spaceNode = targets.get("spaceNode") attrName = targets.get("attributeName", "parent") targetInfo = targets["targets"] targetLabels, targetNodes = zip(*targetInfo) # first try to find an existing constraint existingConstraint = findConstraint(source, constraintType, includeReferenced=False) # if we found existing constraint then check to see if the target is already # constraining, if so just excluded it. targetList = targetNodes if existingConstraint: existingTargets = list(iterTargetsFromConstraint(existingConstraint)) targetList = [t for t in targetNodes if t not in existingTargets] # in the case that all target already exist just early out if not targetList: return None, [] # create the constraint constraintMap = APITOCMDS_CONSTRAINT_MAP[constraintType] cmdsFunc = getattr(cmds, constraintMap["type"]) arguments = {"maintainOffset": maintainOffset} arguments.update(kwargs) constraint = cmdsFunc(map(nodes.nameFromMObject, targetList), nodes.nameFromMObject(source), **arguments)[0] # if we have been provided a spaceNode, which will contain our switch, otherwise ignore the setup of a switch # and just return the constraint constraintMObject = nodes.asMObject(constraint) if spaceNode is None: return constraintMObject, [] spaceFn = om2.MFnDependencyNode(spaceNode) if spaceFn.hasAttribute(attrName): spacePlug = spaceFn.findPlug(attrName, False) existingFieldNames = plugs.enumNames(spacePlug) spaceAttr = om2.MFnEnumAttribute(spacePlug.attribute()) # add any missing fields to enumAttribute for field in targetLabels: if field not in existingFieldNames: spaceAttr.addField(field, len(existingFieldNames)) else: spaceAttr = nodes.addAttribute(spaceNode, attrName, attrName, attrType=attrtypes.kMFnkEnumAttribute, keyable=True, channelBox=True, locked=False, enums=targetLabels) spacePlug = om2.MPlug(spaceNode, spaceAttr.object()) constraintFn = om2.MFnDependencyNode(constraintMObject) targetArray = constraintFn.findPlug("target", False) sourceShortName = nodes.nameFromMObject(source, partialName=True, includeNamespace=False) conditions = [] constraintTargetWeightIndex = constraintMap["targetPlugIndex"] # first iterate over the target array on the constraint for index in targetArray.getExistingArrayAttributeIndices(): targetElement = targetArray.elementByLogicalIndex(index) targetElementWeight = targetElement.child(constraintTargetWeightIndex) targetWeightSource = targetElementWeight.source() # just in case the target weight plug is disconnected if targetWeightSource is None: targetWeightSource = targetElementWeight else: # lets make sure that we're not already connected to a condition node # if so skip weightSourceNode = targetWeightSource.node() # if we connected to the constraint i.e spaceWO1 if weightSourceNode == constraintMObject: upstreamWeight = targetWeightSource.source() if upstreamWeight and upstreamWeight.node().apiType() == om2.MFn.kCondition: continue else: if weightSourceNode.apiType() == om2.MFn.kCondition: continue targetNode = targetElement.child(0).source().node() targetShortName = nodes.nameFromMObject(targetNode, partialName=True, includeNamespace=False) # create the condition node and do the connections conditionNode = creation.conditionVector(firstTerm=spacePlug, secondTerm=float(targetElement.logicalIndex()), colorIfTrue=(1.0, 0.0, 0.0), colorIfFalse=(0.0, 0.0, 0.0), operation=0, name="_".join([targetShortName, sourceShortName, "space"])) condFn = om2.MFnDependencyNode(conditionNode) plugs.connectPlugs(condFn.findPlug("outColorR", False), targetWeightSource) conditions.append(conditionNode) return constraintMObject, conditions
def addProxyAttribute(node, sourcePlug, longName, shortName, attrType=attrtypes.kMFnNumericDouble): attr1 = addAttribute(node, longName, shortName, attrType) attr1.isProxyAttribute = True plugs.connectPlugs(sourcePlug, om2.MPlug(node, attr1.object())) return attr1