Draw cam passepartout and UI changes

This commit is contained in:
Pullusb
2021-06-05 01:20:35 +02:00
parent 2754ebf89b
commit d8f71e3356
6 changed files with 197 additions and 335 deletions
+127 -293
View File
@@ -6,201 +6,6 @@ from gpu_extras.batch import batch_for_shader
from bpy_extras.view3d_utils import location_3d_to_region_2d
from bpy.app.handlers import persistent
from bpy.types import GizmoGroup, Gizmo
def view3d_camera_border(context, cam):
# based on https://blender.stackexchange.com/questions/6377/coordinates-of-corners-of-camera-view-border
# cam = context.scene.camera
frame = cam.data.view_frame(scene=context.scene)
# to world-space
frame = [cam.matrix_world @ v for v in frame]
# to pixelspace
region, rv3d = context.region, context.space_data.region_3d
frame_px = [location_3d_to_region_2d(region, rv3d, v) for v in frame]
return frame_px
def draw_cam_frame_callback(self, context):
if context.region_data.view_perspective != 'CAMERA':
return
if context.scene.camera.name != 'draw_cam':
return
main_cam = context.scene.camera.parent
if not main_cam:
return
# if context.area != self._draw_area:
# return
# green -> (0.06, 0.4, 0.040, 0.6)
# orange -> (0.45, 0.18, 0.03, 1.0)
osd_color = (0.06, 0.4, 0.040, 0.4)
frame_point = view3d_camera_border(context, main_cam)
self.shader_2d = gpu.shader.from_builtin('2D_UNIFORM_COLOR')
self.screen_framing = batch_for_shader(
self.shader_2d, 'LINE_LOOP', {"pos": frame_point})
bgl.glLineWidth(1)
self.shader_2d.bind()
self.shader_2d.uniform_float("color", osd_color)
self.screen_framing.draw(self.shader_2d)
# Reset
# bgl.glLineWidth(1)
# # Display Text
# if self.use_osd_text:
# font_id = 0
# dpi = context.preferences.system.dpi
# # Display current frame text
# blf.color(font_id, *osd_color) # unpack color in argument
# blf.position(font_id, context.region.width/3, 15, 0) # context.region.height-
# blf.size(font_id, 16, dpi)
# blf.draw(font_id, f'Draw cam')
# As a modal for tests
class GPTB_OT_cam_frame_draw(bpy.types.Operator):
bl_idname = "gp.draw_cam_frame"
bl_label = "Draw Cam Frame"
bl_description = "Draw the camera frame using a modal"
bl_options = {"REGISTER"} # , "INTERNAL"
# @classmethod
# def poll(cls, context):
# return True
def invoke(self, context, event):
# screen color frame
# r = bpy.context.region
# w = r.width
# h = r.height
# self.shader_2d = gpu.shader.from_builtin('2D_UNIFORM_COLOR')
# self.screen_framing = batch_for_shader(
# self.shader_2d, 'LINE_LOOP', {"pos": [(0,0), (0,h), (w,h), (w,0)]})
# OpenGL handler
self._draw_area = context.area
args = (self, context)
self._handle = bpy.types.SpaceView3D.draw_handler_add(
draw_cam_frame_callback, args, "WINDOW", "POST_PIXEL")
context.window_manager.modal_handler_add(self)
return {'RUNNING_MODAL'}
def exit(self, context):
bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
context.area.tag_redraw()
def modal(self, context, event):
if event.type in {'ESC'}:
self.exit(context)
return {"CANCELLED"}
return {'PASS_THROUGH'}
# GIZMO method
'''
class CameraFrameWidget(Gizmo):
bl_idname = "VIEW3D_GT_CAM"
# bl_target_properties = (
# {"id": "offset", "type": 'FLOAT', "array_length": 1},
# )
# __slots__ = (
# "custom_shape",
# "init_mouse_y",
# "init_value",
# )
# def _update_offset_matrix(self):
# # offset behind the light
# self.matrix_offset.col[3][2] = self.target_get_value("offset") / -10.0
def draw(self, context):
# self._update_offset_matrix()
# self.draw_custom_shape(self.custom_shape)
osd_color = (0.06, 0.4, 0.040, 0.4)
frame_point = view3d_camera_border_3d(context, context.scene.camera.parent)
self.shader_2d = gpu.shader.from_builtin('3D_UNIFORM_COLOR')
self.screen_framing = batch_for_shader(
self.shader_2d, 'LINE_LOOP', {"pos": frame_point})
bgl.glLineWidth(1)
self.shader_2d.bind()
self.shader_2d.uniform_float("color", osd_color)
self.screen_framing.draw(self.shader_2d)
# def draw_select(self, context, select_id):
# self._update_offset_matrix()
# self.draw_custom_shape(self.custom_shape, select_id=select_id)
# def setup(self):
# if not hasattr(self, "custom_shape"):
# self.custom_shape = self.new_custom_shape('LINE_LOOP', custom_shape_verts)
def invoke(self, context, event):
# self.init_mouse_y = event.mouse_y
# self.init_value = self.target_get_value("offset")
return {'RUNNING_MODAL'}
def exit(self, context, cancel):
context.area.header_text_set(None)
# if cancel:
# self.target_set_value("offset", self.init_value)
def modal(self, context, event, tweak):
# context.area.header_text_set("My Gizmo: %.4f" % value)
return {'RUNNING_MODAL'}
class CameraFrameWidgetGroup(GizmoGroup):
bl_idname = "OBJECT_GGT_light_test"
bl_label = "Test Light Widget"
bl_space_type = 'VIEW_3D'
bl_region_type = 'WINDOW'
bl_options = {'3D', 'PERSISTENT'}
@classmethod
def poll(cls, context):
# if context.region_data.view_perspective != 'CAMERA':
# return
# if context.scene.camera.name != 'draw_cam':
# return
# if not context.scene.camera.parent:
# return
# return True
return context.region_data.view_perspective == 'CAMERA' and context.scene.camera.name == 'draw_cam' and context.scene.camera.parent
def setup(self, context):
# Assign the 'offset' target property to the light energy.
ob = context.object
gz = self.gizmos.new(CameraFrameWidget.bl_idname)
print('In setup')
# gz.target_set_prop("offset", ob.data, "energy")
# gz.color = 1.0, 0.5, 1.0
# gz.alpha = 0.5
# gz.color_highlight = 1.0, 1.0, 1.0
# gz.alpha_highlight = 0.5
# units are large, so shrink to something more reasonable.
# gz.scale_basis = 0.1
gz.use_draw_modal = True
def refresh(self, context):
ob = context.object0
# gz = self.energy_gizmo
# gz.matrix_basis = ob.matrix_world.normalized()
'''
# USED 0CODE
def extrapolate_points_by_length(a, b, length):
@@ -214,123 +19,152 @@ def extrapolate_points_by_length(a, b, length):
return None
return b + (ab.normalized() * length)
def view3d_camera_border_3d(context, cam):
'''Return frame border as 3D coordinate'''
def view3d_camera_border_2d(context, cam):
# based on https://blender.stackexchange.com/questions/6377/coordinates-of-corners-of-camera-view-border
# cam = context.scene.camera
frame = cam.data.view_frame(scene=context.scene)
# to world-space
frame = [cam.matrix_world @ v for v in frame]
return frame
# to pixelspace
region, rv3d = context.region, context.space_data.region_3d
frame_px = [location_3d_to_region_2d(region, rv3d, v) for v in frame]
return frame_px
def draw_cam_frame_callback_2d():
context = bpy.context
if context.region_data.view_perspective != 'CAMERA':
return
if context.scene.camera.name != 'draw_cam':
return
main_cam = context.scene.camera.parent
if not main_cam:
return
bgl.glEnable(bgl.GL_BLEND)
frame_point = view3d_camera_border_2d(
context, context.scene.camera.parent)
shader_2d = gpu.shader.from_builtin('2D_UNIFORM_COLOR')
if context.scene.gptoolprops.drawcam_passepartout:
### PASSEPARTOUT
# frame positions
#
# lupext lup rup rupext
# D-----A
# | |
# C-----B
# ldnext ldn rdn lnext
a = frame_point[0]
b = frame_point[1]
c = frame_point[2]
d = frame_point[3]
ext = 1000
rup = extrapolate_points_by_length(b,a, ext)
rdn = extrapolate_points_by_length(a,b, ext)
rupext = rup + ((a-d).normalized() * ext)
rdnext = rdn + ((a-d).normalized() * ext)
lup = extrapolate_points_by_length(c,d, ext)
ldn = extrapolate_points_by_length(d,c, ext)
lupext = lup + ((c-b).normalized() * ext)
ldnext = ldn + ((c-b).normalized() * ext)
class CameraFrameWidget(Gizmo):
bl_idname = "VIEW3D_GT_CAM"
def draw(self, context):
# 3D0 draw
osd_color = (0.06, 0.4, 0.040, 0.4)
frame_point = view3d_camera_border_3d(
context, context.scene.camera.parent)
self.shader_2d = gpu.shader.from_builtin('3D_UNIFORM_COLOR')
self.screen_framing = batch_for_shader(
self.shader_2d, 'LINE_LOOP', {"pos": frame_point})
bgl.glLineWidth(1)
self.shader_2d.bind()
self.shader_2d.uniform_float("color", osd_color)
self.screen_framing.draw(self.shader_2d)
# WIP -> custom passepartout
# ppp_color = (1.0, 1.0, 0.0, 1)
ppp_color = (0.0, 0.0, 0.0, context.scene.camera.data.passepartout_alpha)
rect = [rup, rdn, rupext, rdnext,
lup, ldn, lupext, ldnext,
a, b, c, d]
## frame positions
# D-----A
# | |
# C-----B
## convert to 2d
# region, rv3d = context.region, context.space_data.region_3d
# rect = [location_3d_to_region_2d(region, rv3d, v) for v in rect]
# a = frame_point[0]
# b = frame_point[1]
# c = frame_point[2]
# d = frame_point[3]
# lupext=6 lup=4 rup=0 rupext=2
# d=11, a=8
# c=10, b=9
# ldnext=7 ldn=5 rdn=1 dnpext=3
indices = [(0,1,2), (1,2,3),
(4,5,6), (5,6,7),
(8,11,4), (8,4,0),
(10,9,5), (9,5,1),
]
# ext = 0.2
# rup = extrapolate_points_by_length(a,b, ext)
# rdn = extrapolate_points_by_length(b,a, ext)
# ### passpartout_points
# rupext = rup + ((a-c).normalized() * ext)
# rdnext = rdn + ((a-c).normalized() * ext)
passepartout = batch_for_shader(
shader_2d, 'TRIS', {"pos": rect}, indices=indices)
# shader_2d, 'LINE_LOOP', {"pos": rect})
shader_2d.bind()
shader_2d.uniform_float("color", ppp_color)
passepartout.draw(shader_2d)
### Camera framing trace over
bgl.glLineWidth(1)
bgl.glEnable(bgl.GL_LINE_SMOOTH)
"""
## need to accurately detect viewport background color (difficult)
### COUNTER CURRENT FRAMING
if False:
camf = view3d_camera_border_2d(
context, context.scene.camera)
ca = (camf[0].x + 1, camf[0].y + 1)
cb = (camf[1].x + 1, camf[1].y - 1)
cc = (camf[2].x - 1, camf[2].y - 1)
cd = (camf[3].x - 1, camf[3].y + 1)
screen_framing = batch_for_shader(
shader_2d, 'LINE_LOOP', {"pos": [ca, cb, cc, cd]})
shader_2d.bind()
shader_2d.uniform_float("color", (0.25, 0.25, 0.25, 1.0))
# shader_2d.uniform_float("color", (0.9, 0.9, 0.9, 1.0))
screen_framing.draw(shader_2d)
"""
### FRAMING
# frame_color = (0.06, 0.4, 0.040, 0.5)
frame_color = (0.0, 0.0, 0.25, 1.0)
screen_framing = batch_for_shader(
shader_2d, 'LINE_LOOP', {"pos": frame_point})
shader_2d.bind()
shader_2d.uniform_float("color", frame_color)
screen_framing.draw(shader_2d)
# bgl.glLineWidth(1)
bgl.glDisable(bgl.GL_LINE_SMOOTH)
bgl.glDisable(bgl.GL_BLEND)
# rect = [rup, rdn, rupext, rdnext]
# ### passpartout_points = []
# self.passepartout = batch_for_shader(
# self.shader_2d, 'TRI_FAN', {"pos": rect}) # TRIS
# self.shader_2d.bind()
# self.shader_2d.uniform_float("color", osd_color)
# self.passepartout.draw(self.shader_2d)
# def invoke(self, context, event):
# return {'RUNNING_MODAL'}
# def exit(self, context, cancel):
# # context.area.header_text_set(None)
# return
# def modal(self, context, event, tweak):
# return {'RUNNING_MODAL'}
class CameraFrameWidgetGroup(GizmoGroup):
bl_idname = "OBJECT_GGT_light_test"
bl_label = "Test Light Widget"
bl_space_type = 'VIEW_3D'
bl_region_type = 'WINDOW'
bl_options = {'3D', 'PERSISTENT'}
@classmethod
def poll(cls, context):
return context.region_data.view_perspective == 'CAMERA' and context.scene.camera.name == 'draw_cam' and context.scene.camera.parent
def setup(self, context):
gz = self.gizmos.new(CameraFrameWidget.bl_idname)
# --- REGISTER ---
classes = (
# GPTB_OT_cam_frame_draw,
CameraFrameWidget,
CameraFrameWidgetGroup,
)
draw_handle = None
def register():
if not bpy.app.background:
for cls in classes:
bpy.utils.register_class(cls)
if bpy.app.background:
return
# ha = DrawClass()
global draw_handle
draw_handle = bpy.types.SpaceView3D.draw_handler_add(
draw_cam_frame_callback_2d, (), "WINDOW", "POST_PIXEL")
# _handle = bpy.types.SpaceView3D.draw_handler_add(
# draw_cam_frame_callback, args, "WINDOW", "POST_PIXEL")
def unregister():
if not bpy.app.background:
for cls in classes:
bpy.utils.unregister_class(cls)
# ha.remove_handle()
# bpy.types.SpaceView3D.draw_handler_remove(_handle, 'WINDOW')
# if 'draw_cam_frame_callback' in [hand.__name__ for hand in bpy.app.handlers.save_pre]:
# bpy.app.handlers.save_pre.remove(remap_relative)
if bpy.app.background:
return
global draw_handle
if draw_handle:
bpy.types.SpaceView3D.draw_handler_remove(draw_handle, 'WINDOW')
if __name__ == "__main__":
register()