123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557 |
- # ##### BEGIN GPL LICENSE BLOCK #####
- #
- # This program is free software; you can redistribute it and/or
- # modify it under the terms of the GNU General Public License
- # as published by the Free Software Foundation; either version 2
- # of the License, or (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program; if not, write to the Free Software Foundation,
- # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- #
- # ##### END GPL LICENSE BLOCK #####
- # <pep8 compliant>
- import bpy
- from bpy.types import Panel
- from rna_prop_ui import PropertyPanel
- from bl_ui.utils import PresetPanel
- class CameraButtonsPanel:
- bl_space_type = 'PROPERTIES'
- bl_region_type = 'WINDOW'
- bl_context = "data"
- @classmethod
- def poll(cls, context):
- engine = context.engine
- return context.camera and (engine in cls.COMPAT_ENGINES)
- class CAMERA_PT_presets(PresetPanel, Panel):
- bl_label = "Camera Presets"
- preset_subdir = "camera"
- preset_operator = "script.execute_preset"
- preset_add_operator = "camera.preset_add"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
- class SAFE_AREAS_PT_presets(PresetPanel, Panel):
- bl_label = "Camera Presets"
- preset_subdir = "safe_areas"
- preset_operator = "script.execute_preset"
- preset_add_operator = "safe_areas.preset_add"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
- class DATA_PT_context_camera(CameraButtonsPanel, Panel):
- bl_label = ""
- bl_options = {'HIDE_HEADER'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
- def draw(self, context):
- layout = self.layout
- ob = context.object
- cam = context.camera
- space = context.space_data
- if ob:
- layout.template_ID(ob, "data")
- elif cam:
- layout.template_ID(space, "pin_id")
- class DATA_PT_lens(CameraButtonsPanel, Panel):
- bl_label = "Lens"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
- cam = context.camera
- layout.prop(cam, "type")
- col = layout.column()
- col.separator()
- if cam.type == 'PERSP':
- col = layout.column()
- if cam.lens_unit == 'MILLIMETERS':
- col.prop(cam, "lens")
- elif cam.lens_unit == 'FOV':
- col.prop(cam, "angle")
- col.prop(cam, "lens_unit")
- elif cam.type == 'ORTHO':
- col.prop(cam, "ortho_scale")
- elif cam.type == 'PANO':
- engine = context.engine
- if engine == 'CYCLES':
- ccam = cam.cycles
- col.prop(ccam, "panorama_type")
- if ccam.panorama_type == 'FISHEYE_EQUIDISTANT':
- col.prop(ccam, "fisheye_fov")
- elif ccam.panorama_type == 'FISHEYE_EQUISOLID':
- col.prop(ccam, "fisheye_lens", text="Lens")
- col.prop(ccam, "fisheye_fov")
- elif ccam.panorama_type == 'EQUIRECTANGULAR':
- sub = col.column(align=True)
- sub.prop(ccam, "latitude_min", text="Latitude Min")
- sub.prop(ccam, "latitude_max", text="Max")
- sub = col.column(align=True)
- sub.prop(ccam, "longitude_min", text="Longitude Min")
- sub.prop(ccam, "longitude_max", text="Max")
- elif engine in {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}:
- if cam.lens_unit == 'MILLIMETERS':
- col.prop(cam, "lens")
- elif cam.lens_unit == 'FOV':
- col.prop(cam, "angle")
- col.prop(cam, "lens_unit")
- col = layout.column()
- col.separator()
- sub = col.column(align=True)
- sub.prop(cam, "shift_x", text="Shift X")
- sub.prop(cam, "shift_y", text="Y")
- col.separator()
- sub = col.column(align=True)
- sub.prop(cam, "clip_start", text="Clip Start")
- sub.prop(cam, "clip_end", text="End")
- class DATA_PT_camera_stereoscopy(CameraButtonsPanel, Panel):
- bl_label = "Stereoscopy"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
- @classmethod
- def poll(cls, context):
- render = context.scene.render
- return (super().poll(context) and render.use_multiview and
- render.views_format == 'STEREO_3D')
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
- render = context.scene.render
- st = context.camera.stereo
- cam = context.camera
- is_spherical_stereo = cam.type != 'ORTHO' and render.use_spherical_stereo
- use_spherical_stereo = is_spherical_stereo and st.use_spherical_stereo
- layout.prop(st, "convergence_mode")
- col = layout.column()
- sub = col.column()
- sub.active = st.convergence_mode != 'PARALLEL'
- sub.prop(st, "convergence_distance")
- col.prop(st, "interocular_distance")
- if is_spherical_stereo:
- col.separator()
- col.prop(st, "use_spherical_stereo")
- sub = col.column()
- sub.active = st.use_spherical_stereo
- sub.prop(st, "use_pole_merge")
- sub = col.column(align=True)
- sub.active = st.use_pole_merge
- sub.prop(st, "pole_merge_angle_from", text="Pole Merge Angle Start")
- sub.prop(st, "pole_merge_angle_to", text="End")
- col = layout.column()
- col.active = not use_spherical_stereo
- col.separator()
- col.prop(st, "pivot")
- class DATA_PT_camera(CameraButtonsPanel, Panel):
- bl_label = "Camera"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
- def draw_header_preset(self, _context):
- CAMERA_PT_presets.draw_panel_header(self.layout)
- def draw(self, context):
- layout = self.layout
- cam = context.camera
- layout.use_property_split = True
- col = layout.column()
- col.prop(cam, "sensor_fit")
- if cam.sensor_fit == 'AUTO':
- col.prop(cam, "sensor_width", text="Size")
- else:
- sub = col.column(align=True)
- sub.active = cam.sensor_fit == 'HORIZONTAL'
- sub.prop(cam, "sensor_width", text="Width")
- sub = col.column(align=True)
- sub.active = cam.sensor_fit == 'VERTICAL'
- sub.prop(cam, "sensor_height", text="Height")
- class DATA_PT_camera_dof(CameraButtonsPanel, Panel):
- bl_label = "Depth of Field"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
- def draw_header(self, context):
- cam = context.camera
- dof = cam.dof
- self.layout.prop(dof, "use_dof", text="")
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
- cam = context.camera
- dof = cam.dof
- layout.active = dof.use_dof
- col = layout.column()
- col.prop(dof, "focus_object", text="Focus on Object")
- sub = col.column()
- sub.active = (dof.focus_object is None)
- sub.prop(dof, "focus_distance", text="Focus Distance")
- class DATA_PT_camera_dof_aperture(CameraButtonsPanel, Panel):
- bl_label = "Aperture"
- bl_parent_id = "DATA_PT_camera_dof"
- COMPAT_ENGINES = {'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
- cam = context.camera
- dof = cam.dof
- layout.active = dof.use_dof
- flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
- col = flow.column()
- col.prop(dof, "aperture_fstop")
- col = flow.column()
- col.prop(dof, "aperture_blades")
- col.prop(dof, "aperture_rotation")
- col.prop(dof, "aperture_ratio")
- class DATA_PT_camera_background_image(CameraButtonsPanel, Panel):
- bl_label = "Background Images"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
- def draw_header(self, context):
- cam = context.camera
- self.layout.prop(cam, "show_background_images", text="")
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
- layout.use_property_decorate = False
- cam = context.camera
- use_multiview = context.scene.render.use_multiview
- col = layout.column()
- col.operator("view3d.background_image_add", text="Add Image")
- for i, bg in enumerate(cam.background_images):
- layout.active = cam.show_background_images
- box = layout.box()
- row = box.row(align=True)
- row.prop(bg, "show_expanded", text="", emboss=False)
- if bg.source == 'IMAGE' and bg.image:
- row.prop(bg.image, "name", text="", emboss=False)
- elif bg.source == 'MOVIE_CLIP' and bg.clip:
- row.prop(bg.clip, "name", text="", emboss=False)
- elif bg.source and bg.use_camera_clip:
- row.label(text="Camera Clip")
- else:
- row.label(text="Not Set")
- row.prop(
- bg,
- "show_background_image",
- text="",
- emboss=False,
- icon='RESTRICT_VIEW_OFF' if bg.show_background_image else 'RESTRICT_VIEW_ON',
- )
- row.operator("view3d.background_image_remove", text="", emboss=False, icon='X').index = i
- if bg.show_expanded:
- row = box.row()
- row.prop(bg, "source", expand=True)
- has_bg = False
- if bg.source == 'IMAGE':
- row = box.row()
- row.template_ID(bg, "image", open="image.open")
- if bg.image is not None:
- box.template_image(bg, "image", bg.image_user, compact=True)
- has_bg = True
- if use_multiview:
- box.prop(bg.image, "use_multiview")
- column = box.column()
- column.active = bg.image.use_multiview
- column.label(text="Views Format:")
- column.row().prop(bg.image, "views_format", expand=True)
- sub = column.box()
- sub.active = bg.image.views_format == 'STEREO_3D'
- sub.template_image_stereo_3d(bg.image.stereo_3d_format)
- elif bg.source == 'MOVIE_CLIP':
- box.prop(bg, "use_camera_clip")
- column = box.column()
- column.active = not bg.use_camera_clip
- column.template_ID(bg, "clip", open="clip.open")
- if bg.clip:
- column.template_movieclip(bg, "clip", compact=True)
- if bg.use_camera_clip or bg.clip:
- has_bg = True
- column = box.column()
- column.active = has_bg
- column.prop(bg.clip_user, "use_render_undistorted")
- column.prop(bg.clip_user, "proxy_render_size")
- if has_bg:
- col = box.column()
- col.prop(bg, "alpha", slider=True)
- col.row().prop(bg, "display_depth", expand=True)
- col.row().prop(bg, "frame_method", expand=True)
- row = box.row()
- row.prop(bg, "offset")
- col = box.column()
- col.prop(bg, "rotation")
- col.prop(bg, "scale")
- col.prop(bg, "use_flip_x")
- col.prop(bg, "use_flip_y")
- class DATA_PT_camera_display(CameraButtonsPanel, Panel):
- bl_label = "Viewport Display"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
- cam = context.camera
- col = layout.column(align=True)
- col.separator()
- col.prop(cam, "display_size", text="Size")
- col.separator()
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=False, even_rows=False, align=False)
- col = flow.column()
- col.prop(cam, "show_limits", text="Limits")
- col = flow.column()
- col.prop(cam, "show_mist", text="Mist")
- col = flow.column()
- col.prop(cam, "show_sensor", text="Sensor")
- col = flow.column()
- col.prop(cam, "show_name", text="Name")
- class DATA_PT_camera_display_composition_guides(CameraButtonsPanel, Panel):
- bl_label = "Composition Guides"
- bl_parent_id = "DATA_PT_camera_display"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
- cam = context.camera
- flow = layout.grid_flow(row_major=False, columns=0, even_columns=False, even_rows=False, align=False)
- col = flow.column()
- col.prop(cam, "show_composition_center")
- col = flow.column()
- col.prop(cam, "show_composition_center_diagonal")
- col = flow.column()
- col.prop(cam, "show_composition_thirds")
- col = flow.column()
- col.prop(cam, "show_composition_golden")
- col = flow.column()
- col.prop(cam, "show_composition_golden_tria_a")
- col = flow.column()
- col.prop(cam, "show_composition_golden_tria_b")
- col = flow.column()
- col.prop(cam, "show_composition_harmony_tri_a")
- col = flow.column()
- col.prop(cam, "show_composition_harmony_tri_b")
- class DATA_PT_camera_display_passepartout(CameraButtonsPanel, Panel):
- bl_label = "Passepartout"
- bl_parent_id = "DATA_PT_camera_display"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
- def draw_header(self, context):
- cam = context.camera
- self.layout.prop(cam, "show_passepartout", text="")
- def draw(self, context):
- layout = self.layout
- layout.use_property_split = True
- cam = context.camera
- layout.active = cam.show_passepartout
- layout.prop(cam, "passepartout_alpha", text="Opacity", slider=True)
- class DATA_PT_camera_safe_areas(CameraButtonsPanel, Panel):
- bl_label = "Safe Areas"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
- def draw_header(self, context):
- cam = context.camera
- self.layout.prop(cam, "show_safe_areas", text="")
- def draw_header_preset(self, _context):
- SAFE_AREAS_PT_presets.draw_panel_header(self.layout)
- def draw(self, context):
- layout = self.layout
- safe_data = context.scene.safe_areas
- camera = context.camera
- layout.use_property_split = True
- layout.active = camera.show_safe_areas
- col = layout.column()
- sub = col.column()
- sub.prop(safe_data, "title", slider=True)
- sub.prop(safe_data, "action", slider=True)
- class DATA_PT_camera_safe_areas_center_cut(CameraButtonsPanel, Panel):
- bl_label = "Center-Cut Safe Areas"
- bl_parent_id = "DATA_PT_camera_safe_areas"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
- def draw_header(self, context):
- cam = context.camera
- layout = self.layout
- layout.active = cam.show_safe_areas
- layout.prop(cam, "show_safe_center", text="")
- def draw(self, context):
- layout = self.layout
- safe_data = context.scene.safe_areas
- camera = context.camera
- layout.use_property_split = True
- layout.active = camera.show_safe_areas and camera.show_safe_center
- col = layout.column()
- col.prop(safe_data, "title_center", slider=True)
- class DATA_PT_custom_props_camera(CameraButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
- _context_path = "object.data"
- _property_type = bpy.types.Camera
- def draw_display_safe_settings(layout, safe_data, settings):
- show_safe_areas = settings.show_safe_areas
- show_safe_center = settings.show_safe_center
- layout.use_property_split = True
- col = layout.column()
- col.active = show_safe_areas
- sub = col.column()
- sub.prop(safe_data, "title", slider=True)
- sub.prop(safe_data, "action", slider=True)
- col.separator()
- col.prop(settings, "show_safe_center", text="Center-Cut Safe Areas")
- sub = col.column()
- sub.active = show_safe_areas and show_safe_center
- sub.prop(safe_data, "title_center", slider=True)
- sub.prop(safe_data, "action_center", slider=True)
- classes = (
- CAMERA_PT_presets,
- SAFE_AREAS_PT_presets,
- DATA_PT_context_camera,
- DATA_PT_lens,
- DATA_PT_camera_dof,
- DATA_PT_camera_dof_aperture,
- DATA_PT_camera,
- DATA_PT_camera_stereoscopy,
- DATA_PT_camera_safe_areas,
- DATA_PT_camera_safe_areas_center_cut,
- DATA_PT_camera_background_image,
- DATA_PT_camera_display,
- DATA_PT_camera_display_composition_guides,
- DATA_PT_camera_display_passepartout,
- DATA_PT_custom_props_camera,
- )
- if __name__ == "__main__": # only for live edit.
- from bpy.utils import register_class
- for cls in classes:
- register_class(cls)
|