1 # SPDX-License-Identifier: GPL-2.0-or-later
6 from gpu_extras
.batch
import batch_for_shader
9 from mathutils
import Vector
11 SpaceView3D
= bpy
.types
.SpaceView3D
14 if not bpy
.app
.background
:
15 single_color_shader
= gpu
.shader
.from_builtin('UNIFORM_COLOR')
16 smooth_color_shader
= gpu
.shader
.from_builtin('SMOOTH_COLOR')
18 single_color_shader
= None
19 smooth_color_shader
= None
21 COLOR_POINT
= (1.0, 0.0, 1.0, 1)
22 COLOR_LINE
= (0.5, 0.5, 1, 1)
23 COLOR_LINE_ACTIVE
= (1.0, 1.0, 0.5, 1)
24 COLOR_BOUNDING_BOX
= (1.0, 1.0, 1.0, 1.0)
25 COLOR_BOUNDING_BOX_ACTIVE
= (1.0, 0.5, 0.0, 1.0)
28 def tag_redraw_areas():
31 # Py can't access notifers
32 for window
in context
.window_manager
.windows
:
33 for area
in window
.screen
.areas
:
34 if area
.type in ['VIEW_3D', 'PROPERTIES']:
38 def callback_enable():
42 handle_pixel
= SpaceView3D
.draw_handler_add(draw_callback_px
, (), 'WINDOW', 'POST_PIXEL')
43 handle_view
= SpaceView3D
.draw_handler_add(draw_callback_view
, (), 'WINDOW', 'POST_VIEW')
44 callback_handle
[:] = handle_pixel
, handle_view
49 def callback_disable():
50 if not callback_handle
:
53 handle_pixel
, handle_view
= callback_handle
54 SpaceView3D
.draw_handler_remove(handle_pixel
, 'WINDOW')
55 SpaceView3D
.draw_handler_remove(handle_view
, 'WINDOW')
56 callback_handle
[:] = []
61 def draw_callback_px():
64 if context
.window_manager
.MathVisProp
.name_hide
:
68 ui_scale
= context
.preferences
.system
.ui_scale
69 blf
.size(font_id
, round(12 * ui_scale
))
71 data_matrix
, data_quat
, data_euler
, data_vector
, data_vector_array
= utils
.console_math_data()
72 if not data_matrix
and not data_quat
and not data_euler
and not data_vector
and not data_vector_array
:
75 region
= context
.region
76 region3d
= context
.space_data
.region_3d
78 region_mid_width
= region
.width
/ 2.0
79 region_mid_height
= region
.height
/ 2.0
81 perspective_matrix
= region3d
.perspective_matrix
.copy()
83 def draw_text(text
, vec
, dx
=3.0, dy
=-4.0):
84 vec_4d
= perspective_matrix
@ vec
.to_4d()
86 x
= region_mid_width
+ region_mid_width
* (vec_4d
.x
/ vec_4d
.w
)
87 y
= region_mid_height
+ region_mid_height
* (vec_4d
.y
/ vec_4d
.w
)
89 blf
.position(font_id
, x
+ dx
, y
+ dy
, 0.0)
90 blf
.draw(font_id
, text
)
93 for key
, vec
in data_vector
.items():
97 for key
, vec
in data_vector_array
.items():
99 draw_text(key
, vec
[0])
102 for key
, mat
in data_matrix
.items():
103 loc
= Vector((mat
[0][3], mat
[1][3], mat
[2][3]))
104 draw_text(key
, loc
, dx
=10, dy
=-20)
108 loc
= context
.scene
.cursor
.location
.copy()
109 for key
, mat
in data_quat
.items():
110 draw_text(key
, loc
, dy
=-offset_y
)
114 loc
= context
.scene
.cursor
.location
.copy()
115 for key
, mat
in data_euler
.items():
116 draw_text(key
, loc
, dy
=-offset_y
)
120 def draw_callback_view():
121 settings
= bpy
.context
.window_manager
.MathVisProp
122 prop_states
= bpy
.context
.window_manager
.MathVisStatePropList
124 scale
= settings
.bbox_scale
125 with_bounding_box
= not settings
.bbox_hide
127 if settings
.in_front
:
128 gpu
.state
.depth_test_set('ALWAYS')
130 gpu
.state
.depth_test_set('LESS')
132 data_matrix
, data_quat
, data_euler
, data_vector
, data_vector_array
= utils
.console_math_data()
133 if settings
.index
in range(0,len(prop_states
)):
134 active_index
= settings
.index
135 active_key
= prop_states
[active_index
].name
141 coords
= [tuple(vec
.to_3d()) for vec
in data_vector
.values()]
144 if data_vector_array
:
145 for key
, line
in data_vector_array
.items():
146 coords
= [tuple(vec
.to_3d()) for vec
in line
]
147 if key
== active_key
:
148 draw_line(coords
, COLOR_LINE_ACTIVE
)
150 draw_line(coords
, COLOR_LINE
)
153 draw_matrices(data_matrix
, scale
, with_bounding_box
, active_key
)
155 if data_euler
or data_quat
:
156 cursor
= bpy
.context
.scene
.cursor
.location
.copy()
157 derived_matrices
= []
158 for key
, quat
in data_quat
.values():
159 matrix
= quat
.to_matrix().to_4x4()
160 matrix
.translation
= cursor
161 derived_matrices
[key
] = matrix
162 for key
, eul
in data_euler
.values():
163 matrix
= eul
.to_matrix().to_4x4()
164 matrix
.translation
= cursor
165 derived_matrices
[key
] = matrix
166 draw_matrices(derived_matrices
, scale
, with_bounding_box
, active_key
)
169 def draw_points(points
):
170 batch
= batch_from_points(points
, "POINTS")
171 single_color_shader
.bind()
172 single_color_shader
.uniform_float("color", COLOR_POINT
)
173 batch
.draw(single_color_shader
)
176 def draw_line(points
, color
):
177 batch
= batch_from_points(points
, "LINE_STRIP")
178 single_color_shader
.bind()
179 single_color_shader
.uniform_float("color", color
)
180 batch
.draw(single_color_shader
)
183 def batch_from_points(points
, type):
184 return batch_for_shader(single_color_shader
, type, {"pos": points
})
187 def draw_matrices(matrices
, scale
, with_bounding_box
, active_key
):
188 x_p
= Vector((scale
, 0.0, 0.0))
189 x_n
= Vector((-scale
, 0.0, 0.0))
190 y_p
= Vector((0.0, scale
, 0.0))
191 y_n
= Vector((0.0, -scale
, 0.0))
192 z_p
= Vector((0.0, 0.0, scale
))
193 z_n
= Vector((0.0, 0.0, -scale
))
195 red_dark
= (0.2, 0.0, 0.0, 1.0)
196 red_light
= (1.0, 0.2, 0.2, 1.0)
197 green_dark
= (0.0, 0.2, 0.0, 1.0)
198 green_light
= (0.2, 1.0, 0.2, 1.0)
199 blue_dark
= (0.0, 0.0, 0.2, 1.0)
200 blue_light
= (0.4, 0.4, 1.0, 1.0)
206 for key
, matrix
in matrices
.items():
207 coords
.append(matrix
@ x_n
)
208 coords
.append(matrix
@ x_p
)
209 colors
.extend((red_dark
, red_light
))
210 coords
.append(matrix
@ y_n
)
211 coords
.append(matrix
@ y_p
)
212 colors
.extend((green_dark
, green_light
))
213 coords
.append(matrix
@ z_n
)
214 coords
.append(matrix
@ z_p
)
215 colors
.extend((blue_dark
, blue_light
))
216 if key
== active_key
:
217 active
.append(matrix
)
219 selected
.append(matrix
)
221 batch
= batch_for_shader(smooth_color_shader
, "LINES", {
225 batch
.draw(smooth_color_shader
)
227 if with_bounding_box
:
229 draw_bounding_boxes(selected
, scale
, COLOR_BOUNDING_BOX
)
231 draw_bounding_boxes(active
, scale
, COLOR_BOUNDING_BOX_ACTIVE
)
234 def draw_bounding_boxes(matrices
, scale
, color
):
236 for x
in (-scale
, scale
):
237 for y
in (-scale
, scale
):
238 for z
in (-scale
, scale
):
239 boundbox_points
.append(Vector((x
, y
, z
)))
242 (0, 1), (1, 3), (3, 2), (2, 0), (0, 4), (4, 5),
243 (5, 7), (7, 6), (6, 4), (1, 5), (2, 6), (3, 7)
247 for matrix
in matrices
:
248 for v1
, v2
in boundbox_lines
:
249 points
.append(matrix
@ boundbox_points
[v1
])
250 points
.append(matrix
@ boundbox_points
[v2
])
252 batch
= batch_from_points(points
, "LINES")
254 single_color_shader
.bind()
255 single_color_shader
.uniform_float("color", color
)
256 batch
.draw(single_color_shader
)