WIP: uv-simple-select #1

Closed
Chris Blackbourn wants to merge 182 commits from uv-simple-select into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
3 changed files with 67 additions and 158 deletions
Showing only changes of commit b47bd6e619 - Show all commits

View File

@ -41,6 +41,7 @@ typedef enum eAttrDomainMask {
ATTR_DOMAIN_MASK_CURVE = (1 << 4), ATTR_DOMAIN_MASK_CURVE = (1 << 4),
ATTR_DOMAIN_MASK_ALL = (1 << 5) - 1 ATTR_DOMAIN_MASK_ALL = (1 << 5) - 1
} eAttrDomainMask; } eAttrDomainMask;
ENUM_OPERATORS(eAttrDomainMask, ATTR_DOMAIN_MASK_ALL);
#define ATTR_DOMAIN_AS_MASK(domain) ((eAttrDomainMask)((1 << (int)(domain)))) #define ATTR_DOMAIN_AS_MASK(domain) ((eAttrDomainMask)((1 << (int)(domain))))

View File

@ -905,8 +905,10 @@ Vector<AttributeTransferData> retrieve_attributes_for_transfer(
BLI_assert(src); BLI_assert(src);
bke::GSpanAttributeWriter dst = dst_attributes.lookup_or_add_for_write_only_span( bke::GSpanAttributeWriter dst = dst_attributes.lookup_or_add_for_write_only_span(
id, meta_data.domain, meta_data.data_type); id, meta_data.domain, meta_data.data_type);
BLI_assert(dst); if (dst) {
attributes.append({std::move(src), meta_data, std::move(dst)}); /* Writing the the legacy "normal" attribute will fail. */
attributes.append({std::move(src), meta_data, std::move(dst)});
}
return true; return true;
}); });

View File

@ -64,18 +64,6 @@ struct IndexAttributes {
/** \name Utility Functions /** \name Utility Functions
* \{ */ * \{ */
static Map<AttributeIDRef, AttributeKind> gather_attributes_without_id(
const GeometrySet &geometry_set,
const GeometryComponentType component_type,
const AnonymousAttributePropagationInfo &propagation_info)
{
Map<AttributeIDRef, AttributeKind> attributes;
geometry_set.gather_attributes_for_propagation(
{component_type}, component_type, false, propagation_info, attributes);
attributes.remove("id");
return attributes;
};
static OffsetIndices<int> accumulate_counts_to_offsets(const IndexMask selection, static OffsetIndices<int> accumulate_counts_to_offsets(const IndexMask selection,
const VArray<int> &counts, const VArray<int> &counts,
Array<int> &r_offset_data) Array<int> &r_offset_data)
@ -183,39 +171,25 @@ static void copy_stable_id_point(const OffsetIndices<int> offsets,
dst_attribute.finish(); dst_attribute.finish();
} }
static void copy_attributes_without_id(GeometrySet &geometry_set, static void copy_attributes_without_id(const OffsetIndices<int> offsets,
const GeometryComponentType component_type,
const eAttrDomain domain,
const OffsetIndices<int> offsets,
const IndexMask selection, const IndexMask selection,
const AnonymousAttributePropagationInfo &propagation_info, const AnonymousAttributePropagationInfo &propagation_info,
const eAttrDomain domain,
const bke::AttributeAccessor src_attributes, const bke::AttributeAccessor src_attributes,
bke::MutableAttributeAccessor dst_attributes) bke::MutableAttributeAccessor dst_attributes)
{ {
const Map<AttributeIDRef, AttributeKind> attributes = gather_attributes_without_id( for (auto &attribute : bke::retrieve_attributes_for_transfer(src_attributes,
geometry_set, component_type, propagation_info); dst_attributes,
ATTR_DOMAIN_AS_MASK(domain),
for (const Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) { propagation_info,
const AttributeIDRef attribute_id = entry.key; {"id"})) {
GAttributeReader src_attribute = src_attributes.lookup(attribute_id); attribute_math::convert_to_static_type(attribute.src.type(), [&](auto dummy) {
if (!src_attribute || src_attribute.domain != domain) {
continue;
}
eAttrDomain out_domain = src_attribute.domain;
const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(
src_attribute.varray.type());
GSpanAttributeWriter dst_attribute = dst_attributes.lookup_or_add_for_write_only_span(
attribute_id, out_domain, data_type);
if (!dst_attribute) {
continue;
}
attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
using T = decltype(dummy); using T = decltype(dummy);
VArraySpan<T> src = src_attribute.varray.typed<T>(); const Span<T> src = attribute.src.typed<T>();
MutableSpan<T> dst = dst_attribute.span.typed<T>(); MutableSpan<T> dst = attribute.dst.span.typed<T>();
threaded_slice_fill<T>(offsets, selection, src, dst); threaded_slice_fill<T>(offsets, selection, src, dst);
}); });
dst_attribute.finish(); attribute.dst.finish();
} }
} }
@ -230,42 +204,26 @@ static void copy_attributes_without_id(GeometrySet &geometry_set,
* copied with an offset fill, otherwise a mapping is used. * copied with an offset fill, otherwise a mapping is used.
*/ */
static void copy_curve_attributes_without_id( static void copy_curve_attributes_without_id(
const GeometrySet &geometry_set,
const bke::CurvesGeometry &src_curves, const bke::CurvesGeometry &src_curves,
const IndexMask selection, const IndexMask selection,
const OffsetIndices<int> curve_offsets, const OffsetIndices<int> curve_offsets,
const AnonymousAttributePropagationInfo &propagation_info, const AnonymousAttributePropagationInfo &propagation_info,
bke::CurvesGeometry &dst_curves) bke::CurvesGeometry &dst_curves)
{ {
Map<AttributeIDRef, AttributeKind> attributes = gather_attributes_without_id(
geometry_set, GEO_COMPONENT_TYPE_CURVE, propagation_info);
const OffsetIndices src_points_by_curve = src_curves.points_by_curve(); const OffsetIndices src_points_by_curve = src_curves.points_by_curve();
const OffsetIndices dst_points_by_curve = dst_curves.points_by_curve(); const OffsetIndices dst_points_by_curve = dst_curves.points_by_curve();
for (const Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) { for (auto &attribute : bke::retrieve_attributes_for_transfer(src_curves.attributes(),
const AttributeIDRef attribute_id = entry.key; dst_curves.attributes_for_write(),
GAttributeReader src_attribute = src_curves.attributes().lookup(attribute_id); ATTR_DOMAIN_MASK_ALL,
if (!src_attribute) { propagation_info,
continue; {"id"})) {
} attribute_math::convert_to_static_type(attribute.src.type(), [&](auto dummy) {
eAttrDomain out_domain = src_attribute.domain;
const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(
src_attribute.varray.type());
GSpanAttributeWriter dst_attribute =
dst_curves.attributes_for_write().lookup_or_add_for_write_only_span(
attribute_id, out_domain, data_type);
if (!dst_attribute) {
continue;
}
attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
using T = decltype(dummy); using T = decltype(dummy);
VArraySpan<T> src{src_attribute.varray.typed<T>()}; const Span<T> src = attribute.src.typed<T>();
MutableSpan<T> dst = dst_attribute.span.typed<T>(); MutableSpan<T> dst = attribute.dst.span.typed<T>();
switch (out_domain) { switch (attribute.meta_data.domain) {
case ATTR_DOMAIN_CURVE: case ATTR_DOMAIN_CURVE:
threaded_slice_fill<T>(curve_offsets, selection, src, dst); threaded_slice_fill<T>(curve_offsets, selection, src, dst);
break; break;
@ -281,10 +239,11 @@ static void copy_curve_attributes_without_id(
}); });
break; break;
default: default:
BLI_assert_unreachable();
break; break;
} }
}); });
dst_attribute.finish(); attribute.dst.finish();
} }
} }
@ -394,8 +353,7 @@ static void duplicate_curves(GeometrySet &geometry_set,
}); });
all_dst_offsets.last() = dst_points_num; all_dst_offsets.last() = dst_points_num;
copy_curve_attributes_without_id( copy_curve_attributes_without_id(curves, selection, curve_offsets, propagation_info, new_curves);
geometry_set, curves, selection, curve_offsets, propagation_info, new_curves);
copy_stable_id_curves(curves, selection, curve_offsets, new_curves); copy_stable_id_curves(curves, selection, curve_offsets, new_curves);
@ -422,7 +380,6 @@ static void duplicate_curves(GeometrySet &geometry_set,
* copied with an offset fill, otherwise a mapping is used. * copied with an offset fill, otherwise a mapping is used.
*/ */
static void copy_face_attributes_without_id( static void copy_face_attributes_without_id(
GeometrySet &geometry_set,
const Span<int> edge_mapping, const Span<int> edge_mapping,
const Span<int> vert_mapping, const Span<int> vert_mapping,
const Span<int> loop_mapping, const Span<int> loop_mapping,
@ -432,31 +389,14 @@ static void copy_face_attributes_without_id(
const bke::AttributeAccessor src_attributes, const bke::AttributeAccessor src_attributes,
bke::MutableAttributeAccessor dst_attributes) bke::MutableAttributeAccessor dst_attributes)
{ {
Map<AttributeIDRef, AttributeKind> attributes = gather_attributes_without_id( for (auto &attribute : bke::retrieve_attributes_for_transfer(
geometry_set, GEO_COMPONENT_TYPE_MESH, propagation_info); src_attributes, dst_attributes, ATTR_DOMAIN_MASK_ALL, propagation_info, {"id"})) {
attribute_math::convert_to_static_type(attribute.src.type(), [&](auto dummy) {
for (const Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) {
const AttributeIDRef attribute_id = entry.key;
GAttributeReader src_attribute = src_attributes.lookup(attribute_id);
if (!src_attribute) {
continue;
}
eAttrDomain out_domain = src_attribute.domain;
const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(
src_attribute.varray.type());
GSpanAttributeWriter dst_attribute = dst_attributes.lookup_or_add_for_write_only_span(
attribute_id, out_domain, data_type);
if (!dst_attribute) {
continue;
}
attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
using T = decltype(dummy); using T = decltype(dummy);
VArraySpan<T> src{src_attribute.varray.typed<T>()}; const Span<T> src = attribute.src.typed<T>();
MutableSpan<T> dst = dst_attribute.span.typed<T>(); MutableSpan<T> dst = attribute.dst.span.typed<T>();
switch (out_domain) { switch (attribute.meta_data.domain) {
case ATTR_DOMAIN_POINT: case ATTR_DOMAIN_POINT:
array_utils::gather(src, vert_mapping, dst); array_utils::gather(src, vert_mapping, dst);
break; break;
@ -470,10 +410,11 @@ static void copy_face_attributes_without_id(
array_utils::gather(src, loop_mapping, dst); array_utils::gather(src, loop_mapping, dst);
break; break;
default: default:
BLI_assert_unreachable();
break; break;
} }
}); });
dst_attribute.finish(); attribute.dst.finish();
} }
} }
@ -607,8 +548,7 @@ static void duplicate_faces(GeometrySet &geometry_set,
new_mesh->loose_edges_tag_none(); new_mesh->loose_edges_tag_none();
copy_face_attributes_without_id(geometry_set, copy_face_attributes_without_id(edge_mapping,
edge_mapping,
vert_mapping, vert_mapping,
loop_mapping, loop_mapping,
duplicates, duplicates,
@ -646,7 +586,6 @@ static void duplicate_faces(GeometrySet &geometry_set,
* copied with an offset fill, for point domain a mapping is used. * copied with an offset fill, for point domain a mapping is used.
*/ */
static void copy_edge_attributes_without_id( static void copy_edge_attributes_without_id(
GeometrySet &geometry_set,
const Span<int> point_mapping, const Span<int> point_mapping,
const OffsetIndices<int> offsets, const OffsetIndices<int> offsets,
const IndexMask selection, const IndexMask selection,
@ -654,30 +593,18 @@ static void copy_edge_attributes_without_id(
const bke::AttributeAccessor src_attributes, const bke::AttributeAccessor src_attributes,
bke::MutableAttributeAccessor dst_attributes) bke::MutableAttributeAccessor dst_attributes)
{ {
Map<AttributeIDRef, AttributeKind> attributes = gather_attributes_without_id( for (auto &attribute :
geometry_set, GEO_COMPONENT_TYPE_MESH, propagation_info); bke::retrieve_attributes_for_transfer(src_attributes,
dst_attributes,
for (const Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) { ATTR_DOMAIN_MASK_POINT | ATTR_DOMAIN_MASK_EDGE,
const AttributeIDRef attribute_id = entry.key; propagation_info,
GAttributeReader src_attribute = src_attributes.lookup(attribute_id); {"id"})) {
if (!src_attribute) { attribute_math::convert_to_static_type(attribute.src.type(), [&](auto dummy) {
continue;
}
const eAttrDomain out_domain = src_attribute.domain;
const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(
src_attribute.varray.type());
GSpanAttributeWriter dst_attribute = dst_attributes.lookup_or_add_for_write_only_span(
attribute_id, out_domain, data_type);
if (!dst_attribute) {
continue;
}
attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
using T = decltype(dummy); using T = decltype(dummy);
VArraySpan<T> src{src_attribute.varray.typed<T>()}; const Span<T> src = attribute.src.typed<T>();
MutableSpan<T> dst = dst_attribute.span.typed<T>(); MutableSpan<T> dst = attribute.dst.span.typed<T>();
switch (out_domain) { switch (attribute.meta_data.domain) {
case ATTR_DOMAIN_EDGE: case ATTR_DOMAIN_EDGE:
threaded_slice_fill<T>(offsets, selection, src, dst); threaded_slice_fill<T>(offsets, selection, src, dst);
break; break;
@ -685,10 +612,11 @@ static void copy_edge_attributes_without_id(
array_utils::gather(src, point_mapping, dst); array_utils::gather(src, point_mapping, dst);
break; break;
default: default:
BLI_assert_unreachable();
break; break;
} }
}); });
dst_attribute.finish(); attribute.dst.finish();
} }
} }
@ -791,8 +719,7 @@ static void duplicate_edges(GeometrySet &geometry_set,
} }
}); });
copy_edge_attributes_without_id(geometry_set, copy_edge_attributes_without_id(vert_orig_indices,
vert_orig_indices,
duplicates, duplicates,
selection, selection,
propagation_info, propagation_info,
@ -855,32 +782,16 @@ static void duplicate_points_curve(GeometrySet &geometry_set,
} }
new_curve_offsets.last() = dst_num; new_curve_offsets.last() = dst_num;
Map<AttributeIDRef, AttributeKind> attributes = gather_attributes_without_id( for (auto &attribute : bke::retrieve_attributes_for_transfer(src_curves.attributes(),
geometry_set, GEO_COMPONENT_TYPE_CURVE, propagation_info); new_curves.attributes_for_write(),
ATTR_DOMAIN_MASK_ALL,
for (const Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) { propagation_info,
const AttributeIDRef attribute_id = entry.key; {"id"})) {
GAttributeReader src_attribute = src_curves.attributes().lookup(attribute_id); attribute_math::convert_to_static_type(attribute.src.type(), [&](auto dummy) {
if (!src_attribute) {
continue;
}
eAttrDomain domain = src_attribute.domain;
const eCustomDataType data_type = bke::cpp_type_to_custom_data_type(
src_attribute.varray.type());
GSpanAttributeWriter dst_attribute =
new_curves.attributes_for_write().lookup_or_add_for_write_only_span(
attribute_id, domain, data_type);
if (!dst_attribute) {
continue;
}
attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
using T = decltype(dummy); using T = decltype(dummy);
VArraySpan<T> src{src_attribute.varray.typed<T>()}; const Span<T> src = attribute.src.typed<T>();
MutableSpan<T> dst = dst_attribute.span.typed<T>(); MutableSpan<T> dst = attribute.dst.span.typed<T>();
switch (attribute.meta_data.domain) {
switch (domain) {
case ATTR_DOMAIN_CURVE: case ATTR_DOMAIN_CURVE:
threading::parallel_for(selection.index_range(), 512, [&](IndexRange range) { threading::parallel_for(selection.index_range(), 512, [&](IndexRange range) {
for (const int i_selection : range) { for (const int i_selection : range) {
@ -893,10 +804,11 @@ static void duplicate_points_curve(GeometrySet &geometry_set,
threaded_slice_fill(duplicates, selection, src, dst); threaded_slice_fill(duplicates, selection, src, dst);
break; break;
default: default:
BLI_assert_unreachable();
break; break;
} }
}); });
dst_attribute.finish(); attribute.dst.finish();
} }
copy_stable_id_point(duplicates, src_curves.attributes(), new_curves.attributes_for_write()); copy_stable_id_point(duplicates, src_curves.attributes(), new_curves.attributes_for_write());
@ -940,12 +852,10 @@ static void duplicate_points_mesh(GeometrySet &geometry_set,
Mesh *new_mesh = BKE_mesh_new_nomain(duplicates.total_size(), 0, 0, 0, 0); Mesh *new_mesh = BKE_mesh_new_nomain(duplicates.total_size(), 0, 0, 0, 0);
copy_attributes_without_id(geometry_set, copy_attributes_without_id(duplicates,
GEO_COMPONENT_TYPE_MESH,
ATTR_DOMAIN_POINT,
duplicates,
selection, selection,
propagation_info, propagation_info,
ATTR_DOMAIN_POINT,
mesh.attributes(), mesh.attributes(),
new_mesh->attributes_for_write()); new_mesh->attributes_for_write());
@ -990,12 +900,10 @@ static void duplicate_points_pointcloud(GeometrySet &geometry_set,
PointCloud *pointcloud = BKE_pointcloud_new_nomain(duplicates.total_size()); PointCloud *pointcloud = BKE_pointcloud_new_nomain(duplicates.total_size());
copy_attributes_without_id(geometry_set, copy_attributes_without_id(duplicates,
GEO_COMPONENT_TYPE_POINT_CLOUD,
ATTR_DOMAIN_POINT,
duplicates,
selection, selection,
propagation_info, propagation_info,
ATTR_DOMAIN_POINT,
src_points.attributes(), src_points.attributes(),
pointcloud->attributes_for_write()); pointcloud->attributes_for_write());
@ -1103,12 +1011,10 @@ static void duplicate_instances(GeometrySet &geometry_set,
dst_instances->reference_handles().slice(range).fill(new_handle); dst_instances->reference_handles().slice(range).fill(new_handle);
} }
copy_attributes_without_id(geometry_set, copy_attributes_without_id(duplicates,
GEO_COMPONENT_TYPE_INSTANCES,
ATTR_DOMAIN_INSTANCE,
duplicates,
selection, selection,
propagation_info, propagation_info,
ATTR_DOMAIN_INSTANCE,
src_instances.attributes(), src_instances.attributes(),
dst_instances->attributes_for_write()); dst_instances->attributes_for_write());