When object deleted, delete children. Huh?


#21

it doesn’t crash for me… tell me all steps those make max crash.

That’s exactly what I’m doing.

 Copy code, open Max, new file, paste code.
 Ctrl-E. It works.
 Ctrl-E a second time. It works again.
 Ctrl-E 19 more times, it works.
 Run it a 22nd time, though, and "An error has occurred and the application will now close..."
By the way, this happens on both my desktop and laptop (both running Max 2012 64-bit). 22 times exactly to crash the program.

#22

But are you doing anything else between the “CTRL E” operations? That’s what he is asking…


#23

No I’m not. I can do other things between the executions or not, but it crashes either way after the same number of times.


#24

Okay, I think I have an idea what’s going on. I had initially thought that each the script was run, it would overwrite the previous definitions. But apparently that’s not the case. If you append

(custAttributes.getSceneDefs()).count

to the end of the script, you will see that every time it is run the number goes up.

Possibly at least a clue as to the cause of the crashes?


#25

as i told my previous code don’t crash… but here is another version

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 and not isdeleted n collect n)
				attr.container = #()
			)
		)
	)
	parameters params 
	(
		container type:#nodeTab tabsizevariable:on
		on container set val do constructNode()
	)

	on update do constructNode()
	on load do constructNode()
)
(
	num = [50,10,10]
	for i=1 to num[1] do 
	(
		gc()
		delete objects
		for k=1 to num[2] do
		(
			y = (k-1)*20
			global b = dummy name:(uniquename "master") pos:[0,y,0]
			custattributes.add b ContainerAttrib
			b.ContainerAttrib.constructNode()
			b.container = for k = 1 to num[3] collect (point pos:[k*20,y,0] wirecolor:orange)
		)
	)
	print "DONE!"
	ok
)

#26

I’m having no problems with this one!

I’d always assumed that “Max Doctor” was just a figure of speech, but I’m beginning to wonder if you don’t, in fact, have a PhD in Maxscript. :smiley:

Thank you so much for your efforts on this. I will study your code hard and become a better scripter.


#27

add this line to the attribute’s code end…

on create do when parameters container change handleAt:#redrawViews do format "something was changed...
"

you will be very surprised trying to move any contained object


#28

Why would I be surprised? That did exactly what I expected it to :stuck_out_tongue:

Anyway, I think I have a decent understanding of how everything you have in there works except for the theHold stuff (which as far as I’m concerned is made of quantum physics and voodoo. Not even gonna try to figure that out at this time).

I do have some question though: the only place the handler variable seems to be used is in “deleteChangeHandler attr.handler”. Is that even necessary, since the node is being deleted anyway? I tried running the script without it and there doesn’t seem to be any change (threw in a few debugging lines to check all the values) if that is removed.

If it IS necessary, what does it actually do? And if it’s not, then are the handler variable and the code that operates on it even necessary, or can the when construct definition just be placed directly inside the constructNode function?


#29

you will… when for example… you will try to store the node’s children the way is shown above.


#30

I’m either incredibly dense or just don’t know what I’m looking for (possibly both). What am I supposed to be surprised by?


#31

you probably just don’t really understand how the when parameters container change works.
in our case the container property is not an array!
it’s a parameter block property and this property receives some specific messages. but it receives them only if nodes in this property transfer them to client.
try to put children to the container… delete master and try to undo…


#32

…in our case the container property is not an array! …

…try to put children to the container…

Hm. I think maybe I’m not following the terminology. The Maxscript documentation says that the nodeTab parameter is an array of the node base type. And as far as working with them, they seem to behave just like an array to me (meaning I can use append, deleteItem, etc…)

And when you say “children” do you mean the items contained in the nodeTab (not an) array?

I’m still not getting anything unexpected when I do what you’re saying. :shrug:

Also… I had added something to my original setup so that if ANY of the nodes in the nodeTab were deleted, it would delete all of them as well as the master node. I could probably find a way to adapt that to the solution you’ve provided (currently what I have can make it delete everything but the master), but maybe you can show me the “right” way to do it?


#33

use my sample… link any point to its master. delete master. undo…

actually there is a sample

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 and not isdeleted n collect n)
				attr.container = #()
			)
		)
	)
	parameters params 
	(
		container type:#nodeTab tabsizevariable:on
		on container set val do constructNode()
	)

	on update do constructNode()
	on load do constructNode()
)
(
	num = [1,1,10]
	for i=1 to num[1] do 
	(
		gc()
		delete objects
		for k=1 to num[2] do
		(
			y = (k-1)*20
			global b = dummy name:(uniquename "master") pos:[0,y,0]
			custattributes.add b ContainerAttrib
			b.ContainerAttrib.constructNode()
			in b (b.container = for k = 1 to num[3] collect (point pos:[k*20,y,0] wirecolor:orange))
		)
	)
	print "DONE!"
	ok
)

try to delete master and undo


#34

use my sample… link any point to its master.

It won’t let me get past that part. Says it would create a dependency loop.


#35

now you start to understand the problem… my last sample does do link… you can see it.

and about a container property … try

classof $.container

it just looks like an array but has sometimes very different behavior.


#36

Good to know, I’ll keep that in mind. And I see what you mean about linking and undoing. Interestingly, I noticed 2 other things:

  1. It throws the dependency alert for all nodes in the arrayParameter even if only one has been parented to the master
  2. Once the undo is completed, it will no longer let you parent any of the nodes to the master.

Anyway… if I want deleting any of the nodes to result in deleting all of them (and the master), how do I approach that?

EDIT:
Wait a second, no. It throws the dependency alert even if nothing has been linked to the master node. Wait, what…?


#37

so because of possible ‘dependency loop’ issue in general case we cannot use #nodeTab. we have to use the Weak Referencing (for the begging read about it in the mxs help)


#38

Okay, well, I tried linking the various nodes from the tabs to each other instead of to the master, and there were no problems with undo. So can we just create a something to hold the nodeTab array without actually having anything parented to it, and tell it if the parent node is deleted to delete the rest?

Or, do you already have something in mind besides using nodeTab?


#39

sure… i knew that #nodeTab can’t work. read about weak references


#40

What about my other suggestion? Not worth looking into? x)