42 const bool flush_selection,
43 const bool flush_hidden)
47 const int *index_array =
nullptr;
51 if (
mesh ==
nullptr) {
59 if (flush_selection) {
60 bke::mesh_select_face_flush(*
mesh);
66 if (ob_eval ==
nullptr) {
81 ".hide_poly", bke::AttrDomain::Face,
false);
84 bke::AttrDomain::Face);
86 hide_poly_orig.finish();
88 if (flush_selection) {
90 ".select_poly", bke::AttrDomain::Face,
false);
93 bke::AttrDomain::Face);
95 select_poly_orig.finish();
102 ".hide_poly", bke::AttrDomain::Face,
false);
105 bke::AttrDomain::Face);
107 const int orig_face_index = index_array[i];
109 hide_poly_eval.
span[i] = hide_poly_orig[orig_face_index];
112 hide_poly_eval.finish();
114 if (flush_selection) {
116 ".select_poly", bke::AttrDomain::Face,
false);
119 bke::AttrDomain::Face);
121 const int orig_face_index = index_array[i];
123 select_poly_eval.
span[i] = select_poly_orig[orig_face_index];
126 select_poly_eval.finish();
160 ".hide_poly", bke::AttrDomain::Face);
162 ".select_poly", bke::AttrDomain::Face);
165 if (!hide_poly.
span[i]) {
166 if (!select_poly.span[i] == unselected) {
167 hide_poly.
span[i] =
true;
171 if (hide_poly.
span[i]) {
172 select_poly.span[i] =
false;
177 select_poly.finish();
179 bke::mesh_hide_face_flush(*
mesh);
196 ".hide_poly", bke::AttrDomain::Face,
false);
198 ".select_poly", bke::AttrDomain::Face);
201 select_poly.
span[i] =
true;
204 select_poly.finish();
207 attributes.
remove(
".hide_poly");
209 bke::mesh_hide_face_flush(*
mesh);
222 const bool skip_seams =
true)
225 const OffsetIndices
faces =
mesh.faces();
230 "uv_seam", bke::AttrDomain::Edge,
false);
232 ".hide_poly", bke::AttrDomain::Face,
false);
237 for (const int face_index : range) {
238 if (hide_poly[face_index]) {
241 const Span<int> face_edges = corner_edges.slice(faces[face_index]);
243 for (const int poly_loop_index : face_edges.index_range()) {
244 const int outer_edge = face_edges[poly_loop_index];
245 if (skip_seams && uv_seams[outer_edge]) {
249 for (const int inner_edge :
250 face_edges.slice(poly_loop_index, face_edges.size() - poly_loop_index))
252 if (outer_edge == inner_edge) {
255 if (skip_seams && uv_seams[inner_edge]) {
258 islands.join(inner_edge, outer_edge);
275 const OffsetIndices
faces =
mesh.faces();
280 "uv_seam", bke::AttrDomain::Edge,
false);
282 ".select_poly", bke::AttrDomain::Face);
285 for (
const int i : face_indices) {
286 for (
const int edge : corner_edges.
slice(
faces[i])) {
287 if (uv_seams[edge]) {
290 const int root = islands.
find_root(edge);
291 selected_roots.add(root);
295 threading::parallel_for(select_poly.span.index_range(), 1024, [&](
const IndexRange range) {
296 for (const int face_index : range) {
297 for (const int edge : corner_edges.slice(faces[face_index])) {
298 const int root = islands.find_root(edge);
299 if (selected_roots.contains(root)) {
300 select_poly.span[face_index] = select;
307 select_poly.finish();
320 ".select_poly", bke::AttrDomain::Face);
331 select_poly.
span[index] =
true;
336 for (
const int i : select_poly.
span.index_range()) {
337 if (!select_poly.
span[i]) {
352 const int current_edge_index)
354 const int index_in_poly = corner_edges.
slice(face).
first_index(current_edge_index);
356 if (index_in_poly >= 2) {
357 return corner_edges[face[index_in_poly - 2]];
360 return corner_edges[face[index_in_poly + 2]];
368 const int edge_start_index,
376 int current_face_index = face_start_index;
377 int current_edge_index = edge_start_index;
379 while (current_edge_index > 0) {
380 int next_face_index = -1;
382 for (
const int face_index : edge_to_face_map[current_edge_index]) {
383 if (face_index != current_face_index) {
384 next_face_index = face_index;
390 if (next_face_index == -1) {
395 if (
faces[next_face_index].
size() != 4) {
400 if (r_loop_faces.
contains(next_face_index)) {
405 if (hide_poly[next_face_index]) {
409 r_loop_faces.
add(next_face_index);
413 current_face_index = next_face_index;
436 if (closest_edge_index == -1) {
446 const OffsetIndices
faces =
mesh->faces();
450 const GroupedSpan<int> edge_to_face_map = bke::mesh::build_edge_to_face_map(
457 ".hide_poly", bke::AttrDomain::Face,
false);
459 const Span<int> faces_to_closest_edge = edge_to_face_map[closest_edge_index];
462 if (faces_to_closest_edge.is_empty()) {
474 if (!traced_full_loop && faces_to_closest_edge.size() > 1) {
486 ".select_poly", bke::AttrDomain::Face);
490 bool any_adjacent_poly_selected =
false;
491 for (
const int i : faces_to_closest_edge) {
492 any_adjacent_poly_selected |= select_poly.
span[i];
494 const bool select_toggle =
select && !any_adjacent_poly_selected;
495 select_poly.
span.fill_indices(faces_to_select.
as_span(), select_toggle);
506 for (
const int edge_index : face_edges) {
511 if (select_vert[edge[0]] || select_vert[edge[1]]) {
516 if (select_vert[edge[0]] && select_vert[edge[1]]) {
530 ".select_poly", bke::AttrDomain::Face);
532 ".select_vert", bke::AttrDomain::Point);
534 ".hide_poly", bke::AttrDomain::Face,
false);
536 const OffsetIndices
faces =
mesh->faces();
540 threading::parallel_for(select_poly.
span.index_range(), 1024, [&](
const IndexRange range) {
541 for (const int i : range) {
542 if (select_poly.span[i] || hide_poly[i]) {
545 const IndexRange face = faces[i];
546 if (poly_has_selected_neighbor(corner_edges.slice(face), edges, select_vert.span, face_step))
548 select_poly.span[i] = true;
553 select_poly.finish();
554 select_vert.finish();
562 for (
const int edge_index : face_edges) {
565 if (verts_of_unselected_faces[edge[0]] || verts_of_unselected_faces[edge[1]]) {
570 if (verts_of_unselected_faces[edge[0]] && verts_of_unselected_faces[edge[1]]) {
584 ".select_poly", bke::AttrDomain::Face);
586 ".hide_poly", bke::AttrDomain::Face,
false);
588 const OffsetIndices
faces =
mesh->faces();
596 for (
const int i :
faces.index_range()) {
597 if (select_poly.
span[i]) {
601 for (
const int vert : corner_verts.
slice(face)) {
602 verts_of_unselected_faces[vert].set(
true);
607 for (const int i : range) {
608 if (!select_poly.span[i] || hide_poly[i]) {
611 const IndexRange face = faces[i];
612 if (poly_has_unselected_neighbor(
613 corner_edges.slice(face), edges, verts_of_unselected_faces, face_step))
615 select_poly.span[i] = false;
620 select_poly.finish();
627 if (
mesh ==
nullptr) {
633 ".hide_poly", bke::AttrDomain::Face,
false);
635 ".select_poly", bke::AttrDomain::Face);
641 if (!hide_poly[i] && select_poly.span[i]) {
648 bool changed =
false;
654 const bool old_selection = select_poly.
span[i];
657 select_poly.span[i] =
true;
660 select_poly.span[i] =
false;
663 select_poly.span[i] = !select_poly.span[i];
667 if (old_selection != select_poly.span[i]) {
672 select_poly.finish();
686 float vec[3], bmat[3][3];
693 copy_m3_m4(bmat, ob->object_to_world().ptr());
696 const OffsetIndices
faces =
mesh->faces();
700 ".hide_poly", bke::AttrDomain::Face,
false);
702 ".select_poly", bke::AttrDomain::Face,
false);
705 if (hide_poly[i] || !select_poly[i]) {
709 for (
const int vert : corner_verts.
slice(
faces[i])) {
711 add_v3_v3v3(vec, vec, ob->object_to_world().location());
728 bool changed =
false;
736 ".hide_poly", bke::AttrDomain::Face,
false);
738 ".select_poly", bke::AttrDomain::Face);
741 if (index < mesh->faces_num) {
742 if (!hide_poly[index]) {
749 if ((found &&
params.select_passthrough) && select_poly.varray[index]) {
752 else if (found ||
params.deselect_all) {
764 select_poly.varray.set(index,
true);
767 select_poly.varray.set(index,
false);
770 select_poly.varray.set(index, !select_poly.varray[index]);
783 select_poly.finish();
784 return changed || found;
792 if (
mesh ==
nullptr) {
798 bke::mesh_select_vert_flush(*
mesh);
800 if (mesh_eval ==
nullptr) {
810 ".hide_vert", bke::AttrDomain::Point,
false);
813 bke::AttrDomain::Point);
815 for (
const int i : hide_vert_eval.span.index_range()) {
817 hide_vert_eval.
span[i] = hide_vert_orig[orig_indices[i]];
824 hide_vert_eval.finish();
827 ".select_vert", bke::AttrDomain::Point,
false);
830 bke::AttrDomain::Point);
832 for (
const int i : select_vert_eval.span.index_range()) {
834 select_vert_eval.
span[i] = select_vert_orig[orig_indices[i]];
839 select_vert_orig.
materialize(select_vert_eval.span);
841 select_vert_eval.finish();
865 for (const int2 &edge : edges.slice(range)) {
866 islands.join(edge[0], edge[1]);
872 ".select_vert", bke::AttrDomain::Point);
876 for (
const int i : vertex_indices) {
877 const int root = islands.find_root(i);
878 selected_roots.
add(root);
881 threading::parallel_for(select_vert.
span.index_range(), 1024, [&](
const IndexRange range) {
882 for (const int i : range) {
883 const int root = islands.find_root(i);
884 if (selected_roots.contains(root)) {
885 select_vert.span[i] = select;
898 const int region_coordinates[2],
923 for (
const int i : select_vert.
span.index_range()) {
924 if (!select_vert.
span[i]) {
939 ".select_vert", bke::AttrDomain::Point);
941 ".hide_edge", bke::AttrDomain::Edge,
false);
943 ".hide_poly", bke::AttrDomain::Face,
false);
945 const OffsetIndices
faces =
mesh->faces();
954 edge_to_face_map = bke::mesh::build_edge_to_face_map(
961 select_vert_original[i].set(select_vert.
span[i]);
967 const int2 &edge = edges[i];
968 if ((!select_vert_original[edge[0]] && !select_vert_original[edge[1]]) || hide_edge[i]) {
971 select_vert.
span[edge[0]] =
true;
972 select_vert.
span[edge[1]] =
true;
976 const Span<int> neighbor_polys = edge_to_face_map[i];
977 for (
const int face_i : neighbor_polys) {
978 if (hide_poly[face_i]) {
982 for (
const int vert : corner_verts.
slice(face)) {
983 select_vert.
span[vert] =
true;
997 ".select_vert", bke::AttrDomain::Point);
999 ".hide_edge", bke::AttrDomain::Edge,
false);
1001 ".hide_poly", bke::AttrDomain::Face,
false);
1003 const OffsetIndices
faces =
mesh->faces();
1012 edge_to_face_map = bke::mesh::build_edge_to_face_map(
1013 faces, corner_edges, edges.
size(), edge_to_face_offsets, edge_to_face_indices);
1019 select_vert_original[i].set(select_vert.
span[i]);
1023 const int2 &edge = edges[i];
1024 if ((select_vert_original[edge[0]] && select_vert_original[edge[1]]) && !hide_edge[i]) {
1027 select_vert.
span[edge[0]] =
false;
1028 select_vert.
span[edge[1]] =
false;
1033 for (
const int face_i : edge_to_face_map[i]) {
1034 if (hide_poly[face_i]) {
1038 for (
const int vert : corner_verts.
slice(face)) {
1039 select_vert.
span[vert] =
false;
1056 if (
mesh ==
nullptr) {
1062 ".hide_vert", bke::AttrDomain::Point,
false);
1064 ".select_vert", bke::AttrDomain::Point);
1070 if (!hide_vert[i] && select_vert.span[i]) {
1077 bool changed =
false;
1082 const bool old_selection = select_vert.
span[i];
1085 select_vert.span[i] =
true;
1088 select_vert.span[i] =
false;
1091 select_vert.span[i] = !select_vert.span[i];
1094 if (old_selection != select_vert.span[i]) {
1099 select_vert.finish();
1124 if (
mesh ==
nullptr) {
1138 ".hide_vert", bke::AttrDomain::Point,
false);
1140 ".select_vert", bke::AttrDomain::Point);
1142 for (
const int i : select_vert.span.index_range()) {
1143 if (!hide_vert[i]) {
1144 if (dverts[i].dw ==
nullptr) {
1146 select_vert.
span[i] =
true;
1151 select_vert.finish();
1168 ".hide_vert", bke::AttrDomain::Point);
1170 ".select_vert", bke::AttrDomain::Point);
1172 for (
const int i : hide_vert.
span.index_range()) {
1173 if (!hide_vert.
span[i]) {
1174 if (!select_vert.span[i] == unselected) {
1175 hide_vert.
span[i] =
true;
1179 if (hide_vert.
span[i]) {
1180 select_vert.span[i] =
false;
1184 select_vert.finish();
1186 bke::mesh_hide_vert_flush(*
mesh);
1202 ".hide_vert", bke::AttrDomain::Point,
false);
1204 ".select_vert", bke::AttrDomain::Point);
1206 for (
const int i : select_vert.span.index_range()) {
1212 select_vert.finish();
1215 attributes.
remove(
".hide_vert");
1217 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)
@ BKE_MESH_BATCH_DIRTY_SELECT_PAINT
@ BKE_MESH_BATCH_DIRTY_ALL
void BKE_mesh_mselect_validate(Mesh *mesh)
Mesh * BKE_mesh_from_object(Object *ob)
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)
T * DEG_get_evaluated(const Depsgraph *depsgraph, T *id)
Object is a sort of wrapper for general info.
#define ED_MESH_PICK_DEFAULT_VERT_DIST
bool ED_mesh_pick_edge(bContext *C, Object *ob, const int mval[2], uint dist_px, uint *r_index)
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)
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)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
int find_root(int x) const
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 IndexRange index_range() const
constexpr bool is_empty() const
IndexRange index_range() const
void materialize(MutableSpan< T > r_span) const
bool contains(const Key &key) const
Span< Key > as_span() 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_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
GAttributeWriter lookup_or_add_for_write(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
bool remove(const StringRef attribute_id)
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 ¶ms, 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 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)
static BMFace * face_step(BMEdge *edge, BMFace *f)
ObjectRuntimeHandle * runtime
MutableVArraySpan< T > span
void WM_event_add_notifier(const bContext *C, uint type, void *reference)