8
$\begingroup$

I am trying to loop over all the cameras in my scene to populate a menu, and be able to access properties of each camera from the submenu of each menu item. For the minute, I'm just trying to get it to work with one property, the focal length:

enter image description here

I am able to loop over each camera and create a menu item by simply using the camera.name property in the text property of the menu item:

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

    for camera in bpy.data.cameras:

        row = layout.row()

        row.menu(CamerasSubMenu.bl_idname, text=camera.name)

However, what I don't really know how to do is make each submenu's properties relate to whichever camera I selected in the first menu. I managed to pass the camera_name to the submenu class with this in the last line of the camera loop:

CamerasSubMenu.camera_name = camera.name  

And then access it with:

class CamerasSubMenu(bpy.types.Menu):
    bl_label = "Camera Properties"
    bl_idname = "view3d.camera_properties_menu"

    camera_name = bpy.props.StringProperty()

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

        row = layout.row()
        row.prop(bpy.data.cameras[self.camera_name], "lens")    

But the lens property (the focal length) is always the focal length of whichever camera name got passed in last in the loop, e.g. 'Camera.001'. So all submenus are accessing Camera.001's focal length instead of the individual focal lengths.

I presume I'm going about this completely the wrong way, but I attempted it in a similar way I would pass data to an operator (which works).

So, is there a way to have a unique submenu per camera or should I just try something completely different?

Full code:

import bpy

class CamerasSubMenu(bpy.types.Menu):
    bl_label = "Camera Properties"
    bl_idname = "view3d.camera_properties_menu"

    camera_name = bpy.props.StringProperty()

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

        row = layout.row()
        row.prop(bpy.data.cameras[self.camera_name], "lens")    


class CamerasMenu(bpy.types.Menu):
    bl_label = "Cameras"
    bl_idname = "view3d.cameras_menu"

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

        for camera in bpy.data.cameras:

            row = layout.row()

            row.menu(CamerasSubMenu.bl_idname,text=camera.name)

            CamerasSubMenu.camera_name = camera.name      


def register():
    bpy.utils.register_module(__name__)    


def unregister():
    bpy.utils.unregister_module(__name__)  

if __name__ == "__main__":
    register()


bpy.ops.wm.call_menu(name=CamerasMenu.bl_idname)                
$\endgroup$
7
$\begingroup$

You can make each submenu have its own context by setting a variable in the UILayout.

The script can be made to work as expected with only minor changes.

Modified example script:

import bpy

class CamerasSubMenu(bpy.types.Menu):
    bl_label = "Camera Properties"
    bl_idname = "view3d.camera_properties_menu"

    # <-- Line removed (menu's don't store properties)

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

        row = layout.row()
        row.prop(context.my_camera, "lens")  # <-- Changed from original


class CamerasMenu(bpy.types.Menu):
    bl_label = "Cameras"
    bl_idname = "view3d.cameras_menu"

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

        for camera in bpy.data.cameras:

            row = layout.row()

            row.context_pointer_set("my_camera", camera)  # <-- Added to original
            row.menu(CamerasSubMenu.bl_idname, text=camera.name)
            # <-- Line removed (camera set above)

def register():
    bpy.utils.register_module(__name__)    


def unregister():
    bpy.utils.unregister_module(__name__)  

if __name__ == "__main__":
    register()


bpy.ops.wm.call_menu(name=CamerasMenu.bl_idname)      
$\endgroup$
  • 2
    $\begingroup$ Thank you, that's brilliant. Had no idea about context_pointer_set $\endgroup$ – Ray Mairlot Jan 29 '16 at 10:22

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.