ObjectData handles - Unexpected position jitter
-
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/handleissueHere'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 ] = pAny ideas to what's going on / what I'm doing wrong would be greatly appreciated.
Thanks,
Adam
-
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_FREEand 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 implementMoveHandleto 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 -
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=1All 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
-
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
Clampis called onpbefore it is fed back intohandle_position. In my bezier handle example I usedMoveHandleto project the current mouse pick point into the plane where I wanted to have it. You could also do the same inSetHandle. 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