def getNodesCreatedBy( function, *args, **kwargs ):
	'''
	returns a 2-tuple containing all the nodes created by the passed function, and
	the return value of said function

	NOTE: if any container nodes were created, their contents are omitted from the
	resulting node list - the container itself encapsulates them
	'''

	newNodes, ret = apiExtensions.getNodesCreatedBy( function, *args, **kwargs )

	#now remove nodes from all containers from the newNodes list
	newContainers = apiExtensions.filterByType( newNodes, apiExtensions.MFn.kSet )

	#NOTE: nodes are MObject instances at this point
	newNodes = set( [ node for node in newNodes if node is not None ] )
	for c in newContainers:
		for n in sets( c, q=True ) or []:
			if n in newNodes:
				newNodes.remove( n )


	#containers contained by other containers don't need to be returned (as they're already contained by a parent)
	newTopLevelContainers = []
	for c in newContainers:
		parentContainer = sets( c, q=True, parentContainer=True )
		if parentContainer:
			continue

		newTopLevelContainers.append( c )
		newNodes.add( c )


	return newNodes, ret
示例#2
0
	def construct( self ):
		'''
		builds the actual dynamic hair network
		'''
		setNode = self._node
		objs = self.getObjs()

		#before we do anything, check to see whether the selected objects have any incoming connections
		warnAboutDisconnections = False
		for obj in objs:

			#check the object for incoming connections - if it has any, remove them
			for chan in ('t', 'r'):
				for ax in Axis.BASE_AXES:
					cons = listConnections( '%s.%s%s' % (obj, chan, ax), d=False )
					if cons:
						warnAboutDisconnections = True
						if objectType( cons[0], isAType='animCurve' ):
							delete( cons[0] )
						else:
							raise TypeError( "The object %s has non anim curve incoming connections - aborting!  Please remove connections manually before proceeding" % obj )

		if warnAboutDisconnections:
			printWarningStr( "Some of the objects had incoming connections (probably from animation).  These connections have been broken!  undo if you want them back" )

		#wrap the creation of the nodes in a function - below this we execute this function via a wrapper which returns a list of new nodes created
		#this is done so we can easily capture the nodes created and store them in the set that describes this dynamic chain
		def doCreate():
			positions = []
			for obj in objs:
				positions.append( xform( obj, q=True, ws=True, rp=True ) )

			#the objs may not be in the same hierarchy, so create a proxy chain that IS in a heirarchy
			proxyJoints = []
			for obj in objs:
				select( cl=True )
				j = createNode( 'joint' )
				j = rename( j, '%s_dynChainProxy#' % obj.split( ':' )[-1].split( '|' )[-1] )
				if proxyJoints:
					parent( j, proxyJoints[-1] )

				delete( parentConstraint( obj, j ) )
				proxyJoints.append( j )

				#constrain the original to the proxy
				parentConstraint( j, obj )

			#hook up the proxy root to a special message attribute so we can easily find the proxy chain again for things like baking etc...
			connectAttr( '%s.message' % proxyJoints[0], '%s.proxyRoot' % setNode )

			#build a linear curve
			linearCurve = curve( d=1, p=positions )
			linearCurveShape = listRelatives( linearCurve, s=True, pa=True )[0]
			select( linearCurve )
			maya.mel.eval( 'makeCurvesDynamicHairs 1 0 1;' )

			#find the dynamic curve shape
			cons = listConnections( '%s.worldSpace' % linearCurveShape, s=False )
			if not cons:
				printWarningStr( "Cannot find follicle" )
				return

			follicleShape = cons[0]
			cons = listConnections( '%s.outHair' % follicleShape, s=False )
			if not cons:
				printWarningStr( "Cannot find hair system!" )
				return

			hairSystemNode = cons[0]
			setAttr( '%s.startFrame' % hairSystemNode, playbackOptions( q=True, min=True ) )
			cons = listConnections( '%s.outCurve' % follicleShape, s=False )
			if not cons:
				printWarningStr( "Cannot find out curve!" )
				return

			dynamicCurve = cons[0]
			dynamicCurveParent = listRelatives( dynamicCurve, p=True, pa=True )  #grab the dynamic curve's shape

			select( dynamicCurve )
			maya.mel.eval( 'displayHairCurves "current" 1;' )

			follicle = listRelatives( linearCurve, p=True, pa=True )[0]
			objParent = listRelatives( objs[0], p=True, pa=True )
			if objParent:
				objParent = objParent[0]
				parent( follicle, objParent )
				parent( proxyJoints[0], objParent )

			setAttr( '%s.overrideDynamics' % follicle, 1 )
			setAttr( '%s.pointLock' % follicle, 1 )

			#hook up all the attributes
			connectAttr( '%s.stiffness' % setNode, '%s.stiffness' % follicle )
			connectAttr( '%s.lengthFlex' % setNode, '%s.lengthFlex' % follicle )
			connectAttr( '%s.damping' % setNode, '%s.damp' % follicle )
			connectAttr( '%s.drag' % setNode, '%s.drag' % hairSystemNode )
			connectAttr( '%s.friction' % setNode, '%s.friction' % hairSystemNode )
			connectAttr( '%s.gravity' % setNode, '%s.gravity' % hairSystemNode )
			connectAttr( '%s.turbStrength' % setNode, '%s.turbulenceStrength' % hairSystemNode )
			connectAttr( '%s.turbFreq' % setNode, '%s.turbulenceFrequency' % hairSystemNode )
			connectAttr( '%s.turbSpeed' % setNode, '%s.turbulenceSpeed' % hairSystemNode )

			splineIkHandle = ikHandle( sj=proxyJoints[0], ee=proxyJoints[-1], curve=dynamicCurve, sol='ikSplineSolver', ccv=False )[0]

			#for some reason the dynamic curve gets re-parented by the ikHandle command (weird) so set the parent back to what it was originally
			parent( dynamicCurve, dynamicCurveParent )

		newNodes, returnValue = getNodesCreatedBy( doCreate )

		#stuff the nodes created into the set that describes this dynamic chain - just add transform nodes...
		for aNode in newNodes:
			if objectType( aNode, isAType='transform' ):
				sets( aNode, e=True, add=setNode )
示例#3
0
    def construct(self):
        '''
		builds the actual dynamic hair network
		'''
        setNode = self._node
        objs = self.getObjs()

        #before we do anything, check to see whether the selected objects have any incoming connections
        warnAboutDisconnections = False
        for obj in objs:

            #check the object for incoming connections - if it has any, remove them
            for chan in ('t', 'r'):
                for ax in Axis.BASE_AXES:
                    cons = listConnections('%s.%s%s' % (obj, chan, ax),
                                           d=False)
                    if cons:
                        warnAboutDisconnections = True
                        if objectType(cons[0], isAType='animCurve'):
                            delete(cons[0])
                        else:
                            raise TypeError(
                                "The object %s has non anim curve incoming connections - aborting!  Please remove connections manually before proceeding"
                                % obj)

        if warnAboutDisconnections:
            printWarningStr(
                "Some of the objects had incoming connections (probably from animation).  These connections have been broken!  undo if you want them back"
            )

        #wrap the creation of the nodes in a function - below this we execute this function via a wrapper which returns a list of new nodes created
        #this is done so we can easily capture the nodes created and store them in the set that describes this dynamic chain
        def doCreate():
            positions = []
            for obj in objs:
                positions.append(xform(obj, q=True, ws=True, rp=True))

            #the objs may not be in the same hierarchy, so create a proxy chain that IS in a heirarchy
            proxyJoints = []
            for obj in objs:
                select(cl=True)
                j = createNode('joint')
                j = rename(
                    j, '%s_dynChainProxy#' % obj.split(':')[-1].split('|')[-1])
                if proxyJoints:
                    parent(j, proxyJoints[-1])

                delete(parentConstraint(obj, j))
                proxyJoints.append(j)

                #constrain the original to the proxy
                parentConstraint(j, obj)

            #hook up the proxy root to a special message attribute so we can easily find the proxy chain again for things like baking etc...
            connectAttr('%s.message' % proxyJoints[0],
                        '%s.proxyRoot' % setNode)

            #build a linear curve
            linearCurve = curve(d=1, p=positions)
            linearCurveShape = listRelatives(linearCurve, s=True, pa=True)[0]
            select(linearCurve)
            maya.mel.eval('makeCurvesDynamicHairs 1 0 1;')

            #find the dynamic curve shape
            cons = listConnections('%s.worldSpace' % linearCurveShape, s=False)
            if not cons:
                printWarningStr("Cannot find follicle")
                return

            follicleShape = cons[0]
            cons = listConnections('%s.outHair' % follicleShape, s=False)
            if not cons:
                printWarningStr("Cannot find hair system!")
                return

            hairSystemNode = cons[0]
            setAttr('%s.startFrame' % hairSystemNode,
                    playbackOptions(q=True, min=True))
            cons = listConnections('%s.outCurve' % follicleShape, s=False)
            if not cons:
                printWarningStr("Cannot find out curve!")
                return

            dynamicCurve = cons[0]
            dynamicCurveParent = listRelatives(
                dynamicCurve, p=True, pa=True)  #grab the dynamic curve's shape

            select(dynamicCurve)
            maya.mel.eval('displayHairCurves "current" 1;')

            follicle = listRelatives(linearCurve, p=True, pa=True)[0]
            objParent = listRelatives(objs[0], p=True, pa=True)
            if objParent:
                objParent = objParent[0]
                parent(follicle, objParent)
                parent(proxyJoints[0], objParent)

            setAttr('%s.overrideDynamics' % follicle, 1)
            setAttr('%s.pointLock' % follicle, 1)

            #hook up all the attributes
            connectAttr('%s.stiffness' % setNode, '%s.stiffness' % follicle)
            connectAttr('%s.lengthFlex' % setNode, '%s.lengthFlex' % follicle)
            connectAttr('%s.damping' % setNode, '%s.damp' % follicle)
            connectAttr('%s.drag' % setNode, '%s.drag' % hairSystemNode)
            connectAttr('%s.friction' % setNode,
                        '%s.friction' % hairSystemNode)
            connectAttr('%s.gravity' % setNode, '%s.gravity' % hairSystemNode)
            connectAttr('%s.turbStrength' % setNode,
                        '%s.turbulenceStrength' % hairSystemNode)
            connectAttr('%s.turbFreq' % setNode,
                        '%s.turbulenceFrequency' % hairSystemNode)
            connectAttr('%s.turbSpeed' % setNode,
                        '%s.turbulenceSpeed' % hairSystemNode)

            splineIkHandle = ikHandle(sj=proxyJoints[0],
                                      ee=proxyJoints[-1],
                                      curve=dynamicCurve,
                                      sol='ikSplineSolver',
                                      ccv=False)[0]

            #for some reason the dynamic curve gets re-parented by the ikHandle command (weird) so set the parent back to what it was originally
            parent(dynamicCurve, dynamicCurveParent)

        newNodes, returnValue = getNodesCreatedBy(doCreate)

        #stuff the nodes created into the set that describes this dynamic chain - just add transform nodes...
        for aNode in newNodes:
            if objectType(aNode, isAType='transform'):
                sets(aNode, e=True, add=setNode)