Writes to camera.matrix_local are applied, but can't be read back

I have the following function which gets called from operator modal() MOUSEMOVE and INBETWEEN_MOUSEMOVE event handling; viewPos and viewRot represent transform components to be applied to whatever camera is currently being locked to view. They are set according to mouse movements.

def applyCameraTranformation(sv3d: bpy.types.SpaceView3D, rv3d: bpy.types.RegionView3D, viewPos: Vector, viewRot: Quaternion):
    if rv3d.view_perspective == "CAMERA" and sv3d.lock_camera and sv3d.camera is not None:
        axis, angle = viewRot.to_axis_angle()
        scale = sv3d.camera.matrix_local.to_scale()
        mat = mathutils.Matrix.Translation(viewPos) @ mathutils.Matrix.Rotation(angle, 4, axis) @ mathutils.Matrix.Diagonal(Vector((scale[0], scale[1], scale[2], 1)))
        isChange = mat != sv3d.camera.matrix_local
        sv3d.camera.matrix_local = mat
        isApplied = mat == sv3d.camera.matrix_local
        if isChange and not isApplied:
            print(f"isChange and not isApplied! Matrices (applied, current):\n{mat}\n{sv3d.camera.matrix_local}")

I would expect the print statement to never be reached. However, here is an excerpt from the logs after briefly swinging my mouse around:

isChange and not isApplied! Matrices (applied, current):
<Matrix 4x4 ( 0.7080, 0.3967, -0.5842,  7.3589)
            (-0.7062, 0.3977, -0.5858, -6.9258)
            ( 0.0000, 0.8273,  0.5617,  4.9583)
            ( 0.0000, 0.0000,  0.0000,  1.0000)>
<Matrix 4x4 ( 0.7206, 0.3895, -0.5736,  7.3589)
            (-0.6933, 0.4048, -0.5962, -6.9258)
            ( 0.0000, 0.8273,  0.5617,  4.9583)
            ( 0.0000, 0.0000,  0.0000,  1.0000)>
isChange and not isApplied! Matrices (applied, current):
<Matrix 4x4 ( 0.5922, 0.4527, -0.6667,  7.3589)
            (-0.8058, 0.3326, -0.4899, -6.9258)
            ( 0.0000, 0.8273,  0.5617,  4.9583)
            ( 0.0000, 0.0000,  0.0000,  1.0000)>
<Matrix 4x4 ( 0.7080, 0.3967, -0.5842,  7.3589)
            (-0.7062, 0.3977, -0.5858, -6.9258)
            ( 0.0000, 0.8273,  0.5617,  4.9583)
            ( 0.0000, 0.0000,  0.0000,  1.0000)>

It would seem that setting camera.matrix_local is applied only before handling of the next event begins? This sort of is a problem for me, because I rely on reading camera.matrix_local in a timer registered with bpy.app.timers.register() to make other changes. However, since I consistently get the old value when reading camera.matrix_local, I end up overwriting changes made by applyCameraTransformation(). Do I need to hack this, or is there some deeper meaning to be understood here?

Have you tried updating the view layer? context.view_layer.update()

[edit- some more info now that I’m not on my phone: https://docs.blender.org/api/current/info_gotcha.html#no-updates-after-setting-values]

2 Likes