How to deal with array attributes maya Api

Hello everyone, i am writing a plugin using maya api2 , im pretty fresh with api in general but i stumbled upon an issue for which i can’t find any real answer to it.

How do you deal with array’s attributes ?
For instance,
i have an attribute
MFnNumericAttribute , which is called “params” , this is an array attribute, and all seems fine to here.
When i run the node and connect stuff to it in maya , it creates extra inputs as it should, im able to query and do stuff with it.

Now , i have also another MFnNumericAttribute , which is called “outTranslate”, this is also an array attribute, but has only outputs.

my initialize looks like something like this :


nAttr = om.MFnNumericAttribute()
cls.params = nAttr.create(“params”, “p”, om.MFnNumericData.kDouble, 0.0)
nAttr.array = True
cls.outTranslate = nAttr.create(“outTranslate”, “ot”, om.MFnNumericData.k3Double, 0.0)
nAttr.array = True


cls.attributeAffects(cls.params, cls.outTranslate)


Now , how do i make so that , when i connect something into my input params array attribute , it also update the array attributes for outTranslate ? so that the two arrays are in sync and each input index is paired to the output index ?

Do i need to do this inside the compute() function ? if so, how ?
Do i need to do this using a maya script as im connecting stuff to it on creation ? ( from outside the node?)

im a little unclear if im missing something out, i was hoping that attributeAffects would actually also connect the array number out automatically being both arrays…but doesn’t look like it…(so naive of me…) .

Any example or explanation would be great, even if in cpp, or api1, i would just like to understand what to do, since i assume, it would be something fairly common on a node? .

i find a way of making this work , alto not sure is really as efficient as i wish it was ,
also I noticed that the node itself does not auto-updates all the time in the node editor ,so keep an eye on the attribute editor when plugging and unplugging stuff.

Finally, the output attribute if is an array attribute, also, auto updates the ports as you plug them outwards, perhaps a more efficient way for the node to work would be to have a setup script that first thing it does, is to create the array attributes, so that they are paired with the inputs, not sure about that tho.

here is what i did in the compute to make this work:

def compute(self, plug, data):
if (plug == self.outTranslate or plug == self.inParams ):

  	inParamsDH		= data.inputArrayValue(ArrayAttrSample.inParams)
  	outTranslateDH	= data.outputArrayValue(ArrayAttrSample.outTranslate)
  	# This function checks on the array length for inParams, and 
  	# auto creates outTranslate attribute elements accordingly so that 
  	# inParams and outTranslate arrays have the same number of elements 
  	if len( inParamsDH ) > len( outTranslateDH ):
  		print("inPar not in line with outTrans elements")
  		thisNode = self.thisMObject()
  		wPlug = om.MPlug( thisNode, ArrayAttrSample.outTranslate )
  		wHandle = wPlug.constructHandle(data)
  		arrayHandle = om.MArrayDataHandle( wHandle )
  		arrayBuilder = arrayHandle.builder()
  		for i in range( len( inParamsDH ) ):
  			handle = arrayBuilder.addElement( i )
  			# i can set values here in the loop or 
  			# later directly on the array attribute 
  			value = 0.55
  			handle.set3Double(value, value, value)
  	print('Do other stuff here .. ')


Well…guess what, i found a better way to do it , which does not involve the compute() function,
i still think is somewhat not as pretty, so i will dig about a little more on how to use perhaps the MArrayDataBuilder , which it seems to be the proper way to do it. (if anyone have a link perhaps would be really apreaciated…)

Anyways, if anyone is interested, this is what i did , im using the two methods
connectionMade and connectionBroken, which refresh as an attribute on the node gets connected in or disconnected from the node, automatically :

def connectionMade(self, myPlug, theirPlug, iAmSrc ):
	Since we can't pass dataBlocks/MArrayDataHandles outside compute function, i have to use
	plugs to set and remove attribute manually from the node.
	#print(' Something got connected to the node! >>>')
	thisNode 		 = self.thisMObject()
	inParamsPlug 	 = om.MPlug ( thisNode, ArrayAttrSample.inParams )
	outTranslatePlug = om.MPlug ( thisNode, ArrayAttrSample.outTranslate )

	# this returns how many array attributes are connected inside the mplug
	# can use numElements() or numConnectedElements()
	inParElemNumber   = inParamsPlug.numConnectedElements()
	outTranElemNumber = outTranslatePlug.numConnectedElements()
	#print ( inParamsPlug.numElements() ) 
	#print ( outTranslatePlug.numElements() ) 

	#print ( inParElemNumber, outTranElemNumber )
	if inParElemNumber > outTranElemNumber:
		#print('inPar not in line with outTrans elements')
		for i in range( inParElemNumber ):
			# one liner to use the plug, grab the element and set it as Double 
			# the MPlug.setDouble is key to update the attr

		#print('Connection updated OutArray.')

def connectionBroken(self, myPlug, theirPlug, iAmSrc):
	Similar deal for removing elements, alto we need to use MDGModifier.removeMultiInstance()
	#print(' Something got Disconnected from the node! <<<')
	thisNode 		 = self.thisMObject()
	inParamsPlug 	 = om.MPlug ( thisNode, ArrayAttrSample.inParams )
	outTranslatePlug = om.MPlug ( thisNode, ArrayAttrSample.outTranslate )
	inParElemNumber   = inParamsPlug.numConnectedElements()
	outTranElemNumber = outTranslatePlug.numConnectedElements()

	if inParElemNumber < outTranElemNumber:
		for i in range( inParElemNumber, -1 ): # count in reverse loop
			if i not in range(outTranElemNumber):
				outTP = outTranslatePlug.elementByLogicalIndex(i).setDouble(0)
				mdgm = om.MDGModifier()
				mdgm.removeMultiInstance(outTP, 1 ) #Disconnect and remove attr on node