I'm using the ControllerOtherEvent to detect changes related to node's transformation matrices. The steps I follow are:
The problem is that, applying changes to the node's matrix in step (3) will derive on the ControllerOtherEvent being called again and again, since the node's controller is modified of course. In the viewport, you'll see my node moving until it reaches the max/min of allowed coordinates.
Is there an elegant way to solve this? How can I manage to set the new node matrix without this event being called forever?
Thanks!
Hi @istan , thanks for replyign.
What I'm trying to do is to grab the matrix of a node that was just transformed, and the apply to it some additional operations that will clamp the node to a surface. Since those operations will modify the point position, I need to find a way to redraw the node with that resultant matrix (the clamped one).
The reason I'm using ControllerOtherEvent is because it will detect the node's transform, so I thought it was a good place to perform the operation. However, I don't know how I should assign that new matrix to the node so the node is clamped to the surface after the calculations.
void MyNodeEventCallback::ControllerOtherEvent(NodeKeyTab &nodes) { INode *node; int nodeCount = nodes.Count(); Matrix3 inMat, outMat; if (nodeCount<1) return; for (int i=0; i<nodecount; ++i)="" {="" node="NodeEventNamespace::GetNodeByKey(nodes[i])" inmat="node-">GetNodeTM(time);
if (IsPointHelperType(node)) {
MyPointHelper *ptH = (MyPointHelper*) node->GetObjectRef();
// apply some additional operations to the matrix of transformed node
outMat = ptH->ClampToSurface(inMat);
// here is the problem, applying the the resultant matrix (outMat) to the node
// derives in this ControllerEvent being raised again and again
inMat = node->SetNodeTM(time); } }
GetCOREInterface()->ForceCompleteRedraw(); }</nodecount;></nodecount;>
Thanks in advance 🙂
You set 'clamped' transformation matrix inside event callback which causes this event firing again and again...
You have two choices:
1. Disable this callback at the moment of your 'transform' modification, and enable it back after the modification.
2. Flag the currently processing node with a special custom flag (using the Animatable flags - Set/Clear/Test AFlagEx), and process nodes based on their current status (means do process or skip).
I would do both.
actually... I would write my own position controller which will do this 'clamping', and apply it to a specified nodes. It will not need any catching of transform events (which are anyway to late in case what you do).
I'm just curious: How would you catch an interactive TM change (i.e. user moves a node per mouse) in such a controller ?
1. Disable this callback at the moment of your 'transform' modification, and enable it back after the modification.
I tried that first solution you gave me with the following:
DetectRaisedPointHelperNodeEvents(FALSE); node->SetNodeTM(time, outMat); DetectRaisedPointHelperNodeEvents(TRUE);
Where DetectRaisedPointHelperNodeEvents, will register and unregister the INodeEventCallback. And it works sometimes but the transform is a lot flickery. I debugged it and the node transform seems to change every time, even when I'm not moving it.
@istan wrote:I'm just curious: How would you catch an interactive TM change (i.e. user moves a node per mouse) in such a controller ?
it depends on what kind of control i will do. i would probably do a Limit control extension. so i will not care about interactive 'change'. the main position control will do it.
your question also explains why the 'transform change event' solution can't work correct. we will always see 'flicker' because the event fires after transform changed and transform controls are validated (and most likely the scene redrawn). that's why i am not sure this solution will work with built-in rendering.
another solution might be a special 'constraint' control (which also doesn't need 'interactive change' implementation). this 'constrain' control might be added as sub-control to a Position List.
if we want to change the whole node transform (not only its position), the task becomes more complicated. but the translation is the last transformation operation, and we still can do 'orientation' constraint on position control level (like a attach control does do it, for example).
it's easy to experiment with this idea playing with MXS scripted controls before going to API implementation.
Hehe... Therefore I wrote: Think about using a RedrawCallback. IMHO this is the most stable and most RT responsive version since Max 9. It handles of course the whole TM and not only the translation.
Let us end this discussion here.
My stuff is working, I just thought you probably found a better approach.
Many Thanks.
Thanks guys for contributing to solving my problem. Enabling/disabling the node event handling when setting the new position works. The 'flickery' stuff is because the node is redrawn before AND after setting the new position. Anyway, I'll leave it that way and in the mean time I'll explore your other options.
@istanif it's possible, could you pls elaborate more? I'm curious about your idea but I couldn't follow it 😞
Thanks again!
Can't find what you're looking for? Ask the community or share your knowledge.