示例#1
0
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
示例#2
0
    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
示例#3
0
    def addAttribute(self, name, value, Type, isArray=False, lock=True):
        mfn = self._mfn
        mobj = mfn.object()
        if mfn.hasAttribute(name):
            return mfn.findPlug(name, False)
        try:
            attr = nodes.addAttribute(mobj,
                                      name,
                                      name,
                                      Type,
                                      isArray=isArray,
                                      apply=True)
        except RuntimeError:
            raise ValueError(
                "Failed to create attribute with name: {}".format(name))
        newPlug = None
        if attr is not None:
            newPlug = om2.MPlug(mobj, attr.object())

        if value is not None and newPlug is not None:
            # if mobject expect it to be a node
            if isinstance(value, om2.MObject):
                self.connectTo(name, value)
            else:
                plugs.setPlugValue(newPlug, value)
        newPlug.isLocked = lock
        return newPlug
示例#4
0
 def addTarget(self, driver):
     """Adds the given driver transform to the constraint
     :param driver: The driver mobject transform
     :type driver: MObject
     @note having to use maya commands here due to api not able to resize the plugs array outside the datablock
     """
     driven = self.drivenObject()
     driverName = nodes.nameFromMObject(driver)  # so we have the fullPath
     driverShortName = om2.MNamespace.stripNamespaceFromName(driverName).split("|")[-1]
     nextWeightIndex = self.numTargets()  # starts at zero so the return is the next element
     drivenFn = om2.MFnDependencyNode(driven)
     offsetMatrix = om2.MTransformationMatrix(nodes.getOffsetMatrix(driver, driven))
     translation = offsetMatrix.translation(om2.MSpace.kTransform)
     rotation = generic.eulerToDegrees(
         offsetMatrix.rotation().reorder(plugs.getPlugValue(drivenFn.findPlug("rotateOrder", False))))
     # create the weight attribute
     weightName = "W".join([driverShortName, str(nextWeightIndex)])
     weightAttr = nodes.addAttribute(self.node.object(), weightName, weightName,
                                     attrType=attrtypes.kMFnNumericDouble)
     weightAttr.setMin(0.0)
     weightAttr.setMax(1.0)
     weightAttr.default = 1.0
     weightAttr.keyable = True
     driverFn = om2.MFnDependencyNode(driver)
     targetPlug = self.mfn.findPlug("target", False).elementByLogicalIndex(nextWeightIndex)
     cmds.connectAttr(driverFn.findPlug("parentMatrix", False).elementByPhysicalIndex(0).name(),
                      targetPlug.child(0).name())  # targetParentMatrix
     cmds.connectAttr(driverFn.findPlug("scale", False).name(), targetPlug.child(13).name())  # targetScale
     cmds.connectAttr(driverFn.findPlug("rotateOrder", False).name(),
                      targetPlug.child(8).name())  # targetRotateOrder
     cmds.connectAttr(driverFn.findPlug("rotate", False).name(), targetPlug.child(7).name())  # targetRotate
     cmds.connectAttr(driverFn.findPlug("rotatePivotTranslate", False).name(),
                      targetPlug.child(5).name())  # targetRotateTranslate
     cmds.connectAttr(driverFn.findPlug("rotatePivot", False).name(),
                      targetPlug.child(4).name())  # targetRotatePivot
     cmds.connectAttr(driverFn.findPlug("translate", False).name(), targetPlug.child(3).name())  # targetTranslate
     cmds.connectAttr(om2.MPlug(self.mfn.object(), weightAttr.object()).name(),
                      targetPlug.child(1).name())  # targetWeight
     # setting offset value
     plugs.setPlugValue(targetPlug.child(6), translation)  # targetOffsetTranslate
     plugs.setPlugValue(targetPlug.child(10), rotation)  # targetOffsetRotate
示例#5
0
    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
示例#6
0
    def addAttribute(self, name, value, Type, isArray=False, lock=True):
        mobj = self._handle.object()
        mfn = om2.MFnDependencyNode(mobj)
        if mfn.hasAttribute(name):
            return
        try:
            attr = nodes.addAttribute(mobj, name, name, Type)
            attr.array = isArray
        except RuntimeError:
            return
        newPlug = None
        if attr is not None:
            newPlug = om2.MPlug(mobj, attr.object())

        if value is not None and newPlug is not None:
            # if mobject expect it to be a node
            if isinstance(value, om2.MObject):
                self.connectTo(name, value)
            else:
                plugs.setPlugValue(newPlug, value)
        newPlug.isLocked = lock
        return attr
示例#7
0
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