[Closed] Preventing node deletion
I’m trying to keep someone from accidentaly (or purposefully for that matter) deleting certain objects in the scene. I’ve trying setting up what I thought would be a pretty straight foward callback, but it doesn’t work. Anyone else ever done this?
Here's my quick test...
fn doTheUndo =
(
max undo
)
callbacks.removeScripts id:#undo_CBK
callbacks.addScript #selectedNodesPostDelete "doTheUndo()" id:#undo_CBK
it mentions about this in the help topic also, James,
This system will also catch events which happen as a result of undo/redo, while the older system sometimes would not.
Naturally i’m going to assume you just can’t freeze the objects because you need to manipulate them?
I’m wondering if you could detect the keypress and then block the actual deletion process based off the object in question, but i’m not sure if that’s possible.
UNfortunitly there is no real good way of stopping it with script. The delete is still called but I don’t know why your method is not working. Try a hold on pre delete and then fetch on post.
I’m going to be watching this since I’ve was trying to do the same thing on some rigs :P.
I posted one example at: http://forums.cgsociety.org/showthread.php?f=98&t=615858
This was using pre/post delete callbacks. I tried all kinds of ideas, including undoing but couldn’t find a good method. I thought about deleting the whole rig if one piece was deleted (like CS) but MAX doesn’t seem to like deleting objects with callbacks and keeps on crashing. I also tried out the hold and fetch method, and it worked perfectly fine. The only thing I didn’t like about it was if the animator was working in a big scene, and how much loading time it would take.
If you aren’t dealing with control objects, you can setup a callback which deselects any object that are a part of the rig. This worked really good, as you can draw a selection box around a bunch of objects, and you can’t even see any selecting/deselecting happening. And since it isn’t frozen, the animator can still link up objects to it.
Anyways there’s my thoughts. If you have any ideas I’ll be happy to try them out
I think Jason is bang on but I will add something i found in the MXS help the other day – It is an new object based callback method – the Node event System.
there are several callbacks of use here – including freezechanged and selectionchanged and all work at the node level, which in the case of jason’s example would mean you could instantly deselect control objects (or refreezethem after an unfreeze all comand)
Haven’t had the time to implement something yet but it’s next on my todo list!
Thanks for the replies. I can’t freeze the objects because they do need to be manipulated. So it sounds like the hold/fetch workaround might be the way to go, but like Jason mentions, it can be unwieldy on large scenes.
The main thing I’m wondering is when exactly the postDelete callback gets triggered. Becuase if it’s truly called right after a node is deleted, then the undo operation should work.
As far as the Node Event system, I’ll try a test with that today, but I need this script to work in Max 8 so it’s out of the question for this particular tool. And a quick note on removing NodeEventCalbacks… As far as I can tell, there is no callbacks.removeScripts equivalent to stop the callback if you ever need to, so what you need to do is initially store the callback as a variable (as in the example) and then when you want to remove it, redefine the variable as undefined, and then (and this is where I got stuck) call a garbage collect to finally remove the callback.
And lastly, Jason mentions deselecting objects through a callback. I’m also doing that and it does work really well. If someone selects an object I don’t want them to manipulate, it automatically transfers the selection to the root (control object) so that they can manipulate that instead. And here’s the sample code to make that work…
-- add custom attribute to non-selectable object with a loose reference to the control object stored in 'myRoot'
selectRootCA = attributes selectRoot
(
parameters main
(
myRoot type:#maxObject
)
)
-- this function deselects the non-selectable object, and then selects the control object
fn selectRoot =
(
for obj in selection do
(
if isProperty obj #myRoot and obj.myRoot != undefined and isValidNode obj.myRoot.node then
(
deselect obj
selectMore obj.myRoot.node
)
)
)
callbacks.removeScripts id:#selectRoot_CBK
callbacks.addScript #selectionSetChanged "selectRoot()" id:#selectRoot_CBK
Hi James,
I’ve never found a really stable, satisfying way to handle this through MXS.
However it would take me only a few minutes to give you the ability through the SDK.
(In the form of an MXS extension so you can still use it via MXS)
Just let me know if you want this.
Take care,
I think a plugin to filter delete events would be such a welcome addition to the toolset that most studios wouldn’t mind rolling it out.
People have been clamouring for this capability for ages.