Hello @Gene,
So far it's doing exactly what I need. Only issue I have is if I need to undo the script. I have to press the Undo button several times because C4D creates an undo state for every Tag/Object selection step in the script, instead of putting all of them under one undo state. I think this is a long-existing limitation of C4D's Undo system?
Well, it depends a bit on what you would consider a "long-existing limitation", but you can consolidate multiple operations into a singular item in the undo-stack. The most relevant methods are BaseDocument.StartUndo, BaseDocument.EndUndo, and BaseDocument.AddUndo (there more undo related methods on BaseDocument).
Cheers,
Ferdinand
"""Demonstrates wrapping selecting all top-level objects in a document into one undo item.
"""
import c4d
doc: c4d.documents.BaseDocument
def main():
"""
"""
obj: c4d.BaseObject = doc.GetFirstObject()
# Start an undo item in the undo stack.
doc.StartUndo()
while obj:
# Add an operation to the undo item, most operations must be invoked BEFORE the actual
# operation is carried out. The only exception is inserting new nodes, AddUndo must here
# be called AFTER the operation.
doc.AddUndo(c4d.UNDOTYPE_ACTIVATE, obj)
doc.SetActiveObject(
obj, c4d.SELECTION_NEW if obj == doc.GetFirstObject() else c4d.SELECTION_ADD)
obj = obj.GetNext()
# Close the item.
doc.EndUndo()
c4d.EventAdd()
if __name__ == "__main__":
main()