A single property
Think of a property layout akin to python's getattr
If we want the value of foo.bar.foo
it's getattr(foo.bar, "foo")
never getattr(foo, "bar.foo")
Avoid using foo.bar["Foo"]
IMO get out of the habit of using, in this example
camera = bpy.data.objects['Camera']
which will fail (throw a KeyError
) if there is no object named camera, which could simply mean its been renamed, or is camera in a different language etc. It could be the camera linked to another scene, or no scene at all... in which case sliding it would appear to do nought.
Use Scene Camera
Suggest in the case of camera, the active camera is assigned to the scene, scene.camera
. As long as this is set can use instead. This is the goto camera when pressing Numpad 0 for camera view.
Object Data Properties
With a camera active or pinned, the object of interest in the object data properties tab (camera icon) in the properties panel is its data. In the usual case of it being the context object.
>>> C.object
bpy.data.objects['Camera']
>>> C.object.data
bpy.data.cameras['Camera']
>>> C.object.data.dof.aperture_fstop
44.41624069213867
>>> C.scene.camera
bpy.data.objects['Camera']
Putting it all together
Have added some changes to code below. Without having the operators mentioned in question have replaced with splash screen proxies. Am assuming that the operators use the context object to set the focus object.
Once again use of the scene camera in those operators would make more sense than relying on the camera named "Camera" being the active camera.
A poll method is added to ensure the scene has an active camera. A poll method on your other custom operators could test for active object. If there is no active object and hence they don't poll, the buttons will appear disabled.
A simple way to have layout in rows is to use one column layout.
Test code.
import bpy
class VIEW3D_PT_dof(bpy.types.Panel):
bl_idname = "VIEW3D_PT_dof"
bl_label = "Quick Focus"
bl_category = "DOF"
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
@classmethod
def poll(cls, context):
return context.scene.camera is not None
def draw_header(self, context):
layout = self.layout
layout.label(icon='CAMERA_DATA')
def draw(self, context):
layout = self.layout
cam = context.scene.camera
col = layout.column()
#col.label(text= "Focus", icon='CAMERA_DATA')
col.operator("wm.splash")
col.operator("wm.splash")
col.prop(cam.data.dof, "aperture_fstop", slider=True)
classes = (
VIEW3D_PT_dof,
)
def register():
for cls in classes:
bpy.utils.register_class(cls)
def unregister():
for cls in reversed(classes):
bpy.utils.unregister_class(cls)
if __name__ == "__main__":
register()
layout.prop(context.object.data.dof, "aperture_fstop")
orlayout.prop(context.object.data, "lens")
Also I'd suggest add a poll method to only display the panel only if the selected object's type is'CAMERA'
Recommend against using using the index operator[]
->return context.object.type == 'CAMERA'
$\endgroup$