126 const Span<int2> src_edges = src_mesh.edges();
128 const Span<int> src_corner_verts = src_mesh.corner_verts();
129 const Span<int> src_corner_edges = src_mesh.corner_edges();
132 if (selection.is_empty()) {
135 if (
const std::optional<bool> single = selection.get_if_single()) {
136 return *single ? std::nullopt : std::make_optional<Mesh *>(
nullptr);
143 switch (selection_domain) {
144 case bke::AttrDomain::Point: {
146 threading::parallel_invoke(
148 [&]() { vert_mask = IndexMask::from_bools(span, memory.local()); },
149 [&]() { edge_mask = edge_selection_from_vert(src_edges, span, memory.local()); },
151 face_mask = face_selection_from_vert(
152 src_faces, src_corner_verts, span, memory.local());
156 case bke::AttrDomain::Edge: {
158 threading::parallel_invoke(
159 src_edges.
size() > 1024,
161 edge_mask = IndexMask::from_bools(span, memory.local());
162 vert_mask = vert_selection_from_edge(
163 src_edges, edge_mask, src_mesh.verts_num, memory.local());
166 face_mask = face_selection_from_edge(
167 src_faces, src_corner_edges, span, memory.local());
171 case bke::AttrDomain::Face: {
173 face_mask = IndexMask::from_bools(span, memory.
local());
174 threading::parallel_invoke(
175 face_mask.
size() > 1024,
177 vert_mask = vert_selection_from_face(
178 src_faces, face_mask, src_corner_verts, src_mesh.verts_num, memory.local());
181 edge_mask = edge_selection_from_face(
182 src_faces, face_mask, src_corner_edges, src_mesh.edges_num, memory.local());
194 const bool same_verts = vert_mask.
size() == src_mesh.
verts_num;
195 const bool same_edges = edge_mask.
size() == src_mesh.
edges_num;
196 const bool same_faces = face_mask.
size() == src_mesh.
faces_num;
197 if (same_verts && same_edges && same_faces) {
201 Mesh *dst_mesh = bke::mesh_new_no_attributes(
202 vert_mask.
size(), edge_mask.
size(), face_mask.
size(), 0);
209 src_faces, face_mask, dst_mesh->face_offsets_for_write());
216 threading::parallel_invoke(
217 vert_mask.
size() > 1024,
219 remap_verts(src_faces,
231 remap_edges(src_faces,
240 gather_vert_attributes(src_mesh, attribute_filter, vert_mask, *dst_mesh);
241 bke::gather_attributes(
243 bke::AttrDomain::Edge,
244 bke::AttrDomain::Edge,
245 bke::attribute_filter_with_skip_ref(attribute_filter, {
".edge_verts"}),
248 bke::gather_attributes(src_attributes,
249 bke::AttrDomain::Face,
250 bke::AttrDomain::Face,
254 bke::gather_attributes_group_to_group(
256 bke::AttrDomain::Corner,
257 bke::AttrDomain::Corner,
258 bke::attribute_filter_with_skip_ref(attribute_filter,
259 {
".corner_edge",
".corner_vert"}),
266 if (selection_domain == bke::AttrDomain::Edge) {
269 else if (selection_domain == bke::AttrDomain::Face) {
283 const Span<int2> src_edges = src_mesh.edges();
285 const Span<int> src_corner_verts = src_mesh.corner_verts();
286 const Span<int> src_corner_edges = src_mesh.corner_edges();
289 if (selection.is_empty()) {
296 switch (selection_domain) {
297 case bke::AttrDomain::Point: {
299 threading::parallel_invoke(
300 src_edges.
size() > 1024,
301 [&]() { edge_mask = edge_selection_from_vert(src_edges, span, memory.local()); },
303 face_mask = face_selection_from_vert(
304 src_faces, src_corner_verts, span, memory.local());
308 case bke::AttrDomain::Edge: {
310 threading::parallel_invoke(
311 src_edges.
size() > 1024,
312 [&]() { edge_mask = IndexMask::from_bools(span, memory.local()); },
314 face_mask = face_selection_from_edge(
315 src_faces, src_corner_edges, span, memory.local());
319 case bke::AttrDomain::Face: {
321 face_mask = IndexMask::from_bools(span, memory.
local());
323 src_faces, face_mask, src_corner_edges, src_edges.
size(), memory.
local());
331 const bool same_edges = edge_mask.
size() == src_mesh.
edges_num;
332 const bool same_faces = face_mask.
size() == src_mesh.
faces_num;
333 if (same_edges && same_faces) {
337 Mesh *dst_mesh = bke::mesh_new_no_attributes(
343 src_faces, face_mask, dst_mesh->face_offsets_for_write());
348 threading::parallel_invoke(
359 bke::copy_attributes(src_attributes,
360 bke::AttrDomain::Point,
361 bke::AttrDomain::Point,
364 bke::gather_attributes(src_attributes,
365 bke::AttrDomain::Edge,
366 bke::AttrDomain::Edge,
370 bke::gather_attributes(src_attributes,
371 bke::AttrDomain::Face,
372 bke::AttrDomain::Face,
376 bke::gather_attributes_group_to_group(
378 bke::AttrDomain::Corner,
379 bke::AttrDomain::Corner,
380 bke::attribute_filter_with_skip_ref(attribute_filter, {
".corner_edge"}),
389 if (selection_domain == bke::AttrDomain::Face) {
405 if (selection.is_empty()) {
411 switch (selection_domain) {
412 case bke::AttrDomain::Point:
414 src_faces, src_mesh.corner_verts(),
VArraySpan(selection), memory);
416 case bke::AttrDomain::Edge:
418 src_faces, src_mesh.corner_edges(),
VArraySpan(selection), memory);
420 case bke::AttrDomain::Face:
421 face_mask = IndexMask::from_bools(selection, memory);
428 const bool same_faces = face_mask.
size() == src_mesh.
faces_num;
433 Mesh *dst_mesh = bke::mesh_new_no_attributes(
439 src_faces, face_mask, dst_mesh->face_offsets_for_write());
444 bke::copy_attributes(src_attributes,
445 bke::AttrDomain::Point,
446 bke::AttrDomain::Point,
449 bke::copy_attributes(src_attributes,
450 bke::AttrDomain::Edge,
451 bke::AttrDomain::Edge,
454 bke::gather_attributes(src_attributes,
455 bke::AttrDomain::Face,
456 bke::AttrDomain::Face,
460 bke::gather_attributes_group_to_group(src_attributes,
461 bke::AttrDomain::Corner,
462 bke::AttrDomain::Corner,
static void remap_verts(const OffsetIndices< int > src_faces, const OffsetIndices< int > dst_faces, const int src_verts_num, const IndexMask &vert_mask, const IndexMask &edge_mask, const IndexMask &face_mask, const Span< int2 > src_edges, const Span< int > src_corner_verts, MutableSpan< int2 > dst_edges, MutableSpan< int > dst_corner_verts)