All right, I’m up to speed up to the point of Gazybara’s version, but I’m not going to be able to figure out what I’m supposed to use in place of the when construct. General event callbacks? Node even system? The question here is not about “is there a way to do it” but “what is the RIGHT way to do it.” I.e. what solution is the fastest, most stable, and uses the least system resources.
The script I have been working on was previously using for this purpose used global variables, node event callbacks, and was overall particularly large and cumbersome. I’m taking it back to formula because of some unpredictable results when undoing and redoing. I do appreciate your help in this, but it would be great if instead of dropping hints you could just show me a working solution.
This works until one of the points gets deleted. I have no idea if I’m even on the right track.
global ContainerAttrib = attributes ContainerAttrib attribID:#(0x1f05aab6, 0x7a59c3a6)
(
local handler
fn getNode = (refs.dependentnodes (custattributes.getowner this) firstonly:on)
fn constructNode node: = if not (theHold.Redoing() or theHold.Holding()) do
(
if node == unsupplied do node = getNode()
if isvalidnode node and not isdeleted node and handler == undefined do
(
handler = when node deleted node do if (attr = node.baseobject.custattributes[#ContainerAttrib]) != undefined do
(
if attr.handler != undefined do deleteChangeHandler attr.handler
attr.handler = undefined
delete (for n in attr.container where isvalidnode n.node and not isdeleted n.node collect n.node)
attr.container = #()
)
)
)
parameters params
(
container type:#maxObjectTab tabsizevariable:on
on container set val do
(
constructNode()
)
)
fn constructTransform =
(
when parameters container change handleAt:#redrawViews do
(
for n in container do
(
when parameters n.node change handleAt:#redrawViews obj do
(
format "% Transform changed
" obj.name
)
)
)
)
on load do constructNode()
on create do
(
constructNode()
constructTransform()
)
on update do
(
constructNode()
constructTransform()
)
)
but thanks to your idea i’ve got the great hierarchically independent node binding interface. i’ve found the terrible bug in the max and fixed it using SDK.
the complete ‘container based’ idea is about 500 lines of my mxs code (plus some c++)…
what does give it to me?
deleting a link of finger deletes whole finger
deleting an arm IK effector deletes all IK related nodes and makes the arm only FK’ed
deleting any ‘key’ bone of a leg/arm/tail hierarchy deletes whole hierarchy
deleting the root deletes whole skeleton(rig)
… etc
i did a lot of work for ‘fool proofing’… but i really like an idea where any Biped node being deleted deletes whole Biped skeleton (rig).
previously i’ve showed a warnings kinda – Hey! you’ve deleted a ‘key’ node! are you stupid?
now i’m deleting whole skeleton with no giving any warning message. i give a chance to an user to feel himself stupid.
That’s very much along the lines of what I was going for. Glad you got it working properly, because if it got to the point of requiring C++ I clearly never would have.
I ended up going with my “storing the array of related nodes on a separate control object” approach. I also eventually figured out that if
a) deleting any of the stored nodes will delete the master, and
b) deleting the master will delete all the stored nodes,
then deleting /any/ of the stored nodes will end up indirectly deleting /all/ of them, without having to loop through them in the parameters!
And with only about 50 lines of code, so I feel pretty good about that.
Now, the REST of what I’m going to do with this…
i’ve found the BIG bug in the max node deleting mechanism… any node is becoming deleted gets a status of a ‘being deleted node’. but if you ask the system about its state, the system answered that the node is not deleted and it can be deleted. this is wrong! the deleting of a node that is in a process of deleting causes the max crash on REDO
Luckily my method does not cause any crashing on undo or redo, but that does sound like a significant problem that should be addressed to Autodesk…
Okay, very weird. Apparently it is not crashing on undo or redo, but it DOES crash if I load another file.
I’ve tried setting it up as a function, a when construct, etc. but it has the same problem every time. The simplest version is simply putting the following into my parameters:
on nodes tabChanged change do
(
if change == #refDeleted do
(
owner = (refs.dependentNodes (custAttributes.getOwner this))[1]
if (isValidNode owner) and (not isDeleted owner) do delete owner
)
)
As I said, it’s not crashing on undo or redo, but only when I try to open a different file, or create a new one. Any ideas on how to get around this?
On a possibly related note, something I tried had the deleted/to-be-deleted objects showing up as $<unknown>:nodename @ [x,y,z]. Unfortunately, the program crashed and I don’t remember what I did to get to that point.