184 lines
5.5 KiB
Python
184 lines
5.5 KiB
Python
import bpy
|
|
import gpu
|
|
# import blf
|
|
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
|
|
|
|
|
|
def extrapolate_points_by_length(a, b, length):
|
|
'''
|
|
Return a third point C from by continuing in AB direction
|
|
Length define BC distance. both vector2 and vector3
|
|
'''
|
|
# return b + ((b - a).normalized() * length)# one shot
|
|
ab = b - a
|
|
if not ab:
|
|
return None
|
|
return b + (ab.normalized() * length)
|
|
|
|
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]
|
|
# 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 vertices_to_line_loop(v_list, closed=True) -> list:
|
|
'''Take a sequence of vertices
|
|
return a position lists of segments to create a line loop passing in all points
|
|
the result is usable with gpu_shader 'LINES'
|
|
ex: vlist = [a,b,c] -> closed=True return [a,b,b,c,c,a], closed=False return [a,b,b,c]
|
|
'''
|
|
loop = []
|
|
for i in range(len(v_list) - 1):
|
|
loop += [v_list[i], v_list[i + 1]]
|
|
if closed:
|
|
# Add segment between last and first to close loop
|
|
loop += [v_list[-1], v_list[0]]
|
|
return loop
|
|
|
|
def draw_cam_frame_callback_2d():
|
|
context = bpy.context
|
|
if context.region_data.view_perspective != 'CAMERA':
|
|
return
|
|
if not context.scene.camera or context.scene.camera.name != 'draw_cam':
|
|
return
|
|
|
|
main_cam = context.scene.camera.parent
|
|
if not main_cam:
|
|
return
|
|
|
|
gpu.state.blend_set('ALPHA')
|
|
|
|
frame_point = view3d_camera_border_2d(
|
|
context, context.scene.camera.parent)
|
|
shader_2d = gpu.shader.from_builtin('UNIFORM_COLOR') # POLYLINE_FLAT_COLOR
|
|
# 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 = 10000
|
|
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)
|
|
|
|
|
|
# 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]
|
|
|
|
## 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]
|
|
|
|
# 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),
|
|
]
|
|
|
|
# ### passpartout_points
|
|
|
|
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
|
|
|
|
gpu.state.line_width_set(1.0)
|
|
# bgl.glEnable(bgl.GL_LINE_SMOOTH) # old 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, 'LINES', {"pos": vertices_to_line_loop(frame_point)})
|
|
|
|
shader_2d.bind()
|
|
shader_2d.uniform_float("color", frame_color)
|
|
screen_framing.draw(shader_2d)
|
|
|
|
# bgl.glDisable(bgl.GL_LINE_SMOOTH) # old smooth
|
|
gpu.state.blend_set('NONE')
|
|
|
|
|
|
draw_handle = None
|
|
|
|
def register():
|
|
if bpy.app.background:
|
|
return
|
|
|
|
global draw_handle
|
|
draw_handle = bpy.types.SpaceView3D.draw_handler_add(
|
|
draw_cam_frame_callback_2d, (), "WINDOW", "POST_PIXEL")
|
|
|
|
|
|
|
|
def unregister():
|
|
if bpy.app.background:
|
|
return
|
|
|
|
global draw_handle
|
|
if draw_handle:
|
|
bpy.types.SpaceView3D.draw_handler_remove(draw_handle, 'WINDOW')
|
|
|
|
if __name__ == "__main__":
|
|
register()
|