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 #####
25 from gpu_extras
.batch
import batch_for_shader
28 from mathutils
import Vector
30 SpaceView3D
= bpy
.types
.SpaceView3D
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')
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():
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']:
54 def callback_enable():
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
65 def callback_disable():
66 if not callback_handle
:
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
[:] = []
77 def draw_callback_px():
80 if context
.window_manager
.MathVisProp
.name_hide
:
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
:
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()
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
)
110 for key
, vec
in data_vector
.items():
113 if data_vector_array
:
114 for key
, vec
in data_vector_array
.items():
116 draw_text(key
, vec
[0])
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)
125 loc
= context
.scene
.cursor
.location
.copy()
126 for key
, mat
in data_quat
.items():
127 draw_text(key
, loc
, dy
=-offset_y
)
131 loc
= context
.scene
.cursor
.location
.copy()
132 for key
, mat
in data_euler
.items():
133 draw_text(key
, loc
, dy
=-offset_y
)
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
)
144 bgl
.glDepthFunc(bgl
.GL_LESS
)
146 data_matrix
, data_quat
, data_euler
, data_vector
, data_vector_array
= utils
.console_math_data()
149 coords
= [tuple(vec
.to_3d()) for vec
in data_vector
.values()]
152 if data_vector_array
:
153 for line
in data_vector_array
.values():
154 coords
= [tuple(vec
.to_3d()) for vec
in line
]
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)
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", {
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
):
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
)))
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)
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
)