3
11
This repository has been archived on 2024-05-16. You can view files and clone it, but cannot push or open issues or pull requests.
blender-addons-contrib/camera_overscan.py
Aaron Carlisle 42da56aa73 Update class names after api changes to Blender
In rB4ddad5a7ee5d9c3245593c509714f8c1359f9342
the `RENDER_PT_dimensions` class was renamed to
`RENDER._PT_format`
2021-09-05 23:24:09 -04:00

196 lines
7.0 KiB
Python

# ##### 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 #####
bl_info = {
"name": "Camera Overscan",
"author": "John Roper, Barnstorm VFX, Luca Scheller",
"version": (1, 2, 2),
"blender": (2, 80, 0),
"location": "Render Settings > Camera Overscan",
"description": "Render Overscan",
"warning": "",
"doc_url": "https://wiki.blender.org/index.php/Extensions:2.6/Py/Scripts/Render/Camera_Overscan",
"tracker_url": "",
"category": "Render"}
import bpy
from bpy.types import (
Operator,
PropertyGroup,
)
from bpy.props import (
BoolProperty,
IntProperty,
FloatProperty,
StringProperty,
PointerProperty,
)
class CODuplicateCamera(Operator):
bl_idname = "scene.co_duplicate_camera"
bl_label = "Bake to New Camera"
bl_description = ("Make a new overscan camera with all the settings builtin\n"
"Needs an active Camera type in the Scene")
@classmethod
def poll(cls, context):
active_cam = getattr(context.scene, "camera", None)
return active_cam is not None
def execute(self, context):
active_cam = getattr(context.scene, "camera", None)
try:
if active_cam and active_cam.type == 'CAMERA':
cam_obj = active_cam.copy()
cam_obj.data = active_cam.data.copy()
cam_obj.name = "Camera_Overscan"
context.collection.objects.link(cam_obj)
except:
self.report({'WARNING'}, "Setting up a new Overscan Camera has failed")
return {'CANCELLED'}
return {'FINISHED'}
def RO_Update(self, context):
scene = context.scene
overscan = scene.camera_overscan
render_settings = scene.render
active_camera = getattr(scene, "camera", None)
active_cam = getattr(active_camera, "data", None)
# Check if there is a camera type in the scene (Object as camera doesn't work)
if not active_cam or active_camera.type not in {'CAMERA'}:
return None
if overscan.RO_Activate:
if overscan.RO_Safe_SensorSize == -1:
# Safe Property Values
overscan.RO_Safe_Res_X = render_settings.resolution_x
overscan.RO_Safe_Res_Y = render_settings.resolution_y
overscan.RO_Safe_SensorSize = active_cam.sensor_width
overscan.RO_Safe_SensorFit = active_cam.sensor_fit
if overscan.RO_Custom_Res_X == 0 or overscan.RO_Custom_Res_Y == 0:
# avoid infinite recursion on props update
if overscan.RO_Custom_Res_X != render_settings.resolution_x:
overscan.RO_Custom_Res_X = render_settings.resolution_x
if overscan.RO_Custom_Res_Y != render_settings.resolution_y:
overscan.RO_Custom_Res_Y = render_settings.resolution_y
# Reset Property Values
active_cam.sensor_width = scene.camera_overscan.RO_Safe_SensorSize
# Calc Sensor Size
active_cam.sensor_fit = 'HORIZONTAL'
sensor_size_factor = overscan.RO_Custom_Res_X / overscan.RO_Safe_Res_X
Old_SensorSize = active_cam.sensor_width
New_SensorSize = Old_SensorSize * sensor_size_factor
# Set New Property Values
active_cam.sensor_width = New_SensorSize
render_settings.resolution_x = overscan.RO_Custom_Res_X
render_settings.resolution_y = overscan.RO_Custom_Res_Y
else:
if overscan.RO_Safe_SensorSize != -1:
# Set Property Values
render_settings.resolution_x = overscan.RO_Safe_Res_X
render_settings.resolution_y = overscan.RO_Safe_Res_Y
active_cam.sensor_width = overscan.RO_Safe_SensorSize
active_cam.sensor_fit = overscan.RO_Safe_SensorFit
overscan.RO_Safe_SensorSize = -1
def RO_Menu(self, context):
scene = context.scene
overscan = scene.camera_overscan
active_cam = getattr(scene, "camera", None)
layout = self.layout
if active_cam and active_cam.type == 'CAMERA':
col = layout.column(align=True)
col.prop(overscan, "RO_Activate", text="Use Overscan")
sub = col.column(align=True)
sub.active = overscan.RO_Activate
sub.prop(overscan, "RO_Custom_Res_X", text="Overscan X")
sub.prop(overscan, "RO_Custom_Res_Y", text="Y")
col = layout.column(align=True)
col.active = overscan.RO_Activate
col.operator("scene.co_duplicate_camera", icon="RENDER_STILL")
else:
col = layout.column()
col.label(text="No active Camera type in the Scene", icon='INFO')
class camera_overscan_props(PropertyGroup):
RO_Activate: BoolProperty(
default=False,
description="Enable/Disable Camera Overscan\n"
"Affects the active Scene Camera only\n"
"(Objects as cameras are not supported)",
update=RO_Update
)
RO_Custom_Res_X: IntProperty(
default=0,
min=4,
max=65536,
subtype='PIXEL',
update=RO_Update
)
RO_Custom_Res_Y: IntProperty(
default=0,
min=4,
max=65536,
subtype='PIXEL',
update=RO_Update
)
RO_Safe_Res_X: FloatProperty()
RO_Safe_Res_Y: FloatProperty()
# the hard limit is sys.max which is too much, used 65536 instead
RO_Safe_SensorSize: FloatProperty(
default=-1,
min=-1,
max=65536
)
RO_Safe_SensorFit: StringProperty()
def register():
bpy.utils.register_class(CODuplicateCamera)
bpy.utils.register_class(camera_overscan_props)
bpy.types.RENDER_PT_format.append(RO_Menu)
bpy.types.Scene.camera_overscan = PointerProperty(
type=camera_overscan_props
)
def unregister():
bpy.utils.unregister_class(CODuplicateCamera)
bpy.utils.unregister_class(camera_overscan_props)
bpy.types.RENDER_PT_format.remove(RO_Menu)
del bpy.types.Scene.camera_overscan
if __name__ == "__main__":
register()