Beispiel #1
0
def updateColliderUI(nodeName):
    """
	Called when the attribute editor UI for the rigid body
	needs to be updated to reflect the latest attribute
	values. Enables and disables controls.
	"""
    logger.debug(maya.stringTable['y_RigidBodyUI.kUpdatingCollider'] %
                 nodeName)

    cst = _getAttr(nodeName, 'colliderShapeType')
    autoFit = _getAttr(nodeName, 'autoFit')

    maya.cmds.editorTemplate(dimControl=(nodeName, "colliderShapeOffset",
                                         autoFit))
    maya.cmds.editorTemplate(
        dimControl=(nodeName, "axis",
                    autoFit or cst not in (eShapeType.kColliderCylinder,
                                           eShapeType.kColliderCapsule)))
    maya.cmds.editorTemplate(
        dimControl=(nodeName, "length",
                    autoFit or cst not in (eShapeType.kColliderCylinder,
                                           eShapeType.kColliderCapsule)))
    maya.cmds.editorTemplate(
        dimControl=(nodeName, "radius",
                    autoFit or cst not in (eShapeType.kColliderCylinder,
                                           eShapeType.kColliderCapsule,
                                           eShapeType.kColliderSphere)))
    maya.cmds.editorTemplate(
        dimControl=(nodeName, "extents",
                    autoFit or cst not in (eShapeType.kColliderBox, )))
Beispiel #2
0
def updateSoftBodyUI(nodeName):
    """
	Called when the attribute editor UI for the soft body
	needs to be updated to reflect the latest attribute
	values. Enables and disables controls.
	"""
    logger.debug(maya.stringTable['y_SoftBodyUI.kUpdatingSoftBody'] % nodeName)

    generateBendConstraints = cmds.getAttr(
        '{0}.generateBendConstraints'.format(nodeName))
    enableVolumeMatching = cmds.getAttr(
        '{0}.enableVolumeMatching'.format(nodeName))
    enableShapeMatching = cmds.getAttr(
        '{0}.enableShapeMatching'.format(nodeName))

    cmds.editorTemplate(dimControl=(nodeName, "bendResistance",
                                    not generateBendConstraints))

    cmds.editorTemplate(dimControl=(nodeName, "volumeCoefficient",
                                    not enableVolumeMatching))

    cmds.editorTemplate(dimControl=(nodeName, "maxVolumeRatio",
                                    not enableVolumeMatching))

    cmds.editorTemplate(dimControl=(nodeName, "shapeCoefficient",
                                    not enableShapeMatching))
Beispiel #3
0
def updateConstraintUI(nodeName):
    """
	Called when the attribute editor UI for the rigid body constraints
	needs to be updated to reflect the latest attribute
	values. Enables and disables controls.
	"""
    logger.debug(
        maya.stringTable['y_RigidBodyConstraintUI.kUpdatingConstrUI'] %
        nodeName)

    # Limit Properties section
    constraintType = cmds.getAttr('{0}.constraintType'.format(nodeName))
    for attrName in dictConstraintAttributes.keys():
        _enableControl(nodeName, attrName, constraintType,
                       dictConstraintAttributes[attrName])

    linearMotorEnabled = cmds.getAttr(
        '{0}.linearMotorEnabled'.format(nodeName))
    cmds.editorTemplate(dimControl=(nodeName, "linearMotorTargetSpeed",
                                    not linearMotorEnabled))
    cmds.editorTemplate(dimControl=(nodeName, "linearMotorMaxForce",
                                    not linearMotorEnabled))

    angularMotorEnabled = cmds.getAttr(
        '{0}.angularMotorEnabled'.format(nodeName))
    cmds.editorTemplate(dimControl=(nodeName, "angularMotorTargetSpeed",
                                    not angularMotorEnabled))
    cmds.editorTemplate(dimControl=(nodeName, "angularMotorMaxForce",
                                    not angularMotorEnabled))
Beispiel #4
0
def getRigidBodyFromTransform(transform):
    """
	Given a transform (by name), return the rigid body.

	This method encapsulates the logic behind the RB
	hierarchies. Currently that hierarchy looks like:

	init_xform
		rb_xform
			rb_shape
	"""
    logger.debug(maya.stringTable['y_BulletUtils.kGettingRB'] % transform)
    if transform:
        xformNode = _longName(transform)
    else:
        return None

    # first check if this is a rigid body xform...
    shapeNodes = _getChildren(xformNode,
                              type=("bulletRigidBodyShape",
                                    "bulletSoftBodyShape", "bulletSolverShape",
                                    "bulletRigidBodyConstraintShape",
                                    "bulletSoftConstraintShape"))
    if (len(shapeNodes) > 1):
        logger.warn(maya.stringTable['y_BulletUtils.kExceptedShapeUnder'] %
                    xformNode)
    if (len(shapeNodes) > 0):
        return shapeNodes[0]

    # no match? check if the xform was the init xform...
    for childXformNode in _getChildren(xformNode, type="transform"):
        shapeNodes = _getChildren(
            childXformNode,
            type=("bulletRigidBodyShape", "bulletSoftBodyShape",
                  "bulletSolverShape", "bulletRigidBodyConstraintShape",
                  "bulletSoftConstraintShape"))
        if (len(shapeNodes) > 1):
            logger.warn(
                maya.stringTable['y_BulletUtils.kExceptedShapeUnder2'] %
                childXformNode)
        if (len(shapeNodes) > 0):
            return shapeNodes[0]
    # end-for

    # didn't find any RB shapes in the expected places
    return None
Beispiel #5
0
def disconnectFromSolver(bulletShape):
    """
	Given a Bullet shape, disconnect its connections to any
	BulletSolverShape nodes.
	"""
    @Trace()
    def _inputs(obj):
        return zip( maya.cmds.listConnections( bulletShape, plugs=True, \
             source=True, destination=False ),
           maya.cmds.listConnections( bulletShape, \
             source=True, destination=False, sh=True ) )

    @Trace()
    def _nodeFromPlug(plug):
        return _longName(plug.split('.')[0])

    @Trace()
    def _disconnect(outPlug, inPlug):
        maya.cmds.disconnectAttr(outPlug, inPlug)

    bulletShape = _longName(bulletShape)

    logger.debug(maya.stringTable['y_BulletUtils.kDisconnectShape'] %
                 bulletShape)
    # into the shape from other nodes

    for outPlug, outSrc in _inputs(bulletShape):
        if not _isType(outSrc, 'bulletSolverShape'):
            logger.debug(maya.stringTable['y_BulletUtils.kSkipNonSolverConn'] %
                         outPlug)
            continue
        # get input plugs connected to output plug
        for inPlug in maya.cmds.connectionInfo(outPlug, \
                   destinationFromSource=True):
            # get the node from plug
            if (_nodeFromPlug(inPlug) != bulletShape):
                logger.debug(
                    maya.stringTable['y_BulletUtils.kSkipUnrelatedConn'] %
                    inPlug)
                continue

            logger.debug(maya.stringTable['y_BulletUtils.kDisconnectConn'] %
                         (outPlug, inPlug))
            _disconnect(outPlug, inPlug)
        # end-for
    # end-for

    # these are connections out from the shape to other nodes
    destinations = maya.cmds.listConnections( _longName(bulletShape), plugs=True, \
            source=False, destination=True )
    for inPlug in destinations:
        if (not _isType(inPlug, 'bulletSolverShape')):
            logger.debug(
                maya.stringTable['y_BulletUtils.kSkipNonSolverConn2'] % inPlug)
            continue

        outPlug \
         = maya.cmds.connectionInfo(_name(inPlug), \
                  sourceFromDestination=True)

        if _nodeFromPlug(outPlug) != bulletShape:
            logger.debug(
                maya.stringTable['y_BulletUtils.kSkipUnrelatedConn2'] %
                outPlug)
            continue

        logger.debug(maya.stringTable['y_BulletUtils.kDisconnectConn2'] %
                     (outPlug, inPlug))
        _disconnect(outPlug, inPlug)
    # end-for

    return True
Beispiel #6
0
    def command(
        rigidBodyA=None,
        rigidBodyB=None,
        parent=None,
        # Attrs
        constraintType=None,
        useReferenceFrame=None,
        linearDamping=None,
        linearSoftness=None,
        linearRestitution=None,
        angularDamping=None,
        angularSoftness=None,
        angularRestitution=None,
        linearConstraintX=None,
        linearConstraintY=None,
        linearConstraintZ=None,
        linearConstraintMin=None,
        linearConstraintMax=None,
        angularConstraintX=None,
        angularConstraintY=None,
        angularConstraintZ=None,
        angularConstraintMin=None,
        angularConstraintMax=None,
        linearLimitSoftness=None,
        linearLimitBias=None,
        linearLimitRelaxation=None,
        angularLimitSoftness=None,
        angularLimitBias=None,
        angularLimitRelaxation=None,
        linearMotorEnabled=None,
        linearMotorTargetSpeed=None,
        linearMotorMaxForce=None,
        angularMotorEnabled=None,
        angularMotorTargetSpeed=None,
        angularMotorMaxForce=None,
        linearSpringEnabledX=None,
        linearSpringEnabledY=None,
        linearSpringEnabledZ=None,
        linearSpringStiffness=None,
        linearSpringDamping=None,
        angularSpringEnabledX=None,
        angularSpringEnabledY=None,
        angularSpringEnabledZ=None,
        angularSpringStiffness=None,
        angularSpringDamping=None,
        breakable=None,
        breakingThreshold=None,
    ):
        logger.debug( maya.stringTable[ 'y_RigidBodyConstraint.kCreatingRBC'  ] \
                       % (rigidBodyA, rigidBodyB) )
        # List settable attrs (setAttr below)
        settableAttrs = [
            'constraintType',
            'useReferenceFrame',
            'linearDamping',
            'linearSoftness',
            'linearRestitution',
            'angularDamping',
            'angularSoftness',
            'angularRestitution',
            'linearConstraintX',
            'linearConstraintY',
            'linearConstraintZ',
            'linearConstraintMin',
            'linearConstraintMax',
            'angularConstraintX',
            'angularConstraintY',
            'angularConstraintZ',
            'angularConstraintMin',
            'angularConstraintMax',
            'linearLimitSoftness',
            'linearLimitBias',
            'linearLimitRelaxation',
            'angularLimitSoftness',
            'angularLimitBias',
            'angularLimitRelaxation',
            'linearMotorEnabled',
            'linearMotorTargetSpeed',
            'linearMotorMaxForce',
            'angularMotorEnabled',
            'angularMotorTargetSpeed',
            'angularMotorMaxForce',
            'linearSpringEnabledX',
            'linearSpringEnabledY',
            'linearSpringEnabledZ',
            'linearSpringStiffness',
            'linearSpringDamping',
            'angularSpringEnabledX',
            'angularSpringEnabledY',
            'angularSpringEnabledZ',
            'angularSpringStiffness',
            'angularSpringDamping',
            'breakable',
            'breakingThreshold',
        ]
        # Get the rigid body/bodies.
        rigids = [i for i in [rigidBodyA, rigidBodyB]
                  if i != None]  # list of non-None rigid bodies
        if len(rigids) == 0:  # if no rigids specified, then look at selection
            rigids = BulletUtils.getConnectedRigidBodies()
        logger.info(
            maya.stringTable['y_RigidBodyConstraint.kRigidBodiesToConnect'] %
            (rigids, parent))
        if len(rigids) == 0 or len(rigids) > 2:
            # TODO: this produces a pretty difficult to read error for the user.
            maya.OpenMaya.MGlobal.displayError(
                maya.
                stringTable['y_RigidBodyConstraint.kPleaseSelectRigidbodies'])
            return []
        if len(rigids) == 1 and locals()['constraintType'] in (
                eConstraintType.kRBConstraintHinge2,
                eConstraintType.kRBConstraintSixDOF2):
            maya.OpenMaya.MGlobal.displayError(maya.stringTable[
                'y_RigidBodyConstraint.kPleaseSelectTwoRigidbodies'])
            return []

        # Get Solver
        solver = BulletUtils.getSolver()
        # Create Node
        constraint = maya.cmds.createNode('bulletRigidBodyConstraintShape',
                                          parent=parent)
        # Set Attrs (optional, set if value != None)
        # Use the settableAttrs list above to qualify kwargs passed into the
        # function
        for k, v in locals().iteritems():
            if k in settableAttrs and v != None:
                if isinstance(v, list):
                    maya.cmds.setAttr('%s.%s' % (constraint, k),
                                      *v)  # covers float3 cases
                else:
                    maya.cmds.setAttr('%s.%s' % (constraint, k), v)
        # Connect
        maya.cmds.connectAttr((solver + ".outSolverInitialized"),
                              (constraint + ".solverInitialized"))
        maya.cmds.connectAttr((rigids[0] + ".outRigidBodyData"),
                              (constraint + ".rigidBodyA"))
        if len(rigids) > 1:
            maya.cmds.connectAttr((rigids[1] + ".outRigidBodyData"),
                                  (constraint + ".rigidBodyB"))
        maya.cmds.connectAttr((constraint + ".outConstraintData"),
                              (solver + ".rigidBodyConstraints"),
                              na=True)
        # REVISIT: Consider alternatives like a single initSystem bool attr
        #          instead of startTime and currentTime.
        #          Might be able to get around needing it at all
        maya.cmds.connectAttr((solver + ".startTime"),
                              (constraint + ".startTime"))
        maya.cmds.connectAttr((solver + ".currentTime"),
                              (constraint + ".currentTime"))

        # Translate (avg the rigid body positions)
        t = maya.cmds.xform(maya.cmds.listRelatives(rigids[0],
                                                    fullPath=True,
                                                    parent=True),
                            q=True,
                            ws=True,
                            t=True)
        if len(rigids) > 1:
            t2 = maya.cmds.xform(maya.cmds.listRelatives(rigids[1],
                                                         fullPath=True,
                                                         parent=True),
                                 q=True,
                                 ws=True,
                                 t=True)
            t = [(t[0] + t2[0]) * 0.5, (t[1] + t2[1]) * 0.5,
                 (t[2] + t2[2]) * 0.5]

        constraintT = maya.cmds.listRelatives(constraint, parent=True)
        maya.cmds.xform(constraintT, ws=True, t=t)

        ret = [constraint]
        # If command echoing is off, echo this short line.
        if (not maya.cmds.commandEcho(query=True, state=True)):
            print(
                "RigidBodyConstraint.CreateRigidBodyConstraint.executeCommandCB()"
            )
            print "// Result: %s //" % constraint

        return ret
Beispiel #7
0
def createRagdoll(rootJoint=None,
                  angularDamping=DEFAULT_ANGULAR_DAMPING,
                  angularSoftness=DEFAULT_ANGULAR_SOFTNESS,
                  angularRestitution=DEFAULT_ANGULAR_RESTITUTION,
                  capsuleBoneRatio=DEFAULT_CAPSULE_LENGTH,
                  capsuleRadiusRatio=DEFAULT_CAPSULE_RADIUS,
                  capsuleMass=DEFAULT_CAPSULE_MASS,
                  jointNameSeparator=DEFAULT_NAME_SEPARATOR):
    """
	Creates a ragdoll of capsules joined by constraints, that matches
	the skeleton starting from the joint named by rootJoint. If no
	root is specified, the current selection is used.
	"""
    nodesToVisit = deque(_getNodesToVisit(rootJoint))

    if not nodesToVisit or len(nodesToVisit) < 1:
        maya.OpenMaya.MGlobal.displayError(
            maya.stringTable['y_Ragdoll.kCreateRagdollSelectJoint'])
        return

    ragdollRootNode = maya.cmds.createNode('transform',
                                           name="Ragdoll#",
                                           skipSelect=True)

    currentJoint = None
    while (len(nodesToVisit) > 0):
        logger.debug( maya.stringTable[ 'y_Ragdoll.kStartingIterCurrJoint'  ] \
               % (currentJoint, nodesToVisit) )
        currentJoint = nodesToVisit.popleft()
        # NOTE: assumes joints are directly connected to each other
        try:
            parentJoint = _firstParent(currentJoint)
            if (not _isJoint(parentJoint)):
                parentJoint = None
        except:
            parentJoint = None
        # end-try

        logger.debug(maya.stringTable['y_Ragdoll.kVisiting2'] % currentJoint)
        (rbAXform, rbA) = _getRagdollCapsule(ragdollRootNode, parentJoint,
                                             currentJoint, jointNameSeparator)
        childJoints = _getChildren(currentJoint, type="joint")
        nodesToVisit.extend(childJoints)

        prevChildJoint = None
        for childJoint in childJoints:
            # Here's what we're working with within this loop:
            #
            # parent		   current		   child
            #  joint --[rbA]--> joint --[rbB]--> joint
            (rbBXform, rbB) \
             = _createCapsule( currentJoint, childJoint, False,
                   eBodyType.kDynamicRigidBody, capsuleMass,
                   capsuleBoneRatio, capsuleRadiusRatio,
                   "%s%s%s" % (_name(currentJoint),
                      jointNameSeparator,
                      _name(childJoint)) )
            rbBXform = _setParent(rbBXform, ragdollRootNode)
            rbBName = None
            if (rbB is not None):
                rbBName = _getChildren(rbBXform,
                                       type='bulletRigidBodyShape')[0]
            rbBXformName = None
            if (rbBXform is not None): rbBXformName = _longName(rbBXform)

            # figure out what to anchor this rigid body to
            if (rbA is None and prevChildJoint is not None):
                # prevChildJoint implies that a sibling capsule was
                # created in a previous iteration, which this capsule
                # can be constrained to.
                (sibXform, sib) \
                 = _getRagdollCapsule( ragdollRootNode, currentJoint, prevChildJoint,
                        jointNameSeparator )
                rbAnchorName = _longName(sib)
            elif (rbA is not None):
                rbAnchorName = _longName(rbA)
            else:
                # NOTE: don't create constraints without an anchor, or
                # else the ragdoll will end up constrained to the world.
                rbAnchorName = None
            # end-if

            if (rbAnchorName is not None):
                logger.info( maya.stringTable[ 'y_Ragdoll.kCreatingConstr'  ] \
                      % (rbAnchorName, rbB) )
                # "constraint" abbreviated "constr"
                constrName = _createRigidBodyConstraint( \
                     constraintType=eConstraintType.kRBConstraintSixDOF,
                     rigidBodyA=rbAnchorName,
                     rigidBodyB=rbBName,
                     parent=None )[0]
                constrNode = constrName
                constrXformNode = _firstParent(constrNode)

                # configure the transform
                constrXformNode = maya.cmds.rename(
                    constrXformNode, "constraint_%s" % _name(currentJoint))
                constrXformNode = _setParent(constrXformNode, ragdollRootNode)
                constrNode = _getChildren(
                    constrXformNode, type='bulletRigidBodyConstraintShape')[0]
                _setTranslation(constrXformNode,
                                _getTranslation(currentJoint, space="world"))
                _setRotation(constrXformNode,
                             _getRotation(currentJoint, space="world"))

                # configure the constraint
                _setAttr(constrNode, 'angularDamping', angularDamping)
                _setAttr(constrNode, 'angularSoftness', angularSoftness)
                _setAttr(constrNode, 'angularRestitution', angularRestitution)

                # lock the linear motion, to behave like a point constraint
                _setAttr(constrNode,'linearConstraintX', \
                 eConstraintLimitType.kRBConstraintLimitLocked )
                _setAttr(constrNode,'linearConstraintY', \
                 eConstraintLimitType.kRBConstraintLimitLocked )
                _setAttr(constrNode,'linearConstraintZ', \
                 eConstraintLimitType.kRBConstraintLimitLocked )

                # set the rotational limits to match the joint
                _applyJointLimits(currentJoint, constrNode)
            # end-if

            prevChildJoint = childJoint
        # end-for
    # end-while

    maya.cmds.select(ragdollRootNode, replace=True)
Beispiel #8
0
def addCapsulesToSkeleton(rootJointName=None,
                          capsuleBoneRatio=DEFAULT_CAPSULE_LENGTH,
                          capsuleRadiusRatio=DEFAULT_CAPSULE_RADIUS):
    """
	This method traverses a joint hierarchy, adding kinematic rigid
	body capsules to the bones. If the name of the root joint is
	provided, the traversal will begin at that joint. Otherwise, the
	currently selected joint(s) will be used.
	"""
    initialSelection = maya.cmds.ls(long=True, selection=True)
    nodesToVisit = deque(_getNodesToVisit(rootJointName))

    if not nodesToVisit or len(nodesToVisit) < 1:
        maya.OpenMaya.MGlobal.displayError(
            maya.stringTable['y_Ragdoll.kAddCollidersSelectJoint'])
        return

    while (len(nodesToVisit) > 0):
        currentJoint = nodesToVisit.popleft()
        logger.debug(maya.stringTable['y_Ragdoll.kVisiting'] % currentJoint)

        # within the current iteration, we will consider only other
        # joints attached to the current joint
        children = [ child for child in _getChildren(currentJoint) \
             if _isJoint(child) ]
        # future iterations need only consider joints with children
        nodesToVisit.extend( [child for child in children \
                if _numChildren(child) > 0] )
        prevCapsules = [child for child in _getChildren(currentJoint) \
             if RB_XFORM_PREFIX in _name(child)]

        # examine the bones between this joint and its child joints...
        for childJoint in children:
            logger.debug(maya.stringTable['y_Ragdoll.kBoneFromTo'] %
                         (currentJoint, childJoint))
            boneVector = _getTranslation(childJoint)

            bCapsuleExists = False
            for prevCapsuleXform in prevCapsules:
                if _getTranslation(prevCapsuleXform) == boneVector * 0.5:
                    bCapsuleExists = True
                    break
                # end-if
            # end-for
            if (bCapsuleExists):
                logger.warn(maya.stringTable['y_Ragdoll.kSkippingBone'])
                continue
            # end-if

            _createCapsule(
                currentJoint,
                childJoint,
                bAttachToJoint=True,
                # colliders for animation should be kinematic,
                # with zero mass
                bodyType=eBodyType.kKinematicRigidBody,
                mass=0.0,
                boneLengthRatio=capsuleBoneRatio,
                lengthRadiusRatio=capsuleRadiusRatio)
        # end-for
    # end-while

    # restore the initial selection
    maya.cmds.select(initialSelection, replace=True)