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?