sun_position: fix warning from deleted prop in User Preferences
[blender-addons.git] / space_view3d_math_vis / draw.py
blob8adeeb0bec1bf9b4124b2621f780ef53974b7868
1 # ##### BEGIN GPL LICENSE BLOCK #####
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software Foundation,
15 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 # ##### END GPL LICENSE BLOCK #####
19 # <pep8 compliant>
21 import bpy
22 import blf
23 import gpu
24 import bgl
25 from gpu_extras.batch import batch_for_shader
27 from . import utils
28 from mathutils import Vector
30 SpaceView3D = bpy.types.SpaceView3D
31 callback_handle = []
33 if not bpy.app.background:
34 single_color_shader = gpu.shader.from_builtin('3D_UNIFORM_COLOR')
35 smooth_color_shader = gpu.shader.from_builtin('3D_SMOOTH_COLOR')
36 else:
37 single_color_shader = None
38 smooth_color_shader = None
40 COLOR_POINT = (1.0, 0.0, 1.0, 1)
41 COLOR_LINE = (0.5, 0.5, 1, 1)
42 COLOR_BOUNDING_BOX = (1.0, 1.0, 1.0, 1.0)
44 def tag_redraw_areas():
45 context = bpy.context
47 # Py cant access notifers
48 for window in context.window_manager.windows:
49 for area in window.screen.areas:
50 if area.type in ['VIEW_3D', 'PROPERTIES']:
51 area.tag_redraw()
54 def callback_enable():
55 if callback_handle:
56 return
58 handle_pixel = SpaceView3D.draw_handler_add(draw_callback_px, (), 'WINDOW', 'POST_PIXEL')
59 handle_view = SpaceView3D.draw_handler_add(draw_callback_view, (), 'WINDOW', 'POST_VIEW')
60 callback_handle[:] = handle_pixel, handle_view
62 tag_redraw_areas()
65 def callback_disable():
66 if not callback_handle:
67 return
69 handle_pixel, handle_view = callback_handle
70 SpaceView3D.draw_handler_remove(handle_pixel, 'WINDOW')
71 SpaceView3D.draw_handler_remove(handle_view, 'WINDOW')
72 callback_handle[:] = []
74 tag_redraw_areas()
77 def draw_callback_px():
78 context = bpy.context
80 if context.window_manager.MathVisProp.name_hide:
81 return
83 font_id = 0
84 ui_scale = context.preferences.system.ui_scale
85 blf.size(font_id, round(12 * ui_scale), 72)
87 data_matrix, data_quat, data_euler, data_vector, data_vector_array = utils.console_math_data()
88 if not data_matrix and not data_quat and not data_euler and not data_vector and not data_vector_array:
89 return
92 region = context.region
93 region3d = context.space_data.region_3d
95 region_mid_width = region.width / 2.0
96 region_mid_height = region.height / 2.0
98 perspective_matrix = region3d.perspective_matrix.copy()
100 def draw_text(text, vec, dx=3.0, dy=-4.0):
101 vec_4d = perspective_matrix @ vec.to_4d()
102 if vec_4d.w > 0.0:
103 x = region_mid_width + region_mid_width * (vec_4d.x / vec_4d.w)
104 y = region_mid_height + region_mid_height * (vec_4d.y / vec_4d.w)
106 blf.position(font_id, x + dx, y + dy, 0.0)
107 blf.draw(font_id, text)
109 if data_vector:
110 for key, vec in data_vector.items():
111 draw_text(key, vec)
113 if data_vector_array:
114 for key, vec in data_vector_array.items():
115 if vec:
116 draw_text(key, vec[0])
118 if data_matrix:
119 for key, mat in data_matrix.items():
120 loc = Vector((mat[0][3], mat[1][3], mat[2][3]))
121 draw_text(key, loc, dx=10, dy=-20)
123 offset_y = 20
124 if data_quat:
125 loc = context.scene.cursor.location.copy()
126 for key, mat in data_quat.items():
127 draw_text(key, loc, dy=-offset_y)
128 offset_y += 20
130 if data_euler:
131 loc = context.scene.cursor.location.copy()
132 for key, mat in data_euler.items():
133 draw_text(key, loc, dy=-offset_y)
134 offset_y += 20
136 def draw_callback_view():
137 settings = bpy.context.window_manager.MathVisProp
138 scale = settings.bbox_scale
139 with_bounding_box = not settings.bbox_hide
141 if settings.in_front:
142 bgl.glDepthFunc(bgl.GL_ALWAYS)
143 else:
144 bgl.glDepthFunc(bgl.GL_LESS)
146 data_matrix, data_quat, data_euler, data_vector, data_vector_array = utils.console_math_data()
148 if data_vector:
149 coords = [tuple(vec.to_3d()) for vec in data_vector.values()]
150 draw_points(coords)
152 if data_vector_array:
153 for line in data_vector_array.values():
154 coords = [tuple(vec.to_3d()) for vec in line]
155 draw_line(coords)
157 if data_matrix:
158 draw_matrices(list(data_matrix.values()), scale, with_bounding_box)
160 if data_euler or data_quat:
161 cursor = bpy.context.scene.cursor.location.copy()
162 derived_matrices = []
163 for quat in data_quat.values():
164 matrix = quat.to_matrix().to_4x4()
165 matrix.translation = cursor
166 derived_matrices.append(matrix)
167 for eul in data_euler.values():
168 matrix = eul.to_matrix().to_4x4()
169 matrix.translation = cursor
170 derived_matrices.append(matrix)
171 draw_matrices(derived_matrices, scale, with_bounding_box)
173 def draw_points(points):
174 batch = batch_from_points(points, "POINTS")
175 single_color_shader.bind()
176 single_color_shader.uniform_float("color", COLOR_POINT)
177 batch.draw(single_color_shader)
179 def draw_line(points):
180 batch = batch_from_points(points, "LINE_STRIP")
181 single_color_shader.bind()
182 single_color_shader.uniform_float("color", COLOR_LINE)
183 batch.draw(single_color_shader)
185 def batch_from_points(points, type):
186 return batch_for_shader(single_color_shader, type, {"pos" : points})
188 def draw_matrices(matrices, scale, with_bounding_box):
189 x_p = Vector(( scale, 0.0, 0.0))
190 x_n = Vector((-scale, 0.0, 0.0))
191 y_p = Vector((0.0, scale, 0.0))
192 y_n = Vector((0.0, -scale, 0.0))
193 z_p = Vector((0.0, 0.0, scale))
194 z_n = Vector((0.0, 0.0, -scale))
196 red_dark = (0.2, 0.0, 0.0, 1.0)
197 red_light = (1.0, 0.2, 0.2, 1.0)
198 green_dark = (0.0, 0.2, 0.0, 1.0)
199 green_light = (0.2, 1.0, 0.2, 1.0)
200 blue_dark = (0.0, 0.0, 0.2, 1.0)
201 blue_light = (0.4, 0.4, 1.0, 1.0)
203 coords = []
204 colors = []
205 for matrix in matrices:
206 coords.append(matrix @ x_n)
207 coords.append(matrix @ x_p)
208 colors.extend((red_dark, red_light))
209 coords.append(matrix @ y_n)
210 coords.append(matrix @ y_p)
211 colors.extend((green_dark, green_light))
212 coords.append(matrix @ z_n)
213 coords.append(matrix @ z_p)
214 colors.extend((blue_dark, blue_light))
216 batch = batch_for_shader(smooth_color_shader, "LINES", {
217 "pos" : coords,
218 "color" : colors
220 batch.draw(smooth_color_shader)
222 if with_bounding_box:
223 draw_bounding_boxes(matrices, scale, COLOR_BOUNDING_BOX)
225 def draw_bounding_boxes(matrices, scale, color):
226 boundbox_points = []
227 for x in (-scale, scale):
228 for y in (-scale, scale):
229 for z in (-scale, scale):
230 boundbox_points.append(Vector((x, y, z)))
232 boundbox_lines = [
233 (0, 1), (1, 3), (3, 2), (2, 0), (0, 4), (4, 5),
234 (5, 7), (7, 6), (6, 4), (1, 5), (2, 6), (3, 7)
237 points = []
238 for matrix in matrices:
239 for v1, v2 in boundbox_lines:
240 points.append(matrix @ boundbox_points[v1])
241 points.append(matrix @ boundbox_points[v2])
243 batch = batch_from_points(points, "LINES")
245 single_color_shader.bind()
246 single_color_shader.uniform_float("color", color)
247 batch.draw(single_color_shader)