Hey @pyr,
Thank you for reaching out to us. The sentence 'if i do the whole thing via obj.InsertUnder(null) i miss the material' is a bit ambiguous, how do you mean that? I assume you mean that when you load two documents A and B and then start copying objects over by either cloning them or removing them from A and inserting them into B, that you then miss material references. Because the call you show us will load both objects and materials found at f into doc.
A straightforward way to do what you want to do, parent everything that has been imported to a null, is to track the state of the top-level objects before and after the import. The difference between the states then tells you what to move where. In practice, there are some technical hoops to jump through, primarily the problem that you might run into dead references when you try to store objects references over the import process.
Cheers,
Ferdinand
Result:
Code:
"""Demonstrates how to parent the objects merged into a document to a null object.
Must be run as a script manager script and will import the contents of #FILE into the active
document.
"""
import c4d
doc: c4d.documents.BaseDocument # The active document.
FILE: str = r"file:///e:/test.c4d" # The document to import.
def main() -> None:
"""
"""
# Get the UUID markers of all top level objects. We get the markers and not the object
# references because importing a document bears a good chance that these references will be
# dead (C4DAtom.IsAlive() == False) when we access them again.
uuidCollection: list[bytes] = []
op: c4d.BaseObject = doc.GetFirstObject()
while op:
uuidCollection.append(bytes(op.FindUniqueID(c4d.MAXON_CREATOR_ID)))
op = op.GetNext()
# Now we import our document.
c4d.documents.MergeDocument(doc, FILE, c4d.SCENEFILTER_OBJECTS |
c4d.SCENEFILTER_MATERIALS |
c4d.SCENEFILTER_MERGESCENE)
# We create our null object to parent the imported stuff to. We also add its UUID to
# #uuidCollection, so that we do not attempt to parent #null to itself ;)
null: c4d.BaseObject = c4d.BaseObject(c4d.Onull)
null.SetName(FILE)
doc.InsertObject(null)
c4d.EventAdd()
uuidCollection.append(bytes(null.FindUniqueID(c4d.MAXON_CREATOR_ID)))
# Now we iterate again over all top level objects and parent everything that does not appear in
# #uuidCollection to #null.
op: c4d.BaseObject = doc.GetFirstObject()
# We have to do this on two steps, because when we would already move #op in the first step
# where we find the things to move, we would sabotage our own loop here (because as soon as
# we move the first op to the null, op.GetNext() would be None).
move: list[c4d.BaseObject] = []
while op:
if bytes(op.FindUniqueID(c4d.MAXON_CREATOR_ID)) not in uuidCollection:
move.append(op)
op = op.GetNext()
# Actually move the items.
for op in move:
op.InsertUnderLast(null)
c4d.EventAdd()
if __name__ == "__main__":
main()