SOLVED c4d.BaseTag.Remove() method negates all the changes I made from the object


You can see an illustration of the problem here:

Without the .Remove() method, the script works as expected (i.e. the sphere snaps to the circle).
When I add the .Remove Method. It no longer works. (i.e. the sphere no longer snaps to the circle)

You can check the working code here:

import c4d
from c4d import gui

def create_constraint(mo=False):

    obj_sel = doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_SELECTIONORDER)
    driven = obj_sel[-1]
    driver = obj_sel[0]

    tag = c4d.BaseTag(1019364)
    tag[c4d.ID_CA_CONSTRAINT_TAG_PSR] = True

    if mo == True:
        tag[c4d.ID_CA_CONSTRAINT_TAG_PSR_MAINTAIN] = False

    tag[10001] = driver


if __name__=='__main__':

Thank you for looking at my problem

Okay, but what do you expect that script to do? You create a constraint - and then you throw the constraint away. Once you have thrown it away, it will no longer influence the scene and, naturally, do nothing.

Do you perhaps assume that the influence of a constraint permanently alters the position of the affected object?

So, I checked that issue with a manual setup. I found that, indeed, removing an active PSR constraint will leave the affected object in the place where it was last. The original position is apparently lost.

Unfortunately, I was not yet able to make the "live" version do what your script seems to be doing (restoring the original position), with neither option from the script.

I can only guess that it has something to do with EventAdd() not being executed after the insertion. Will keep looking...

Ahyup. If you add the following line after setting the driver but before removing the tag:

doc.ExecutePasses(None, True, True, True, c4d.BUILDFLAGS_0)

then the affected object will stay where it is. I would assume the explanation is that between creating and deleting the tag, you didn't give Cinema 4D the chance to actually apply the tag to the object (to move it to the target position). ExecutePasses will enforce the evaluation of the tree and therefore the tag, reposition the target object, and then you can delete the tag again.

EventAdd() doesn't seem to suffice here, as it only refreshes the GUI? I'll leave that for an actual Maxon person to explain 😉

Hi bentraje, thanks for reaching out us.

With regard to your request, be aware that call c4d.EventsAdd() just add an event to the Cinema 4D scene evaluation queue, but you're actually not granted this to be executed immediately. Rather different instead is to call c4d.BaseDocument.ExecutePasses() which instead has the direct effect to the have Cinema 4D immediately evaluating a scene.

Finally assuming that the final intent was, as shown in the screen-recording, to align orientation of items in the scene why not taking advantage of BaseObject.SetMg() / BaseObject.GetMg()?

Best, R

@Cairyn and @r_gigante

Apologies for the late response.
Yes, the ExecutePasses works as expected. Thanks for the solution.

I can't use the SetMg()/GetMg() because the script is part of a larger base code which is not limited only to the PSR tag.

Thanks again. Have a great day ahead!