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
    • Recent
    • Tags
    • Users
    • Login

    ObjectData handles - Unexpected position jitter

    Scheduled Pinned Locked Moved Cinema 4D SDK
    python2026
    4 Posts 2 Posters 15 Views 2 Watching
    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.
    • PixelsInProgressP Offline
      PixelsInProgress
      last edited by PixelsInProgress

      Hi Maxon team,

      I'm creating a python ObjectData plugin which uses handles and I'm experiencing some strange behaviour.

      I can transform the object and then move the handles without issue in any viewport as expected. The issue arises if I have multiple views. So, say I'm using a 2 view setup, if I transform the object in one viewport and immediately move the handle in the other viewport, sometimes it triggers erratic behavior where the handle position appears to be flickering between it's expected position and somewhere in another plane. Once the behaviour is triggered it seems to remain.

      Some anectodal notes:

      • Closing and reopening the file makes the issue dissapear
      • Deleting the object and creating a new one and the issue remains

      Here's a video showing the flickering (starts about 19 seconds) :
      https://www.pixelsinprogress.com/handleissue

      Here's my handles code in it's simplest form:

          def GetHandleCount(self, op):
              return 1
      
          def GetHandle(self, op, i, info):
      
              info.position  = op[c4d.ID_USERDATA,1 ] # this is a simplified example so using UD instead of a parameter
              info.type      = c4d.HANDLECONSTRAINTTYPE_FREE
      
          def SetHandle(self, op, i, p, info):
              op[c4d.ID_USERDATA,1 ] = p
      
      

      Any ideas to what's going on / what I'm doing wrong would be greatly appreciated.

      Thanks,

      Adam

      ferdinandF 1 Reply Last reply Reply Quote 1
      • ferdinandF Offline
        ferdinand @PixelsInProgress
        last edited by ferdinand

        Hey @PixelsInProgress,

        thank you for reaching out to us. That is not possible to answer like this, please provide an executable code example of what you are doing.

        I guess the the reason for your problems are that you use the a bit niche constraint type HANDLECONSTRAINTTYPE_FREE and create a transform feedback loop when you feed your own user data into your handle without constraining that data. Keep in mind that handle code is called view-based. You might have to implement MoveHandle to correctly transform your point. But I have no idea what you are trying to do, so I am mostly guessing.

        I have written a while ago this C++ code example which implements a camera dependent handle, which might be what you are trying to do here.

        Cheers,
        Ferdinand

        MAXON SDK Specialist
        developers.maxon.net

        1 Reply Last reply Reply Quote 0
        • PixelsInProgressP Offline
          PixelsInProgress
          last edited by

          Hi Ferdinand,

          Thanks for the swift reply. I've built an example where the behaviour is repeatable (although as in the video it sometimes requires transforming the object multiple times before it starts) here:
          https://www.dropbox.com/scl/fo/k76j6qja2u6n0nrmj11o8/AMhO7GwhSFnm-9saHFxhuB8?rlkey=pet07qeoeuev9zpfc5f30qhg8&dl=1

          All I'm expecting from the handle, is for it to behave as it does as in the ealier part of the video I posted i.e if I'm in a parallel viewport and I move the handle, it moves in the plane of that particular viewport and not in the depth axis. Instead of flickering to a different plane in the other viewports. ( As far as I can tell, triggered immediately after transforming in one view and then moving the handle in another straight after)

          WIth regards to the feedback loop. It seems that in the SDK examples that this is how it's normally managed? As in take some stored data, feed it to the handle position in GetHandle and then retreive the updated position is SetHandle and safely store position for the next iteration?

          Thanks for your C++ camera dependent example, that looks like it could be super use to implement a fallback if HANDLECONSTRAINTTYPE_FREE isn't going to work.

          Cheers,

          Adam

          1 Reply Last reply Reply Quote 0
          • ferdinandF Offline
            ferdinand
            last edited by ferdinand

            Well, what I meant with feedback loop, is that you never constraint your data in any shape or form. All code examples and internal code work like this:

            def GetHandle(self, op, i, info):
                info.position  = self.handle_position # or op[c4d.ID_INTERNAL_HANDLE_STORAGE]
                info.type = c4d.HANDLECONSTRAINTTYPE_SOMETYPE
                info.direction = Vector(...)
            
            def SetHandle(self, op, i, p, info):
                self.handle_position = Clamp(p)
            

            I.e., here Clamp is called on p before it is fed back into handle_position. In my bezier handle example I used MoveHandle to project the current mouse pick point into the plane where I wanted to have it. You could also do the same in SetHandle. The viewport picking algorithm has no idea where you consider to be the 'correct' working plane. It does its best to guess, but you must still check and or help.

            I haven't had a look at your code yet, will do next week (hopefully on Monday). It could be that there is a bug in the Python API, but that unbound nature of your code does strike me as incorrect.

            Cheers,
            Ferdinand

            MAXON SDK Specialist
            developers.maxon.net

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