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

    CSTO over object.GetClone() produces excess geometry

    Cinema 4D SDK
    python
    2
    5
    707
    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.
    • bacaB
      baca
      last edited by

      Hi,

      I need alternative to GetCache(), and CSTO seems to be a good option.
      But Python tag produces wrong geometry when executed over clone of the object with CSTO.
      It additionally produces geometry which should be hidden by parent generators (for ex. Cloner under Volume Builder).
      Behavior is the same in Python Expression, or Python Tag Plugin, and it affects Cinema4D R21+ at the least.

      Here's the code:

                      srcClone = srcObj.GetClone(c4d.COPYFLAGS_NO_ANIMATION)
                      doc.InsertObject(srcClone)
      
                      cstoResult = c4d.utils.SendModelingCommand(
                          command=c4d.MCOMMAND_CURRENTSTATETOOBJECT,
                          list = [srcClone],
                          mode = c4d.MODELINGCOMMANDMODE_ALL,
                          bc = c4d.BaseContainer(),
                          doc = doc
                      )
      
                      srcClone.Remove()
      
                  for resObj in cstoResult:
                      for resChildObj in HierarchyIterator(resObj.GetDown()):
                          cloneObject = resChildObj.GetClone(c4d.COPYFLAGS_NO_HIERARCHY)
                          cloneObject.InsertUnderLast(selfObj)
      

      Viewport:
      bug.jpg

      Don't like the idea to call CSTO over original object, because it rebuilds object cache and affect DIRTYFLAGS_CACHE.
      What's the issue, is it possible to resolve it?

      Plugin https://www.dropbox.com/s/fxz8g7p8uuwc5y0/c4d_tag_csto.zip?dl=0
      Scene simple csto test.c4d

      Thanks.

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

        Hi,

        Not related to the issue, you are modifying the scene inside the execute function from a TagData, this function isn't executed on the main thread, so you are not allowed to modify the scene. That's really a bad idea.

        I got some questions:
        why can't you use GetCache? Why you can't affect DIRTYFLAGS_CACHE?

        The bahaviour is the same if you use the script manager. The problem is that you clone the object but it doesn't clone the caches.
        The following code works on the script manager, but the problem is that you need to ExecutePasses that could modify the DIRTYFLAGS_CACHE. (specially if you are using mograph)

        You could isolate the object on a new document (using IsolateObjects) the problem is that with mograph, the effector will not follow. So you would need to write some code to copy also those effectors and re-link them inside the new document.

        If you can tell us more about what you are trying to do, we could maybe find a better solution. Using a NodeData for example to generate this "polygon result".

        def main():
            srcClone = op.GetClone(c4d.COPYFLAGS_NO_ANIMATION)
            doc.InsertObject(srcClone)
            doc.ExecutePasses(None, False, False, False, c4d.BUILDFLAGS_NONE)
            srcClone.GetDown().Message(c4d.MSG_UPDATE)
            
        
            cstoResult = utils.SendModelingCommand(
                            command=c4d.MCOMMAND_CURRENTSTATETOOBJECT,
                            list = [srcClone],
                            mode = c4d.MODELINGCOMMANDMODE_ALL,
                            bc = c4d.BaseContainer(),
                            doc=doc
                        )
            srcClone.Remove()
            doc.InsertObject(cstoResult[0])
            c4d.EventAdd()
        # Execute main()
        

        Cheers,
        Manuel

        MAXON SDK Specialist

        MAXON Registered Developer

        bacaB 1 Reply Last reply Reply Quote 0
        • bacaB
          baca @Manuel
          last edited by

          @m_magalhaes Hi Manuel,

          Thanks for the reply.

          1. I've read the caution in API documentation, but I have tried it once and now can't stop to use it.
            At least for now I don't face app crashes, so maybe C4D have some safety margin for python developers 😉
          2. I can use cache, and I use it. But I want both options to be available.
            BTW when I'm using Cache from execute it also gives me whole tree including the Cloner sub-tree, when executing at Expression priority. In Generator priority GetCache() produces expected results.
          3. I don't like to affect DIRTYFLAGS_CACHE, because I'm also optimizing redraw based on dirty check with flag c4d.DIRTYFLAGS_DESCRIPTION | c4d.DIRTYFLAGS_DATA | c4d.DIRTYFLAGS_CHILDREN | c4d.DIRTYFLAGS_CACHE
            Also it seems like VolumeBuilder starts to re-generate mesh after CSTO called, and I went into infinite redraw.
          4. Thanks for pointing to IsolateObjects method, but as you mentioned I have to find all linked objects, which is not a trivial task in C4D.
            I wouldn't go that way.
          5. Provided solution with the ExecutePasses is updating geometry very rarely (if it supposed to be executed from python tag).
          6. Currently made a solution to check baseObject.GetInfo() & c4d.OBJECT_INPUT to stop further children processing.
            Seems to work good enough.
          1 Reply Last reply Reply Quote 0
          • ManuelM
            Manuel
            last edited by Manuel

            hi,

            1- it's might not be a crash but a scenario where an NodeData starts with some hierarchy, a tag modifies the object's order, the NodeData doesn't work anymore because the hierarchy have changed.
            2 - Sounds logical to me as you may know, the calculation is done in a sequence Generators are executed after Expressions. That's why you must make your code execute after the generators to be able to retrieve the caches.
            5 - some c4d object (specially mograph) have some special behavior. if ExecutePasses doesn't work, try two time in a row, or even three. It may sound like a joke but it is not. But if you do that in a tag, that could lead to an infinite loop.
            6 - as long as it's working fine for you, I'm happy 😄

            Cheers,
            Manuel

            MAXON SDK Specialist

            MAXON Registered Developer

            bacaB 1 Reply Last reply Reply Quote 0
            • bacaB
              baca @Manuel
              last edited by

              @m_magalhaes Thanks Manuel,
              I appreciate your wise support every time.

              Merry Xmas and Happy New Year!

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