PDA

View Full Version : Preventing node deletion


JHaywood
04-30-2008, 12:53 AM
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

erilaz
04-30-2008, 01:21 AM
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.

PEN
04-30-2008, 01:40 AM
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.

labbejason
04-30-2008, 02:40 AM
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 :)

LoneRobot
04-30-2008, 08:42 AM
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!

LoneRobot
04-30-2008, 08:44 AM
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?


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.

JHaywood
04-30-2008, 04:48 PM
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

kees
04-30-2008, 04:59 PM
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,

JHaywood
04-30-2008, 06:04 PM
Thanks Kees. That would be great.

thatoneguy
04-30-2008, 06:41 PM
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.

PEN
04-30-2008, 07:19 PM
Yes please Kees. This would be great. Can you compile for Max 8?

kees
04-30-2008, 08:50 PM
Here you go:

www.lumonix.net/DeleteProtection_MXS.zip (http://www.lumonix.net/DeleteProtection_MXS.zip)


The zip contains a text file that explains how to use it in Maxscript, it should be pretty straight forward.

The zip contains compiled plugins for 3dsmax 8, 9, 2008 and 2009.

The source code is also in the zip, in case you want to compile it in the future.


Take care,

labbejason
04-30-2008, 11:51 PM
Thanks Kees! Hope things are going well for you.

PEN
05-01-2008, 12:44 AM
You da man, Thanks Kees.

LoneRobot
05-01-2008, 09:16 AM
brilliant - this is a helpful thread. Kees - in your help file you mention about going through the selected objects backwards when deleting, Is there a reason for doing this via script?

IkerCLoN
05-01-2008, 09:35 AM
Great, Kees! Thanks for sharing :-)

kees
05-01-2008, 02:09 PM
Kees - in your help file you mention about going through the selected objects backwards when deleting, Is there a reason for doing this via script?

It depends on how you walk the array.

If you do:

for i=1 to selection.count do
(
delete selection[i]
)

then your 'selection.count' keeps on shrinking and you'll eventually get an error.
By deleting backwards you'll avoid the problem.

If you loop like so:

for each in selection do
(

)

then its fine too.

It was just a small reminder I put in there too avoid getting emails saying 'it doesn't work' :P

Take care,

JHaywood
05-02-2008, 05:20 PM
Thanks Kees. It works great. The only thing I would mention for others using this is that it has the same issue I found with the callbacks, in that if you try to undo the delete Max will crash (you have to hit undo a few times before it will crash). So I add a query box telling the user that this an undoable operation and make sure they really want to do it, and then I add a 'clearUndoBuffer()' command at the end to make sure they really can't undo it and crash the program.

kees
05-02-2008, 05:42 PM
James,

You delete the object through maxscript, then undo and then it crashes?

I'm not sure that the two are related in that case...
All the MXS extension does is prevent the delete message from going any further in max.

You may want to look in 'theHold' options in maxscript to better control the undo process.

I've not had a problem myself when deleting objects this way, though in my case the deleting happened in c++.
The process being the same though:

- Catch the delete button being pressed via the MXS extension
- open undo buffer
- delete objects (via MXS or SDK)
- close undo buffer.

If that doesn't work, I wouldn't mind seeing a repro case of it to see why.

JHaywood
05-02-2008, 06:03 PM
The repro case if very easy. Run the following code, delete the teapot using the Delete button, hold down Ctrl-Z until Max crashes. It happens in both 8, 2008 and 2009, that I've tested.

global deleteProtectFunc
function deleteProtectFunc = (delete selection)
setDeleteProtection true
t = teapot()
select t

kees
05-02-2008, 06:57 PM
Hi James,

The code you send does not crash for me.
But no matter, you are not using the undo buffer:

global deleteProtectFunc
function deleteProtectFunc = (undo "delete" on (delete selection))
setDeleteProtection true
t = teapot size:4
select t

JHaywood
05-02-2008, 07:58 PM
It must be something having to do with my toolset then. I uninstalled my tools and didn't get the crash like you said. But adding the undo buffer solves the problem even with the tools installed. So thanks for pointing that out.

kees
05-02-2008, 08:08 PM
No problem.
Glad it is working now :)

Take care,

LoneRobot
05-02-2008, 08:15 PM
then your 'selection.count' keeps on shrinking and you'll eventually get an error.
By deleting backwards you'll avoid the problem.


of course! thanks for clarifying that Kees. :thumbsup:

JHaywood
05-09-2008, 10:09 PM
Hey Kees, the maxScript extension works great, but I was wondering if you have a "quiet" option for the get/setDeleteProtection command? Or a way to test whether it has been set so that I can only set it if it's not already, and vice versa. It's a small thing, but because of the way I have my callbacks set up, I get a bunch of the "Delete Protection Enabled/Disabled" messages in the listener.

CGTalk Moderation
05-09-2008, 10:09 PM
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.