This commit implements described in the #104573. The goal is to fix the confusion of the submodule hashes change, which are not ideal for any of the supported git-module configuration (they are either always visible causing confusion, or silently staged and committed, also causing confusion). This commit replaces submodules with a checkout of addons and addons_contrib, covered by the .gitignore, and locale and developer tools are moved to the main repository. This also changes the paths: - /release/scripts are moved to the /scripts - /source/tools are moved to the /tools - /release/datafiles/locale is moved to /locale This is done to avoid conflicts when using bisect, and also allow buildbot to automatically "recover" wgen building older or newer branches/patches. Running `make update` will initialize the local checkout to the changed repository configuration. Another aspect of the change is that the make update will support Github style of remote organization (origin remote pointing to thy fork, upstream remote pointing to the upstream blender/blender.git). Pull Request #104755
585 lines
18 KiB
Python
585 lines
18 KiB
Python
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
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_EEVEE_NEXT',
|
|
'BLENDER_WORKBENCH',
|
|
'BLENDER_WORKBENCH_NEXT'}
|
|
|
|
|
|
class CAMERA_PT_safe_areas_presets(PresetPanel, Panel):
|
|
bl_label = "Camera Presets"
|
|
preset_subdir = "safe_areas"
|
|
preset_operator = "script.execute_preset"
|
|
preset_add_operator = "camera.safe_areas_preset_add"
|
|
COMPAT_ENGINES = {
|
|
'BLENDER_RENDER',
|
|
'BLENDER_EEVEE',
|
|
'BLENDER_EEVEE_NEXT',
|
|
'BLENDER_WORKBENCH',
|
|
'BLENDER_WORKBENCH_NEXT'}
|
|
|
|
|
|
class DATA_PT_context_camera(CameraButtonsPanel, Panel):
|
|
bl_label = ""
|
|
bl_options = {'HIDE_HEADER'}
|
|
COMPAT_ENGINES = {
|
|
'BLENDER_RENDER',
|
|
'BLENDER_EEVEE',
|
|
'BLENDER_EEVEE_NEXT',
|
|
'BLENDER_WORKBENCH',
|
|
'BLENDER_WORKBENCH_NEXT'}
|
|
|
|
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_EEVEE_NEXT',
|
|
'BLENDER_WORKBENCH',
|
|
'BLENDER_WORKBENCH_NEXT'}
|
|
|
|
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':
|
|
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 ccam.panorama_type == 'FISHEYE_LENS_POLYNOMIAL':
|
|
col.prop(ccam, "fisheye_fov")
|
|
col.prop(ccam, "fisheye_polynomial_k0", text="K0")
|
|
col.prop(ccam, "fisheye_polynomial_k1", text="K1")
|
|
col.prop(ccam, "fisheye_polynomial_k2", text="K2")
|
|
col.prop(ccam, "fisheye_polynomial_k3", text="K3")
|
|
col.prop(ccam, "fisheye_polynomial_k4", text="K4")
|
|
|
|
elif engine in {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH', 'BLENDER_WORKBENCH_NEXT'}:
|
|
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_EEVEE_NEXT',
|
|
'BLENDER_WORKBENCH',
|
|
'BLENDER_WORKBENCH_NEXT'}
|
|
|
|
@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_EEVEE_NEXT',
|
|
'BLENDER_WORKBENCH',
|
|
'BLENDER_WORKBENCH_NEXT'}
|
|
|
|
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_EEVEE_NEXT', 'BLENDER_WORKBENCH', 'BLENDER_WORKBENCH_NEXT'}
|
|
|
|
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")
|
|
if dof.focus_object and dof.focus_object.type == 'ARMATURE':
|
|
col.prop_search(dof, "focus_subtarget", dof.focus_object.data, "bones", text="Focus on Bone")
|
|
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_EEVEE_NEXT', 'BLENDER_WORKBENCH', 'BLENDER_WORKBENCH_NEXT'}
|
|
|
|
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_EEVEE_NEXT',
|
|
'BLENDER_WORKBENCH',
|
|
'BLENDER_WORKBENCH_NEXT'}
|
|
|
|
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="Active 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", text="Active 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 = box.column(heading="Flip")
|
|
col.prop(bg, "use_flip_x", text="X")
|
|
col.prop(bg, "use_flip_y", text="Y")
|
|
|
|
|
|
class DATA_PT_camera_display(CameraButtonsPanel, Panel):
|
|
bl_label = "Viewport Display"
|
|
bl_options = {'DEFAULT_CLOSED'}
|
|
COMPAT_ENGINES = {
|
|
'BLENDER_RENDER',
|
|
'BLENDER_EEVEE',
|
|
'BLENDER_EEVEE_NEXT',
|
|
'BLENDER_WORKBENCH',
|
|
'BLENDER_WORKBENCH_NEXT'}
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
layout.use_property_split = True
|
|
|
|
cam = context.camera
|
|
|
|
col = layout.column(align=True)
|
|
|
|
col.prop(cam, "display_size", text="Size")
|
|
|
|
col = layout.column(heading="Show")
|
|
col.prop(cam, "show_limits", text="Limits")
|
|
col.prop(cam, "show_mist", text="Mist")
|
|
col.prop(cam, "show_sensor", text="Sensor")
|
|
col.prop(cam, "show_name", text="Name")
|
|
|
|
col = layout.column(align=False, heading="Passepartout")
|
|
col.use_property_decorate = False
|
|
row = col.row(align=True)
|
|
sub = row.row(align=True)
|
|
sub.prop(cam, "show_passepartout", text="")
|
|
sub = sub.row(align=True)
|
|
sub.active = cam.show_passepartout
|
|
sub.prop(cam, "passepartout_alpha", text="")
|
|
row.prop_decorator(cam, "passepartout_alpha")
|
|
|
|
|
|
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_EEVEE_NEXT',
|
|
'BLENDER_WORKBENCH',
|
|
'BLENDER_WORKBENCH_NEXT'}
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
layout.use_property_split = True
|
|
|
|
cam = context.camera
|
|
|
|
layout.prop(cam, "show_composition_thirds")
|
|
|
|
col = layout.column(heading="Center", align=True)
|
|
col.prop(cam, "show_composition_center")
|
|
col.prop(cam, "show_composition_center_diagonal", text="Diagonal")
|
|
|
|
col = layout.column(heading="Golden", align=True)
|
|
col.prop(cam, "show_composition_golden", text="Ratio")
|
|
col.prop(cam, "show_composition_golden_tria_a", text="Triangle A")
|
|
col.prop(cam, "show_composition_golden_tria_b", text="Triangle B")
|
|
|
|
col = layout.column(heading="Harmony", align=True)
|
|
col.prop(cam, "show_composition_harmony_tri_a", text="Triangle A")
|
|
col.prop(cam, "show_composition_harmony_tri_b", text="Triangle B")
|
|
|
|
|
|
class DATA_PT_camera_safe_areas(CameraButtonsPanel, Panel):
|
|
bl_label = "Safe Areas"
|
|
bl_options = {'DEFAULT_CLOSED'}
|
|
COMPAT_ENGINES = {
|
|
'BLENDER_RENDER',
|
|
'BLENDER_EEVEE',
|
|
'BLENDER_EEVEE_NEXT',
|
|
'BLENDER_WORKBENCH',
|
|
'BLENDER_WORKBENCH_NEXT'}
|
|
|
|
def draw_header(self, context):
|
|
cam = context.camera
|
|
|
|
self.layout.prop(cam, "show_safe_areas", text="")
|
|
|
|
def draw_header_preset(self, _context):
|
|
CAMERA_PT_safe_areas_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_EEVEE_NEXT',
|
|
'BLENDER_WORKBENCH',
|
|
'BLENDER_WORKBENCH_NEXT'}
|
|
|
|
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)
|
|
col.prop(safe_data, "action_center", slider=True)
|
|
|
|
|
|
class DATA_PT_custom_props_camera(CameraButtonsPanel, PropertyPanel, Panel):
|
|
COMPAT_ENGINES = {
|
|
'BLENDER_RENDER',
|
|
'BLENDER_EEVEE',
|
|
'BLENDER_EEVEE_NEXT',
|
|
'BLENDER_WORKBENCH',
|
|
'BLENDER_WORKBENCH_NEXT'}
|
|
_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,
|
|
CAMERA_PT_safe_areas_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_custom_props_camera,
|
|
)
|
|
|
|
if __name__ == "__main__": # only for live edit.
|
|
from bpy.utils import register_class
|
|
for cls in classes:
|
|
register_class(cls)
|