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. b=box pos:[40,0,0] |
| 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 def |
| 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 |



