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_ALL = (1 << 5) - 1
} eAttrDomainMask;
ENUM_OPERATORS(eAttrDomainMask, ATTR_DOMAIN_MASK_ALL);
#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);
bke::GSpanAttributeWriter dst = dst_attributes.lookup_or_add_for_write_only_span(
id, meta_data.domain, meta_data.data_type);
BLI_assert(dst);
attributes.append({std::move(src), meta_data, std::move(dst)});
if (dst) {
/* Writing the the legacy "normal" attribute will fail. */
attributes.append({std::move(src), meta_data, std::move(dst)});
}
return true;
});

View File

@ -64,18 +64,6 @@ struct IndexAttributes {
/** \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,
const VArray<int> &counts,
Array<int> &r_offset_data)
@ -183,39 +171,25 @@ static void copy_stable_id_point(const OffsetIndices<int> offsets,
dst_attribute.finish();
}
static void copy_attributes_without_id(GeometrySet &geometry_set,
const GeometryComponentType component_type,
const eAttrDomain domain,
const OffsetIndices<int> offsets,
static void copy_attributes_without_id(const OffsetIndices<int> offsets,
const IndexMask selection,
const AnonymousAttributePropagationInfo &propagation_info,
const eAttrDomain domain,
const bke::AttributeAccessor src_attributes,
bke::MutableAttributeAccessor dst_attributes)
{
const Map<AttributeIDRef, AttributeKind> attributes = gather_attributes_without_id(
geometry_set, component_type, propagation_info);
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 || 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) {
for (auto &attribute : bke::retrieve_attributes_for_transfer(src_attributes,
dst_attributes,
ATTR_DOMAIN_AS_MASK(domain),
propagation_info,
{"id"})) {
attribute_math::convert_to_static_type(attribute.src.type(), [&](auto dummy) {
using T = decltype(dummy);
VArraySpan<T> src = src_attribute.varray.typed<T>();
MutableSpan<T> dst = dst_attribute.span.typed<T>();
const Span<T> src = attribute.src.typed<T>();
MutableSpan<T> dst = attribute.dst.span.typed<T>();
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.
*/
static void copy_curve_attributes_without_id(
const GeometrySet &geometry_set,
const bke::CurvesGeometry &src_curves,
const IndexMask selection,
const OffsetIndices<int> curve_offsets,
const AnonymousAttributePropagationInfo &propagation_info,
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 dst_points_by_curve = dst_curves.points_by_curve();
for (const Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) {
const AttributeIDRef attribute_id = entry.key;
GAttributeReader src_attribute = src_curves.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_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) {
for (auto &attribute : bke::retrieve_attributes_for_transfer(src_curves.attributes(),
dst_curves.attributes_for_write(),
ATTR_DOMAIN_MASK_ALL,
propagation_info,
{"id"})) {
attribute_math::convert_to_static_type(attribute.src.type(), [&](auto dummy) {
using T = decltype(dummy);
VArraySpan<T> src{src_attribute.varray.typed<T>()};
MutableSpan<T> dst = dst_attribute.span.typed<T>();
const Span<T> src = attribute.src.typed<T>();
MutableSpan<T> dst = attribute.dst.span.typed<T>();
switch (out_domain) {
switch (attribute.meta_data.domain) {
case ATTR_DOMAIN_CURVE:
threaded_slice_fill<T>(curve_offsets, selection, src, dst);
break;
@ -281,10 +239,11 @@ static void copy_curve_attributes_without_id(
});
break;
default:
BLI_assert_unreachable();
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;
copy_curve_attributes_without_id(
geometry_set, curves, selection, curve_offsets, propagation_info, new_curves);
copy_curve_attributes_without_id(curves, selection, curve_offsets, propagation_info, 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.
*/
static void copy_face_attributes_without_id(
GeometrySet &geometry_set,
const Span<int> edge_mapping,
const Span<int> vert_mapping,
const Span<int> loop_mapping,
@ -432,31 +389,14 @@ static void copy_face_attributes_without_id(
const bke::AttributeAccessor src_attributes,
bke::MutableAttributeAccessor dst_attributes)
{
Map<AttributeIDRef, AttributeKind> attributes = gather_attributes_without_id(
geometry_set, GEO_COMPONENT_TYPE_MESH, propagation_info);
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) {
for (auto &attribute : bke::retrieve_attributes_for_transfer(
src_attributes, dst_attributes, ATTR_DOMAIN_MASK_ALL, propagation_info, {"id"})) {
attribute_math::convert_to_static_type(attribute.src.type(), [&](auto dummy) {
using T = decltype(dummy);
VArraySpan<T> src{src_attribute.varray.typed<T>()};
MutableSpan<T> dst = dst_attribute.span.typed<T>();
const Span<T> src = attribute.src.typed<T>();
MutableSpan<T> dst = attribute.dst.span.typed<T>();
switch (out_domain) {
switch (attribute.meta_data.domain) {
case ATTR_DOMAIN_POINT:
array_utils::gather(src, vert_mapping, dst);
break;
@ -470,10 +410,11 @@ static void copy_face_attributes_without_id(
array_utils::gather(src, loop_mapping, dst);
break;
default:
BLI_assert_unreachable();
break;
}
});
dst_attribute.finish();
attribute.dst.finish();
}
}
@ -607,8 +548,7 @@ static void duplicate_faces(GeometrySet &geometry_set,
new_mesh->loose_edges_tag_none();
copy_face_attributes_without_id(geometry_set,
edge_mapping,
copy_face_attributes_without_id(edge_mapping,
vert_mapping,
loop_mapping,
duplicates,
@ -646,7 +586,6 @@ static void duplicate_faces(GeometrySet &geometry_set,
* copied with an offset fill, for point domain a mapping is used.
*/
static void copy_edge_attributes_without_id(
GeometrySet &geometry_set,
const Span<int> point_mapping,
const OffsetIndices<int> offsets,
const IndexMask selection,
@ -654,30 +593,18 @@ static void copy_edge_attributes_without_id(
const bke::AttributeAccessor src_attributes,
bke::MutableAttributeAccessor dst_attributes)
{
Map<AttributeIDRef, AttributeKind> attributes = gather_attributes_without_id(
geometry_set, GEO_COMPONENT_TYPE_MESH, propagation_info);
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;
}
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) {
for (auto &attribute :
bke::retrieve_attributes_for_transfer(src_attributes,
dst_attributes,
ATTR_DOMAIN_MASK_POINT | ATTR_DOMAIN_MASK_EDGE,
propagation_info,
{"id"})) {
attribute_math::convert_to_static_type(attribute.src.type(), [&](auto dummy) {
using T = decltype(dummy);
VArraySpan<T> src{src_attribute.varray.typed<T>()};
MutableSpan<T> dst = dst_attribute.span.typed<T>();
const Span<T> src = attribute.src.typed<T>();
MutableSpan<T> dst = attribute.dst.span.typed<T>();
switch (out_domain) {
switch (attribute.meta_data.domain) {
case ATTR_DOMAIN_EDGE:
threaded_slice_fill<T>(offsets, selection, src, dst);
break;
@ -685,10 +612,11 @@ static void copy_edge_attributes_without_id(
array_utils::gather(src, point_mapping, dst);
break;
default:
BLI_assert_unreachable();
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,
vert_orig_indices,
copy_edge_attributes_without_id(vert_orig_indices,
duplicates,
selection,
propagation_info,
@ -855,32 +782,16 @@ static void duplicate_points_curve(GeometrySet &geometry_set,
}
new_curve_offsets.last() = dst_num;
Map<AttributeIDRef, AttributeKind> attributes = gather_attributes_without_id(
geometry_set, GEO_COMPONENT_TYPE_CURVE, propagation_info);
for (const Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) {
const AttributeIDRef attribute_id = entry.key;
GAttributeReader src_attribute = src_curves.attributes().lookup(attribute_id);
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) {
for (auto &attribute : bke::retrieve_attributes_for_transfer(src_curves.attributes(),
new_curves.attributes_for_write(),
ATTR_DOMAIN_MASK_ALL,
propagation_info,
{"id"})) {
attribute_math::convert_to_static_type(attribute.src.type(), [&](auto dummy) {
using T = decltype(dummy);
VArraySpan<T> src{src_attribute.varray.typed<T>()};
MutableSpan<T> dst = dst_attribute.span.typed<T>();
switch (domain) {
const Span<T> src = attribute.src.typed<T>();
MutableSpan<T> dst = attribute.dst.span.typed<T>();
switch (attribute.meta_data.domain) {
case ATTR_DOMAIN_CURVE:
threading::parallel_for(selection.index_range(), 512, [&](IndexRange 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);
break;
default:
BLI_assert_unreachable();
break;
}
});
dst_attribute.finish();
attribute.dst.finish();
}
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);
copy_attributes_without_id(geometry_set,
GEO_COMPONENT_TYPE_MESH,
ATTR_DOMAIN_POINT,
duplicates,
copy_attributes_without_id(duplicates,
selection,
propagation_info,
ATTR_DOMAIN_POINT,
mesh.attributes(),
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());
copy_attributes_without_id(geometry_set,
GEO_COMPONENT_TYPE_POINT_CLOUD,
ATTR_DOMAIN_POINT,
duplicates,
copy_attributes_without_id(duplicates,
selection,
propagation_info,
ATTR_DOMAIN_POINT,
src_points.attributes(),
pointcloud->attributes_for_write());
@ -1103,12 +1011,10 @@ static void duplicate_instances(GeometrySet &geometry_set,
dst_instances->reference_handles().slice(range).fill(new_handle);
}
copy_attributes_without_id(geometry_set,
GEO_COMPONENT_TYPE_INSTANCES,
ATTR_DOMAIN_INSTANCE,
duplicates,
copy_attributes_without_id(duplicates,
selection,
propagation_info,
ATTR_DOMAIN_INSTANCE,
src_instances.attributes(),
dst_instances->attributes_for_write());