Hey @mats,
I ran your code, and I cannot reproduce your problem. The line tag( [c4d.ID_CA_CONSTRAINT_TAG_PARENT] = True
is not really wrong but makes not too much sense as you are calling there C4DAtom.__call__
, the line should be tag[c4d.ID_CA_CONSTRAINT_TAG_PARENT] = True
.
I also added undo steps to your script, but it was working without them for me too. Maybe I am misunderstanding what you mean with 'When doing it manually, I get no offset on the objects, they all stay in place as intended.', but for me there is no 'offset'.
I ran the code on 2023.0.0
and 2023.1.0
to the same effect, find my code below. If the problem does persist for you, I will have to ask you to explain what you would consider wrong with the result.
Cheers,
Ferdinand
The result:

The code:
"""Constraints the two currently selected objects with a parent-child constraint.
"""
import c4d
import typing
doc: c4d.documents.BaseDocument # The active document
op: typing.Optional[c4d.BaseObject] # The active object, None if unselected
def main() -> None:
"""
"""
# Get the object selection in order and bail when not exactly two objects are selected.
selection: list[c4d.BaseObject] = doc.GetActiveObjects(
c4d.GETACTIVEOBJECTFLAGS_SELECTIONORDER | c4d.GETACTIVEOBJECTFLAGS_CHILDREN)
if len(selection) != 2:
raise RuntimeError("Please select exactly two objects.")
# Unpack the selection into a parent and child variable, rename the two objects, and add undos
# for the operation.
parent, child = selection
doc.StartUndo()
doc.AddUndo(c4d.UNDOTYPE_CHANGE, parent)
doc.AddUndo(c4d.UNDOTYPE_CHANGE, child)
parent.SetName(f"{parent.GetName()} (Parent)")
child.SetName(f"{child.GetName()} (Child)")
# Create the tag.
tag: c4d.BaseTag = child.MakeTag(c4d.Tcaconstraint)
if tag is None:
raise MemoryError("Could not allocate tag.")
# Add an undo for the tag being added (must be done after the operation) and add another undo
# for the tag being modified (not really necessary here, but good form).
doc.AddUndo(c4d.UNDOTYPE_NEWOBJ, tag)
doc.AddUndo(c4d.UNDOTYPE_CHANGE, tag)
# Constraint #child to #parent.
tag[c4d.ID_CA_CONSTRAINT_TAG_PARENT] = True
tag[30001] = parent
doc.EndUndo()
c4d.EventAdd()
if __name__ == '__main__':
main()