1
$\begingroup$

I am writing an operator to create a new camera to capture one frame renders, thumbnails etc.

It works if you are in a 3D View and not looking through an existing camera. However if you are looking through a camera it fails here: 'RuntimeError: Operator bpy.ops.view3d.camera_to_view.poll() failed, context is incorrect'

I'm confused as I believe the context should be correct? Any help much appreciated.

import bpy


class OBJECT_OT_make_test_camera(bpy.types.Operator):
    """Make a test camera"""
    bl_idname = "object.make_test_camera"
    bl_label = "Make Test Camera"

    @classmethod
    def poll(cls, context):
        return context.area.type == 'VIEW_3D'

    def execute(self, context):
        cameraName = "SimpleRenderCam"
        cam = bpy.data.cameras.new(cameraName)
        cam.lens = 90
        cameraObject = bpy.data.objects.new(cameraName, cam)
        bpy.context.scene.collection.objects.link(cameraObject)
        bpy.context.scene.camera = bpy.data.objects[cameraObject.name]
        area = bpy.context.area.type
        print(str(area))
        bpy.ops.view3d.camera_to_view()
        return{'FINISHED'}


class VIEW_3D_PT_test_camera(bpy.types.Panel):
    """Creates a Panel in the Object properties window"""
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = "Test Camera"
    bl_label = "Create camera to test area"
    # bl_context = "object"

    def draw(self, context):
        layout = self.layout

        area = bpy.context.area.type

        row = layout.row(align=True)
        row.label(text="View type is:")
        row.label(text=str(area))

        row = layout.row()
        row.operator('object.make_test_camera')


def register():
    bpy.utils.register_class(VIEW_3D_PT_test_camera)
    bpy.utils.register_class(OBJECT_OT_make_test_camera)


def unregister():
    bpy.utils.unregister_class(VIEW_3D_PT_test_camera)
    bpy.utils.unregister_class(OBJECT_OT_make_test_camera)


if __name__ == "__main__":
    register()
```
$\endgroup$

1 Answer 1

2
$\begingroup$

The operator does not poll in 'CAMERA' view.

Conveniently when using an operator that relies on another, can use the others poll method as our own.

The button will now be disabled when the operator does not poll, and avoid the error above. The operator is also disabled in the Align View menu

enter image description here Button disabled in Camera Perspective View

This is perhaps a good thing since you get in this state by assigning camera to view, and will have to re-orientate to make the op viable again.

Otherwise set the 3d viewport to another mode or tweak view matrix slightly to move from camera view.

import bpy


class OBJECT_OT_make_test_camera(bpy.types.Operator):
    """Make a test camera"""
    bl_idname = "object.make_test_camera"
    bl_label = "Make Test Camera"

    @classmethod
    def poll(cls, context):
        return bpy.ops.view3d.camera_to_view.poll()

    def execute(self, context):
        cameraName = "SimpleRenderCam"
        cam = bpy.data.cameras.new(cameraName)
        cam.lens = 90
        cameraObject = bpy.data.objects.new(cameraName, cam)
        context.scene.collection.objects.link(cameraObject)
        context.scene.camera = cameraObject
        print(context.area.type)
        bpy.ops.view3d.camera_to_view()
        return{'FINISHED'}


class VIEW_3D_PT_test_camera(bpy.types.Panel):
    """Creates a Panel in the Object properties window"""
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = "Test Camera"
    bl_label = "Create camera to test area"
    # bl_context = "object"

    def draw(self, context):
        layout = self.layout

        row = layout.row(align=True)
        row.label(text="View type is:")
        row.label(text=f"{context.area.type}")

        row = layout.row()
        row.operator('object.make_test_camera')


def register():
    bpy.utils.register_class(VIEW_3D_PT_test_camera)
    bpy.utils.register_class(OBJECT_OT_make_test_camera)


def unregister():
    bpy.utils.unregister_class(VIEW_3D_PT_test_camera)
    bpy.utils.unregister_class(OBJECT_OT_make_test_camera)


if __name__ == "__main__":
    register()

To make the operator return in a state to run again, set the view to perspective before return in operator execute.

        context.space_data.region_3d.view_perspective = 'PERSP'
        return{'FINISHED'}

To have your operator poll and run in camera view add an or clause .

return bpy.ops.view3d.camera_to_view.poll() or context.space_data.region_3d.view_perspective == 'CAMERA'

Since the view operator wont poll outside 3d view, this being false saves us the need to worry that the space is anything but a 3d space.

Will also have to set the view before calling operator to avoid the operator poll.

$\endgroup$
4
  • $\begingroup$ Great explanation. One thing I'm not seeing at the moment when testing polling the camera_to_view operator is the button being disabled when looking through a camera. I can see that the operator in the view menu is disabled though. Did I misunderstand something? $\endgroup$
    – Mal Reed
    May 28, 2020 at 8:13
  • $\begingroup$ Not sure. Added an image showing button in Camera view disabled via camera to view poll method. $\endgroup$
    – batFINGER
    May 28, 2020 at 8:22
  • $\begingroup$ Ok try now. Lost a poll() pasting it appears. Handy little op btw, found I've used it heaps already. $\endgroup$
    – batFINGER
    May 28, 2020 at 8:26
  • $\begingroup$ Ah yeah, working now. Very handy indeed, I hadn't realised you could use poll to that extent. Many thanks :) $\endgroup$
    – Mal Reed
    May 28, 2020 at 12:02

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .