Never ending node transform detection through ControllerOtherEvent (C++ SDK)

This widget could not be displayed.

Never ending node transform detection through ControllerOtherEvent (C++ SDK)

Anonymous
Not applicable

I'm using the  ControllerOtherEvent to detect changes related to node's transformation matrices. The steps I follow are:

  1. Get the matrix of the transformed node (INode::GetNodeTM)
  2. Perform some operations on that matrix to clamp it to a surface
  3. Use that resultant matrix to set the final matrix of the given node (INode::SetNodeTM)

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!

0 Likes
Reply
1,425 Views
15 Replies
Replies (15)

istan
Advisor
Advisor

What do you actually want to do? Can't you make it more simple by using the RedrawCallback instead?

0 Likes

Anonymous
Not applicable

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 🙂

0 Likes

denisT.MaxDoctor
Advisor
Advisor

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.

0 Likes

denisT.MaxDoctor
Advisor
Advisor

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).  

0 Likes

istan
Advisor
Advisor

I'm just curious: How would you catch an interactive TM change (i.e. user moves a node per mouse) in such a controller ?

0 Likes

Anonymous
Not applicable

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.

0 Likes

denisT.MaxDoctor
Advisor
Advisor

@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.

 

  

 

0 Likes

denisT.MaxDoctor
Advisor
Advisor

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.  

0 Likes

istan
Advisor
Advisor

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.

0 Likes

denisT.MaxDoctor
Advisor
Advisor

RedrawCallback can't be used during rendering. And it's also too late  

istan
Advisor
Advisor

Is for sure, but I was talking about interactive mouse actions.

0 Likes

denisT.MaxDoctor
Advisor
Advisor

@istan wrote:

Is for sure, but I was talking about interactive mouse actions.


as I could understand there is a problem with 'flickering'. Redraw callback can't solve this problem. It sent after everything was already happened - transform changed and view drawn.

 

0 Likes

istan
Advisor
Advisor

Let us end this discussion here.

My stuff is working, I just thought you probably found a better approach.

Many Thanks.

0 Likes

Anonymous
Not applicable

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!

0 Likes

denisT.MaxDoctor
Advisor
Advisor

@istan wrote:

My stuff is working, I just thought you probably found a better approach.

 


the better and right approach (IMHO) to write your own controller. It's easy now to experiment, because mxs scripted controllers are available in the recent versions.

0 Likes