I am adding a bunch of properties to cameras with my add-on. To support animation during renders, I add a frame_change_post handler like this:

import bpy
from bpy.app.handlers import persistent
from .camera import PhotographerCameraSettings

def update_render_camera(self,depsgraph):
    camera_ob = bpy.context.scene.camera
    camera_ob_eval = camera_ob.evaluated_get(depsgraph)
    # Dictionary of Photographer Camera properties
    for key in PhotographerCameraSettings.__annotations__.keys():
            key_eval = camera_ob_eval.data.photographer[key]
            camera_ob.data.photographer[key] = key_eval
        except KeyError:
            # Properties that haven't been changed will return a KeyError

def register():

It works fine, except for the first frame of the render if the current frame is different.

For instance, if I render from frame 1 to 10, and in the viewport I am looking at frame 5, then when rendering the animation (CTRL+F12), frame 1 will use camera property values of frame 5. Frame 2 gets updated properly and the renders continues fine.

It seems that the frame_change_post doesn't get triggered when moving to the first frame. Is there a way to fix it?

  • 1
    $\begingroup$ IMO don't mix context and handlers. First argument of a handler is scene. The intersection of annotation keys and object keys eg (ob.data.keys()) would remove the need for try catch. TBH not sure what this is doing? consider a setter / getter on the property instead. Assuming you are looking for properties that haven't been set, rather than changed. $\endgroup$ – batFINGER May 13 at 17:01
  • $\begingroup$ Maybe the intersection of the camera_ob_eval then, because I think the object.data would have all the keys. Properties use update functions, isn't that a correct way to do it? I am looking for properties that have been set and not using default values, and make sure they are evaluated for animation. Annotation keys don't exists if they haven't been set. I am not sure I understand how to make sure animations are evaluated for viewport and rendering, is it just because I should use get/set? $\endgroup$ – chafouin May 13 at 19:47
  • 1
    $\begingroup$ To check if set can also use ob.is_property_set("foo") , used in conjunction with getattr(ob, "foo") (ie avoid try catch see best practices in API manual) Re the getter setter example on the properties page see blender.stackexchange.com/a/134310/15543 Might pay to have a look at the auto tile size addon for cycles. On start has a button to fix what appears to be a similar situation as here. May also pay to add a test example of your property group class and property update method. $\endgroup$ – batFINGER May 14 at 8:35
  • $\begingroup$ Thanks a lot for your help. I have removed the try catch with the intersection you mentioned, but in the end I am replacing update functions with getter setter, it fixes the first frame issue. Is it OK to access bpy.context from a set function though? $\endgroup$ – chafouin May 14 at 20:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.