PDA

View Full Version : attributeAffects dirty propagation via matrix attributes


vfxectropy
07-12-2012, 12:31 AM
Hello! I've built a tool that I would like to run the compute for whenever it moves in world space. I've tried setting up an attribute with a kMatrix type that has setWorldSpace(true). I then set this to affect my main data attr. Using pymel/mel's isDirty command with datablock set to true I found that the worldspace matrix attribute indeed does get set to dirty but my attr does not.

I google'd this problem and found another wayward soul who found the workaround of having a setWorldSpace attr connected to ANOTHER dummy attribute that should then propagate my dirty flag. So, I made another kMatrix attr, wrote a script to hook up my inWorldSpace to my dummyWSMatrix attr and continued my attributeAffects chain from dummyWSMatrix to my fieldData attr. Unfortunately, both of the matrix attr's are now dirty but the fieldData is indeed still clean.

Does anyone have any tips or tricks to force computes based off of transforms in world space?

theflash
07-12-2012, 10:17 AM
Difficult to read the purpose of your node, but generally you don't have to force compute. It will be called when input changes and output needs to be computed. What's your compute calculating for output?

zoharl
07-12-2012, 01:56 PM
In short, please provide a code for a small demo plugin which reproduces your problem.

vfxectropy
07-12-2012, 04:02 PM
Small test code from an esteemed colleague who really took a liking to this puzzle:
We were making a custom locator to show force lines from a field. Fields take an inputData input (a compound attribute of positions, current velocity, mass and a delta time) and in return give us outputForce.
We created a worldspace attribute and set it to affect our outputData for the field. We wiggled the locator around, the worldspace attr was dirty and then our outputData attribute was not dirty in turn (aka, our force lines never update).

newFile(f=1)
if pluginInfo('PymelTestNode.py', q=1, loaded=1):
unloadPlugin('PymelTestNode.py')
loadPlugin('PymelTestNode.py')
tn = createNode('PymelTestNode')
pm.select(None)
tn.hide()

myT = pm.createNode('transform')
myT.worldMatrix[0].connect(tn.worldIn)

print "initial output get:", getAttr('PymelTestNode1.output')
myT.tx.set(1)
print "set parent tx..."

print pm.isDirty('PymelTestNode1.worldIn', d=1)
print pm.isDirty('PymelTestNode1.output', d=1)
print "final output get:", getAttr('PymelTestNode1.output')

import math

import pymel.api.plugins as plugins
import maya.OpenMaya as om

class PymelTestNode(plugins.LocatorNode):
'''Test plugin node
'''
_typeId = om.MTypeId(0x9000F)
_name = 'PymelTestNode'

@classmethod
def initialize(cls):

nAttr = om.MFnNumericAttribute()
mAttr = om.MFnMatrixAttribute()
cAttr = om.MFnCompoundAttribute()

cls.input = nAttr.create( "input", "in", om.MFnNumericData.kFloat, 0.0 )
nAttr.setStorable(1)
nAttr.setWritable(1)
nAttr.setKeyable(1)
cls.addAttribute( cls.input )

# outputFloat
cls.outputFloat = nAttr.create( "outputFloat", "of", om.MFnNumericData.kFloat, 0.0 )
nAttr.setStorable(0)
nAttr.setWritable(0)
cls.addAttribute( cls.outputFloat )

# outputInt
cls.outputInt = nAttr.create( "outputInt", "oi", om.MFnNumericData.kInt, 0.0 )
nAttr.setStorable(0)
nAttr.setWritable(0)
cls.addAttribute( cls.outputInt )

# output
cls.output = cAttr.create( "output", "out")
cAttr.addChild(cls.outputFloat)
cAttr.addChild(cls.outputInt)
nAttr.setStorable(0)
nAttr.setWritable(0)
nAttr.setArray(True)
cls.addAttribute( cls.output )

# worldFloat
#cls.worldFloat = nAttr.create("worldFloat", "wf", om.MFnNumericData.kFloat, 0.0 )
#nAttr.setStorable(False)
#nAttr.setWritable(False)
#nAttr.setArray(True)
#nAttr.setWorldSpace(1)
#cls.addAttribute( cls.worldFloat )

# dummyWorldDest
#cls.dummyWorldDest = nAttr.create("dummyWorldDest", "d", om.MFnNumericData.kFloat, 0.0 )
#nAttr.setStorable(False)
#nAttr.setWritable(True)
#nAttr.setReadable(True)
#nAttr.setHidden(True)
#nAttr.setArray(True)
#nAttr.setIndexMatters(False)
#cls.addAttribute( cls.dummyWorldDest )

# worldIn
cls.worldIn = mAttr.create("worldIn", "wi")
mAttr.setStorable(True)
nAttr.setWritable(True)
nAttr.setReadable(True)
nAttr.setArray(False)
cls.addAttribute( cls.worldIn )

# set attribute affects
cls.attributeAffects( cls.input, cls.output )
#cls.attributeAffects( cls.dummyWorldDest, cls.output )
cls.attributeAffects( cls.worldIn, cls.output )


def compute(self, plug, dataBlock):
print "compute called for:", plug.name()
if ( plug == self.output ):
return om.MStatus.kSuccess
return om.MStatus.kUnknownParameter

## initialize the script plug-in
def initializePlugin(mobject):
PymelTestNode.register(mobject)

# uninitialize the script plug-in
def uninitializePlugin(mobject):
PymelTestNode.deregister(mobject)

verbatimline
07-18-2012, 09:04 PM
I'm having a similar problem with the API (C++). I have matrices coming into a compound set to array, and outputing position vectors in an output compound set to be an array. If I do a simple inputData affects outputData my plug does not update. My workaround was to create a time attr. The time attr affects the outputData attr. I connect the time1 node to my time attr and then check if the individual child attrs where set to dirty as opposed to the compound parent.

ex; if( (plug == childPosA) || (plug == childPosB) || (plug == childPosC) )
{}

The problem that I am now having is that my plug does not update in batch render mode. :hmm: :banghead:

zoharl
07-18-2012, 09:18 PM
Sorry, somehow I missed your previous post. I'll take a look later on.

theflash
07-19-2012, 07:27 AM
I missed the post as well.

I think the main problem is that you are dirtying a compound attribute which will not cause a compute since you don't really connect compound attribute as output. Maya will not automatically mark children attributes dirty when you mark compound attribute dirty. You have to do that yourself.

Here are some pointers that I learned:
1. Mark output plug dirty that will be calculated/updated in compute and which is requested by other nodes via connections.
2. You have to connect or request output in some way to tell Maya to compute a node.

CGTalk Moderation
07-19-2012, 07:27 AM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.