Phone: 905 409-1589
Email: info@penproductions.ca
RSS LinkedIn Twitter Twitter
Weak Referencing
Weak Referencing:
Weak references have been added in Max 8 to help increase speed in character and other rigs when node references need to be stored. This affects tools like script controllers that now store variables as well as custom attributes and scripted plugins that can store references to objects in param block 2.

In previous versions of Max objects could be stored in param block 2 as the type #node. This allowed for references of scene nodes to be stored as name independent objects so that renaming a rig wouldn't break it. The problem with storing the node is the referencing system would need to calls to the stored nodes even if it wasn't necessary. Using the new system of Weak Referencing the node isn't stored but instead a nodeTransformMonitor is stored that holds a reference to refTargMonitorRefMaker using a callback method. Using this system means dependency loop errors are avoided and objects can hold reference to each other without errors.

Here is a break down of a script that stores nodes as nodeTransformMonitor and then displays the node names in a listbox. Note that you can even store the node that the custom attribute is one in the param2 #maxObjectTab.

Down load full script: weakReferences.zip

Create objects to work with:
--Empty array for storing spheres.

sph=#()
--Create three spheres with random positions. 

for i = 1 to 3 do 
(
	s=sphere radius:10 pos:(random [-100,0,0] [0,0,0])
	append sph s
)

--Create a box.                        
                        
Create a custom attribute definition:
--Custom attribute definition

def=attributes nodeStore
(

--Param2 with #maxObjectTab

	parameters nodesP rollout:nodesR
	(
		refNodes type:#maxObjectTab tabSize:0 tabSizeVariable:true
	)

--Rollout for the UI to control which nodes are stored. 

	rollout nodesR "Nodes"
	(
		local btW=135, btW2=65
		listBox nodesListLb "Nodes:"
		pickButton addObject "Add Object" width:btW2 across:2
		button deleteObject "Delete" width:btW2
		
		group "Tests:"
		(
			button printRefNodes "Print refNodes" width:btW
			button printRefNodesNode "Print Nodes" width:btW
		)

--Function to update the listBox when the UI is opened or a new node is added. 		
		fn updateList=
		(
			nNames=for n in refNodes collect n.node.name
			nodesListLb.items=nNames
		)

--Called when the Add Node picked button has selected an object. 		
		on addObject picked obj do
		(
--Creates a nodeTransformMonitor from using the selected node and appends refNodes with it. 
			append refNodes (nodeTransformMonitor node:obj forwardTransformChangeMsgs:false)
			updateList()
		)

--Called when delete is pressed.
		on deleteObject pressed do
		(
			num=nodesListLb.selection
			if num>0 then
			(
				deleteItem refNodes num
				updateList()
			)
		)
		
--Prints the contents of refNodes to the listener. 
		on printRefNodes pressed do
		(
			for n in refNodes do
			(
				print n
			)
		)

--Get the referenced nodes held in nodeTransformMonitor and prints then to the listener. 
		on printRefNodesNode pressed do
		(
			for n in refNodes do
			(
				print n.node
			)
		)
		
		on nodesR open do
		(
			updateList()
		)
	)
)                        
                        
Add an attribute holder modifier to the box and then add the attribute definition to the modifier:
--Creates an instance of an attribute holder modifier. 
ah=(EmptyModifier())
--Adds the modifier to the box that was created. 
addModifier b ah
--Adds the custom attribute definition to the attribute holder. 
custAttributes.add ah                        
                        
Adds the created spheres to the refNodes parameter:
--Loops through all the spheres and adds them to nodeTransformMonitor and then appends then
--to the refNodes parameter on the attribute holder. 
for s in sph do
(
	obj=nodeTransformMonitor node:s forwardTransformChangeMsgs:false
	append b.modifiers[1].refNodes obj
)

--Select the box.
select b