51 const bool flush_selection,
52 const bool flush_hidden)
56 const int *index_array =
nullptr;
60 if (mesh ==
nullptr) {
68 if (flush_selection) {
69 bke::mesh_select_face_flush(*mesh);
75 if (ob_eval ==
nullptr) {
86 if (me_orig !=
nullptr && mesh_eval !=
nullptr && me_orig->
faces_num == mesh->faces_num) {
90 ".hide_poly", bke::AttrDomain::Face,
false);
93 bke::AttrDomain::Face);
95 hide_poly_orig.finish();
97 if (flush_selection) {
99 ".select_poly", bke::AttrDomain::Face,
false);
102 bke::AttrDomain::Face);
104 select_poly_orig.finish();
111 ".hide_poly", bke::AttrDomain::Face,
false);
114 bke::AttrDomain::Face);
116 const int orig_face_index = index_array[i];
118 hide_poly_eval.
span[i] = hide_poly_orig[orig_face_index];
121 hide_poly_eval.finish();
123 if (flush_selection) {
125 ".select_poly", bke::AttrDomain::Face,
false);
128 bke::AttrDomain::Face);
130 const int orig_face_index = index_array[i];
132 select_poly_eval.
span[i] = select_poly_orig[orig_face_index];
135 select_poly_eval.finish();
163 if (mesh ==
nullptr || mesh->faces_num == 0) {
169 ".hide_poly", bke::AttrDomain::Face);
171 ".select_poly", bke::AttrDomain::Face);
173 for (
int i = 0; i < mesh->faces_num; i++) {
174 if (!hide_poly.
span[i]) {
175 if (!select_poly.span[i] == unselected) {
176 hide_poly.
span[i] =
true;
180 if (hide_poly.
span[i]) {
181 select_poly.span[i] =
false;
186 select_poly.finish();
188 bke::mesh_hide_face_flush(*mesh);
197 if (mesh ==
nullptr || mesh->faces_num == 0) {
204 const VArray<bool> hide_poly = *attributes.lookup_or_default<
bool>(
205 ".hide_poly", bke::AttrDomain::Face,
false);
207 ".select_poly", bke::AttrDomain::Face);
210 select_poly.
span[i] =
true;
213 select_poly.finish();
216 attributes.remove(
".hide_poly");
218 bke::mesh_hide_face_flush(*mesh);
231 const bool skip_seams =
true)
234 const OffsetIndices faces = mesh.faces();
235 const Span<int> corner_edges = mesh.corner_edges();
238 const VArray<bool> uv_seams = *attributes.lookup_or_default<
bool>(
239 ".uv_seam", bke::AttrDomain::Edge,
false);
240 const VArray<bool> hide_poly = *attributes.lookup_or_default<
bool>(
241 ".hide_poly", bke::AttrDomain::Face,
false);
245 threading::parallel_for(faces.index_range(), 1024, [&](
const IndexRange range) {
246 for (const int face_index : range) {
247 if (hide_poly[face_index]) {
250 const Span<int> face_edges = corner_edges.slice(faces[face_index]);
252 for (const int poly_loop_index : face_edges.index_range()) {
253 const int outer_edge = face_edges[poly_loop_index];
254 if (skip_seams && uv_seams[outer_edge]) {
258 for (const int inner_edge :
259 face_edges.slice(poly_loop_index, face_edges.size() - poly_loop_index))
261 if (outer_edge == inner_edge) {
264 if (skip_seams && uv_seams[inner_edge]) {
267 islands.join(inner_edge, outer_edge);
284 const OffsetIndices faces = mesh.faces();
285 const Span<int> corner_edges = mesh.corner_edges();
288 const VArray<bool> uv_seams = *attributes.lookup_or_default<
bool>(
289 ".uv_seam", bke::AttrDomain::Edge,
false);
291 ".select_poly", bke::AttrDomain::Face);
293 Set<int> selected_roots;
294 for (
const int i : face_indices) {
295 for (
const int edge : corner_edges.
slice(faces[i])) {
296 if (uv_seams[edge]) {
299 const int root = islands.find_root(edge);
300 selected_roots.add(root);
304 threading::parallel_for(select_poly.span.index_range(), 1024, [&](
const IndexRange range) {
305 for (const int face_index : range) {
306 for (const int edge : corner_edges.slice(faces[face_index])) {
307 const int root = islands.find_root(edge);
308 if (selected_roots.contains(root)) {
309 select_poly.span[face_index] = select;
323 if (mesh ==
nullptr || mesh->faces_num == 0) {
329 ".select_poly", bke::AttrDomain::Face);
340 select_poly.
span[index] =
true;
341 indices.append(index);
345 for (
const int i : select_poly.
span.index_range()) {
346 if (!select_poly.
span[i]) {
366 int closest_edge_index;
370 for (
const int i : face_edges) {
372 const int2 edge = edges[i];
374 vert_positions[edge[1]]);
381 if (distance < min_distance) {
383 closest_edge_index = i;
386 return closest_edge_index;
391 const int current_edge_index)
393 const int index_in_poly = corner_edges.
slice(face).
first_index(current_edge_index);
395 if (index_in_poly >= 2) {
396 return corner_edges[face[index_in_poly - 2]];
399 return corner_edges[face[index_in_poly + 2]];
407 const int edge_start_index,
415 int current_face_index = face_start_index;
416 int current_edge_index = edge_start_index;
418 while (current_edge_index > 0) {
419 int next_face_index = -1;
421 for (
const int face_index : edge_to_face_map[current_edge_index]) {
422 if (face_index != current_face_index) {
423 next_face_index = face_index;
429 if (next_face_index == -1) {
434 if (faces[next_face_index].
size() != 4) {
439 if (r_loop_faces.
contains(next_face_index)) {
444 if (hide_poly[next_face_index]) {
448 r_loop_faces.
add(next_face_index);
450 const IndexRange next_face = faces[next_face_index];
452 current_face_index = next_face_index;
480 const Span<int> corner_edges = mesh->corner_edges();
482 const OffsetIndices faces = mesh->faces();
485 const IndexRange face = faces[poly_pick_index];
487 region, edges, corner_edges.
slice(face),
verts, mval);
491 const GroupedSpan<int> edge_to_face_map = bke::mesh::build_edge_to_face_map(
492 faces, corner_edges, mesh->edges_num, edge_to_face_offsets, edge_to_face_indices);
497 const VArray<bool> hide_poly = *attributes.lookup_or_default<
bool>(
498 ".hide_poly", bke::AttrDomain::Face,
false);
500 const Span<int> faces_to_closest_edge = edge_to_face_map[closest_edge_index];
509 if (!traced_full_loop && faces_to_closest_edge.size() > 1) {
521 ".select_poly", bke::AttrDomain::Face);
525 bool any_adjacent_poly_selected =
false;
526 for (
const int i : faces_to_closest_edge) {
527 any_adjacent_poly_selected |= select_poly.
span[i];
529 const bool select_toggle =
select && !any_adjacent_poly_selected;
530 select_poly.
span.fill_indices(faces_to_select.
as_span(), select_toggle);
541 for (
const int edge_index : face_edges) {
546 if (select_vert[edge[0]] || select_vert[edge[1]]) {
551 if (select_vert[edge[0]] && select_vert[edge[1]]) {
565 ".select_poly", bke::AttrDomain::Face);
567 ".select_vert", bke::AttrDomain::Point);
568 const VArray<bool> hide_poly = *attributes.lookup_or_default<
bool>(
569 ".hide_poly", bke::AttrDomain::Face,
false);
571 const OffsetIndices faces = mesh->faces();
572 const Span<int> corner_edges = mesh->corner_edges();
575 threading::parallel_for(select_poly.
span.index_range(), 1024, [&](
const IndexRange range) {
576 for (const int i : range) {
577 if (select_poly.span[i] || hide_poly[i]) {
580 const IndexRange face = faces[i];
581 if (poly_has_selected_neighbor(corner_edges.slice(face), edges, select_vert.span, face_step))
583 select_poly.span[i] = true;
588 select_poly.finish();
589 select_vert.finish();
597 for (
const int edge_index : face_edges) {
600 if (verts_of_unselected_faces[edge[0]] || verts_of_unselected_faces[edge[1]]) {
605 if (verts_of_unselected_faces[edge[0]] && verts_of_unselected_faces[edge[1]]) {
619 ".select_poly", bke::AttrDomain::Face);
620 const VArray<bool> hide_poly = *attributes.lookup_or_default<
bool>(
621 ".hide_poly", bke::AttrDomain::Face,
false);
623 const OffsetIndices faces = mesh->faces();
624 const Span<int> corner_verts = mesh->corner_verts();
625 const Span<int> corner_edges = mesh->corner_edges();
628 BitVector<> verts_of_unselected_faces(mesh->verts_num);
631 for (
const int i : faces.index_range()) {
632 if (select_poly.
span[i]) {
636 for (
const int vert : corner_verts.
slice(face)) {
637 verts_of_unselected_faces[vert].set(
true);
641 threading::parallel_for(faces.index_range(), 1024, [&](
const IndexRange range) {
642 for (const int i : range) {
643 if (!select_poly.span[i] || hide_poly[i]) {
646 const IndexRange face = faces[i];
647 if (poly_has_unselected_neighbor(
648 corner_edges.slice(face), edges, verts_of_unselected_faces, face_step))
650 select_poly.span[i] = false;
655 select_poly.finish();
662 if (mesh ==
nullptr) {
667 const VArray<bool> hide_poly = *attributes.lookup_or_default<
bool>(
668 ".hide_poly", bke::AttrDomain::Face,
false);
670 ".select_poly", bke::AttrDomain::Face);
675 for (
int i = 0; i < mesh->faces_num; i++) {
676 if (!hide_poly[i] && select_poly.span[i]) {
683 bool changed =
false;
685 for (
int i = 0; i < mesh->faces_num; i++) {
689 const bool old_selection = select_poly.
span[i];
692 select_poly.span[i] =
true;
695 select_poly.span[i] =
false;
698 select_poly.span[i] = !select_poly.span[i];
702 if (old_selection != select_poly.span[i]) {
707 select_poly.finish();
721 float vec[3], bmat[3][3];
728 copy_m3_m4(bmat, ob->object_to_world().ptr());
731 const OffsetIndices faces = mesh->faces();
732 const Span<int> corner_verts = mesh->corner_verts();
734 const VArray<bool> hide_poly = *attributes.lookup_or_default<
bool>(
735 ".hide_poly", bke::AttrDomain::Face,
false);
736 const VArray<bool> select_poly = *attributes.lookup_or_default<
bool>(
737 ".select_poly", bke::AttrDomain::Face,
false);
739 for (
int i = 0; i < mesh->faces_num; i++) {
740 if (hide_poly[i] || !select_poly[i]) {
744 for (
const int vert : corner_verts.
slice(faces[i])) {
746 add_v3_v3v3(vec, vec, ob->object_to_world().location());
763 bool changed =
false;
770 const VArray<bool> hide_poly = *attributes.lookup_or_default<
bool>(
771 ".hide_poly", bke::AttrDomain::Face,
false);
773 ".select_poly", bke::AttrDomain::Face);
776 if (index < mesh->faces_num) {
777 if (!hide_poly[index]) {
784 if ((found &&
params->select_passthrough) && select_poly.varray[index]) {
787 else if (found ||
params->deselect_all) {
794 mesh->act_face =
int(index);
799 select_poly.varray.set(index,
true);
802 select_poly.varray.set(index,
false);
805 select_poly.varray.set(index, !select_poly.varray[index]);
818 select_poly.finish();
819 return changed || found;
827 if (mesh ==
nullptr) {
833 bke::mesh_select_vert_flush(*mesh);
835 if (mesh_eval ==
nullptr) {
845 ".hide_vert", bke::AttrDomain::Point,
false);
848 bke::AttrDomain::Point);
850 for (
const int i : hide_vert_eval.span.index_range()) {
852 hide_vert_eval.
span[i] = hide_vert_orig[orig_indices[i]];
859 hide_vert_eval.finish();
862 ".select_vert", bke::AttrDomain::Point,
false);
865 bke::AttrDomain::Point);
867 for (
const int i : select_vert_eval.span.index_range()) {
869 select_vert_eval.
span[i] = select_vert_orig[orig_indices[i]];
874 select_vert_orig.
materialize(select_vert_eval.span);
876 select_vert_eval.finish();
889 if (mesh ==
nullptr || mesh->faces_num == 0) {
899 threading::parallel_for(edges.index_range(), 1024, [&](
const IndexRange range) {
900 for (const int2 &edge : edges.slice(range)) {
901 islands.join(edge[0], edge[1]);
907 ".select_vert", bke::AttrDomain::Point);
909 Set<int> selected_roots;
911 for (
const int i : vertex_indices) {
912 const int root = islands.find_root(i);
913 selected_roots.add(root);
916 threading::parallel_for(select_vert.
span.index_range(), 1024, [&](
const IndexRange range) {
917 for (const int i : range) {
918 const int root = islands.find_root(i);
919 if (selected_roots.contains(root)) {
920 select_vert.span[i] = select;
933 const int region_coordinates[2],
949 if (mesh ==
nullptr || mesh->faces_num == 0) {
955 attributes.lookup_or_add_for_write_span<
bool>(
".select_vert", bke::AttrDomain::Point);
958 for (
const int i : select_vert.
span.index_range()) {
959 if (!select_vert.
span[i]) {
974 ".select_vert", bke::AttrDomain::Point);
975 const VArray<bool> hide_edge = *attributes.lookup_or_default<
bool>(
976 ".hide_edge", bke::AttrDomain::Edge,
false);
977 const VArray<bool> hide_poly = *attributes.lookup_or_default<
bool>(
978 ".hide_poly", bke::AttrDomain::Face,
false);
980 const OffsetIndices faces = mesh->faces();
981 const Span<int> corner_edges = mesh->corner_edges();
982 const Span<int> corner_verts = mesh->corner_verts();
989 edge_to_face_map = bke::mesh::build_edge_to_face_map(
990 faces, corner_edges, mesh->edges_num, edge_to_face_offsets, edge_to_face_indices);
994 BitVector<> select_vert_original(mesh->verts_num,
false);
995 for (
int i = 0; i < mesh->verts_num; i++) {
996 select_vert_original[i].set(select_vert.
span[i]);
1001 for (
const int i : edges.index_range()) {
1002 const int2 &edge = edges[i];
1003 if ((!select_vert_original[edge[0]] && !select_vert_original[edge[1]]) || hide_edge[i]) {
1006 select_vert.
span[edge[0]] =
true;
1007 select_vert.
span[edge[1]] =
true;
1011 const Span<int> neighbor_polys = edge_to_face_map[i];
1012 for (
const int face_i : neighbor_polys) {
1013 if (hide_poly[face_i]) {
1017 for (
const int vert : corner_verts.
slice(face)) {
1018 select_vert.
span[vert] =
true;
1032 ".select_vert", bke::AttrDomain::Point);
1033 const VArray<bool> hide_edge = *attributes.lookup_or_default<
bool>(
1034 ".hide_edge", bke::AttrDomain::Edge,
false);
1035 const VArray<bool> hide_poly = *attributes.lookup_or_default<
bool>(
1036 ".hide_poly", bke::AttrDomain::Face,
false);
1038 const OffsetIndices faces = mesh->faces();
1039 const Span<int> corner_edges = mesh->corner_edges();
1040 const Span<int> corner_verts = mesh->corner_verts();
1047 edge_to_face_map = bke::mesh::build_edge_to_face_map(
1048 faces, corner_edges, edges.
size(), edge_to_face_offsets, edge_to_face_indices);
1052 BitVector<> select_vert_original(mesh->verts_num);
1053 for (
int i = 0; i < mesh->verts_num; i++) {
1054 select_vert_original[i].set(select_vert.
span[i]);
1057 for (
const int i : edges.index_range()) {
1058 const int2 &edge = edges[i];
1059 if ((select_vert_original[edge[0]] && select_vert_original[edge[1]]) && !hide_edge[i]) {
1062 select_vert.
span[edge[0]] =
false;
1063 select_vert.
span[edge[1]] =
false;
1068 for (
const int face_i : edge_to_face_map[i]) {
1069 if (hide_poly[face_i]) {
1073 for (
const int vert : corner_verts.
slice(face)) {
1074 select_vert.
span[vert] =
false;
1091 if (mesh ==
nullptr) {
1096 const VArray<bool> hide_vert = *attributes.lookup_or_default<
bool>(
1097 ".hide_vert", bke::AttrDomain::Point,
false);
1099 ".select_vert", bke::AttrDomain::Point);
1104 for (
int i = 0; i < mesh->verts_num; i++) {
1105 if (!hide_vert[i] && select_vert.span[i]) {
1112 bool changed =
false;
1113 for (
int i = 0; i < mesh->verts_num; i++) {
1117 const bool old_selection = select_vert.
span[i];
1120 select_vert.span[i] =
true;
1123 select_vert.span[i] =
false;
1126 select_vert.span[i] = !select_vert.span[i];
1129 if (old_selection != select_vert.span[i]) {
1134 select_vert.finish();
1159 if (mesh ==
nullptr) {
1172 const VArray<bool> hide_vert = *attributes.lookup_or_default<
bool>(
1173 ".hide_vert", bke::AttrDomain::Point,
false);
1175 ".select_vert", bke::AttrDomain::Point);
1177 for (
const int i : select_vert.span.index_range()) {
1178 if (!hide_vert[i]) {
1179 if (dverts[i].dw ==
nullptr) {
1181 select_vert.
span[i] =
true;
1186 select_vert.finish();
1197 if (mesh ==
nullptr || mesh->verts_num == 0) {
1203 ".hide_vert", bke::AttrDomain::Point);
1205 ".select_vert", bke::AttrDomain::Point);
1207 for (
const int i : hide_vert.
span.index_range()) {
1208 if (!hide_vert.
span[i]) {
1209 if (!select_vert.span[i] == unselected) {
1210 hide_vert.
span[i] =
true;
1214 if (hide_vert.
span[i]) {
1215 select_vert.span[i] =
false;
1219 select_vert.finish();
1221 bke::mesh_hide_vert_flush(*mesh);
1231 if (mesh ==
nullptr || mesh->verts_num == 0) {
1236 const VArray<bool> hide_vert = *attributes.lookup_or_default<
bool>(
1237 ".hide_vert", bke::AttrDomain::Point,
false);
1239 ".select_vert", bke::AttrDomain::Point);
1241 for (
const int i : select_vert.span.index_range()) {
1247 select_vert.finish();
1250 attributes.remove(
".hide_vert");
1252 bke::mesh_hide_vert_flush(*mesh);
Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
CustomData interface, see also DNA_customdata_types.h.
const void * CustomData_get_layer(const CustomData *data, eCustomDataType type)
bool CustomData_has_layer(const CustomData *data, eCustomDataType type)
void BKE_mesh_batch_cache_dirty_tag(Mesh *mesh, eMeshBatchDirtyMode mode)
void BKE_mesh_mselect_clear(Mesh *mesh)
void BKE_mesh_mselect_validate(Mesh *mesh)
Mesh * BKE_mesh_from_object(Object *ob)
@ BKE_MESH_BATCH_DIRTY_SELECT_PAINT
@ BKE_MESH_BATCH_DIRTY_ALL
General operations, lookup, etc. for blender objects.
Mesh * BKE_object_get_evaluated_mesh(const Object *object_eval)
#define BLI_assert_unreachable()
void copy_m3_m4(float m1[3][3], const float m2[4][4])
void mul_v3_m3v3(float r[3], const float M[3][3], const float a[3])
void minmax_v3v3_v3(float min[3], float max[3], const float vec[3])
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
void DEG_id_tag_update(ID *id, unsigned int flags)
Object * DEG_get_evaluated_object(const Depsgraph *depsgraph, Object *object)
Object is a sort of wrapper for general info.
#define ED_MESH_PICK_DEFAULT_VERT_DIST
bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], uint dist_px, uint *r_index)
#define ED_MESH_PICK_DEFAULT_FACE_DIST
bool ED_mesh_pick_vert(bContext *C, Object *ob, const int mval[2], uint dist_px, bool use_zbuf, uint *r_index)
void ED_region_tag_redraw(ARegion *region)
eV3DProjStatus ED_view3d_project_float_object(const ARegion *region, const float co[3], float r_co[2], eV3DProjTest flag)
void ED_view3d_init_mats_rv3d(const Object *ob, RegionView3D *rv3d)
void ED_view3d_select_id_validate(const ViewContext *vc)
ViewContext ED_view3d_viewcontext_init(bContext *C, Depsgraph *depsgraph)
#define V3D_PROJ_TEST_CLIP_DEFAULT
Contains defines and structs used throughout the imbuf module.
Read Guarded memory(de)allocation.
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
constexpr Span slice(int64_t start, int64_t size) const
constexpr int64_t first_index(const T &search_value) const
constexpr int64_t size() const
constexpr bool is_empty() const
IndexRange index_range() const
void materialize(MutableSpan< T > r_span) const
Span< Key > as_span() const
bool contains(const Key &key) const
void append(const T &value)
GAttributeReader lookup_or_default(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const void *default_value=nullptr) const
GSpanAttributeWriter lookup_or_add_for_write_only_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type)
const Depsgraph * depsgraph
static void build_poly_connections(blender::AtomicDisjointSet &islands, Mesh &mesh, const bool skip_seams=true)
static bool follow_face_loop(const int face_start_index, const int edge_start_index, const blender::OffsetIndices< int > faces, const blender::VArray< bool > &hide_poly, const blender::Span< int > corner_edges, const blender::GroupedSpan< int > edge_to_face_map, blender::VectorSet< int > &r_loop_faces)
static bool poly_has_unselected_neighbor(blender::Span< int > face_edges, blender::Span< blender::int2 > edges, blender::BitSpan verts_of_unselected_faces, const bool face_step)
bool paintface_minmax(Object *ob, float r_min[3], float r_max[3])
void paintvert_flush_flags(Object *ob)
void paintface_flush_flags(bContext *C, Object *ob, const bool flush_selection, const bool flush_hidden)
void paintface_reveal(bContext *C, Object *ob, const bool select)
void paintvert_tag_select_update(bContext *C, Object *ob)
void paintface_hide(bContext *C, Object *ob, const bool unselected)
void paintvert_select_ungrouped(Object *ob, bool extend, bool flush_flags)
static int get_opposing_edge_index(const blender::IndexRange face, const blender::Span< int > corner_edges, const int current_edge_index)
void paintface_select_less(Mesh *mesh, const bool face_step)
void paintface_select_more(Mesh *mesh, const bool face_step)
bool paintface_mouse_select(bContext *C, const int mval[2], const SelectPick_Params *params, Object *ob)
bool paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags)
void paintvert_select_linked(bContext *C, Object *ob)
void paintvert_select_linked_pick(bContext *C, Object *ob, const int region_coordinates[2], const bool select)
static int find_closest_edge_in_poly(ARegion *region, blender::Span< blender::int2 > edges, blender::Span< int > face_edges, blender::Span< blender::float3 > vert_positions, const int mval[2])
static void paintface_select_linked_faces(Mesh &mesh, const blender::Span< int > face_indices, const bool select)
static bool poly_has_selected_neighbor(blender::Span< int > face_edges, blender::Span< blender::int2 > edges, blender::Span< bool > select_vert, const bool face_step)
void paintvert_hide(bContext *C, Object *ob, const bool unselected)
void paintvert_reveal(bContext *C, Object *ob, const bool select)
void paintvert_select_less(Mesh *mesh, const bool face_step)
bool paintface_deselect_all_visible(bContext *C, Object *ob, int action, bool flush_flags)
void paintface_select_loop(bContext *C, Object *ob, const int mval[2], const bool select)
void paintvert_select_more(Mesh *mesh, const bool face_step)
void paintface_select_linked(bContext *C, Object *ob, const int mval[2], const bool select)
static void paintvert_select_linked_vertices(bContext *C, Object *ob, const blender::Span< int > vertex_indices, const bool select)
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
ccl_device_inline float4 select(const int4 mask, const float4 a, const float4 b)
static BMFace * face_step(BMEdge *edge, BMFace *f)
T midpoint(const T &a, const T &b)
T distance_squared(const VecBase< T, Size > &a, const VecBase< T, Size > &b)
float distance(float a, float b)
ObjectRuntimeHandle * runtime
MutableVArraySpan< T > span
void WM_event_add_notifier(const bContext *C, uint type, void *reference)