Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware 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

    Error after hitting Undo.

    Cinema 4D SDK
    r20 python
    3
    13
    1.9k
    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.
    • ferdinandF
      ferdinand
      last edited by ferdinand

      Hi,

      the actual script would be helpful, or more specifically the type of undo you did apply, I assume c4d.UNDOTYPE_CHANGE? Have you tried the recommended procedure of applying SMC to a copy of the object? You would then have to open an undo group, apply c4d.UNDOTYPE_DELETE, delete the original, insert the copy, apply c4d.UNDOTYPE_NEW, and finally close the undo group.

      Cheers
      zipit

      MAXON SDK Specialist
      developers.maxon.net

      1 Reply Last reply Reply Quote 0
      • ManuelM
        Manuel
        last edited by Manuel

        Hello,

        the actual script or a part of it would help yes.

        I've also marked this thread as a question as you seem to never do it 😜

        Cheers,
        Manuel.

        MAXON SDK Specialist

        MAXON Registered Developer

        R 1 Reply Last reply Reply Quote 0
        • R
          rui_mac
          last edited by rui_mac

          I made the changes in order to work on a duplicate of the original spline.
          It still works, but it also still returns the same error when I undo.
          Here is the script:

          import c4d
          from c4d import gui
          # Welcome to the world of Python
          
          # Find the length of the spline segment between points p1 and p2
          def GetLength(op,p1,p2):
              select=op.GetPointS()
              select.DeselectAll()
              select.Select(p1)
              select.Select(p2)
          
              bc=c4d.BaseContainer()
              result=c4d.utils.SendModelingCommand(c4d.MCOMMAND_SPLIT, [op], mode=c4d.MODELINGCOMMANDMODE_POINTSELECTION, bc=bc, doc=doc)
              leng=10000000.0
              if result!=False and result!=[]:
                  op2=result[0]
                  segm=c4d.utils.SplineHelp()
                  segm.InitSplineWith(op2, flags=c4d.SPLINEHELPFLAGS_GLOBALSPACE|c4d.SPLINEHELPFLAGS_CONTINUECURVE)
                  leng=segm.GetSplineLength()
                  segm.FreeSpline()
              return leng
          
          # Main function
          def main():
              selected=doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_0)
              if len(selected) == 0:
                  c4d.gui.MessageDialog("You must select a spline and two consecutive points of that spline.")    
                  return
          
              op=selected[0]
              if op.GetType()!=5101:
                  c4d.gui.MessageDialog("You must select a spline and two consecutive points of that spline.")    
                  return
          
              selection=op.GetPointS()
              if selection.GetCount()!=2:
                  c4d.gui.MessageDialog("You must select two consecutive points of the spline.")
                  return
          
              # check if the selected points are consecutive
              p1,p2=-1,-1
              num=op.GetPointCount()
              for s in range(num):
                  if selection.IsSelected(s):
                      if p1==-1:
                          p1=s
                      else:
                          p2=s
          
              if p2-p1!=1:
                  c4d.gui.MessageDialog("You must select two consecutive points of the spline.")
                  return
          
              # get the size of the segment
              shortest=GetLength(op,p1,p2)
              
              # work on a copy of the original spline
              op2=op.GetClone()
          
              # start at point 0
              i=0
              while i<num:
                  # get the length of the current segment between point i and i+1
                  new_length=GetLength(op2,i,i+1)
          
                  # if the segment is, at least one and a half times the size of the initial segment...
                  if (new_length>(shortest*1.5)):
                      subdivs=int(new_length/shortest)+1
          
                      # select point i and i+1
                      selection=op2.GetPointS()
                      selection.DeselectAll()
                      selection.Select(i)
                      selection.Select(i+1)
          
                      # subdivide that segment
                      bc=c4d.BaseContainer()
                      bc.SetInt32(c4d.MDATA_SUBDIVIDE_SPLINESUB,subdivs)
                      result=c4d.utils.SendModelingCommand(c4d.MCOMMAND_SUBDIVIDE, [op2], mode=c4d.MODELINGCOMMANDMODE_POINTSELECTION, bc=bc, doc=doc)
                      
                      # update the counter
                      i=i+subdivs-1
                      # update the limit
                      num=num+subdivs-1
                  
                  # increase the counter
                  i=i+1
          
              # insert the new subdivided spline after the original spline
              # and delete the original spline, making sure this is undoable
              doc.StartUndo()
              doc.InsertObject(op2, parent=None, pred=op, checknames=False)
              doc.AddUndo(c4d.UNDOTYPE_NEW, op2)
              doc.AddUndo(c4d.UNDOTYPE_DELETE, op)    
              op.Remove()
              doc.EndUndo()
              
              # update the document
              c4d.EventAdd()
          
          # Execute main()
          if __name__=='__main__':
              main()
          
          1 Reply Last reply Reply Quote 0
          • R
            rui_mac @Manuel
            last edited by

            @m_magalhaes said in Error after hitting Undo.:

            I've also marked this thread as a question as you seem to never do it 😜

            How can I mark it as a question?

            1 Reply Last reply Reply Quote 0
            • R
              rui_mac
              last edited by

              I finally made it work without the error after hitting undo, by replacing calls to GetLength, in the form:

              GetLength(op,p1,p2)

              to

              GetLength(op.GetClone(),p1,p2)

              1 Reply Last reply Reply Quote 0
              • ManuelM
                Manuel
                last edited by

                Hello,

                i just scratch a bit your code, but i've discovered that with the R21, MCOMMAND_SPLIT only return true.
                I've opened a bug entry for that.

                Happy to see your code is working. I will have a look at it and my comment on that.
                Like it's not a good idea to use GetType() you should use IsInstanceOf

                About the forum, those are the thread where you can have information on how to use the new functionalities of the forum. This will help futur user to find resolved question and the right post.

                • Q&A New Functionality.
                • How to Post Questions especially the tagging part.

                MAXON SDK Specialist

                MAXON Registered Developer

                1 Reply Last reply Reply Quote 0
                • R
                  rui_mac
                  last edited by

                  Thank you, Manuel.

                  From what I see, several things are working differently in R21.
                  I suspect the MCOMMAND_EDGE_TO_SPLINE is also not working properly.
                  And the MCOMMAND_CURRENTSTATETOOBJECT (a very important one) is also not working as expected, requiring that the object to be converted to be in a new document.

                  I will start using IsInstanceOf instead of GetType 🙂

                  I will also pay more attention to the tagging part of my posts.

                  Once again, thank you.

                  1 Reply Last reply Reply Quote 0
                  • ManuelM
                    Manuel
                    last edited by Manuel

                    @rui_mac said in Error after hitting Undo.:

                    MCOMMAND_CURRENTSTATETOOBJECT

                    This one is fixed on the next update.

                    I'll check MCOMMAND_EDGE_TO_SPLINE thanks.

                    MAXON SDK Specialist

                    MAXON Registered Developer

                    1 Reply Last reply Reply Quote 0
                    • ManuelM
                      Manuel
                      last edited by Manuel

                      hello,

                      just dig in a little bit more on your code.
                      I've added some AddUndo and i'm using the flag of the SendModelingCommand to add an undo.
                      Removing the need of a clone except in the GetLength function where you have to split the spline.

                      import c4d
                      from c4d import gui
                      # Welcome to the world of Python
                      
                      # Find the length of the spline segment between points p1 and p2
                      def GetLength(op,p1,p2):
                          newSpline  = op.GetClone()
                      
                          select = newSpline.GetPointS()
                          select.DeselectAll()
                          select.Select(p1)
                          select.Select(p2)
                      
                          bc = c4d.BaseContainer()
                          result=c4d.utils.SendModelingCommand(c4d.MCOMMAND_SPLIT, [newSpline], mode=c4d.MODELINGCOMMANDMODE_POINTSELECTION, bc=bc, doc=doc)
                          leng = 10000000.0
                          if result:
                              print "ok "
                              segm=c4d.utils.SplineHelp()
                              segm.InitSplineWith(result[0], flags=c4d.SPLINEHELPFLAGS_GLOBALSPACE|c4d.SPLINEHELPFLAGS_CONTINUECURVE)
                              leng=segm.GetSplineLength()
                              segm.FreeSpline()
                              print leng
                          return leng
                      
                      # Main function
                      def main():
                          selected = doc.GetActiveObject() if  doc.GetActiveObject().IsInstanceOf(c4d.Ospline) else None
                          if selected is None:
                              c4d.gui.MessageDialog("Select a spline")    
                              return
                      
                          selection = op.GetPointS()
                          if selection.GetCount() != 2:
                              c4d.gui.MessageDialog("You must select two points of the spline.")
                              return
                      
                          # check if the selected points are consecutive
                          p1 = p2 = -1
                      
                          num = op.GetPointCount()
                          for s in range(num):
                              if selection.IsSelected(s):
                                  if p1 == -1:
                                      p1 = s
                                  else:
                                      p2 = s
                      
                          if p2-p1 != 1:
                              c4d.gui.MessageDialog("You must select two consecutive points of the spline.")
                              return
                      
                          # get the size of the segment
                          shortest = GetLength(op,p1,p2)
                          
                          # start at point 0
                          i = 0
                          doc.StartUndo()
                          while i<num:
                              # get the length of the current segment between point i and i+1
                              new_length = GetLength(op,i,i+1)
                      
                              # if the segment is, at least one and a half times the size of the initial segment...
                              if (new_length > (shortest * 1.5)):
                                  subdivs=int(new_length/shortest)+1
                      
                                  # select point i and i+1
                                  selection=op.GetPointS()
                                  doc.AddUndo(c4d.UNDOTYPE_CHANGE, op)
                                  selection.DeselectAll()
                                  doc.AddUndo(c4d.UNDOTYPE_CHANGE, op)
                                  selection.Select(i)
                                  doc.AddUndo(c4d.UNDOTYPE_CHANGE, op)
                                  selection.Select(i+1)
                      
                                  # subdivide that segment
                                  bc=c4d.BaseContainer()
                                  bc.SetInt32(c4d.MDATA_SUBDIVIDE_SPLINESUB,subdivs)
                      
                                  result=c4d.utils.SendModelingCommand(c4d.MCOMMAND_SUBDIVIDE, [op], mode=c4d.MODELINGCOMMANDMODE_POINTSELECTION, bc=bc, doc=doc, flags =c4d.MODELINGCOMMANDFLAGS_CREATEUNDO)
                                  if result == False:
                                      raise ValueError("the subdivde command failed")
                                  # update the counter
                                  i=i+subdivs-1
                                  # update the limit
                                  num=num+subdivs-1
                              
                              # increase the counter
                              i=i+1
                      
                          doc.EndUndo()
                          
                          
                          # update the document
                          c4d.EventAdd()
                      
                      # Execute main()
                      if __name__=='__main__':
                          main()
                      

                      Cheers,
                      Manuel

                      MAXON SDK Specialist

                      MAXON Registered Developer

                      1 Reply Last reply Reply Quote 0
                      • ManuelM
                        Manuel
                        last edited by

                        @rui_mac said in Error after hitting Undo.:

                        I suspect the MCOMMAND_EDGE_TO_SPLINE is also not working properly.

                        what doesn't work properly ?

                        import c4d
                        from c4d import gui
                        from c4d import utils
                        
                        def main():
                            #edge to spline.    
                            bc = c4d.BaseContainer()
                            res = utils.SendModelingCommand(c4d.MCOMMAND_EDGE_TO_SPLINE, list = [op], bc = bc, doc= doc)
                            c4d.EventAdd()
                        
                        # Execute main()
                        if __name__=='__main__':
                            main()
                        

                        MAXON SDK Specialist

                        MAXON Registered Developer

                        1 Reply Last reply Reply Quote 0
                        • R
                          rui_mac
                          last edited by

                          The addition of the undo as a flag is great. Thank you 🙂

                          What was not working was that, in R21, I was getting no spline as the return result of the SendModelingCommand, set to MCOMMAND_EDGE_TO_SPLINE.
                          I will try again, at home, as I don't have R21 here, at work.

                          1 Reply Last reply Reply Quote 0
                          • ManuelM
                            Manuel
                            last edited by

                            @m_magalhaes said in Error after hitting Undo.:

                            i just scratch a bit your code, but i've discovered that with the R21, MCOMMAND_SPLIT only return true.
                            I've opened a bug entry for that.

                            this is fixed in R21.1

                            MAXON SDK Specialist

                            MAXON Registered Developer

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