Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Copying Layers along with Objects

    Cinema 4D SDK
    c++ r20 sdk
    3
    6
    730
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • D
      d_schmidt
      last edited by d_schmidt

      Hello!

      I'm trying to copy an object from one document to another using GetClone(), which works for that. But if I have the object with a Layer that Layer is not copied over to the new document. Is there a way to automatically copy the Layer along with the object?

      User preformed copy/paste does bring over the Layer, but using this code it doesn't.

              // with two documents open and an object selected
              BaseDocument* activedocument = GetActiveDocument();
              BaseDocument* firstdoc = GetFirstDocument();
              
              BaseObject* first = activedocument->GetFirstObject();
              BaseObject* clone = static_cast<BaseObject*>(first->GetClone(COPYFLAGS::NONE, nullptr));
              firstdoc->InsertObject(clone, nullptr, nullptr);
              EventAdd();
      

      Dan

      1 Reply Last reply Reply Quote 0
      • CairynC
        Cairyn
        last edited by

        As I understand it, you need to copy the layers separately and then restore the connections by using an AliasTrans object.

        Here's some code in Python, is faster to prototype, sorry:

        import c4d
        from c4d import gui
        
        def main():
            if op == None: return
        
            activeDoc = c4d.documents.GetActiveDocument() # source
            firstDoc = c4d.documents.GetFirstDocument() # target
            # user must make sure that the first doc is really the target
            # and the second doc active!
        
            trans = c4d.AliasTrans()
            if not trans or not trans.Init(doc):
                return
        
            firstDoc.StartUndo()
        
            op2 = op.GetClone(c4d.COPYFLAGS_RECURSIONCHECK, trans)
            op2[c4d.ID_BASELIST_NAME] = "This is a clone!"
            firstDoc.InsertObject(op2)
        
            layer = op.GetLayerObject(activeDoc)
            layercopy = layer != None
            if layercopy:
                layer2 = layer.GetClone(c4d.COPYFLAGS_RECURSIONCHECK, trans)
                if layer2 == None: 
                    print "Layer copy failed"
                    layercopy = False
                else:
                    layerHead = firstDoc.GetLayerObjectRoot() # should return GeListHead
                    # but returns BaseList2D
                    if layerHead == None:
                        print "Layer head not returned"
                        layercopy = False
                    else:
                        layer2.InsertUnder(layerHead)
                        # layerHead.InsertFirst(layer2)
            else:
                print "No layer to copy"
        
            trans.Translate(True)
        
            firstDoc.AddUndo(c4d.UNDOTYPE_NEW, op2)
            if layercopy:
                firstDoc.AddUndo(c4d.UNDOTYPE_NEW, layer2)
            firstDoc.EndUndo()
            c4d.EventAdd()
        
        if __name__=='__main__':
            main()
        

        AliasTrans is used in all clone operations, and then after inserting the elements into the new document, called with Translate to resolve all links that got broken during the separate clonings.

        Haven't tested whether this works for nested layers; the code obviously only copies the layer of the selected object; you may need to traverse the hierarchy to find all used layers and clone them.

        1 Reply Last reply Reply Quote 1
        • r_giganteR
          r_gigante
          last edited by

          Hi Daniel, thanks for reaching out us.

          With regard to your question, @Cairyn's observations are indeed correct and there's nothing in our API automatically copying layer upon objects being copied.

          Cheers, R

          1 Reply Last reply Reply Quote 1
          • D
            d_schmidt
            last edited by

            Thanks, @Cairyn, that does work to copy the object and maintain the Layer link.

            The problem I'm running into with it, is that if you run your code multiple times each time the Layer gets copied over again. With a Cinema copy/paste it would link with the first Layer instead of inserting a new copy of the Layer.

            Would it be possible to duplicate that functionality?

            CairynC 1 Reply Last reply Reply Quote 0
            • CairynC
              Cairyn @d_schmidt
              last edited by

              @d_schmidt There are many more problems, this is just a snippet to demonstrate AliasTrans. E.g. If the copied object has children with other layers, these would not be copied. If the layer is child of another layer, then it would not be inserted in the right place. etc

              As for your question, I just checked: If you use the programmatic clone/insert/translate method and do NOT copy a layer in that AliasTrans, then the objects using that layer will NOT be relinked automatically with the "same" layer in the target scene, so the layer link remains empty. So I am afraid you will need to do everything manually:

              • check which layers are used in the copied hierarchy
              • determine which ones of these are already present in the target scene
              • for these, remember which objects are using them
              • also remember the structure of the layers (as they can be hierarchically ordered)
              • for layers that are not present in the target scene, copy them in the scope of the same AliasTrans
              • also copy layers that are needed as parents for copied layers but are not used themselves
              • then you insert everything in the target scene
              • finally, you use your own remembering structures to identify and restore all layer links that lead to layers that were already present in the target scene
              D 1 Reply Last reply Reply Quote 1
              • D
                d_schmidt @Cairyn
                last edited by

                @Cairyn Thanks again!

                That's what I was afraid of, but thanks for the information!

                1 Reply Last reply Reply Quote 0
                • First post
                  Last post