How to make Python Field react to camera?
-
I'm working on a Python Field that updates based on a camera linked by user data. I was able to get the field to update as the camera attributes are modified or animated by "forwarding" the camera's dirty state to the field object. However, this doesn't work when viewing through the camera and manipulating with shortcuts in the viewport.
I tried reading the dirty state of the associated BaseDraw but that didn't seem to work. Is this a priority issue? Is there an alternative method to trigger calculation of the field when manipulating the active camera?
Thanks.
-
Hi,
while i understood the issue with the camera it is a bit hard to be sure where you are checking the camera dirty state on your field object.
Would it be possible to share your scene or code so we can reproduce the issue faster without guessing what you did?
Cheers,
Manuel -
@manuel thanks for getting back to me and apologies for the delay in providing more information.
I'm attaching a C4D scene file here that includes the setup with Python Field and Camera object.
The part of the code where I'm attempting to trigger a refresh of the sampling is in the
InitSampling()
function and it's pretty simple:if camera.GetDirty(c4d.DIRTYFLAGS_MATRIX | c4d.DIRTYFLAGS_DATA): op.SetDirty(c4d.DIRTYFLAGS_DATA)
I had also attempted getting the active BaseDraw from the document, checking whether it's linked camera was the one linked in the field, and checking the BaseDraw dirty state instead of the camera but that didn't work out.
I've also noticed that if I transform the camera and undo the transform the field does not update.
-
hi,
The camera is a special beast in some cases. Fields also. They are supposed to trigger the less updates possible.
There is no direct way of fixing this issue. One workaround (pretty dirty) is to create a python tag attached to your plain effector.
As showed in this thread, this python tag can register and react to an event.The idea is to set the effector itself or the field layer dirty. (Not the field object).
You can react to the message that have the ID c4d.MSG_GETREALCAMERADATA. If this message is received, then you can set the effector dirty. This will trigger the field layer to be recalculated and the field object to be re-evaluated.This is a bit dirty because the effector will be re-evaluated every time you move the camera, even if this is the viewport camera.
But you can add a few lines of code to check if the active camera is the object camera linked in your field object.For this to work, you must use the function AddEventNotification. Have a look at the c++ documentation as it is more precise in the way it describes the flags to use.
Be aware that will also slow down the viewport as maybe some useless calculation will be triggered.
import c4d def message(msgType, data): if msgType == c4d.MSG_NOTIFY_EVENT: if data["eventid"] == c4d.NOTIFY_EVENT_MESSAGE: if data["event_data"]["msg_id"] == c4d.MSG_GETREALCAMERADATA: obj = op.GetObject() obj.SetDirty(c4d.DIRTYFLAGS_DATA) def main(): obj = op.GetObject() # Chekc if the event nofication is already added otherwise add it. if not obj.FindEventNotification(doc, op, c4d.NOTIFY_EVENT_MESSAGE): obj.AddEventNotification(op, c4d.NOTIFY_EVENT_MESSAGE, c4d.NOTIFY_EVENT_FLAG_COPY, c4d.BaseContainer()) if __name__=='__main__': main()
Cheers,
Manuel -
@manuel Amazing! Thank you for stepping through this with me.
I was thinking that messages could be the solution here but I'd only ever dealt with them in the context of a MessageData plug-in and was not aware of
AddEventNotification()
. -
Calling
AddEventNotification()
in Python seems to consistently crash Cinema 4D -
hi,
it happens with the scene you provided ? -
Hello @wuzelwazel,
without further questions or postings, we will consider this topic as solved by Friday 02/06/2023 and flag it accordingly.
Thank you for your understanding,
Maxime.