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

    Undo loading and replacing materials

    Scheduled Pinned Locked Moved PYTHON Development
    9 Posts 0 Posters 1.3k Views
    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.
    • H Offline
      Helper
      last edited by

      On 16/06/2017 at 03:05, xxxxxxxx wrote:

      import c4d
        
      def main() :
        
          File=r"d:	est\Mats.c4d"
        
          TempDoc = c4d.documents.LoadDocument(File, c4d.SCENEFILTER_MATERIALS)
          MatListTemp = list()
          MatTemp = TempDoc.GetFirstMaterial()
          while(MatTemp) :
              nMatTemp = MatTemp.GetNext()
              MatListTemp.append(MatTemp)
              MatTemp = nMatTemp
          TempDoc.Remove()
        
          MatCurentDoc = doc.GetFirstMaterial()
          MatList = list()
          while(MatCurentDoc) :
              nMatCurentDoc = MatCurentDoc.GetNext()
              MatList.append(MatCurentDoc)
              MatCurentDoc = nMatCurentDoc
        
        
          doc.StartUndo()
        
          for Mat in MatList:
              for MatTemp in MatListTemp:
                  if MatTemp.GetName() == Mat.GetName() :
                      LayerMat = Mat.GetLayerObject(doc)
                      ObjLink = Mat[c4d.ID_MATERIALASSIGNMENTS]
        
                      list_tags = list()
                      for i in xrange(ObjLink.GetObjectCount()) :
                          list_tags.append(ObjLink.ObjectFromIndex(doc, i))
        
                      doc.AddUndo(c4d.UNDOTYPE_CHANGE, Mat)
        
                      Mat.Remove()
                      doc.AddUndo(c4d.UNDOTYPE_DELETE, Mat)
        
                      doc.InsertMaterial(MatTemp)
                      doc.AddUndo(c4d.UNDOTYPE_NEW, MatTemp)
        
                      doc.AddUndo(c4d.UNDOTYPE_CHANGE, MatTemp)
                      MatTemp.SetLayerObject(LayerMat)
        
                      for tag in list_tags:
                          doc.AddUndo(c4d.UNDOTYPE_CHANGE, tag)
                          tag[c4d.TEXTURETAG_MATERIAL] = MatTemp
        
          doc.EndUndo()
          c4d.EventAdd()
        
      if __name__ == '__main__':
          main()
      

      I'm downloading and replacing the materials with a script. All assigned objects are visible in the material assignments. If you undo the action (Ctrl + Z), the objects are missing in the material assignments.

      1 Reply Last reply Reply Quote 0
      • H Offline
        Helper
        last edited by

        On 16/06/2017 at 04:03, xxxxxxxx wrote:

        Yo do undo in the wrong under. Take the Add Undo command as Save Current State.

        So logically

                        doc.AddUndo(c4d.UNDOTYPE_CHANGE, Mat)
          
                        doc.AddUndo(c4d.UNDOTYPE_DELETE, Mat)
                        Mat.Remove()
          
                        doc.AddUndo(c4d.UNDOTYPE_NEW, MatTemp) #Since MatTemp already exist in memory
                        doc.InsertMaterial(MatTemp)
          
                        doc.AddUndo(c4d.UNDOTYPE_CHANGE, MatTemp)
                        MatTemp.SetLayerObject(LayerMat)
          
                        for tag in list_tags:
                            doc.AddUndo(c4d.UNDOTYPE_CHANGE, tag)
                            tag[c4d.TEXTURETAG_MATERIAL] = MatTemp
        
        1 Reply Last reply Reply Quote 0
        • H Offline
          Helper
          last edited by

          On 16/06/2017 at 04:34, xxxxxxxx wrote:

          Actually, UNDOTYPE_NEW needs to be called after  the insertion. 🙂

          https://developers.maxon.net/docs/py/2023_2/modules/c4d.documents/BaseDocument/index.html?highlight=addundo#BaseDocument.AddUndo

          Cheers

          1 Reply Last reply Reply Quote 0
          • H Offline
            Helper
            last edited by

            On 16/06/2017 at 04:41, xxxxxxxx wrote:

            UNDOTYPE_NEW New object/node/tag etc. was created. (Needs to be called AFTER action.)

            _<_t_>_

            The result is similar, after undo(ctrl+z) in "Material editor: Assignment" empty.

            1 Reply Last reply Reply Quote 0
            • H Offline
              Helper
              last edited by

              On 16/06/2017 at 04:52, xxxxxxxx wrote:

              If you save and reopen the project, then everything will be fine

              1 Reply Last reply Reply Quote 0
              • H Offline
                Helper
                last edited by

                On 19/06/2017 at 08:38, xxxxxxxx wrote:

                Hi,

                I think both Niklas and gr4phos are basically right, it has to do with the order of AddUndo() and action.
                Just to avoid confusion, in the original script posted doc.AddUndo(c4d.UNDOTYPE_DELETE, Mat) was wrongly called after Remove(), UNDOTYPE_DELETE has to be done before the action (correctly pointed out by gr4ph0s). Then gr4ph0s probably got confused himself and mixed up the order of  UNDOTYPE_NEW in his script, which has to be done after the action (as correctly pointed out by Niklas).
                Getting both of these right, should fix the issue.

                1 Reply Last reply Reply Quote 0
                • H Offline
                  Helper
                  last edited by

                  On 19/06/2017 at 21:28, xxxxxxxx wrote:

                  Alas it does not work

                  screencast

                  1 Reply Last reply Reply Quote 0
                  • H Offline
                    Helper
                    last edited by

                    On 20/06/2017 at 02:57, xxxxxxxx wrote:

                    Hi,

                    please forgive me for not taking a closer look first. The AddUndo() order seemed like an obvious bug and explained the issues pretty well.
                    The actual issue is, that you are removing the old material too early from the document. So when the material assignment gets changed and the undo step is added, the document already has no more reference to the old material.

                    Here's the fixed script, with a few other notes:

                    import c4d
                      
                    def main() :
                      
                        File = "<some path>/Mats.c4d"
                      
                        TempDoc = c4d.documents.LoadDocument(File, c4d.SCENEFILTER_MATERIALS)
                        MatListTemp = list()
                        MatTemp = TempDoc.GetFirstMaterial()
                        while(MatTemp) :
                            MatListTemp.append(MatTemp.GetClone()) # use clone here, later on you don't want to insert a material already inserted in another doc
                            MatTemp = MatTemp.GetNext()
                        TempDoc.Remove()
                      
                        MatCurentDoc = doc.GetFirstMaterial()
                        MatList = list()
                        while(MatCurentDoc) :
                            MatList.append(MatCurentDoc)
                            MatCurentDoc = MatCurentDoc.GetNext()
                      
                        doc.StartUndo()
                      
                        for Mat in MatList:
                            for MatTemp in MatListTemp:
                                if MatTemp.GetName() == Mat.GetName() :
                                    LayerMat = Mat.GetLayerObject(doc)
                                    ObjLink = Mat[c4d.ID_MATERIALASSIGNMENTS]
                      
                                    list_tags = list()
                                    for i in xrange(ObjLink.GetObjectCount()) :
                                        print ObjLink.ObjectFromIndex(doc, i)
                                        list_tags.append(ObjLink.ObjectFromIndex(doc, i))
                      
                                    #doc.AddUndo(c4d.UNDOTYPE_CHANGE, Mat) # redundant
                      
                                    # moved to the end
                                    #Mat.Remove()
                                    #doc.AddUndo(c4d.UNDOTYPE_DELETE, Mat)
                      
                                    doc.InsertMaterial(MatTemp)
                                    doc.AddUndo(c4d.UNDOTYPE_NEW, MatTemp)
                      
                                    doc.AddUndo(c4d.UNDOTYPE_CHANGE, MatTemp)
                                    MatTemp.SetLayerObject(LayerMat)
                      
                                    for tag in list_tags:
                                        doc.AddUndo(c4d.UNDOTYPE_CHANGE, tag)
                                        tag[c4d.TEXTURETAG_MATERIAL] = MatTemp
                      
                                    doc.AddUndo(c4d.UNDOTYPE_DELETE, Mat)  # swapped, AddUndo(DELETE) before Remove()
                                    Mat.Remove()
                                    #doc.AddUndo(c4d.UNDOTYPE_DELETE, Mat)
                      
                        doc.EndUndo()
                        c4d.EventAdd()
                      
                    if __name__ == '__main__':
                        main()
                    
                    1 Reply Last reply Reply Quote 0
                    • H Offline
                      Helper
                      last edited by

                      On 20/06/2017 at 03:19, xxxxxxxx wrote:

                      thank you, things work. 👍

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