When object deleted, delete children. Huh?


#103

On my computer, the code from http://forums.cgsociety.org/showpost.php?p=7678675&postcount=88 does in fact crash after a redo of an object deletion.

And as for your assertion that

we NEED AN EVENT THAT SAYS THAT ALL NODES OF CURRENT DELETING SESSION WERE DELETED

I agree entirely, but am at a loss as to what that event would be. If you know, maybe you can share?

I have an almost-completed version of a project I have been at for quite a long time. I’m redoing parts of the script to make it cleaner and faster, and get rid of irritating bugs. That doesn’t mean I don’t want to get the thing finished as soon as possible. Most of everything works. This is a tiny part of the project, and is holding me back from getting it completed. Giving me hints rather than solutions, even if you’re trying to be helpful by doing so, isn’t what I need right now…


#104

i’m kinda in an opposite situation. all my rigs are working very well, but with your helpful idea i found that they could work better. i don’t want just simply share the final solution. as you see not many people are really interested. i can send my solution privately to you but i would prefer to see a discussion on this forum.


#105

If you could, that would be fantastic, thank you!


#106
callbacks.removescripts id:#delete_same_class
 try
 (
 	PostDelete_NodeEventCallback.enabled = off
 	PostDelete_NodeEventCallback = undefined
 )
 catch()
 
 global NodesForDeletion = #()
 fn preDeleteWholeClass = if not theHold.Redoing() do
 (
 	node = callbacks.notificationParam()
 	if isvalidnode node do
 	(
 		join NodesForDeletion (for n in (getclassinstances (classof node) astrackviewpick:on) where isvalidnode n.client and n != n.client collect n.client)
 	)
 )
 callbacks.addscript #nodePreDelete "preDeleteWholeClass()" id:#delete_same_class
 
 fn PostDelete_Callback event handles = 
 (
 	nodes = for node in NodesForDeletion where isvalidnode node collect node
 	NodesForDeletion = #()
 	if nodes.count > 0 do 
 	(
 		undo "Post Delete" on delete nodes
 		redrawviews()
 	)
 )
 PostDelete_NodeEventCallback = NodeEventCallback deleted:PostDelete_Callback
 PostDelete_NodeEventCallback.enabled = on
 
 delete objects
 with redraw off
 (
 	for k=0 to 4 do box pos:[k*30,0,0] width:20 length:20 height:20
 	for k=0 to 4 do cylinder pos:[k*30,40,0] radius:10
 	for k=0 to 4 do sphere pos:[k*30,80,0] radius:10
 )

how to make only one UNDO record try to find on your own


#107

… also all above can be done using only one global variable (structure)


#108

I’m feeling pretty stupid about now. Not getting it at all :confused:


#109

(whoops, double posted)


#110

I had something that worked on the initial undo/redo, but not on subsequent runs, and apparently forgot to save it before the program crashed again. I thought I remembered what I did, but I guess not


#111

Still don’t have the single undo working, but I got it so that the “redo” does the same thing as the initial deletion. No idea if I am on the right track here or not…

callbacks.removescripts id:#delete_same_class
try
(
	PostDelete_NodeEventCallback.enabled = off
	PostDelete_NodeEventCallback = undefined
)
catch()

global NodesForDeletion = #() 

fn PostDelete_Callback event handles = 
(
	nodes = for node in NodesForDeletion where isvalidnode node collect node
	NodesForDeletion = #()

	if nodes.count > 0 do
	(
		undo "Post Delete" on delete nodes
		redrawViews()
	)
	PostDelete_NodeEventCallback.enabled = off
)
PostDelete_NodeEventCallback = NodeEventCallback deleted:PostDelete_Callback

fn preDeleteWholeClass =
(
	if not theHold.Redoing() do
	(
		node = callbacks.notificationParam()
		if isvalidnode node do
		(
			join NodesForDeletion (for n in (getclassinstances (classof node) astrackviewpick:on) where isvalidnode n.client and n != n.client collect n.client)
		)
	)
	PostDelete_NodeEventCallback.enabled = on
)
callbacks.addscript #nodePreDelete "preDeleteWholeClass()" id:#delete_same_class

delete objects
with redraw off
(
	for k=0 to 4 do box pos:[k*30,0,0] width:20 length:20 height:20
	for k=0 to 4 do cylinder pos:[k*30,40,0] radius:10
	for k=0 to 4 do sphere pos:[k*30,80,0] radius:10
)

#112

Perhaps this node “Delete Protection” Maxscript Extension plugin created by Kees Rijnen can help you achieve your goals (protecting your rig components from deletion-- not sure… never tried it)… it is available for 3ds Max versions 8 thru 2014.

[http://www.maxplugins.de/max2014.php?search=Delete Protection&sort=Author](http://www.maxplugins.de/max2014.php?search=Delete Protection&sort=Author)


#113

Aw man, you got my hopes up. I was hoping I could see how they went about achieving that effect, but they’re dll files ><


#114

The source code for Max9 and Max2009 versions is included with the Max 8-2009 plugin. Here:

[http://www.maxplugins.de/max8.php?search=delete protection&sort=Author](http://www.maxplugins.de/max8.php?search=delete protection&sort=Author)


#115

Hm. Unfortunately, even if there were something in there that could help me, I wouldn’t know how to use it. But thanks anyway!


#116

So the Delete protection plugin does not work to protect your rig components from deletion? You tried it?


#117

Protecting rig components from deletion is not what I am trying to do.


#118
  Ok... so if I understand correctly, you want to delete a set of nodes, if the user deletes one of the nodes in this set?
  
  Then I think the Character Assembly can work for you... (you will only use this as an assembly to collect your nodes-- you can hide it, set icon size to 1, make it unselectable, whatever...)

[ol]
[li]Select all of the nodes in your scene you want to be under this “Delete All” operation, and then create a character assembly… this will add all these nodes as members to the Character Assembly.[/li][li]Create your script (callback or whatever…) to check if a deleted node is a member of this assembly. Maxscript command is: <node>.assemblyMember (will return true or false).[/li][li]If #2 is true, use Maxscript command: <character_assembly>.assemblyHeadOpen = false. This will LOCK the character assembly.[/li][li]Finally delete the character assembly using: delete <character_assembly>[/li][li]Everything is now deleted! Undo (max undo) and redo (max redo) to your heart’s content.[/li][/ol]
:hmm:
Not an elegant solution, but it should work… if this is all you’re trying to do (as I understand it).


#119

I’ll take a look at it, thanks!


#120

Still haven’t looked at the character assembly stuff, but following up on this post:
http://forums.cgsociety.org/showpost.php?p=7680108&postcount=111


callbacks.removeScripts id:#undo
fn undo_Callback =
(
	if (callbacks.notificationParam()) == "Post Delete" do with undo off max undo
)
callbacks.addScript #sceneUndo "undo_Callback()" id:#undo

Performs the extra undo when necessary. Unfortunately, using this also breaks the redo solution I had in place, and trying to use a similar solution for redo messes with object selections during scene redo in other situations.


#121

A little more work and I’ve got this:

try
(
	PostDelete_NodeEventCallback.enabled = off
	PostDelete_NodeEventCallback = undefined
)
catch()

callbacks.removescripts id:#delete_same_class
callbacks.removeScripts id:#undo
callbacks.removeScripts id:#redo

global NodesForDeletion = #()
global objCount = objects.count


fn PostDelete_Callback event handles = 
(
	nodes = for node in NodesForDeletion where isvalidnode node collect node
	NodesForDeletion = #()
	if nodes.count > 0 do	undo "Post Delete" on delete nodes
	redrawViews()
)

fn preDeleteWholeClass =
(
	if not PostDelete_NodeEventCallback.enabled do
		NodesForDeletion = #()

	if not theHold.Redoing() do
	(
		node = callbacks.notificationParam()
		if isvalidnode node do
		(
			join NodesForDeletion (for n in (getclassinstances (classof node) astrackviewpick:on) where isvalidnode n.client and n != n.client collect n.client)
		)
	)
)

fn undo_Callback =
(
	if (callbacks.notificationParam()) == "Post Delete" do with undo off (max undo)
)

fn redo_Callback =
(
	if objects.count != objCount and (callbacks.notificationParam()) == "Create Selection Set" do
	(
		max redo
		objCount = objects.count
	)
)


PostDelete_NodeEventCallback = NodeEventCallback deleted:(with undo on (PostDelete_Callback))
callbacks.addscript #nodePreDelete "preDeleteWholeClass()" id:#delete_same_class
callbacks.addScript #sceneUndo "undo_Callback()" id:#undo
callbacks.addScript #sceneRedo "redo_Callback()" id:#redo


delete objects
with redraw off
(
	for k=0 to 4 do box pos:[k*30,0,0] width:20 length:20 height:20
	for k=0 to 4 do cylinder pos:[k*30,40,0] radius:10
	for k=0 to 4 do sphere pos:[k*30,80,0] radius:10
)

There is one behavior I’d like to get rid of: If I copy one of the objects, or create a new object that is the same class, and then perform an undo on that create/copy action, it deletes all objects of that class.

This is not a result of any of the changes I have made, as it appears to take place even using the code from http://forums.cgsociety.org/showpost.php?p=7679251&postcount=106


#122

This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.