properties_data_camera.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
  1. # ##### BEGIN GPL LICENSE BLOCK #####
  2. #
  3. # This program is free software; you can redistribute it and/or
  4. # modify it under the terms of the GNU General Public License
  5. # as published by the Free Software Foundation; either version 2
  6. # of the License, or (at your option) any later version.
  7. #
  8. # This program is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. # GNU General Public License for more details.
  12. #
  13. # You should have received a copy of the GNU General Public License
  14. # along with this program; if not, write to the Free Software Foundation,
  15. # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  16. #
  17. # ##### END GPL LICENSE BLOCK #####
  18. # <pep8 compliant>
  19. import bpy
  20. from bpy.types import Panel
  21. from rna_prop_ui import PropertyPanel
  22. from bl_ui.utils import PresetPanel
  23. class CameraButtonsPanel:
  24. bl_space_type = 'PROPERTIES'
  25. bl_region_type = 'WINDOW'
  26. bl_context = "data"
  27. @classmethod
  28. def poll(cls, context):
  29. engine = context.engine
  30. return context.camera and (engine in cls.COMPAT_ENGINES)
  31. class CAMERA_PT_presets(PresetPanel, Panel):
  32. bl_label = "Camera Presets"
  33. preset_subdir = "camera"
  34. preset_operator = "script.execute_preset"
  35. preset_add_operator = "camera.preset_add"
  36. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  37. class SAFE_AREAS_PT_presets(PresetPanel, Panel):
  38. bl_label = "Camera Presets"
  39. preset_subdir = "safe_areas"
  40. preset_operator = "script.execute_preset"
  41. preset_add_operator = "safe_areas.preset_add"
  42. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  43. class DATA_PT_context_camera(CameraButtonsPanel, Panel):
  44. bl_label = ""
  45. bl_options = {'HIDE_HEADER'}
  46. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  47. def draw(self, context):
  48. layout = self.layout
  49. ob = context.object
  50. cam = context.camera
  51. space = context.space_data
  52. if ob:
  53. layout.template_ID(ob, "data")
  54. elif cam:
  55. layout.template_ID(space, "pin_id")
  56. class DATA_PT_lens(CameraButtonsPanel, Panel):
  57. bl_label = "Lens"
  58. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  59. def draw(self, context):
  60. layout = self.layout
  61. layout.use_property_split = True
  62. cam = context.camera
  63. layout.prop(cam, "type")
  64. col = layout.column()
  65. col.separator()
  66. if cam.type == 'PERSP':
  67. col = layout.column()
  68. if cam.lens_unit == 'MILLIMETERS':
  69. col.prop(cam, "lens")
  70. elif cam.lens_unit == 'FOV':
  71. col.prop(cam, "angle")
  72. col.prop(cam, "lens_unit")
  73. elif cam.type == 'ORTHO':
  74. col.prop(cam, "ortho_scale")
  75. elif cam.type == 'PANO':
  76. engine = context.engine
  77. if engine == 'CYCLES':
  78. ccam = cam.cycles
  79. col.prop(ccam, "panorama_type")
  80. if ccam.panorama_type == 'FISHEYE_EQUIDISTANT':
  81. col.prop(ccam, "fisheye_fov")
  82. elif ccam.panorama_type == 'FISHEYE_EQUISOLID':
  83. col.prop(ccam, "fisheye_lens", text="Lens")
  84. col.prop(ccam, "fisheye_fov")
  85. elif ccam.panorama_type == 'EQUIRECTANGULAR':
  86. sub = col.column(align=True)
  87. sub.prop(ccam, "latitude_min", text="Latitude Min")
  88. sub.prop(ccam, "latitude_max", text="Max")
  89. sub = col.column(align=True)
  90. sub.prop(ccam, "longitude_min", text="Longitude Min")
  91. sub.prop(ccam, "longitude_max", text="Max")
  92. elif engine in {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}:
  93. if cam.lens_unit == 'MILLIMETERS':
  94. col.prop(cam, "lens")
  95. elif cam.lens_unit == 'FOV':
  96. col.prop(cam, "angle")
  97. col.prop(cam, "lens_unit")
  98. col = layout.column()
  99. col.separator()
  100. sub = col.column(align=True)
  101. sub.prop(cam, "shift_x", text="Shift X")
  102. sub.prop(cam, "shift_y", text="Y")
  103. col.separator()
  104. sub = col.column(align=True)
  105. sub.prop(cam, "clip_start", text="Clip Start")
  106. sub.prop(cam, "clip_end", text="End")
  107. class DATA_PT_camera_stereoscopy(CameraButtonsPanel, Panel):
  108. bl_label = "Stereoscopy"
  109. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  110. @classmethod
  111. def poll(cls, context):
  112. render = context.scene.render
  113. return (super().poll(context) and render.use_multiview and
  114. render.views_format == 'STEREO_3D')
  115. def draw(self, context):
  116. layout = self.layout
  117. layout.use_property_split = True
  118. render = context.scene.render
  119. st = context.camera.stereo
  120. cam = context.camera
  121. is_spherical_stereo = cam.type != 'ORTHO' and render.use_spherical_stereo
  122. use_spherical_stereo = is_spherical_stereo and st.use_spherical_stereo
  123. layout.prop(st, "convergence_mode")
  124. col = layout.column()
  125. sub = col.column()
  126. sub.active = st.convergence_mode != 'PARALLEL'
  127. sub.prop(st, "convergence_distance")
  128. col.prop(st, "interocular_distance")
  129. if is_spherical_stereo:
  130. col.separator()
  131. col.prop(st, "use_spherical_stereo")
  132. sub = col.column()
  133. sub.active = st.use_spherical_stereo
  134. sub.prop(st, "use_pole_merge")
  135. sub = col.column(align=True)
  136. sub.active = st.use_pole_merge
  137. sub.prop(st, "pole_merge_angle_from", text="Pole Merge Angle Start")
  138. sub.prop(st, "pole_merge_angle_to", text="End")
  139. col = layout.column()
  140. col.active = not use_spherical_stereo
  141. col.separator()
  142. col.prop(st, "pivot")
  143. class DATA_PT_camera(CameraButtonsPanel, Panel):
  144. bl_label = "Camera"
  145. bl_options = {'DEFAULT_CLOSED'}
  146. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  147. def draw_header_preset(self, _context):
  148. CAMERA_PT_presets.draw_panel_header(self.layout)
  149. def draw(self, context):
  150. layout = self.layout
  151. cam = context.camera
  152. layout.use_property_split = True
  153. col = layout.column()
  154. col.prop(cam, "sensor_fit")
  155. if cam.sensor_fit == 'AUTO':
  156. col.prop(cam, "sensor_width", text="Size")
  157. else:
  158. sub = col.column(align=True)
  159. sub.active = cam.sensor_fit == 'HORIZONTAL'
  160. sub.prop(cam, "sensor_width", text="Width")
  161. sub = col.column(align=True)
  162. sub.active = cam.sensor_fit == 'VERTICAL'
  163. sub.prop(cam, "sensor_height", text="Height")
  164. class DATA_PT_camera_dof(CameraButtonsPanel, Panel):
  165. bl_label = "Depth of Field"
  166. bl_options = {'DEFAULT_CLOSED'}
  167. COMPAT_ENGINES = {'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  168. def draw_header(self, context):
  169. cam = context.camera
  170. dof = cam.dof
  171. self.layout.prop(dof, "use_dof", text="")
  172. def draw(self, context):
  173. layout = self.layout
  174. layout.use_property_split = True
  175. cam = context.camera
  176. dof = cam.dof
  177. layout.active = dof.use_dof
  178. col = layout.column()
  179. col.prop(dof, "focus_object", text="Focus on Object")
  180. sub = col.column()
  181. sub.active = (dof.focus_object is None)
  182. sub.prop(dof, "focus_distance", text="Focus Distance")
  183. class DATA_PT_camera_dof_aperture(CameraButtonsPanel, Panel):
  184. bl_label = "Aperture"
  185. bl_parent_id = "DATA_PT_camera_dof"
  186. COMPAT_ENGINES = {'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  187. def draw(self, context):
  188. layout = self.layout
  189. layout.use_property_split = True
  190. cam = context.camera
  191. dof = cam.dof
  192. layout.active = dof.use_dof
  193. flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
  194. col = flow.column()
  195. col.prop(dof, "aperture_fstop")
  196. col = flow.column()
  197. col.prop(dof, "aperture_blades")
  198. col.prop(dof, "aperture_rotation")
  199. col.prop(dof, "aperture_ratio")
  200. class DATA_PT_camera_background_image(CameraButtonsPanel, Panel):
  201. bl_label = "Background Images"
  202. bl_options = {'DEFAULT_CLOSED'}
  203. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  204. def draw_header(self, context):
  205. cam = context.camera
  206. self.layout.prop(cam, "show_background_images", text="")
  207. def draw(self, context):
  208. layout = self.layout
  209. layout.use_property_split = True
  210. layout.use_property_decorate = False
  211. cam = context.camera
  212. use_multiview = context.scene.render.use_multiview
  213. col = layout.column()
  214. col.operator("view3d.background_image_add", text="Add Image")
  215. for i, bg in enumerate(cam.background_images):
  216. layout.active = cam.show_background_images
  217. box = layout.box()
  218. row = box.row(align=True)
  219. row.prop(bg, "show_expanded", text="", emboss=False)
  220. if bg.source == 'IMAGE' and bg.image:
  221. row.prop(bg.image, "name", text="", emboss=False)
  222. elif bg.source == 'MOVIE_CLIP' and bg.clip:
  223. row.prop(bg.clip, "name", text="", emboss=False)
  224. elif bg.source and bg.use_camera_clip:
  225. row.label(text="Camera Clip")
  226. else:
  227. row.label(text="Not Set")
  228. row.prop(
  229. bg,
  230. "show_background_image",
  231. text="",
  232. emboss=False,
  233. icon='RESTRICT_VIEW_OFF' if bg.show_background_image else 'RESTRICT_VIEW_ON',
  234. )
  235. row.operator("view3d.background_image_remove", text="", emboss=False, icon='X').index = i
  236. if bg.show_expanded:
  237. row = box.row()
  238. row.prop(bg, "source", expand=True)
  239. has_bg = False
  240. if bg.source == 'IMAGE':
  241. row = box.row()
  242. row.template_ID(bg, "image", open="image.open")
  243. if bg.image is not None:
  244. box.template_image(bg, "image", bg.image_user, compact=True)
  245. has_bg = True
  246. if use_multiview:
  247. box.prop(bg.image, "use_multiview")
  248. column = box.column()
  249. column.active = bg.image.use_multiview
  250. column.label(text="Views Format:")
  251. column.row().prop(bg.image, "views_format", expand=True)
  252. sub = column.box()
  253. sub.active = bg.image.views_format == 'STEREO_3D'
  254. sub.template_image_stereo_3d(bg.image.stereo_3d_format)
  255. elif bg.source == 'MOVIE_CLIP':
  256. box.prop(bg, "use_camera_clip")
  257. column = box.column()
  258. column.active = not bg.use_camera_clip
  259. column.template_ID(bg, "clip", open="clip.open")
  260. if bg.clip:
  261. column.template_movieclip(bg, "clip", compact=True)
  262. if bg.use_camera_clip or bg.clip:
  263. has_bg = True
  264. column = box.column()
  265. column.active = has_bg
  266. column.prop(bg.clip_user, "use_render_undistorted")
  267. column.prop(bg.clip_user, "proxy_render_size")
  268. if has_bg:
  269. col = box.column()
  270. col.prop(bg, "alpha", slider=True)
  271. col.row().prop(bg, "display_depth", expand=True)
  272. col.row().prop(bg, "frame_method", expand=True)
  273. row = box.row()
  274. row.prop(bg, "offset")
  275. col = box.column()
  276. col.prop(bg, "rotation")
  277. col.prop(bg, "scale")
  278. col.prop(bg, "use_flip_x")
  279. col.prop(bg, "use_flip_y")
  280. class DATA_PT_camera_display(CameraButtonsPanel, Panel):
  281. bl_label = "Viewport Display"
  282. bl_options = {'DEFAULT_CLOSED'}
  283. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  284. def draw(self, context):
  285. layout = self.layout
  286. layout.use_property_split = True
  287. cam = context.camera
  288. col = layout.column(align=True)
  289. col.separator()
  290. col.prop(cam, "display_size", text="Size")
  291. col.separator()
  292. flow = layout.grid_flow(row_major=False, columns=0, even_columns=False, even_rows=False, align=False)
  293. col = flow.column()
  294. col.prop(cam, "show_limits", text="Limits")
  295. col = flow.column()
  296. col.prop(cam, "show_mist", text="Mist")
  297. col = flow.column()
  298. col.prop(cam, "show_sensor", text="Sensor")
  299. col = flow.column()
  300. col.prop(cam, "show_name", text="Name")
  301. class DATA_PT_camera_display_composition_guides(CameraButtonsPanel, Panel):
  302. bl_label = "Composition Guides"
  303. bl_parent_id = "DATA_PT_camera_display"
  304. bl_options = {'DEFAULT_CLOSED'}
  305. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  306. def draw(self, context):
  307. layout = self.layout
  308. layout.use_property_split = True
  309. cam = context.camera
  310. flow = layout.grid_flow(row_major=False, columns=0, even_columns=False, even_rows=False, align=False)
  311. col = flow.column()
  312. col.prop(cam, "show_composition_center")
  313. col = flow.column()
  314. col.prop(cam, "show_composition_center_diagonal")
  315. col = flow.column()
  316. col.prop(cam, "show_composition_thirds")
  317. col = flow.column()
  318. col.prop(cam, "show_composition_golden")
  319. col = flow.column()
  320. col.prop(cam, "show_composition_golden_tria_a")
  321. col = flow.column()
  322. col.prop(cam, "show_composition_golden_tria_b")
  323. col = flow.column()
  324. col.prop(cam, "show_composition_harmony_tri_a")
  325. col = flow.column()
  326. col.prop(cam, "show_composition_harmony_tri_b")
  327. class DATA_PT_camera_display_passepartout(CameraButtonsPanel, Panel):
  328. bl_label = "Passepartout"
  329. bl_parent_id = "DATA_PT_camera_display"
  330. bl_options = {'DEFAULT_CLOSED'}
  331. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  332. def draw_header(self, context):
  333. cam = context.camera
  334. self.layout.prop(cam, "show_passepartout", text="")
  335. def draw(self, context):
  336. layout = self.layout
  337. layout.use_property_split = True
  338. cam = context.camera
  339. layout.active = cam.show_passepartout
  340. layout.prop(cam, "passepartout_alpha", text="Opacity", slider=True)
  341. class DATA_PT_camera_safe_areas(CameraButtonsPanel, Panel):
  342. bl_label = "Safe Areas"
  343. bl_options = {'DEFAULT_CLOSED'}
  344. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  345. def draw_header(self, context):
  346. cam = context.camera
  347. self.layout.prop(cam, "show_safe_areas", text="")
  348. def draw_header_preset(self, _context):
  349. SAFE_AREAS_PT_presets.draw_panel_header(self.layout)
  350. def draw(self, context):
  351. layout = self.layout
  352. safe_data = context.scene.safe_areas
  353. camera = context.camera
  354. layout.use_property_split = True
  355. layout.active = camera.show_safe_areas
  356. col = layout.column()
  357. sub = col.column()
  358. sub.prop(safe_data, "title", slider=True)
  359. sub.prop(safe_data, "action", slider=True)
  360. class DATA_PT_camera_safe_areas_center_cut(CameraButtonsPanel, Panel):
  361. bl_label = "Center-Cut Safe Areas"
  362. bl_parent_id = "DATA_PT_camera_safe_areas"
  363. bl_options = {'DEFAULT_CLOSED'}
  364. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  365. def draw_header(self, context):
  366. cam = context.camera
  367. layout = self.layout
  368. layout.active = cam.show_safe_areas
  369. layout.prop(cam, "show_safe_center", text="")
  370. def draw(self, context):
  371. layout = self.layout
  372. safe_data = context.scene.safe_areas
  373. camera = context.camera
  374. layout.use_property_split = True
  375. layout.active = camera.show_safe_areas and camera.show_safe_center
  376. col = layout.column()
  377. col.prop(safe_data, "title_center", slider=True)
  378. class DATA_PT_custom_props_camera(CameraButtonsPanel, PropertyPanel, Panel):
  379. COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
  380. _context_path = "object.data"
  381. _property_type = bpy.types.Camera
  382. def draw_display_safe_settings(layout, safe_data, settings):
  383. show_safe_areas = settings.show_safe_areas
  384. show_safe_center = settings.show_safe_center
  385. layout.use_property_split = True
  386. col = layout.column()
  387. col.active = show_safe_areas
  388. sub = col.column()
  389. sub.prop(safe_data, "title", slider=True)
  390. sub.prop(safe_data, "action", slider=True)
  391. col.separator()
  392. col.prop(settings, "show_safe_center", text="Center-Cut Safe Areas")
  393. sub = col.column()
  394. sub.active = show_safe_areas and show_safe_center
  395. sub.prop(safe_data, "title_center", slider=True)
  396. sub.prop(safe_data, "action_center", slider=True)
  397. classes = (
  398. CAMERA_PT_presets,
  399. SAFE_AREAS_PT_presets,
  400. DATA_PT_context_camera,
  401. DATA_PT_lens,
  402. DATA_PT_camera_dof,
  403. DATA_PT_camera_dof_aperture,
  404. DATA_PT_camera,
  405. DATA_PT_camera_stereoscopy,
  406. DATA_PT_camera_safe_areas,
  407. DATA_PT_camera_safe_areas_center_cut,
  408. DATA_PT_camera_background_image,
  409. DATA_PT_camera_display,
  410. DATA_PT_camera_display_composition_guides,
  411. DATA_PT_camera_display_passepartout,
  412. DATA_PT_custom_props_camera,
  413. )
  414. if __name__ == "__main__": # only for live edit.
  415. from bpy.utils import register_class
  416. for cls in classes:
  417. register_class(cls)