File import and doc merge -> InsertAfter or c4d.PREF_INTERFACE_I_BOTTOM
-
Dear Team,
I am trying to import files and place them in the object tree in the right order,i tried to set the preferences with
c4d.PREF_INTERFACE_I_BOTTOMbefore import but it did not change my order.interface_preferences = c4d.GetWorldContainer() previous_insert_at = interface_preferences.GetInt32(c4d.PREF_INTERFACE_INSERTAT) interface_preferences.SetInt32(c4d.PREF_INTERFACE_INSERTAT, c4d.PREF_INTERFACE_I_BOTTOM, )Is there a convenient way or do i need to move the "node" manually to the bottom on each import ...
or more universal for me is there a way to sort root nodes in the Object manager tree ? (only found an old coffee thread ... )
thanks in advance ...
mogh -
import c4d doc: c4d.documents.BaseDocument # The currently active document. op: c4d.BaseObject | None # The primary selected object in `doc`. Can be `None`. def main() -> None: obj = c4d.BaseObject(c4d.Ocube) # Insert after the last root object. roots = doc.GetObjects() doc.InsertObject(obj, pred=roots[-1] if roots else None) c4d.EventAdd() if __name__ == '__main__': main()Hope this helps.
Here is another example that can directly execute the importimport c4d def main(): doc = c4d.documents.GetActiveDocument() path = c4d.storage.LoadDialog( c4d.FILESELECTTYPE_SCENES, "Import Scene" ) if not path: return roots = doc.GetObjects() anchor = roots[-1] if roots else None old_guids = {obj.GetGUID() for obj in roots} flags = ( c4d.SCENEFILTER_OBJECTS | c4d.SCENEFILTER_MATERIALS | c4d.SCENEFILTER_MERGESCENE | c4d.SCENEFILTER_DIALOGSALLOWED ) c4d.StopAllThreads() doc.StartUndo() try: doc.AddUndo(c4d.UNDOTYPE_CHANGE, doc) if not c4d.documents.MergeDocument(doc, path, flags, None): c4d.gui.MessageDialog("Import failed.") return # Find the newly imported root objects. imported = [ obj for obj in doc.GetObjects() if obj.GetGUID() not in old_guids ] # Move them below the previous last root object. if anchor: for obj in imported: matrix = obj.GetMg() doc.AddUndo(c4d.UNDOTYPE_CHANGE, obj) obj.Remove() obj.InsertAfter(anchor) obj.SetMg(matrix) anchor = obj finally: doc.EndUndo() c4d.EventAdd() if __name__ == "__main__": main()Cheers,
Anlv -
Hey @mogh,
let me clarify things first a bit.
Reproduce:
- You have a scene A in an alien scene format such as FBX or OBJ.
- You have an existing native Cinema 4D scene B.
- You are trying to merge A into B.
Result:
The objects of A appear before the objects of B in the scene hierarchy of the merged scene. Even when you change the insertion order in Preferences > Interface.First of all, it is not very surprising that "insert at" does not work (and "paste at" does neither), because these are for individual objects within a scene, not for merging entire scenes. What you are effectively missing is a scene merge order option and this does not really have something to do with importers. This would be addressed best by a feature request in our Support Center.
With a pinch of Python, you can solve this yourself as demonstrated by @Anlv (thanks!). Using
BaseList2D.GetGUIDas @Anlv did is okay, but the more native solution would behash(obj), i.e.,C4DAtom.__hash__. Scene elements are for quite a while now natively hashable, so you can for example do this:roots: set[int] = { hash(obj) for obj in doc.GetObjects() } new_roots: set[int] = roots.intersection({ hash(obj) for obj in new_doc.GetObjects() })And it will give you the set of all root level hashes (GeMarker IDs). I think also the transform copying @Anlv does at the end of the script should not be necessary, because these are root level objects, and therefore removing and re-adding them will not affect their transforms (as they have no parents to which their transform would be relative to). But I have not run @Anlv's full script myself, so it could be that I am overlooking something.
Cheers,
Ferdinand -
@ferdinand Thanks for pointing that out. Indeed,
matrix = obj.GetMg()andobj.SetMg(matrix)are not necessary; this is leftover code from when it was previously used to insert into the child or sibling level of the selected object.Cheers,
Anlv