[Closed] node storage and dependency loops
Hey, I’m trying to store some objects’ names within a custom attribute that can be called upon to reference their rotation whenever a button in the CA is clicked (IK/FK snap basically). I’ve used the method of storing them as nodes within the CAs and it’s worked a treat until now. I can’t get it to store an object I want as it gives me a dependency loop error.
How can I get around this? Previously I’ve stored an object linked to the one I’ve wanted and then called upon the parent of the stored object to get back to the one I want. I know that max 8 uses a new node storage method that doesn’t give dependency loops, but how can I access it in a script?
:¬/
hi brad,
just add the node as a variable in a script controller in max 8 (loose referenceing)
you can then refer to the node in the script (can use for expression controllers also
is that what you are looking for?
mark
Hey Mark,
I thought of that but I don’t know how to extract the node/object’s name from the script controller.
:¬/
do you mean by script brad ?
are you assgning the controllers through maxscript or just mannually
you can get all the properties for script controllers by
showinterfaces Float_Script()
if you are doing it mannually you dont need to get the objects name you just store as a variable and use the assign node button to point to the node you want to reference –
then you just use the variable instaed of the node.
am i helping here at all :D?
mark
Yeah, I think it’s helping.
I would assign the node manually within a script controller and then use a script embedded within another object’s custom attribute to extract the node from the original object’s script controller.
The question is, what do I write in the CA to get the name of the object stored in another object’s script controller?
:¬/
Hi Chinwagon,
If I understand you question correctly… you can add node references to a script by doing the following (I will use as example a postion controller, and I am assuming that the position controller is a position_script or some sort of script controller):
$object_name.position.controller.addNode “TheNodesRefName” $object_to_add
later on, if you know with what name you created the reference, you can recall the object with the following:
$object_name.position.controller.getNode “TheNodesRefName”
if not, you can access the $object_name.position.controller.NumVariables() to get the number of variables, 4 is the default with which the script is constructed… “T” is [1], “S” is [2], “F” is [3], “NT” is [4] and [5] and above are your created ones. You can find out which name each index has with $object_name.position.controller.getName 5 (or any other number) and it will reveal the parameter you need to use in the getNode method.
You can even query for the type of variable with $object_name.position.controller.getType “theNodesRefName”
and it will return #node if its a node, so you can write a recurrent
theObjectsInScript = #()
for i = 1 to [i][b]$object_name.position.controller.NumVariables()[/b][/i] do
(
objectName = [b][i]$object_name.position.controller.getName i[/i][/b]
if ([i][b]$object_name.position.controller.getType objectName == #node) [/b][/i]then
( append [b][i]theObjectsInScript[/i][/b] ([i][b]$object_name.position.controller.getNode objectName)[/b][/i] )
)
This will create an array of all the nodes referenced in a script in the theObjectsInScript variable (as implemented by Max8 new script controllers). Of course the script controller doesnt have to be assigned to POSITION controller, it could be in a custom_attribute, or in the Visibility track, or anywhere really, the method will work. The script to recollect the nodes can also be anywhere: in a custom_attribute, in the on pressed do event of a button in a floating window, or rollout of a scripted plug-in… etc.
I hope I have understood your question correctly,
Rafael Poilt Jr.
Quito, Ecuador.
Thanks for the help guys, I think I’ve got it sorted. Luckily for me, at work I sit next to a guy named Grant Adam – arguably one of the best maxscripters out there. I asked him about it, he went down the same route Harvey suggested by using showinterfaces and in a couple of seconds came up with a similar answer to you said Raphael.
So I’ll basically create a point with a position script controller, assign the object I need as a node, get the index number (which is 5 if you only assign one node after the four that are already stored by default) and on the controlling object, store the object with the position script as a node in a CA and in the CA button type something that retrieves the name of the node stored within the node stored in the CA.
Phew!
I’ll try it tonight and see how it works.
Thanks again.
:¬)
Your working with Grant, what are you doing asking us?
I didnt’ see it posted here as an answer so you should look into Weak Referencing. This will help resolve the issues you are having with dependancy loops as well it will speed up the rig. storing lots of nodes in #node params caused slow downs as the referencing system was always checking them for no reason. The new Weak Referencing uses a node monitoring system that is like a call back.
I used the storage of the node within a script controller and referred to it in a CA like I mentioned above and it worked very nicely. So well, that I’m thinking of updating the other stored nodes to this new method. Is this what weak referencing is?
How does weak referencing work? I remember reading in a siggraph pdf that it stored only the node and nothing else so you could call on only the bits of the node you needed …or something like that.
I should ask Grant but as you could imagine, he’s always very busy.
:¬)
taken from the reference:
[left][color=red][/color]
[/left]
[left][color=red]NEW in [/color][color=red]3ds Max[/color][color=red] [/color][color=red]8[/color][color=red]:[/color]
[/left]
[left]Two new classes have been implemented: NodeTransformMonitor and RefTargMonitorRefMaker classes. NodeTransformMonitor is derived from ReferenceTarget, and holds a pointer to a RefTargMonitorRefMaker, which derives from ReferenceMaker.
[/left]
[left]RefTargMonitorRefMaker holds a reference to the node, and passes notification messages to the NodeTransformMonitor through a callback method. The NodeTransformMonitor just looks for REFMSG_CHANGE/PART_TM messages and passes those on to its dependents, unless a message is already being passed on. This prevents potential recursion. Since the NodeTransformMonitor doesn’t hold the node as a reference, we don’t have a circular reference hierachy. If object A has a NodeTransformMonitor that points at Node B, and object A is saved, Node B is also saved. Likewise on merge/xref object, loading object A will cause Node B to be loaded. Also, using NodeTransformMonitor the base object of a node can point at its owning node to get its TM changed messages.
[/left]
[left]Expression controller variables that point at nodes now use the nodeTransformMonitor class to hold the reference to the node. This will speed up scenes where expression controllers with node variables are used since only REFMSG_CHANGE/PART_TM messages are being sent to and invalidating the expression controller and its dependents. Previously, all messages from the node, not just REFMSG_CHANGE/PART_TM, would invalidate the expression controller and its dependents.
[/left]
mark