1

Is there is a way to check when the Active camera has been changed? I'd like to change some Scene settings depending on the camera you look through, and I'm looking for a way to know when a new camera is set as the active camera.

I'd prefer to avoid having to create a custom function to replace the "Set Active Object as Camera".

Thanks!

chafouin
  • 328
  • 1
  • 9
  • Related : https://blender.stackexchange.com/a/90723/29586 - changing properties based on the active camera using drivers. – Rich Sedman Nov 15 '18 at 10:31

3 Answers3

3

Properties updates and handlers

enter image description here

  • Added a scene pointer property (x_camera for want of a better name) which points to a blender object type. The poll method lets it be narrowed down to those of type 'CAMERA'

  • Scene.x_camera has an update method for when this object is changed and changes scene camera to match.

  • Added the property to the UI in the scene panel. The benefit of this approach is the user can choose a camera, and run code based on this choice.

  • Next added a simple getter boolean property, cam_change that is false when our pointer property camera is not the scene camera

  • To handle other ways the active camera is set, eg keystrokes, or markers, a handler is used. The scene update pre handler ticks over a lot. Another boolean could be utilized to turn the handler on or off.

Test code below. Added a couple of convenience methods to uncomment and remove handlers and panel draw_methods.

import bpy
from bpy.props import PointerProperty, BoolProperty

def cam_changed(self):
    return self.x_camera is not self.camera

def cam_update(self, context):
    if self.cam_changed:
        self.camera = self.x_camera
        print("UI UPDATE")
    else:
        print("HANDER UPDATE")

def cam_update_handler(scene):
    if scene.cam_changed:
        scene.x_camera = scene.camera

def cam_poll(self, object):
    return object.type == 'CAMERA'

bpy.types.Scene.x_camera = PointerProperty(
        type=bpy.types.Object,
        update=cam_update,
        poll=cam_poll,
        )

bpy.types.Scene.cam_changed = BoolProperty(
        get=cam_changed
        )

def cam_draw(self, context):
    layout = self.layout
    scene = context.scene
    row = layout.row()
    row.alert = scene.cam_changed
    row.prop(scene, "x_camera")

bpy.types.SCENE_PT_scene.prepend(cam_draw)

# handler

bpy.app.handlers.scene_update_pre.append(cam_update_handler)


def remove_handlers(prefix, handler):
    handlers = getattr(bpy.app.handlers, handler, [])
    remove = (h for h in handers
            if h.__name__.startswith(prefix))
    for h in remove:
        handlers.remove(h)

#emove_handlers("cam_", "scene_update_pre")        

def remove_draw_funcs(prefix, panel):
    funcs = getattr(panel.draw, "_draw_funcs", [])
    remove = (f for f in funcs
            if f.__name__.startswith(prefix))
    for f in remove:
        panel.remove(f)

#remove_draw_funcs("cam_", bpy.types.SCENE_PT_scene)
batFINGER
  • 84,216
  • 10
  • 108
  • 233
0

You need to specify hadnler function with simple condition:

cam_current = None
def camera_handler(scene):            # handler function with condition
    global cam_current                # get global value
    if cam_current != scene.camera: # if camera was chaged
        print('camera was changed')   # print 'camera was changed'
        cam_current = scene.camera  # prevent next actions until camera will be changed

bpy.app.handlers.depsgraph_update_post.append(camera_handler)

Martynas Žiemys
  • 24,274
  • 2
  • 34
  • 77
Bicukow
  • 901
  • 1
  • 5
  • 18
-1

I found a solution by using Animation Nodes add-on.

You just need to set different value of Pass Index (Object Tab) for every camera. And this node-tree will check camera's Pass Index and send its value to rotate Empty. Now you can extract rotation data from Empty and drive everything you need in the scene.

For example, Cube is rotating in accordance with active camera (all cameras are binded to timeline markers).

enter image description here

Serge L
  • 3,915
  • 1
  • 17
  • 33