Notifications
Clear all

[Closed] Strangness in my WHEN construct

Hello, I’m wondering why the code below does not work. When at the end I do “print p” I get 2 values, both 0 and 1, when it should alternate between the two each time the script is evaluated. The function works as is, but inserted here in a “when” expression it seems to evaluate both the “if” and the “else” or something like that. Does anybody know why?

 global p 
global moov
global poov
 
fn klasse k=
(
if p == 0 or p == undefined then
(
moov = polyop.getEdgeSelection $.baseobject
p = 1
)
else if p == 1 do
(
poov = polyop.getEdgeSelection $.baseobject
p = 0
)
)
 
when select $ changes id:#Tup obj do
(
klasse obj
print p
)
 
[size=2][color=white]--deleteAllChangeHandlers id:#Tup
[/color][/size]

[size=1][size=2][color=white]The reason I want to do this is I want to get what was selected before the current selection, so if anybody has got a better way of getting that I would appreciate it too.[/size]
[size=2][/size]
[size=2]CML
[/size][/color][/size]

8 Replies

Hmm, very strange indeed.

But it may also be the way how “when” handles changes. Try selecting a few edges, then click outside of the object to deselect all edges. When all edges are deselected you’ll get a 1 and when any number of edges are selected you’ll get a 0.

Maybe it won’t handle changes in sub-object level.

Also note that you can lose the “if p == 1 do” in this case, as it can only be 0 or 1.

If I can think of another way to ‘save’ the previous selection I’ll let you know.

Good luck!

  • Rens

The when is a callback, so it is called each time Max gets a notification of a change in the selection. If you place a print “Called!” inside the function, you will notice that the callback is invoked twice internally (I assume once releasing the original selection, once setting the new one or something like that), so the script callback is also always called twice.

A way to prevent this is to use the HandleAt optional keyword:

when select $ changes handleAt:#redrawViews id:#Tup obj do
 

This will call the function only once, when the viewport is actually redrawn to show the new selection.

Cheers,
Bobo

I guess it’s how the handler is designed to work… Try this:

· deselect all edges
· enable the change handler
· select one edge [the event gets fired only once]
· select another edge (without CTRL) [the event gets fired twice]

1st event: previous edge was deselected
2nd event: the other edge was selected

If you select one edge and then CTRL-click other edges a couple of times, you’ll see that it only fires the handler only once on those subsequent selections.

A workaround could be to add another global variable that keeps track of the number of selected edges… If NO edges are selected during the event, this means either: 1. user deselected all edges manually, or 2. user started a new selection). You should be able to use this information to skip an event.

Hope this makes any sense

  • Martijn

yep, the handleAt sounds like a more elegant solution

hey, thanks a lot for the help!

Bobo- That sounds like a good idea, but I can’t get it to work. Can you post a easy example of how it should be used together with the function? Do I need to call redrawviews() and is that when the change happens?..Also, is there a way to call undo during the running of a handlers function? That would save me a lot of trouble, heh.

What I have done now is use something like magicm wrote(thanks). I use
if ([size=2]$.selectededges.count != 0) …[/size]
[size=2]and it works to get the value to alternate becuase the first callback is always a deselection.[/size]
[size=2][/size]
[size=2]CML
[/size]

The line I posted fixed your example for me.
You don’t call redrawviews – when the user clicks to select or deselect, Max has to redraw the views itself to show the new selection, so your change handler will wait for that redraw to happen before it calls the function. This way, you get the FINAL result of the selection change without any intermediate calls.

Bobo- Alright thanks, I tried it some and I can see the difference.

The tool I was working on seems pretty ready now:) . It’s a “mode” you can enter where you can autoselect and deselect edgeloops in “LoopMode” and edgerings in “RingMode”. It will be part of the large collection of selection tools I’m working on. You can still edit the object as usual, but in edgesubobject you can hold shift to select loop/ring or alt to deselect loop/ring. (Works in face and vertex too but a bit different) Right now the select part only works when the user is in “select mode”, not in transform mode, because in movemode as an example you can’t hold shift and still select edges so…too bad there are so few keyboard presses you can get the state of. Has anybody got an idea how to set it up to get a nice workflow? Not sure if one can use the mouse states in some way.

CML

Yea, the loop mode is cool, it should be possible to use tools like this for alot of things.

One thing I really miss in max is that you can’t know if a keyboardbutton is pressed. In fact I tried to make an extention for this myself (since i already have an extention for the wacom pencils) but I could never get it to work.

it worked exactly like the keyboard.shiftpressed. You wrote. wise.keyboardpressed “a” and you would get the state of it.

I could also get more info from the mouse, for example the move history and button 4-5 too.

Hmmm, do you guys think it would be worth giving the extention another try later?

Is there something else I could include in the extention?
One thing I really miss is more info from the mouse. For example double clicks, middle clicks etc, 4th, 5th button. Problem is that last I looked you couldn’t do maxScript callbacks from the SDK. So I couldn’t do any double click callbacks. On the other hand if you have a 0.5sec timer that checks ever 0.5 sec if a double click is registred it could still be workable.

Ideas?
/Andreas