-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPreCam.py
172 lines (134 loc) · 5.33 KB
/
PreCam.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
import bpy
import gpu
import numpy as np
from gpu_extras.presets import draw_texture_2d
from bpy.app.handlers import persistent
bl_info = {
"name": "PreCam",
"author": "Kolupsy, iceythe (Kaio), Spectral Vectors",
"version": (0, 0, 2),
"blender": (2, 90, 0),
"location": "Click on Camera or F3 > PreCam",
"description": "A preview of the camera view overlayed on the 3D Viewport",
"warning": "",
"doc_url": "",
"category": "3D View",
}
class LiveCapture_OT_capture(bpy.types.Operator):
bl_idname = 'livecapture.capture'
bl_label = 'Live Capture'
def execute(self, context):
self.report({'WARNING'}, 'Operator has no execution. Use as modal.')
return {'CANCELLED'}
def invoke(self, context, event):
scene = context.scene
render = scene.render
resolution_x = render.resolution_x
resolution_y = render.resolution_y
downscale_factor = 4
width = int(resolution_x/downscale_factor)
height = int(resolution_y/downscale_factor)
offscreen = gpu.types.GPUOffScreen(width, height)
if 'LiveTexture' not in bpy.data.images.keys():
bpy.data.images.new(
'LiveTexture',
width,
height,
alpha=True)
LiveTexture = bpy.data.images['LiveTexture']
LiveTexture.pack()
LiveTexture.use_fake_user = True
LiveTexture.colorspace_settings.name = 'Linear'
def draw(
context=context,
scene=scene,
width=width,
height=height,
offscreen=offscreen,
LiveTexture=LiveTexture):
view_layer = context.view_layer
space_data = context.space_data
region = context.region
object = context.object
camera = bpy.data.objects['Camera']
Camera = object if object.type == 'CAMERA' else camera
view_matrix = Camera.matrix_world.inverted()
projection_matrix = Camera.calc_matrix_camera(
context.evaluated_depsgraph_get(),
x=width,
y=height)
original_overlays = context.space_data.overlay.show_overlays
context.space_data.overlay.show_overlays = False
offscreen.draw_view3d(
scene,
view_layer,
space_data,
region,
view_matrix,
projection_matrix)
context.space_data.overlay.show_overlays = original_overlays
gpu.state.depth_mask_set(False)
buffer = np.array(
offscreen.texture_color.read(),
dtype='float32').flatten(order='F')
buffer = np.divide(buffer, 255)
LiveTexture.pixels.foreach_set(buffer)
area_width = context.area.width
preview_width = area_width/6
horizontal_size = int(preview_width*(resolution_x/resolution_y))
vertical_size = int(preview_width)
offset = 20
horizontal_location = int(area_width - horizontal_size - offset)
draw_texture_2d(
offscreen.texture_color,
(horizontal_location, offset),
horizontal_size,
vertical_size)
self.report({'INFO'}, 'Start realtime update.')
self._handler = bpy.types.SpaceView3D.draw_handler_add(
draw, (), 'WINDOW', 'POST_PIXEL')
context.window_manager.modal_handler_add(self)
return {'RUNNING_MODAL'}
def modal(self, context, event):
if event.type == 'ESC':
return self.finish(context)
return {'PASS_THROUGH'}
def finish(self, context):
bpy.types.SpaceView3D.draw_handler_remove(self._handler, 'WINDOW')
self.report({'INFO'}, 'Stopped realtime update.')
return {'FINISHED'}
@persistent
def on_active_object_changed(context, scene):
active = context.view_layer.objects.active
if active.type == 'CAMERA':
print('It is a Camera')
bpy.ops.livecapture.capture('INVOKE_DEFAULT')
else:
print('NOT A CAMERA!!!')
def custom_draw(self, context):
self.layout.operator(
operator="livecapture.capture",
text="PreCam",
icon='SCENE')
def menu_func(self, context):
self.layout.operator(LiveCapture_OT_capture.bl_idname)
cam_check = object()
def register(cam_check=cam_check):
bpy.utils.register_class(LiveCapture_OT_capture)
bpy.types.VIEW3D_MT_object.append(menu_func)
bpy.types.VIEW3D_MT_view.append(custom_draw)
bpy.app.handlers.load_post.append(on_active_object_changed)
# Subscribe to active object changes.
bpy.msgbus.subscribe_rna(
key=(bpy.types.LayerObjects, "active"),
owner=cam_check,
args=(),
notify=on_active_object_changed)
def unregister(cam_check=cam_check):
bpy.msgbus.clear_by_owner(cam_check)
bpy.app.handlers.load_post.remove(on_active_object_changed)
bpy.types.VIEW3D_MT_view.remove(custom_draw)
bpy.types.VIEW3D_MT_object.remove(menu_func)
bpy.utils.unregister_class(LiveCapture_OT_capture)
if __name__ == "__main__":
register()